You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.3 KiB

4 years ago
  1. var baseToString = require('./_baseToString'),
  2. castSlice = require('./_castSlice'),
  3. hasUnicode = require('./_hasUnicode'),
  4. isObject = require('./isObject'),
  5. isRegExp = require('./isRegExp'),
  6. stringSize = require('./_stringSize'),
  7. stringToArray = require('./_stringToArray'),
  8. toInteger = require('./toInteger'),
  9. toString = require('./toString');
  10. /** Used as default options for `_.truncate`. */
  11. var DEFAULT_TRUNC_LENGTH = 30,
  12. DEFAULT_TRUNC_OMISSION = '...';
  13. /** Used to match `RegExp` flags from their coerced string values. */
  14. var reFlags = /\w*$/;
  15. /**
  16. * Truncates `string` if it's longer than the given maximum string length.
  17. * The last characters of the truncated string are replaced with the omission
  18. * string which defaults to "...".
  19. *
  20. * @static
  21. * @memberOf _
  22. * @since 4.0.0
  23. * @category String
  24. * @param {string} [string=''] The string to truncate.
  25. * @param {Object} [options={}] The options object.
  26. * @param {number} [options.length=30] The maximum string length.
  27. * @param {string} [options.omission='...'] The string to indicate text is omitted.
  28. * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
  29. * @returns {string} Returns the truncated string.
  30. * @example
  31. *
  32. * _.truncate('hi-diddly-ho there, neighborino');
  33. * // => 'hi-diddly-ho there, neighbo...'
  34. *
  35. * _.truncate('hi-diddly-ho there, neighborino', {
  36. * 'length': 24,
  37. * 'separator': ' '
  38. * });
  39. * // => 'hi-diddly-ho there,...'
  40. *
  41. * _.truncate('hi-diddly-ho there, neighborino', {
  42. * 'length': 24,
  43. * 'separator': /,? +/
  44. * });
  45. * // => 'hi-diddly-ho there...'
  46. *
  47. * _.truncate('hi-diddly-ho there, neighborino', {
  48. * 'omission': ' [...]'
  49. * });
  50. * // => 'hi-diddly-ho there, neig [...]'
  51. */
  52. function truncate(string, options) {
  53. var length = DEFAULT_TRUNC_LENGTH,
  54. omission = DEFAULT_TRUNC_OMISSION;
  55. if (isObject(options)) {
  56. var separator = 'separator' in options ? options.separator : separator;
  57. length = 'length' in options ? toInteger(options.length) : length;
  58. omission = 'omission' in options ? baseToString(options.omission) : omission;
  59. }
  60. string = toString(string);
  61. var strLength = string.length;
  62. if (hasUnicode(string)) {
  63. var strSymbols = stringToArray(string);
  64. strLength = strSymbols.length;
  65. }
  66. if (length >= strLength) {
  67. return string;
  68. }
  69. var end = length - stringSize(omission);
  70. if (end < 1) {
  71. return omission;
  72. }
  73. var result = strSymbols
  74. ? castSlice(strSymbols, 0, end).join('')
  75. : string.slice(0, end);
  76. if (separator === undefined) {
  77. return result + omission;
  78. }
  79. if (strSymbols) {
  80. end += (result.length - end);
  81. }
  82. if (isRegExp(separator)) {
  83. if (string.slice(end).search(separator)) {
  84. var match,
  85. substring = result;
  86. if (!separator.global) {
  87. separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
  88. }
  89. separator.lastIndex = 0;
  90. while ((match = separator.exec(substring))) {
  91. var newEnd = match.index;
  92. }
  93. result = result.slice(0, newEnd === undefined ? end : newEnd);
  94. }
  95. } else if (string.indexOf(baseToString(separator), end) != end) {
  96. var index = result.lastIndexOf(separator);
  97. if (index > -1) {
  98. result = result.slice(0, index);
  99. }
  100. }
  101. return result + omission;
  102. }
  103. module.exports = truncate;