repo_description: Node.js JavaScript runtime ✨🐢🚀✨
repo_topics: javascript js linux macos mit node nodejs runtime windows
code: 'use strict';
  
  const {
    ArrayPrototypeJoin,
    ArrayPrototypeMap,
    MathCeil,
    MathMax,
    MathMaxApply,
    ObjectPrototypeHasOwnProperty,
    StringPrototypeRepeat,
  } = primordials;
  
  const { getStringWidth } = require('internal/util/inspect');
  
  // The use of Unicode characters below is the only non-comment use of non-ASCII
  // Unicode characters in Node.js built-in modules. If they are ever removed or
  // rewritten with \u escapes, then a test will need to be (re-)added to Node.js
  // core to verify that Unicode characters work in built-ins.
  // Refs: https://github.com/nodejs/node/issues/10673
  const tableChars = {
    /* eslint-disable node-core/non-ascii-character */
    middleMiddle: '─',
    rowMiddle: '┼',
    topRight: '┐',
    topLeft: '┌',
    leftMiddle: '├',
    topMiddle: '┬',
    bottomRight: '┘',
    bottomLeft: '└',
    bottomMiddle: '┴',
    rightMiddle: '┤',
    left: '│ ',
    right: ' │',
    middle: ' │ ',
    /* eslint-enable node-core/non-ascii-character */
  };
  
  const renderRow = (row, columnWidths) => {
    let out = tableChars.left;
    for (let i = 0; i < row.length; i++) {
      const cell = row[i];
      const len = getStringWidth(cell);
      const needed = (columnWidths[i] - len);
      // round(needed) + ceil(needed) will always add up to the amount
      // of spaces we need while also left justifying the output.
      out += cell + StringPrototypeRepeat(' ', MathCeil(needed));
      if (i !== row.length - 1)
        out += tableChars.middle;
    }
    out += tableChars.right;
    return out;
  };
  
  const table = (head, columns) => {
    const rows = [];
    const columnWidths = ArrayPrototypeMap(head, (h) => getStringWidth(h));
    const longestColumn = MathMaxApply(ArrayPrototypeMap(columns, (a) =>
      a.length));
  
    for (let i = 0; i < head.length; i++) {
      const column = columns[i];
      for (let j = 0; j < longestColumn; j++) {
        if (rows[j] === undefined)
          rows[j] = [];
        const value = rows[j][i] =
          ObjectPrototypeHasOwnProperty(column, j) ? column[j] : '';
        const width = columnWidths[i] || 0;
        const counted = getStringWidth(value);
        columnWidths[i] = MathMax(width, counted);
      }
    }
  
    const divider = ArrayPrototypeMap(columnWidths, (i) =>
      StringPrototypeRepeat(tableChars.middleMiddle, i + 2));
  
    let result = tableChars.topLeft +
                 ArrayPrototypeJoin(divider, tableChars.topMiddle) +
                 tableChars.topRight + '\n' +
                 renderRow(head, columnWidths) + '\n' +
                 tableChars.leftMiddle +
                 ArrayPrototypeJoin(divider, tableChars.rowMiddle) +
                 tableChars.rightMiddle + '\n';
  
    for (const row of rows)
      result += `${renderRow(row, columnWidths)}\n`;
  
    result += tableChars.bottomLeft +
              ArrayPrototypeJoin(divider, tableChars.bottomMiddle) +
              tableChars.bottomRight;
  
    return result;
  };
  
  module.exports = table;
  