1"use strict" 2 3var wcwidth = require('./width') 4 5/** 6 * repeat string `str` up to total length of `len` 7 * 8 * @param String str string to repeat 9 * @param Number len total length of output string 10 */ 11 12function repeatString(str, len) { 13 return Array.apply(null, {length: len + 1}).join(str).slice(0, len) 14} 15 16/** 17 * Pad `str` up to total length `max` with `chr`. 18 * If `str` is longer than `max`, padRight will return `str` unaltered. 19 * 20 * @param String str string to pad 21 * @param Number max total length of output string 22 * @param String chr optional. Character to pad with. default: ' ' 23 * @return String padded str 24 */ 25 26function padRight(str, max, chr) { 27 str = str != null ? str : '' 28 str = String(str) 29 var length = max - wcwidth(str) 30 if (length <= 0) return str 31 return str + repeatString(chr || ' ', length) 32} 33 34/** 35 * Pad `str` up to total length `max` with `chr`. 36 * If `str` is longer than `max`, padCenter will return `str` unaltered. 37 * 38 * @param String str string to pad 39 * @param Number max total length of output string 40 * @param String chr optional. Character to pad with. default: ' ' 41 * @return String padded str 42 */ 43 44function padCenter(str, max, chr) { 45 str = str != null ? str : '' 46 str = String(str) 47 var length = max - wcwidth(str) 48 if (length <= 0) return str 49 var lengthLeft = Math.floor(length/2) 50 var lengthRight = length - lengthLeft 51 return repeatString(chr || ' ', lengthLeft) + str + repeatString(chr || ' ', lengthRight) 52} 53 54/** 55 * Pad `str` up to total length `max` with `chr`, on the left. 56 * If `str` is longer than `max`, padRight will return `str` unaltered. 57 * 58 * @param String str string to pad 59 * @param Number max total length of output string 60 * @param String chr optional. Character to pad with. default: ' ' 61 * @return String padded str 62 */ 63 64function padLeft(str, max, chr) { 65 str = str != null ? str : '' 66 str = String(str) 67 var length = max - wcwidth(str) 68 if (length <= 0) return str 69 return repeatString(chr || ' ', length) + str 70} 71 72/** 73 * Split a String `str` into lines of maxiumum length `max`. 74 * Splits on word boundaries. Preserves existing new lines. 75 * 76 * @param String str string to split 77 * @param Number max length of each line 78 * @return Array Array containing lines. 79 */ 80 81function splitIntoLines(str, max) { 82 function _splitIntoLines(str, max) { 83 return str.trim().split(' ').reduce(function(lines, word) { 84 var line = lines[lines.length - 1] 85 if (line && wcwidth(line.join(' ')) + wcwidth(word) < max) { 86 lines[lines.length - 1].push(word) // add to line 87 } 88 else lines.push([word]) // new line 89 return lines 90 }, []).map(function(l) { 91 return l.join(' ') 92 }) 93 } 94 return str.split('\n').map(function(str) { 95 return _splitIntoLines(str, max) 96 }).reduce(function(lines, line) { 97 return lines.concat(line) 98 }, []) 99} 100 101/** 102 * Add spaces and `truncationChar` between words of 103 * `str` which are longer than `max`. 104 * 105 * @param String str string to split 106 * @param Number max length of each line 107 * @param Number truncationChar character to append to split words 108 * @return String 109 */ 110 111function splitLongWords(str, max, truncationChar) { 112 str = str.trim() 113 var result = [] 114 var words = str.split(' ') 115 var remainder = '' 116 117 var truncationWidth = wcwidth(truncationChar) 118 119 while (remainder || words.length) { 120 if (remainder) { 121 var word = remainder 122 remainder = '' 123 } else { 124 var word = words.shift() 125 } 126 127 if (wcwidth(word) > max) { 128 // slice is based on length no wcwidth 129 var i = 0 130 var wwidth = 0 131 var limit = max - truncationWidth 132 while (i < word.length) { 133 var w = wcwidth(word.charAt(i)) 134 if (w + wwidth > limit) { 135 break 136 } 137 wwidth += w 138 ++i 139 } 140 141 remainder = word.slice(i) // get remainder 142 // save remainder for next loop 143 144 word = word.slice(0, i) // grab truncated word 145 word += truncationChar // add trailing … or whatever 146 } 147 result.push(word) 148 } 149 150 return result.join(' ') 151} 152 153 154/** 155 * Truncate `str` into total width `max` 156 * If `str` is shorter than `max`, will return `str` unaltered. 157 * 158 * @param String str string to truncated 159 * @param Number max total wcwidth of output string 160 * @return String truncated str 161 */ 162 163function truncateString(str, max) { 164 165 str = str != null ? str : '' 166 str = String(str) 167 168 if(max == Infinity) return str 169 170 var i = 0 171 var wwidth = 0 172 while (i < str.length) { 173 var w = wcwidth(str.charAt(i)) 174 if(w + wwidth > max) 175 break 176 wwidth += w 177 ++i 178 } 179 return str.slice(0, i) 180} 181 182 183 184/** 185 * Exports 186 */ 187 188module.exports.padRight = padRight 189module.exports.padCenter = padCenter 190module.exports.padLeft = padLeft 191module.exports.splitIntoLines = splitIntoLines 192module.exports.splitLongWords = splitLongWords 193module.exports.truncateString = truncateString 194