console-toolkit
Version:
Toolkit to produce a fancy console output (boxes, tables, charts, colors).
88 lines (73 loc) • 2.7 kB
JavaScript
import Box from '../box.js';
// An axis structure is an array:
// - every even element is a drawing style defined by a table style
// - if it is falsy (e.g., 0), the line is skipped
// - every odd element is a cell size in symbols not less than 0
// A skip structure:
// - an array of rectangles
// - a rectangle is a structure: {x, y, width, height} in terms of axes' indices.
// - x and y are inclusive
// - width and height are exclusive
const isSkipped = (skip, x, y) => {
for (const rect of skip) {
if (rect.x <= x && x < rect.x + rect.width && rect.y <= y && y < rect.y + rect.height)
return true;
}
return false;
};
const BEFORE = 1,
AFTER = 2,
BOTH = 3;
const getLineIndex = (axis, i) => (i == 0 ? BEFORE : i == axis.length - 1 ? AFTER : 0);
const getIndex = (hAxis, vAxis, skip, x, y) => {
let hIndex = getLineIndex(hAxis, x),
vIndex = getLineIndex(vAxis, y),
skipFlag = false;
if (skip?.length) {
// use the skip list
if (isSkipped(skip, x, y)) {
skipFlag = true;
} else if (!(x & 1) && !(y & 1)) {
if (isSkipped(skip, x - 1, y)) hIndex |= BEFORE;
if (isSkipped(skip, x + 1, y)) hIndex |= AFTER;
if (isSkipped(skip, x, y - 1)) vIndex |= BEFORE;
if (isSkipped(skip, x, y + 1)) vIndex |= AFTER;
if (hIndex == BOTH && vIndex == BOTH) skipFlag = true;
}
}
return {hIndex, vIndex, skipFlag};
};
const drawRow = (lineTheme, hAxis, vAxis, skip, symbol, y, i) =>
hAxis
.map((x, j) => {
if (!x) return '';
const {skipFlag, hIndex, vIndex} = getIndex(hAxis, vAxis, skip, j, i);
if (skipFlag) return symbol.repeat(j & 1 ? x : lineTheme['w_' + x]);
if (j & 1) {
if (i & 1) return symbol.repeat(x);
if (!lineTheme['h_' + y]) throw new TypeError(`Style has no "h_${y}" property`);
return lineTheme['h_' + y][vIndex].repeat(x);
}
if (i & 1) {
if (!lineTheme['v_' + x]) throw new TypeError(`Style has no "v_${x}" property`);
return lineTheme['v_' + x][hIndex];
}
if (!lineTheme['t_' + y + '_' + x]) throw new TypeError(`Style has no "t_${y}_${x}" property`);
return lineTheme['t_' + y + '_' + x][4 * hIndex + vIndex];
})
.join('');
export const draw = (lineTheme, hAxis, vAxis, {skip = [], symbol = ' '} = {}) =>
new Box(
vAxis
.map((y, i) => {
if (!y) return [];
if (i & 1) {
const row = drawRow(lineTheme, hAxis, vAxis, skip, symbol, y, i);
return y == 1 ? row : new Array(y).fill(row);
}
return drawRow(lineTheme, hAxis, vAxis, skip, symbol, y, i);
})
.flat(1),
true
);
export default draw;