utils.js 4.8 KB

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