import _ from 'lodash'; import makeStreamConfig from './makeStreamConfig'; import drawRow from './drawRow'; import { drawBorderBottom, drawBorderJoin, drawBorderTop } from './drawBorder'; import stringifyTableData from './stringifyTableData'; import truncateTableData from './truncateTableData'; import mapDataUsingRowHeightIndex from './mapDataUsingRowHeightIndex'; import alignTableData from './alignTableData'; import padTableData from './padTableData'; import calculateRowHeightIndex from './calculateRowHeightIndex'; /** * @param {Array} data * @param {Object} config * @returns {Array} */ const prepareData = (data, config) => { let rows; rows = stringifyTableData(data); rows = truncateTableData(data, config); const rowHeightIndex = calculateRowHeightIndex(rows, config); rows = mapDataUsingRowHeightIndex(rows, rowHeightIndex, config); rows = alignTableData(rows, config); rows = padTableData(rows, config); return rows; }; /** * @param {string[]} row * @param {number[]} columnWidthIndex * @param {Object} config * @returns {undefined} */ const create = (row, columnWidthIndex, config) => { const rows = prepareData([row], config); const body = rows.map((literalRow) => { return drawRow(literalRow, config.border); }).join(''); let output; output = ''; output += drawBorderTop(columnWidthIndex, config.border); output += body; output += drawBorderBottom(columnWidthIndex, config.border); output = _.trimEnd(output); process.stdout.write(output); }; /** * @param {string[]} row * @param {number[]} columnWidthIndex * @param {Object} config * @returns {undefined} */ const append = (row, columnWidthIndex, config) => { const rows = prepareData([row], config); const body = rows.map((literalRow) => { return drawRow(literalRow, config.border); }).join(''); let output = ''; const bottom = drawBorderBottom(columnWidthIndex, config.border); if (bottom !== '\n') { output = '\r\u001B[K'; } output += drawBorderJoin(columnWidthIndex, config.border); output += body; output += bottom; output = _.trimEnd(output); process.stdout.write(output); }; /** * @param {Object} userConfig * @returns {Object} */ export default (userConfig = {}) => { const config = makeStreamConfig(userConfig); // @todo Use 'Object.values' when Node.js v6 support is dropped. const columnWidthIndex = _.values(_.mapValues(config.columns, (column) => { return column.width + column.paddingLeft + column.paddingRight; })); let empty; empty = true; return { /** * @param {string[]} row * @returns {undefined} */ write: (row) => { if (row.length !== config.columnCount) { throw new Error('Row cell count does not match the config.columnCount.'); } if (empty) { empty = false; return create(row, columnWidthIndex, config); } else { return append(row, columnWidthIndex, config); } } }; };