truncateArgs.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. /**
  7. * @param {any[]} args items to be truncated
  8. * @param {number} maxLength maximum length of args including spaces between
  9. * @returns {string[]} truncated args
  10. */
  11. const truncateArgs = (args, maxLength) => {
  12. const lengths = args.map(a => `${a}`.length);
  13. const availableLength = maxLength - lengths.length + 1;
  14. if (availableLength > 0 && args.length === 1) {
  15. if (availableLength >= args[0].length) {
  16. return args;
  17. } else if (availableLength > 3) {
  18. return ["..." + args[0].slice(-availableLength + 3)];
  19. } else {
  20. return [args[0].slice(-availableLength)];
  21. }
  22. }
  23. // Check if there is space for at least 4 chars per arg
  24. if (availableLength < lengths.reduce((s, i) => s + Math.min(i, 6), 0)) {
  25. // remove args
  26. if (args.length > 1)
  27. return truncateArgs(args.slice(0, args.length - 1), maxLength);
  28. return [];
  29. }
  30. let currentLength = lengths.reduce((a, b) => a + b, 0);
  31. // Check if all fits into maxLength
  32. if (currentLength <= availableLength) return args;
  33. // Try to remove chars from the longest items until it fits
  34. while (currentLength > availableLength) {
  35. const maxLength = Math.max(...lengths);
  36. const shorterItems = lengths.filter(l => l !== maxLength);
  37. const nextToMaxLength =
  38. shorterItems.length > 0 ? Math.max(...shorterItems) : 0;
  39. const maxReduce = maxLength - nextToMaxLength;
  40. let maxItems = lengths.length - shorterItems.length;
  41. let overrun = currentLength - availableLength;
  42. for (let i = 0; i < lengths.length; i++) {
  43. if (lengths[i] === maxLength) {
  44. const reduce = Math.min(Math.floor(overrun / maxItems), maxReduce);
  45. lengths[i] -= reduce;
  46. currentLength -= reduce;
  47. overrun -= reduce;
  48. maxItems--;
  49. }
  50. }
  51. }
  52. // Return args reduced to length in lengths
  53. return args.map((a, i) => {
  54. const str = `${a}`;
  55. const length = lengths[i];
  56. if (str.length === length) {
  57. return str;
  58. } else if (length > 5) {
  59. return "..." + str.slice(-length + 3);
  60. } else if (length > 0) {
  61. return str.slice(-length);
  62. } else {
  63. return "";
  64. }
  65. });
  66. };
  67. module.exports = truncateArgs;