更新
This commit is contained in:
+232
@@ -0,0 +1,232 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user