You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.2 KiB
118 lines
3.2 KiB
var each = require('./each'); |
|
var strWidth = require('./strWidth'); |
|
var map = require('./map'); |
|
var repeat = require('./repeat'); |
|
var cloneDeep = require('./cloneDeep'); |
|
exports = function(rows) { |
|
rows = cloneDeep(rows); |
|
var 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; |
|
} |
|
var defBorder = { |
|
topBody: '─', |
|
topJoin: '┬', |
|
topLeft: '┌', |
|
topRight: '┐', |
|
bottomBody: '─', |
|
bottomJoin: '┴', |
|
bottomLeft: '└', |
|
bottomRight: '┘', |
|
bodyLeft: '│', |
|
bodyRight: '│', |
|
bodyJoin: '│', |
|
joinBody: '─', |
|
joinLeft: '├', |
|
joinRight: '┤', |
|
joinJoin: '┼' |
|
}; |
|
|
|
module.exports = exports;
|
|
|