• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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