index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /**
  2. * lodash (Custom Build) <https://lodash.com/>
  3. * Build: `lodash modularize exports="npm" -o ./`
  4. * Copyright jQuery Foundation and other contributors <https://jquery.org/>
  5. * Released under MIT license <https://lodash.com/license>
  6. * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
  7. * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
  8. */
  9. /** Used as default options for `_.truncate`. */
  10. var DEFAULT_TRUNC_LENGTH = 30,
  11. DEFAULT_TRUNC_OMISSION = '...';
  12. /** Used as references for various `Number` constants. */
  13. var INFINITY = 1 / 0,
  14. MAX_INTEGER = 1.7976931348623157e+308,
  15. NAN = 0 / 0;
  16. /** `Object#toString` result references. */
  17. var regexpTag = '[object RegExp]',
  18. symbolTag = '[object Symbol]';
  19. /** Used to match leading and trailing whitespace. */
  20. var reTrim = /^\s+|\s+$/g;
  21. /** Used to match `RegExp` flags from their coerced string values. */
  22. var reFlags = /\w*$/;
  23. /** Used to detect bad signed hexadecimal string values. */
  24. var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
  25. /** Used to detect binary string values. */
  26. var reIsBinary = /^0b[01]+$/i;
  27. /** Used to detect octal string values. */
  28. var reIsOctal = /^0o[0-7]+$/i;
  29. /** Used to compose unicode character classes. */
  30. var rsAstralRange = '\\ud800-\\udfff',
  31. rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
  32. rsComboSymbolsRange = '\\u20d0-\\u20f0',
  33. rsVarRange = '\\ufe0e\\ufe0f';
  34. /** Used to compose unicode capture groups. */
  35. var rsAstral = '[' + rsAstralRange + ']',
  36. rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
  37. rsFitz = '\\ud83c[\\udffb-\\udfff]',
  38. rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
  39. rsNonAstral = '[^' + rsAstralRange + ']',
  40. rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
  41. rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
  42. rsZWJ = '\\u200d';
  43. /** Used to compose unicode regexes. */
  44. var reOptMod = rsModifier + '?',
  45. rsOptVar = '[' + rsVarRange + ']?',
  46. rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
  47. rsSeq = rsOptVar + reOptMod + rsOptJoin,
  48. rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
  49. /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
  50. var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
  51. /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
  52. var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']');
  53. /** Built-in method references without a dependency on `root`. */
  54. var freeParseInt = parseInt;
  55. /** Detect free variable `global` from Node.js. */
  56. var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
  57. /** Detect free variable `self`. */
  58. var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
  59. /** Used as a reference to the global object. */
  60. var root = freeGlobal || freeSelf || Function('return this')();
  61. /** Detect free variable `exports`. */
  62. var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
  63. /** Detect free variable `module`. */
  64. var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
  65. /** Detect the popular CommonJS extension `module.exports`. */
  66. var moduleExports = freeModule && freeModule.exports === freeExports;
  67. /** Detect free variable `process` from Node.js. */
  68. var freeProcess = moduleExports && freeGlobal.process;
  69. /** Used to access faster Node.js helpers. */
  70. var nodeUtil = (function() {
  71. try {
  72. return freeProcess && freeProcess.binding('util');
  73. } catch (e) {}
  74. }());
  75. /* Node.js helper references. */
  76. var nodeIsRegExp = nodeUtil && nodeUtil.isRegExp;
  77. /**
  78. * Gets the size of an ASCII `string`.
  79. *
  80. * @private
  81. * @param {string} string The string inspect.
  82. * @returns {number} Returns the string size.
  83. */
  84. var asciiSize = baseProperty('length');
  85. /**
  86. * Converts an ASCII `string` to an array.
  87. *
  88. * @private
  89. * @param {string} string The string to convert.
  90. * @returns {Array} Returns the converted array.
  91. */
  92. function asciiToArray(string) {
  93. return string.split('');
  94. }
  95. /**
  96. * The base implementation of `_.property` without support for deep paths.
  97. *
  98. * @private
  99. * @param {string} key The key of the property to get.
  100. * @returns {Function} Returns the new accessor function.
  101. */
  102. function baseProperty(key) {
  103. return function(object) {
  104. return object == null ? undefined : object[key];
  105. };
  106. }
  107. /**
  108. * The base implementation of `_.unary` without support for storing metadata.
  109. *
  110. * @private
  111. * @param {Function} func The function to cap arguments for.
  112. * @returns {Function} Returns the new capped function.
  113. */
  114. function baseUnary(func) {
  115. return function(value) {
  116. return func(value);
  117. };
  118. }
  119. /**
  120. * Checks if `string` contains Unicode symbols.
  121. *
  122. * @private
  123. * @param {string} string The string to inspect.
  124. * @returns {boolean} Returns `true` if a symbol is found, else `false`.
  125. */
  126. function hasUnicode(string) {
  127. return reHasUnicode.test(string);
  128. }
  129. /**
  130. * Gets the number of symbols in `string`.
  131. *
  132. * @private
  133. * @param {string} string The string to inspect.
  134. * @returns {number} Returns the string size.
  135. */
  136. function stringSize(string) {
  137. return hasUnicode(string)
  138. ? unicodeSize(string)
  139. : asciiSize(string);
  140. }
  141. /**
  142. * Converts `string` to an array.
  143. *
  144. * @private
  145. * @param {string} string The string to convert.
  146. * @returns {Array} Returns the converted array.
  147. */
  148. function stringToArray(string) {
  149. return hasUnicode(string)
  150. ? unicodeToArray(string)
  151. : asciiToArray(string);
  152. }
  153. /**
  154. * Gets the size of a Unicode `string`.
  155. *
  156. * @private
  157. * @param {string} string The string inspect.
  158. * @returns {number} Returns the string size.
  159. */
  160. function unicodeSize(string) {
  161. var result = reUnicode.lastIndex = 0;
  162. while (reUnicode.test(string)) {
  163. result++;
  164. }
  165. return result;
  166. }
  167. /**
  168. * Converts a Unicode `string` to an array.
  169. *
  170. * @private
  171. * @param {string} string The string to convert.
  172. * @returns {Array} Returns the converted array.
  173. */
  174. function unicodeToArray(string) {
  175. return string.match(reUnicode) || [];
  176. }
  177. /** Used for built-in method references. */
  178. var objectProto = Object.prototype;
  179. /**
  180. * Used to resolve the
  181. * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
  182. * of values.
  183. */
  184. var objectToString = objectProto.toString;
  185. /** Built-in value references. */
  186. var Symbol = root.Symbol;
  187. /** Used to convert symbols to primitives and strings. */
  188. var symbolProto = Symbol ? Symbol.prototype : undefined,
  189. symbolToString = symbolProto ? symbolProto.toString : undefined;
  190. /**
  191. * The base implementation of `_.isRegExp` without Node.js optimizations.
  192. *
  193. * @private
  194. * @param {*} value The value to check.
  195. * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
  196. */
  197. function baseIsRegExp(value) {
  198. return isObject(value) && objectToString.call(value) == regexpTag;
  199. }
  200. /**
  201. * The base implementation of `_.slice` without an iteratee call guard.
  202. *
  203. * @private
  204. * @param {Array} array The array to slice.
  205. * @param {number} [start=0] The start position.
  206. * @param {number} [end=array.length] The end position.
  207. * @returns {Array} Returns the slice of `array`.
  208. */
  209. function baseSlice(array, start, end) {
  210. var index = -1,
  211. length = array.length;
  212. if (start < 0) {
  213. start = -start > length ? 0 : (length + start);
  214. }
  215. end = end > length ? length : end;
  216. if (end < 0) {
  217. end += length;
  218. }
  219. length = start > end ? 0 : ((end - start) >>> 0);
  220. start >>>= 0;
  221. var result = Array(length);
  222. while (++index < length) {
  223. result[index] = array[index + start];
  224. }
  225. return result;
  226. }
  227. /**
  228. * The base implementation of `_.toString` which doesn't convert nullish
  229. * values to empty strings.
  230. *
  231. * @private
  232. * @param {*} value The value to process.
  233. * @returns {string} Returns the string.
  234. */
  235. function baseToString(value) {
  236. // Exit early for strings to avoid a performance hit in some environments.
  237. if (typeof value == 'string') {
  238. return value;
  239. }
  240. if (isSymbol(value)) {
  241. return symbolToString ? symbolToString.call(value) : '';
  242. }
  243. var result = (value + '');
  244. return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  245. }
  246. /**
  247. * Casts `array` to a slice if it's needed.
  248. *
  249. * @private
  250. * @param {Array} array The array to inspect.
  251. * @param {number} start The start position.
  252. * @param {number} [end=array.length] The end position.
  253. * @returns {Array} Returns the cast slice.
  254. */
  255. function castSlice(array, start, end) {
  256. var length = array.length;
  257. end = end === undefined ? length : end;
  258. return (!start && end >= length) ? array : baseSlice(array, start, end);
  259. }
  260. /**
  261. * Checks if `value` is the
  262. * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
  263. * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
  264. *
  265. * @static
  266. * @memberOf _
  267. * @since 0.1.0
  268. * @category Lang
  269. * @param {*} value The value to check.
  270. * @returns {boolean} Returns `true` if `value` is an object, else `false`.
  271. * @example
  272. *
  273. * _.isObject({});
  274. * // => true
  275. *
  276. * _.isObject([1, 2, 3]);
  277. * // => true
  278. *
  279. * _.isObject(_.noop);
  280. * // => true
  281. *
  282. * _.isObject(null);
  283. * // => false
  284. */
  285. function isObject(value) {
  286. var type = typeof value;
  287. return !!value && (type == 'object' || type == 'function');
  288. }
  289. /**
  290. * Checks if `value` is object-like. A value is object-like if it's not `null`
  291. * and has a `typeof` result of "object".
  292. *
  293. * @static
  294. * @memberOf _
  295. * @since 4.0.0
  296. * @category Lang
  297. * @param {*} value The value to check.
  298. * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
  299. * @example
  300. *
  301. * _.isObjectLike({});
  302. * // => true
  303. *
  304. * _.isObjectLike([1, 2, 3]);
  305. * // => true
  306. *
  307. * _.isObjectLike(_.noop);
  308. * // => false
  309. *
  310. * _.isObjectLike(null);
  311. * // => false
  312. */
  313. function isObjectLike(value) {
  314. return !!value && typeof value == 'object';
  315. }
  316. /**
  317. * Checks if `value` is classified as a `RegExp` object.
  318. *
  319. * @static
  320. * @memberOf _
  321. * @since 0.1.0
  322. * @category Lang
  323. * @param {*} value The value to check.
  324. * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
  325. * @example
  326. *
  327. * _.isRegExp(/abc/);
  328. * // => true
  329. *
  330. * _.isRegExp('/abc/');
  331. * // => false
  332. */
  333. var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
  334. /**
  335. * Checks if `value` is classified as a `Symbol` primitive or object.
  336. *
  337. * @static
  338. * @memberOf _
  339. * @since 4.0.0
  340. * @category Lang
  341. * @param {*} value The value to check.
  342. * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
  343. * @example
  344. *
  345. * _.isSymbol(Symbol.iterator);
  346. * // => true
  347. *
  348. * _.isSymbol('abc');
  349. * // => false
  350. */
  351. function isSymbol(value) {
  352. return typeof value == 'symbol' ||
  353. (isObjectLike(value) && objectToString.call(value) == symbolTag);
  354. }
  355. /**
  356. * Converts `value` to a finite number.
  357. *
  358. * @static
  359. * @memberOf _
  360. * @since 4.12.0
  361. * @category Lang
  362. * @param {*} value The value to convert.
  363. * @returns {number} Returns the converted number.
  364. * @example
  365. *
  366. * _.toFinite(3.2);
  367. * // => 3.2
  368. *
  369. * _.toFinite(Number.MIN_VALUE);
  370. * // => 5e-324
  371. *
  372. * _.toFinite(Infinity);
  373. * // => 1.7976931348623157e+308
  374. *
  375. * _.toFinite('3.2');
  376. * // => 3.2
  377. */
  378. function toFinite(value) {
  379. if (!value) {
  380. return value === 0 ? value : 0;
  381. }
  382. value = toNumber(value);
  383. if (value === INFINITY || value === -INFINITY) {
  384. var sign = (value < 0 ? -1 : 1);
  385. return sign * MAX_INTEGER;
  386. }
  387. return value === value ? value : 0;
  388. }
  389. /**
  390. * Converts `value` to an integer.
  391. *
  392. * **Note:** This method is loosely based on
  393. * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
  394. *
  395. * @static
  396. * @memberOf _
  397. * @since 4.0.0
  398. * @category Lang
  399. * @param {*} value The value to convert.
  400. * @returns {number} Returns the converted integer.
  401. * @example
  402. *
  403. * _.toInteger(3.2);
  404. * // => 3
  405. *
  406. * _.toInteger(Number.MIN_VALUE);
  407. * // => 0
  408. *
  409. * _.toInteger(Infinity);
  410. * // => 1.7976931348623157e+308
  411. *
  412. * _.toInteger('3.2');
  413. * // => 3
  414. */
  415. function toInteger(value) {
  416. var result = toFinite(value),
  417. remainder = result % 1;
  418. return result === result ? (remainder ? result - remainder : result) : 0;
  419. }
  420. /**
  421. * Converts `value` to a number.
  422. *
  423. * @static
  424. * @memberOf _
  425. * @since 4.0.0
  426. * @category Lang
  427. * @param {*} value The value to process.
  428. * @returns {number} Returns the number.
  429. * @example
  430. *
  431. * _.toNumber(3.2);
  432. * // => 3.2
  433. *
  434. * _.toNumber(Number.MIN_VALUE);
  435. * // => 5e-324
  436. *
  437. * _.toNumber(Infinity);
  438. * // => Infinity
  439. *
  440. * _.toNumber('3.2');
  441. * // => 3.2
  442. */
  443. function toNumber(value) {
  444. if (typeof value == 'number') {
  445. return value;
  446. }
  447. if (isSymbol(value)) {
  448. return NAN;
  449. }
  450. if (isObject(value)) {
  451. var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
  452. value = isObject(other) ? (other + '') : other;
  453. }
  454. if (typeof value != 'string') {
  455. return value === 0 ? value : +value;
  456. }
  457. value = value.replace(reTrim, '');
  458. var isBinary = reIsBinary.test(value);
  459. return (isBinary || reIsOctal.test(value))
  460. ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
  461. : (reIsBadHex.test(value) ? NAN : +value);
  462. }
  463. /**
  464. * Converts `value` to a string. An empty string is returned for `null`
  465. * and `undefined` values. The sign of `-0` is preserved.
  466. *
  467. * @static
  468. * @memberOf _
  469. * @since 4.0.0
  470. * @category Lang
  471. * @param {*} value The value to process.
  472. * @returns {string} Returns the string.
  473. * @example
  474. *
  475. * _.toString(null);
  476. * // => ''
  477. *
  478. * _.toString(-0);
  479. * // => '-0'
  480. *
  481. * _.toString([1, 2, 3]);
  482. * // => '1,2,3'
  483. */
  484. function toString(value) {
  485. return value == null ? '' : baseToString(value);
  486. }
  487. /**
  488. * Truncates `string` if it's longer than the given maximum string length.
  489. * The last characters of the truncated string are replaced with the omission
  490. * string which defaults to "...".
  491. *
  492. * @static
  493. * @memberOf _
  494. * @since 4.0.0
  495. * @category String
  496. * @param {string} [string=''] The string to truncate.
  497. * @param {Object} [options={}] The options object.
  498. * @param {number} [options.length=30] The maximum string length.
  499. * @param {string} [options.omission='...'] The string to indicate text is omitted.
  500. * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
  501. * @returns {string} Returns the truncated string.
  502. * @example
  503. *
  504. * _.truncate('hi-diddly-ho there, neighborino');
  505. * // => 'hi-diddly-ho there, neighbo...'
  506. *
  507. * _.truncate('hi-diddly-ho there, neighborino', {
  508. * 'length': 24,
  509. * 'separator': ' '
  510. * });
  511. * // => 'hi-diddly-ho there,...'
  512. *
  513. * _.truncate('hi-diddly-ho there, neighborino', {
  514. * 'length': 24,
  515. * 'separator': /,? +/
  516. * });
  517. * // => 'hi-diddly-ho there...'
  518. *
  519. * _.truncate('hi-diddly-ho there, neighborino', {
  520. * 'omission': ' [...]'
  521. * });
  522. * // => 'hi-diddly-ho there, neig [...]'
  523. */
  524. function truncate(string, options) {
  525. var length = DEFAULT_TRUNC_LENGTH,
  526. omission = DEFAULT_TRUNC_OMISSION;
  527. if (isObject(options)) {
  528. var separator = 'separator' in options ? options.separator : separator;
  529. length = 'length' in options ? toInteger(options.length) : length;
  530. omission = 'omission' in options ? baseToString(options.omission) : omission;
  531. }
  532. string = toString(string);
  533. var strLength = string.length;
  534. if (hasUnicode(string)) {
  535. var strSymbols = stringToArray(string);
  536. strLength = strSymbols.length;
  537. }
  538. if (length >= strLength) {
  539. return string;
  540. }
  541. var end = length - stringSize(omission);
  542. if (end < 1) {
  543. return omission;
  544. }
  545. var result = strSymbols
  546. ? castSlice(strSymbols, 0, end).join('')
  547. : string.slice(0, end);
  548. if (separator === undefined) {
  549. return result + omission;
  550. }
  551. if (strSymbols) {
  552. end += (result.length - end);
  553. }
  554. if (isRegExp(separator)) {
  555. if (string.slice(end).search(separator)) {
  556. var match,
  557. substring = result;
  558. if (!separator.global) {
  559. separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
  560. }
  561. separator.lastIndex = 0;
  562. while ((match = separator.exec(substring))) {
  563. var newEnd = match.index;
  564. }
  565. result = result.slice(0, newEnd === undefined ? end : newEnd);
  566. }
  567. } else if (string.indexOf(baseToString(separator), end) != end) {
  568. var index = result.lastIndexOf(separator);
  569. if (index > -1) {
  570. result = result.slice(0, index);
  571. }
  572. }
  573. return result + omission;
  574. }
  575. module.exports = truncate;