table.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. var each = require('./each');
  2. var strWidth = require('./strWidth');
  3. var map = require('./map');
  4. var repeat = require('./repeat');
  5. var cloneDeep = require('./cloneDeep');
  6. exports = function(rows) {
  7. rows = cloneDeep(rows);
  8. var options = {
  9. border: defBorder
  10. };
  11. options.columns = getColumns(rows);
  12. padData(rows, options);
  13. return render(rows, options);
  14. };
  15. function padData(rows, options) {
  16. var columnCount = options.columns.length;
  17. for (var i = 0, len = rows.length; i < len; i++) {
  18. while (rows[i].length < columnCount) {
  19. rows[i].push('');
  20. }
  21. }
  22. return loopData(rows, function(data, row, column) {
  23. var _options$columns$colu = options.columns[column],
  24. paddingLeft = _options$columns$colu.paddingLeft,
  25. width = _options$columns$colu.width,
  26. paddingRight = _options$columns$colu.paddingRight;
  27. return (
  28. repeat(' ', paddingLeft) +
  29. data +
  30. repeat(' ', width - strWidth(data) - paddingRight)
  31. );
  32. });
  33. }
  34. function loopData(rows, handler) {
  35. for (var i = 0, len = rows.length; i < len; i++) {
  36. var row = rows[i];
  37. for (var j = 0, _len = row.length; j < _len; j++) {
  38. var data = handler(row[j], i, j);
  39. if (data) {
  40. row[j] = data;
  41. }
  42. }
  43. }
  44. }
  45. function getColumns(rows) {
  46. var columns = [];
  47. var paddingLeft = 1;
  48. var paddingRight = 1;
  49. loopData(rows, function(data, row, column) {
  50. columns[column] = columns[column] || {
  51. width: paddingLeft + paddingRight,
  52. paddingLeft: paddingLeft,
  53. paddingRight: paddingRight
  54. };
  55. var width = strWidth(data) + paddingLeft + paddingRight;
  56. if (width > columns[column].width) {
  57. columns[column].width = width;
  58. }
  59. });
  60. return columns;
  61. }
  62. function render(rows, options) {
  63. var ret = '';
  64. ret += renderBorder('top', options);
  65. each(rows, function(row, idx) {
  66. ret += renderRow(row, options);
  67. if (idx === rows.length - 1) {
  68. ret += renderBorder('bottom', options);
  69. } else {
  70. ret += renderBorder('join', options);
  71. }
  72. });
  73. return ret;
  74. }
  75. function renderRow(columns, options) {
  76. var border = options.border;
  77. return (
  78. border.bodyLeft +
  79. columns.join(border.bodyJoin) +
  80. border.bodyRight +
  81. '\n'
  82. );
  83. }
  84. function renderBorder(type, options) {
  85. var border = options.border,
  86. columns = options.columns;
  87. var left = border[type + 'Left'];
  88. var right = border[type + 'Right'];
  89. var body = border[type + 'Body'];
  90. var join = border[type + 'Join'];
  91. var ret = map(columns, function(column) {
  92. return repeat(body, column.width);
  93. }).join(join);
  94. ret = left + ret + right;
  95. if (type !== 'bottom') {
  96. ret += '\n';
  97. }
  98. return ret;
  99. }
  100. var defBorder = {
  101. topBody: '─',
  102. topJoin: '┬',
  103. topLeft: '┌',
  104. topRight: '┐',
  105. bottomBody: '─',
  106. bottomJoin: '┴',
  107. bottomLeft: '└',
  108. bottomRight: '┘',
  109. bodyLeft: '│',
  110. bodyRight: '│',
  111. bodyJoin: '│',
  112. joinBody: '─',
  113. joinLeft: '├',
  114. joinRight: '┤',
  115. joinJoin: '┼'
  116. };
  117. module.exports = exports;