11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeJoin,
51cb0ef41Sopenharmony_ci  ArrayPrototypeMap,
61cb0ef41Sopenharmony_ci  MathCeil,
71cb0ef41Sopenharmony_ci  MathMax,
81cb0ef41Sopenharmony_ci  MathMaxApply,
91cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty,
101cb0ef41Sopenharmony_ci  StringPrototypeRepeat,
111cb0ef41Sopenharmony_ci} = primordials;
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst { getStringWidth } = require('internal/util/inspect');
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci// The use of Unicode characters below is the only non-comment use of non-ASCII
161cb0ef41Sopenharmony_ci// Unicode characters in Node.js built-in modules. If they are ever removed or
171cb0ef41Sopenharmony_ci// rewritten with \u escapes, then a test will need to be (re-)added to Node.js
181cb0ef41Sopenharmony_ci// core to verify that Unicode characters work in built-ins.
191cb0ef41Sopenharmony_ci// Refs: https://github.com/nodejs/node/issues/10673
201cb0ef41Sopenharmony_ciconst tableChars = {
211cb0ef41Sopenharmony_ci  /* eslint-disable node-core/non-ascii-character */
221cb0ef41Sopenharmony_ci  middleMiddle: '─',
231cb0ef41Sopenharmony_ci  rowMiddle: '┼',
241cb0ef41Sopenharmony_ci  topRight: '┐',
251cb0ef41Sopenharmony_ci  topLeft: '┌',
261cb0ef41Sopenharmony_ci  leftMiddle: '├',
271cb0ef41Sopenharmony_ci  topMiddle: '┬',
281cb0ef41Sopenharmony_ci  bottomRight: '┘',
291cb0ef41Sopenharmony_ci  bottomLeft: '└',
301cb0ef41Sopenharmony_ci  bottomMiddle: '┴',
311cb0ef41Sopenharmony_ci  rightMiddle: '┤',
321cb0ef41Sopenharmony_ci  left: '│ ',
331cb0ef41Sopenharmony_ci  right: ' │',
341cb0ef41Sopenharmony_ci  middle: ' │ ',
351cb0ef41Sopenharmony_ci  /* eslint-enable node-core/non-ascii-character */
361cb0ef41Sopenharmony_ci};
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciconst renderRow = (row, columnWidths) => {
391cb0ef41Sopenharmony_ci  let out = tableChars.left;
401cb0ef41Sopenharmony_ci  for (let i = 0; i < row.length; i++) {
411cb0ef41Sopenharmony_ci    const cell = row[i];
421cb0ef41Sopenharmony_ci    const len = getStringWidth(cell);
431cb0ef41Sopenharmony_ci    const needed = (columnWidths[i] - len) / 2;
441cb0ef41Sopenharmony_ci    // round(needed) + ceil(needed) will always add up to the amount
451cb0ef41Sopenharmony_ci    // of spaces we need while also left justifying the output.
461cb0ef41Sopenharmony_ci    out += StringPrototypeRepeat(' ', needed) + cell +
471cb0ef41Sopenharmony_ci           StringPrototypeRepeat(' ', MathCeil(needed));
481cb0ef41Sopenharmony_ci    if (i !== row.length - 1)
491cb0ef41Sopenharmony_ci      out += tableChars.middle;
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci  out += tableChars.right;
521cb0ef41Sopenharmony_ci  return out;
531cb0ef41Sopenharmony_ci};
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ciconst table = (head, columns) => {
561cb0ef41Sopenharmony_ci  const rows = [];
571cb0ef41Sopenharmony_ci  const columnWidths = ArrayPrototypeMap(head, (h) => getStringWidth(h));
581cb0ef41Sopenharmony_ci  const longestColumn = MathMaxApply(ArrayPrototypeMap(columns, (a) =>
591cb0ef41Sopenharmony_ci    a.length));
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  for (let i = 0; i < head.length; i++) {
621cb0ef41Sopenharmony_ci    const column = columns[i];
631cb0ef41Sopenharmony_ci    for (let j = 0; j < longestColumn; j++) {
641cb0ef41Sopenharmony_ci      if (rows[j] === undefined)
651cb0ef41Sopenharmony_ci        rows[j] = [];
661cb0ef41Sopenharmony_ci      const value = rows[j][i] =
671cb0ef41Sopenharmony_ci        ObjectPrototypeHasOwnProperty(column, j) ? column[j] : '';
681cb0ef41Sopenharmony_ci      const width = columnWidths[i] || 0;
691cb0ef41Sopenharmony_ci      const counted = getStringWidth(value);
701cb0ef41Sopenharmony_ci      columnWidths[i] = MathMax(width, counted);
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  const divider = ArrayPrototypeMap(columnWidths, (i) =>
751cb0ef41Sopenharmony_ci    StringPrototypeRepeat(tableChars.middleMiddle, i + 2));
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  let result = tableChars.topLeft +
781cb0ef41Sopenharmony_ci               ArrayPrototypeJoin(divider, tableChars.topMiddle) +
791cb0ef41Sopenharmony_ci               tableChars.topRight + '\n' +
801cb0ef41Sopenharmony_ci               renderRow(head, columnWidths) + '\n' +
811cb0ef41Sopenharmony_ci               tableChars.leftMiddle +
821cb0ef41Sopenharmony_ci               ArrayPrototypeJoin(divider, tableChars.rowMiddle) +
831cb0ef41Sopenharmony_ci               tableChars.rightMiddle + '\n';
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  for (const row of rows)
861cb0ef41Sopenharmony_ci    result += `${renderRow(row, columnWidths)}\n`;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  result += tableChars.bottomLeft +
891cb0ef41Sopenharmony_ci            ArrayPrototypeJoin(divider, tableChars.bottomMiddle) +
901cb0ef41Sopenharmony_ci            tableChars.bottomRight;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  return result;
931cb0ef41Sopenharmony_ci};
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_cimodule.exports = table;
96