123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- var each = require('./each');
- var strWidth = require('./strWidth');
- var map = require('./map');
- var repeat = require('./repeat');
- var cloneDeep = require('./cloneDeep');
- var defaults = require('./defaults');
- var trim = require('./trim');
- var rtrim = require('./rtrim');
- var filter = require('./filter');
- exports = function(rows) {
- var options =
- arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- rows = cloneDeep(rows);
- options.border = options.border || {};
- defaults(options.border, defBorder);
- options.columns = getColumns(rows);
- padData(rows, options);
- return render(rows, options);
- };
- function padData(rows, options) {
- var columnCount = options.columns.length;
- for (var i = 0, len = rows.length; i < len; i++) {
- while (rows[i].length < columnCount) {
- rows[i].push('');
- }
- }
- return loopData(rows, function(data, row, column) {
- var _options$columns$colu = options.columns[column],
- paddingLeft = _options$columns$colu.paddingLeft,
- width = _options$columns$colu.width,
- paddingRight = _options$columns$colu.paddingRight;
- return (
- repeat(' ', paddingLeft) +
- data +
- repeat(' ', width - strWidth(data) - paddingRight)
- );
- });
- }
- function loopData(rows, handler) {
- for (var i = 0, len = rows.length; i < len; i++) {
- var row = rows[i];
- for (var j = 0, _len = row.length; j < _len; j++) {
- var data = handler(row[j], i, j);
- if (data) {
- row[j] = data;
- }
- }
- }
- }
- function getColumns(rows) {
- var columns = [];
- var paddingLeft = 1;
- var paddingRight = 1;
- loopData(rows, function(data, row, column) {
- columns[column] = columns[column] || {
- width: paddingLeft + paddingRight,
- paddingLeft: paddingLeft,
- paddingRight: paddingRight
- };
- var width = strWidth(data) + paddingLeft + paddingRight;
- if (width > columns[column].width) {
- columns[column].width = width;
- }
- });
- return columns;
- }
- function render(rows, options) {
- var ret = '';
- ret += renderBorder('top', options);
- each(rows, function(row, idx) {
- ret += renderRow(row, options);
- if (idx === rows.length - 1) {
- ret += renderBorder('bottom', options);
- } else {
- ret += renderBorder('join', options);
- }
- });
- return ret;
- }
- function renderRow(columns, options) {
- var border = options.border;
- return (
- border.bodyLeft +
- columns.join(border.bodyJoin) +
- border.bodyRight +
- '\n'
- );
- }
- function renderBorder(type, options) {
- var border = options.border,
- columns = options.columns;
- var left = border[type + 'Left'];
- var right = border[type + 'Right'];
- var body = border[type + 'Body'];
- var join = border[type + 'Join'];
- var ret = map(columns, function(column) {
- return repeat(body, column.width);
- }).join(join);
- ret = left + ret + right;
- if (type !== 'bottom') {
- ret += '\n';
- }
- return ret;
- }
- exports.parse = function(table) {
- var options =
- arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- options.border = options.border || {};
- defaults(options.border, defBorder);
- var lines = splitLines(table, options.border);
- return parseLines(lines, options);
- };
- function splitLines(table, border) {
- var lines = table.split(/\n/);
- var trimLines = [];
- var chars = ' ';
- each(border, function(val) {
- return (chars += val);
- });
- each(lines, function(line, idx) {
- line = trim(line);
- line = trim(line, chars);
- trimLines[idx] = line;
- });
- return filter(lines, function(line, idx) {
- return trimLines[idx] !== '';
- });
- }
- function parseLines(lines, options) {
- var border = options.border;
- var maxLen = 0;
- each(lines, function(line) {
- var len = strWidth(line);
- if (len > maxLen) {
- maxLen = len;
- }
- });
- lines = map(lines, function(line) {
- return line + repeat(' ', maxLen - strWidth(line));
- });
- var start = -1;
- var end = -1;
- var firstLine = lines[0];
- if (border.bodyLeft) {
- start = firstLine.indexOf(border.bodyLeft);
- }
- if (border.bodyRight) {
- end = firstLine.lastIndexOf(border.bodyRight);
- }
- lines = map(lines, function(line) {
- if (start > -1) {
- if (end > -1) {
- line = line.slice(start + 1, end);
- } else {
- line = line.slice(start + 1);
- }
- }
- return line;
- });
- maxLen = lines[0].length;
- var rows = [];
- var rowCount = lines.length;
- var column = [];
- var _loop = function() {
- var isSeparator = true;
- var isFakeColumn = false;
- for (var r = 0; r < rowCount; r++) {
- column[r] = column[r] || '';
- var c = lines[r][i] || '';
- if (c !== border.bodyJoin) {
- isSeparator = false;
- }
- column[r] += lines[r][i];
- }
- if (isSeparator || i === maxLen - 1) {
- var emptyLineCount = 0;
- each(column, function(data) {
- data = rtrim(data, ' ' + border.bodyJoin);
- if (data === '') {
- emptyLineCount++;
- }
- });
- if (emptyLineCount >= rowCount - 1) {
- isFakeColumn = true;
- }
- if (isSeparator) {
- column = map(column, function(data) {
- return data.slice(0, data.length - 1);
- });
- }
- column = map(column, function(data) {
- return trim(data);
- });
- for (var _r = 0; _r < rowCount; _r++) {
- var row = rows[_r] || [];
- var data = column[_r];
- if (isFakeColumn) {
- if (row.length !== 0 && data) {
- row[row.length - 1] += border.bodyJoin + data;
- }
- } else {
- row.push(data);
- }
- rows[_r] = row;
- }
- column = [];
- }
- };
- for (var i = 0; i < maxLen; i++) {
- _loop();
- }
- return rows;
- }
- var defBorder = {
- topBody: '─',
- topJoin: '┬',
- topLeft: '┌',
- topRight: '┐',
- bottomBody: '─',
- bottomJoin: '┴',
- bottomLeft: '└',
- bottomRight: '┘',
- bodyLeft: '│',
- bodyRight: '│',
- bodyJoin: '│',
- joinBody: '─',
- joinLeft: '├',
- joinRight: '┤',
- joinJoin: '┼'
- };
- module.exports = exports;
|