takin
Version:
Front end engineering base toolchain and scaffold
294 lines • 12 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConsoleCliTable = void 0;
const chalk_1 = __importDefault(require("chalk"));
const lodash_1 = require("lodash");
const wcwidth_1 = __importDefault(require("wcwidth"));
const colorModifierSupport_1 = require("../utils/colorModifierSupport");
/**
* 用于生成终端表格
*/
class ConsoleCliTable extends Array {
constructor(options) {
super();
this.options = this.mergeOptions({
// prettier-ignore
chars: {
'middle': '│',
'left': '│',
'right': '│',
'top-left': '┌', 'top-mid': '┬', 'top': '─', 'top-right': '┐',
'left-mid': '├', 'mid-mid': '┼', 'mid': '─', 'right-mid': '┤',
'bottom-left': '└', 'bottom-mid': '┴', 'bottom': '─', 'bottom-right': '┘',
},
truncate: '…',
colWidths: [],
colAligns: [],
style: {
'padding-left': 1,
'padding-right': 1,
head: (0, colorModifierSupport_1.isSupportColorModifier)() ? ['bold', 'cyan'] : ['cyan'],
border: ['cyan'],
compact: false
},
head: []
}, options || {});
if (options && options.rows) {
for (let i = 0; i < options.rows.length; i++) {
this.push(options.rows[i]);
}
}
}
mergeOptions(defaults, opts) {
for (const p in opts) {
if (p === '__proto__' || p === 'constructor' || p === 'prototype') {
continue;
}
if (opts[p] && opts[p].constructor && opts[p].constructor === Object) {
defaults[p] = defaults[p] || {};
this.mergeOptions(defaults[p], opts[p]);
}
else {
defaults[p] = opts[p];
}
}
return defaults;
}
get width() {
const str = this.toString().split('\n');
if (str.length)
return str[0].length;
return 0;
}
/**
* For consideration of terminal "color" programs like colors.js,
* which can add ANSI escape color codes to strings,
* we destyle the ANSI color escape codes for padding calculations.
*
* see: http://en.wikipedia.org/wiki/ANSI_escape_code
*/
strlen(str) {
// eslint-disable-next-line no-control-regex
const code = /\u001b\[(?:\d*;){0,5}\d*m/g;
const stripped = ('' + str).replace(code, '');
const split = stripped.split('\n');
return split.reduce(function (memo, s) {
const len = (0, wcwidth_1.default)(s);
return len > memo ? len : memo;
// return s.length > memo ? s.length : memo
}, 0);
}
render() {
let ret = '';
const options = this.options;
const style = options.style || {};
const head = options.head || [];
const chars = options.chars || {};
const truncater = options.truncate;
const colWidths = options.colWidths || new Array(head.length);
let totalWidth = 0;
const getWidth = (obj) => {
return typeof obj === 'object' && obj.width !== undefined
? obj.width
: (typeof obj === 'object' ? this.strlen(obj.text) : this.strlen(obj)) +
(style['padding-left'] || 0) +
(style['padding-right'] || 0);
};
// renders a string, by padding it or truncating it
const renderString = (str, index) => {
var _a;
str = String(typeof str === 'object' && str.text ? str.text : str);
const length = this.strlen(str);
const width = colWidths[index] -
(style['padding-left'] || 0) -
(style['padding-right'] || 0);
const align = ((_a = options.colAligns) === null || _a === void 0 ? void 0 : _a[index]) || 'left';
const padFn = align === 'left' ? lodash_1.padEnd : align === 'middle' ? lodash_1.pad : lodash_1.padStart;
return ((0, lodash_1.repeat)(' ', style['padding-left'] || 0) +
(length === width
? str
: length < width
? padFn(str, width + (str.length - length), ' ')
: truncater
? (0, lodash_1.truncate)(str, {
length: width,
omission: truncater
})
: str) +
(0, lodash_1.repeat)(' ', style['padding-right'] || 0));
};
if (!head.length && !this.length)
return '';
if (!colWidths.length) {
let allRows = this.slice(0);
if (head.length) {
allRows = allRows.concat([head]);
}
allRows.forEach(function (cells) {
// horizontal (arrays)
if (typeof cells === 'object' && cells.length) {
extractColumnWidths(cells);
// vertical (objects)
}
else {
const header_cell = Object.keys(cells)[0], value_cell = cells[header_cell];
colWidths[0] = Math.max(colWidths[0] || 0, getWidth(header_cell) || 0);
// cross (objects w/ array values)
if (typeof value_cell === 'object' && value_cell.length) {
extractColumnWidths(value_cell, 1);
}
else {
colWidths[1] = Math.max(colWidths[1] || 0, getWidth(value_cell) || 0);
}
}
});
}
totalWidth =
(colWidths.length === 1
? colWidths[0]
: colWidths.reduce(function (a, b) {
return a + b;
})) +
colWidths.length +
1;
function extractColumnWidths(arr, offset = 0) {
offset = offset || 0;
arr.forEach(function (cell, i) {
colWidths[i + offset] = Math.max(colWidths[i + offset] || 0, getWidth(cell) || 0);
});
}
// draws a line
function line(line = '', left = '', right = '', intersection = '') {
var _a;
let width = 0;
line = left + (0, lodash_1.repeat)(line, totalWidth - 2) + right;
colWidths.forEach(function (w, i) {
if (i === colWidths.length - 1)
return;
width += w + 1;
line = line.substr(0, width) + intersection + line.substr(width + 1);
});
return applyStyles((_a = options.style) === null || _a === void 0 ? void 0 : _a.border, line);
}
// draws the top line
function lineTop() {
const l = line(chars.top, chars['top-left'] || chars.top, chars['top-right'] || chars.top, chars['top-mid']);
if (l)
ret += l + '\n';
}
function generateRow(items, style) {
var _a;
const cells = [];
let max_height = 0;
let first_cell_head = false;
// prepare vertical and cross table data
if (!Array.isArray(items) && typeof items === 'object') {
const key = Object.keys(items)[0];
const value = items[key];
first_cell_head = true;
if (Array.isArray(value)) {
items = value;
items.unshift(key);
}
else {
items = [key, value];
}
}
// transform array of item strings into structure of cells
items.forEach(function (item, i) {
const contents = item
.toString()
.split('\n')
.reduce(function (memo, l) {
memo.push(renderString(l, i));
return memo;
}, []);
const height = contents.length;
if (height > max_height) {
max_height = height;
}
cells.push({ contents: contents, height: height });
});
// transform vertical cells into horizontal lines
const lines = new Array(max_height);
cells.forEach(function (cell, i) {
cell.contents.forEach(function (line, j) {
var _a, _b;
if (!lines[j]) {
lines[j] = [];
}
if (style || (first_cell_head && i === 0 && ((_a = options.style) === null || _a === void 0 ? void 0 : _a.head))) {
line = applyStyles((_b = options.style) === null || _b === void 0 ? void 0 : _b.head, line);
}
lines[j].push(line);
});
// populate empty lines in cell
for (let j = cell.height, l = max_height; j < l; j++) {
if (!lines[j]) {
lines[j] = [];
}
lines[j].push(renderString('', i));
}
});
let ret = '';
lines.forEach(function (line) {
var _a, _b, _c;
if (ret.length > 0) {
ret += '\n' + applyStyles((_a = options.style) === null || _a === void 0 ? void 0 : _a.border, chars.left);
}
ret +=
line.join(applyStyles((_b = options.style) === null || _b === void 0 ? void 0 : _b.border, chars.middle)) +
applyStyles((_c = options.style) === null || _c === void 0 ? void 0 : _c.border, chars.right);
});
return applyStyles((_a = options.style) === null || _a === void 0 ? void 0 : _a.border, chars.left) + ret;
}
function applyStyles(styles = [], subject) {
if (!subject)
return '';
styles.forEach(function (style) {
subject = chalk_1.default[style](subject);
});
return subject;
}
if (head.length) {
lineTop();
ret += generateRow(head, style.head) + '\n';
}
if (this.length)
this.forEach(function (cells, i) {
if (!head.length && i === 0)
lineTop();
else {
if (!style.compact || i < Number(!!head.length)
? 1
: 0 || cells.length === 0) {
const l = line(chars.mid, chars['left-mid'], chars['right-mid'], chars['mid-mid']);
if (l)
ret += l + '\n';
}
}
if (Object.prototype.hasOwnProperty.call(cells, 'length') &&
!cells.length) {
return;
}
else {
ret += generateRow(cells) + '\n';
}
});
const l = line(chars.bottom, chars['bottom-left'] || chars.bottom, chars['bottom-right'] || chars.bottom, chars['bottom-mid']);
if (l)
ret += l;
// trim the last '\n' if we didn't add the bottom decoration
else
ret = ret.slice(0, -1);
return ret;
}
toString() {
return this.render();
}
}
exports.ConsoleCliTable = ConsoleCliTable;
//# sourceMappingURL=table.js.map