console-toolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +34 -0
- package/README.md +92 -0
- package/package.json +59 -0
- package/src/alphanumeric/arrows.js +31 -0
- package/src/alphanumeric/fractions.js +82 -0
- package/src/alphanumeric/number-formatters.js +131 -0
- package/src/alphanumeric/roman.js +86 -0
- package/src/alphanumeric/unicode-cultural-numbers.js +68 -0
- package/src/alphanumeric/unicode-letters.js +63 -0
- package/src/alphanumeric/unicode-numbers.js +75 -0
- package/src/alphanumeric/utils.js +44 -0
- package/src/ansi/csi.js +67 -0
- package/src/ansi/index.js +20 -0
- package/src/ansi/sgr-constants.js +99 -0
- package/src/ansi/sgr-state.js +398 -0
- package/src/ansi/sgr.js +214 -0
- package/src/box.js +253 -0
- package/src/charts/bars/block-frac-grouped.js +6 -0
- package/src/charts/bars/block-frac.js +36 -0
- package/src/charts/bars/block-grouped.js +6 -0
- package/src/charts/bars/block.js +43 -0
- package/src/charts/bars/draw-grouped.js +39 -0
- package/src/charts/bars/draw-stacked.js +24 -0
- package/src/charts/bars/frac-grouped.js +33 -0
- package/src/charts/bars/plain-grouped.js +6 -0
- package/src/charts/bars/plain.js +63 -0
- package/src/charts/columns/block-frac-grouped.js +6 -0
- package/src/charts/columns/block-frac.js +30 -0
- package/src/charts/columns/block-grouped.js +6 -0
- package/src/charts/columns/block.js +37 -0
- package/src/charts/columns/draw-grouped.js +48 -0
- package/src/charts/columns/draw-stacked.js +31 -0
- package/src/charts/columns/frac-grouped.js +27 -0
- package/src/charts/columns/plain-grouped.js +6 -0
- package/src/charts/columns/plain.js +39 -0
- package/src/charts/themes/default.js +12 -0
- package/src/charts/themes/rainbow-reversed.js +5 -0
- package/src/charts/themes/rainbow.js +8 -0
- package/src/charts/utils.js +75 -0
- package/src/draw-block-frac.js +33 -0
- package/src/draw-block.js +55 -0
- package/src/meta.js +41 -0
- package/src/output/show.js +40 -0
- package/src/output/updater.js +82 -0
- package/src/output/writer.js +131 -0
- package/src/panel.js +748 -0
- package/src/plot/bitmap.js +108 -0
- package/src/plot/draw-line.js +26 -0
- package/src/plot/draw-rect.js +216 -0
- package/src/plot/index.js +24 -0
- package/src/plot/to-quads.js +32 -0
- package/src/spinner/index.js +8 -0
- package/src/spinner/spin.js +51 -0
- package/src/spinner/spinner.js +75 -0
- package/src/spinner/spinners.js +65 -0
- package/src/strings.js +72 -0
- package/src/style.js +620 -0
- package/src/symbols.js +131 -0
- package/src/table/draw-borders.js +87 -0
- package/src/table/index.js +7 -0
- package/src/table/table.js +330 -0
- package/src/themes/blocks/unicode-half.js +9 -0
- package/src/themes/blocks/unicode-thin.js +9 -0
- package/src/themes/lines/ascii-compact.js +11 -0
- package/src/themes/lines/ascii-dots.js +9 -0
- package/src/themes/lines/ascii-girder.js +9 -0
- package/src/themes/lines/ascii-github.js +11 -0
- package/src/themes/lines/ascii-reddit.js +11 -0
- package/src/themes/lines/ascii-rounded.js +11 -0
- package/src/themes/lines/ascii.js +11 -0
- package/src/themes/lines/unicode-bold.js +15 -0
- package/src/themes/lines/unicode-rounded.js +15 -0
- package/src/themes/lines/unicode.js +15 -0
- package/src/themes/utils.js +38 -0
- package/src/turtle/draw-line-art.js +46 -0
- package/src/turtle/draw-unicode.js +33 -0
- package/src/turtle/index.js +12 -0
- package/src/turtle/turtle.js +286 -0
package/src/symbols.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const generateSequence = (base, from, to) => {
|
|
2
|
+
const result = [];
|
|
3
|
+
|
|
4
|
+
let step;
|
|
5
|
+
if (from < to) {
|
|
6
|
+
step = 1;
|
|
7
|
+
++to; // to make inclusive
|
|
8
|
+
} else {
|
|
9
|
+
step = -1;
|
|
10
|
+
--to; // to make inclusive
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
for (let i = from; i != to; i += step) result.push(String.fromCodePoint(base + i));
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// blocks
|
|
18
|
+
|
|
19
|
+
export const vBlocks8th = [' ', ...generateSequence(0x2581, 0, 7)];
|
|
20
|
+
export const hBlocks8th = [' ', ...generateSequence(0x2588, 7, 0, -1)];
|
|
21
|
+
export const fullBlock = '\u{2588}';
|
|
22
|
+
|
|
23
|
+
export const lLine = hBlocks8th[1];
|
|
24
|
+
export const rLine = `\u{2595}`;
|
|
25
|
+
export const tLine = `\u{2594}`;
|
|
26
|
+
export const bLine = vBlocks8th[1];
|
|
27
|
+
|
|
28
|
+
export const lHalf = hBlocks8th[4];
|
|
29
|
+
export const rHalf = `\u{2590}`;
|
|
30
|
+
export const tHalf = `\u{2580}`;
|
|
31
|
+
export const bHalf = vBlocks8th[4];
|
|
32
|
+
|
|
33
|
+
export const tlQuadrant = '\u{2598}';
|
|
34
|
+
export const blQuadrant = '\u{2596}';
|
|
35
|
+
export const trQuadrant = '\u{259D}';
|
|
36
|
+
export const brQuadrant = '\u{2597}';
|
|
37
|
+
|
|
38
|
+
export const tlBrQuadrants = `\u{259A}`;
|
|
39
|
+
export const trBlQuadrants = `\u{259E}`;
|
|
40
|
+
|
|
41
|
+
export const tlNegativeQuadrant = '\u{259F}';
|
|
42
|
+
export const blNegativeQuadrant = '\u{259C}';
|
|
43
|
+
export const trNegativeQuadrant = '\u{2599}';
|
|
44
|
+
export const brNegativeQuadrant = '\u{259B}';
|
|
45
|
+
|
|
46
|
+
export const quadrants = [
|
|
47
|
+
' ',
|
|
48
|
+
tlQuadrant,
|
|
49
|
+
trQuadrant,
|
|
50
|
+
tHalf,
|
|
51
|
+
blQuadrant,
|
|
52
|
+
lHalf,
|
|
53
|
+
trBlQuadrants,
|
|
54
|
+
brNegativeQuadrant,
|
|
55
|
+
brQuadrant,
|
|
56
|
+
tlBrQuadrants,
|
|
57
|
+
rHalf,
|
|
58
|
+
blNegativeQuadrant,
|
|
59
|
+
bHalf,
|
|
60
|
+
trNegativeQuadrant,
|
|
61
|
+
tlNegativeQuadrant,
|
|
62
|
+
fullBlock
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export const quadrant = (tl, tr, bl, br) => quadrants[(tl ? 1 : 0) + (tr ? 2 : 0) + (bl ? 4 : 0) + (br ? 8 : 0)];
|
|
66
|
+
|
|
67
|
+
// shades
|
|
68
|
+
|
|
69
|
+
export const shades = [' ', ...generateSequence(0x2591, 0, 2), fullBlock];
|
|
70
|
+
|
|
71
|
+
export const shadeLight = shades[1];
|
|
72
|
+
export const shadeMedium = shades[2];
|
|
73
|
+
export const shadeDark = shades[3];
|
|
74
|
+
|
|
75
|
+
// ellipses
|
|
76
|
+
|
|
77
|
+
export const hellip = '\u{2026}'; // horizontal ellipsis
|
|
78
|
+
export const vellip = '\u{22EE}'; // vertical ellipsis
|
|
79
|
+
export const ctdot = '\u{22EF}'; // midline horizontal ellipsis
|
|
80
|
+
export const utdot = '\u{22F0}'; // up right diagonal ellipsis
|
|
81
|
+
export const dtdot = '\u{22F1}'; // down right diagonal ellipsis
|
|
82
|
+
|
|
83
|
+
export {hellip as ellipsis};
|
|
84
|
+
|
|
85
|
+
// math
|
|
86
|
+
|
|
87
|
+
export const infinity = '\u{221e}';
|
|
88
|
+
export const plusMinus = '\u{00B1}';
|
|
89
|
+
export const minusPlus = '\u{2213}';
|
|
90
|
+
export const tilde = '\u{223C}';
|
|
91
|
+
export const minus = '\u{2212}';
|
|
92
|
+
export const multiplication = '\u{00D7}';
|
|
93
|
+
export const division = '\u{00F7}';
|
|
94
|
+
export const product = '\u{220F}';
|
|
95
|
+
export const sum = '\u{2211}';
|
|
96
|
+
export const forAll = '\u{2200}';
|
|
97
|
+
export const exist = '\u{2203}';
|
|
98
|
+
export const degree = '\u{00B0}';
|
|
99
|
+
|
|
100
|
+
export {multiplication as times};
|
|
101
|
+
|
|
102
|
+
export const superscriptPlus = '\u{207A}';
|
|
103
|
+
export const superscriptMinus = '\u{207B}';
|
|
104
|
+
export const subscriptPlus = '\u{208A}';
|
|
105
|
+
export const subscriptMinus = '\u{208B}';
|
|
106
|
+
|
|
107
|
+
export const permille = '\u{2030}'; // per thousand
|
|
108
|
+
export const permyriad = '\u{2031}'; // per ten thousand
|
|
109
|
+
|
|
110
|
+
// dashes
|
|
111
|
+
|
|
112
|
+
export const hyphen = '\u{2010}';
|
|
113
|
+
export const figureDash = '\u{2012}';
|
|
114
|
+
export const ndash = '\u{2013}';
|
|
115
|
+
export const mdash = '\u{2014}';
|
|
116
|
+
export const horbar = '\u{2015}';
|
|
117
|
+
|
|
118
|
+
// marks
|
|
119
|
+
|
|
120
|
+
export const ballotBox = '\u{2610}';
|
|
121
|
+
export const ballotBoxChecked = '\u{2611}';
|
|
122
|
+
export const ballotBoxBoldChecked = '\u{1f5f9}';
|
|
123
|
+
export const ballotBoxX = '\u{2612}';
|
|
124
|
+
|
|
125
|
+
export const checkMark = '\u{2713}';
|
|
126
|
+
export const checkMarkHeavy = '\u{2714}';
|
|
127
|
+
export const checkMarkLight = '\u{1f5f8}';
|
|
128
|
+
|
|
129
|
+
export const ballotX = '\u{2716}';
|
|
130
|
+
export const ballotXHeavy = '\u{2717}';
|
|
131
|
+
export const ballotXLight = '\u{1f5f7}';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import Box from '../box.js';
|
|
2
|
+
|
|
3
|
+
// An axis structure is an array:
|
|
4
|
+
// - every even element is a drawing style defined by a table style
|
|
5
|
+
// - if it is falsy (e.g., 0), the line is skipped
|
|
6
|
+
// - every odd element is a cell size in symbols not less than 0
|
|
7
|
+
|
|
8
|
+
// A skip structure:
|
|
9
|
+
// - an array of rectangles
|
|
10
|
+
// - a rectangle is a structure: {x, y, width, height} in terms of axes' indices.
|
|
11
|
+
// - x and y are inclusive
|
|
12
|
+
// - width and height are exclusive
|
|
13
|
+
|
|
14
|
+
const isSkipped = (skip, x, y) => {
|
|
15
|
+
for (const rect of skip) {
|
|
16
|
+
if (rect.x <= x && x < rect.x + rect.width && rect.y <= y && y < rect.y + rect.height)
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const BEFORE = 1,
|
|
23
|
+
AFTER = 2,
|
|
24
|
+
BOTH = 3;
|
|
25
|
+
|
|
26
|
+
const getLineIndex = (axis, i) => (i == 0 ? BEFORE : i == axis.length - 1 ? AFTER : 0);
|
|
27
|
+
|
|
28
|
+
const getIndex = (hAxis, vAxis, skip, x, y) => {
|
|
29
|
+
let hIndex = getLineIndex(hAxis, x),
|
|
30
|
+
vIndex = getLineIndex(vAxis, y),
|
|
31
|
+
skipFlag = false;
|
|
32
|
+
|
|
33
|
+
if (skip?.length) {
|
|
34
|
+
// use the skip list
|
|
35
|
+
if (isSkipped(skip, x, y)) {
|
|
36
|
+
skipFlag = true;
|
|
37
|
+
} else if (!(x & 1) && !(y & 1)) {
|
|
38
|
+
if (isSkipped(skip, x - 1, y)) hIndex |= BEFORE;
|
|
39
|
+
if (isSkipped(skip, x + 1, y)) hIndex |= AFTER;
|
|
40
|
+
if (isSkipped(skip, x, y - 1)) vIndex |= BEFORE;
|
|
41
|
+
if (isSkipped(skip, x, y + 1)) vIndex |= AFTER;
|
|
42
|
+
if (hIndex == BOTH && vIndex == BOTH) skipFlag = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {hIndex, vIndex, skipFlag};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const drawRow = (lineTheme, hAxis, vAxis, skip, symbol, y, i) =>
|
|
50
|
+
hAxis
|
|
51
|
+
.map((x, j) => {
|
|
52
|
+
if (!x) return '';
|
|
53
|
+
const {skipFlag, hIndex, vIndex} = getIndex(hAxis, vAxis, skip, j, i);
|
|
54
|
+
|
|
55
|
+
if (skipFlag) return symbol.repeat(j & 1 ? x : lineTheme['w_' + x]);
|
|
56
|
+
|
|
57
|
+
if (j & 1) {
|
|
58
|
+
if (i & 1) return symbol.repeat(x);
|
|
59
|
+
if (!lineTheme['h_' + y]) throw new TypeError(`Style has no "h_${y}" property`);
|
|
60
|
+
return lineTheme['h_' + y][vIndex].repeat(x);
|
|
61
|
+
}
|
|
62
|
+
if (i & 1) {
|
|
63
|
+
if (!lineTheme['v_' + x]) throw new TypeError(`Style has no "v_${x}" property`);
|
|
64
|
+
return lineTheme['v_' + x][hIndex];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!lineTheme['t_' + y + '_' + x]) throw new TypeError(`Style has no "t_${y}_${x}" property`);
|
|
68
|
+
return lineTheme['t_' + y + '_' + x][4 * hIndex + vIndex];
|
|
69
|
+
})
|
|
70
|
+
.join('');
|
|
71
|
+
|
|
72
|
+
export const draw = (lineTheme, hAxis, vAxis, {skip = [], symbol = ' '} = {}) =>
|
|
73
|
+
new Box(
|
|
74
|
+
vAxis
|
|
75
|
+
.map((y, i) => {
|
|
76
|
+
if (!y) return [];
|
|
77
|
+
if (i & 1) {
|
|
78
|
+
const row = drawRow(lineTheme, hAxis, vAxis, skip, symbol, y, i);
|
|
79
|
+
return y == 1 ? row : new Array(y).fill(row);
|
|
80
|
+
}
|
|
81
|
+
return drawRow(lineTheme, hAxis, vAxis, skip, symbol, y, i);
|
|
82
|
+
})
|
|
83
|
+
.flat(1),
|
|
84
|
+
true
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export default draw;
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import Box from '../box.js';
|
|
2
|
+
import Panel from '../panel.js';
|
|
3
|
+
import {draw as drawBorder} from './draw-borders.js';
|
|
4
|
+
import style, {RESET_STATE} from '../style.js';
|
|
5
|
+
|
|
6
|
+
const getCellAlign = (align, index) => (typeof align == 'string' && align[index] !== 'd' && align[index]) || '';
|
|
7
|
+
|
|
8
|
+
const ensureSize = (cellSize, cellLength, cellGap, pos, lineTheme, axis, lengths) => {
|
|
9
|
+
let available = (cellSize - 1) * cellGap;
|
|
10
|
+
for (let i = 0; i < cellSize; ++i)
|
|
11
|
+
available += lengths[pos + i] + (!axis[pos + i] ? 0 : lineTheme ? lineTheme['w_' + axis[pos + i]] : 1);
|
|
12
|
+
if (cellLength > available) {
|
|
13
|
+
const diff = cellLength - available,
|
|
14
|
+
perCell = Math.floor(diff / cellSize),
|
|
15
|
+
remainder = diff % cellSize;
|
|
16
|
+
if (perCell) {
|
|
17
|
+
for (let i = 0; i < cellSize; ++i) lengths[j + i] += perCell;
|
|
18
|
+
}
|
|
19
|
+
if (remainder) {
|
|
20
|
+
for (let i = 0; i < remainder; ++i) ++lengths[j + i];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const dataInstructions = 'rowFirst,rowLast,columnFirst,columnLast,data,rowOdd,rowEven,columnOdd,columnEven'.split(',');
|
|
26
|
+
|
|
27
|
+
const DIM_STATE = style.dim.getState();
|
|
28
|
+
|
|
29
|
+
export class Table {
|
|
30
|
+
constructor(data, lineTheme, options = {}) {
|
|
31
|
+
let {hAxis = '1', vAxis = '1', hAlign = [], vAlign = [], hMin = 0, vMin = 0, cellPadding = {}} = options;
|
|
32
|
+
|
|
33
|
+
this.height = data.length;
|
|
34
|
+
this.width = this.height ? data[0].length : 0;
|
|
35
|
+
this.data = data;
|
|
36
|
+
|
|
37
|
+
if (!Array.isArray(hAlign)) hAlign = new Array(this.width).fill(hAlign);
|
|
38
|
+
if (!Array.isArray(vAlign)) vAlign = new Array(this.height).fill(vAlign);
|
|
39
|
+
|
|
40
|
+
this.widths = Array.isArray(hMin) ? [...hMin] : new Array(this.width).fill(hMin);
|
|
41
|
+
this.heights = Array.isArray(vMin) ? [...vMin] : new Array(this.height).fill(vMin);
|
|
42
|
+
|
|
43
|
+
if (this.widths.length != this.width)
|
|
44
|
+
throw new Error('hMin should be equal to a row size, not ' + this.widths.length);
|
|
45
|
+
if (this.heights.length != this.height)
|
|
46
|
+
throw new Error('vMin should be equal to a column size, not ' + this.heights.length);
|
|
47
|
+
|
|
48
|
+
this.lineTheme = lineTheme;
|
|
49
|
+
this.skipList = [];
|
|
50
|
+
this.options = {hAxis, vAxis, hAlign, vAlign};
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
const {l = 1, r = 1, t = 0, b = 0} = cellPadding;
|
|
54
|
+
this.cellPadding = {l, r, t, b};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.hAxis = Array.isArray(hAxis) ? hAxis : new Array(this.width + 1).fill(hAxis);
|
|
58
|
+
this.vAxis = Array.isArray(vAxis) ? vAxis : new Array(this.height + 1).fill(vAxis);
|
|
59
|
+
|
|
60
|
+
if (this.hAxis.length != this.width + 1)
|
|
61
|
+
throw new Error('hAxis should be a row size plus 1, not ' + this.hAxis.length);
|
|
62
|
+
if (this.vAxis.length != this.height + 1)
|
|
63
|
+
throw new Error('vAxis should be a column size plus 1, not ' + this.vAxis.length);
|
|
64
|
+
|
|
65
|
+
this.cells = data.map((row, i) => {
|
|
66
|
+
const result = new Array(this.width);
|
|
67
|
+
for (let j = 0; j < this.width; ++j) {
|
|
68
|
+
const data = row[j];
|
|
69
|
+
if (data === null || data === undefined) {
|
|
70
|
+
result[j] = null;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const isObject = data?.hasOwnProperty('value'),
|
|
74
|
+
value = isObject ? data.value : data,
|
|
75
|
+
align = (isObject && data.align) || '',
|
|
76
|
+
box = value instanceof Box ? value : Box.make(value, {symbol: ' ', align: getCellAlign(align, 0) || hAlign[j] || 'left'}),
|
|
77
|
+
width = box.width,
|
|
78
|
+
height = box.height,
|
|
79
|
+
cellWidth = isObject ? data.width || 1 : 1,
|
|
80
|
+
cellHeight = isObject ? data.height || 1 : 1;
|
|
81
|
+
result[j] = {data, value, box, width, height, cellWidth, cellHeight, align};
|
|
82
|
+
if (cellWidth < 2) this.widths[j] = Math.max(this.widths[j], width);
|
|
83
|
+
if (cellHeight < 2) this.heights[i] = Math.max(this.heights[i], height);
|
|
84
|
+
if (cellWidth > 1 || cellHeight > 1) {
|
|
85
|
+
this.skipList.push({x: 2 * j + 1, y: 2 * i + 1, width: 2 * cellWidth - 1, height: 2 * cellHeight - 1});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// merged cells
|
|
92
|
+
this.skipList.forEach(rect => {
|
|
93
|
+
const j = (rect.x - 1) >> 1,
|
|
94
|
+
i = (rect.y - 1) >> 1,
|
|
95
|
+
cell = this.cells[i][j];
|
|
96
|
+
if (cell.cellWidth > 1) {
|
|
97
|
+
ensureSize(
|
|
98
|
+
cell.cellWidth,
|
|
99
|
+
cell.width,
|
|
100
|
+
this.cellPadding.l + this.cellPadding.r,
|
|
101
|
+
j,
|
|
102
|
+
lineTheme,
|
|
103
|
+
this.hAxis,
|
|
104
|
+
this.widths
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
if (cell.cellHeight > 1) {
|
|
108
|
+
ensureSize(
|
|
109
|
+
cell.cellHeight,
|
|
110
|
+
cell.height,
|
|
111
|
+
this.cellPadding.t + this.cellPadding.b,
|
|
112
|
+
i,
|
|
113
|
+
null,
|
|
114
|
+
this.vAxis,
|
|
115
|
+
this.heights
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// TODO: accept `states`, draw even/odd rows/columns, support bg on lines optionally
|
|
122
|
+
draw({lineState = DIM_STATE} = {}) {
|
|
123
|
+
// prepare axes
|
|
124
|
+
|
|
125
|
+
const hAxis = new Array(this.hAxis.length + this.widths.length),
|
|
126
|
+
hPadding = this.cellPadding.l + this.cellPadding.r;
|
|
127
|
+
for (let i = 0; i < this.widths.length; ++i) {
|
|
128
|
+
hAxis[2 * i] = this.hAxis[i];
|
|
129
|
+
hAxis[2 * i + 1] = this.widths[i] + hPadding;
|
|
130
|
+
}
|
|
131
|
+
hAxis[hAxis.length - 1] = this.hAxis[this.hAxis.length - 1];
|
|
132
|
+
|
|
133
|
+
const vAxis = new Array(this.vAxis.length + this.heights.length),
|
|
134
|
+
vPadding = this.cellPadding.t + this.cellPadding.b;
|
|
135
|
+
for (let i = 0; i < this.heights.length; ++i) {
|
|
136
|
+
vAxis[2 * i] = this.vAxis[i];
|
|
137
|
+
vAxis[2 * i + 1] = this.heights[i] + vPadding;
|
|
138
|
+
}
|
|
139
|
+
vAxis[vAxis.length - 1] = this.vAxis[this.vAxis.length - 1];
|
|
140
|
+
|
|
141
|
+
// draw table borders
|
|
142
|
+
|
|
143
|
+
const borderBox = drawBorder(this.lineTheme, hAxis, vAxis, {skip: this.skipList, symbol: '\x07'}),
|
|
144
|
+
panel = Panel.make(borderBox, '\x07');
|
|
145
|
+
panel.fillNonEmptyState(0, 0, panel.width, panel.height, {state: lineState});
|
|
146
|
+
|
|
147
|
+
// draw cells
|
|
148
|
+
|
|
149
|
+
let y = (vAxis[0] ? 1 : 0) + this.cellPadding.t;
|
|
150
|
+
for (let i = 0; i < this.height; ++i) {
|
|
151
|
+
let x = (this.lineTheme['w_' + hAxis[0]] || 0) + this.cellPadding.l;
|
|
152
|
+
for (let j = 0; j < this.width; ++j) {
|
|
153
|
+
const cell = this.cells[i][j];
|
|
154
|
+
if (cell && this.isVisible(j, i)) {
|
|
155
|
+
let diffX = this.widths[j] - cell.width + (cell.cellWidth - 1) * (this.cellPadding.l + this.cellPadding.r);
|
|
156
|
+
for (let k = 1; k < cell.cellWidth; ++k) {
|
|
157
|
+
diffX += this.widths[j + k] + (this.hAxis[j + k] ? this.lineTheme['w_' + this.hAxis[j + k]] : 0);
|
|
158
|
+
}
|
|
159
|
+
let diffY = this.heights[i] - cell.height + (cell.cellHeight - 1) * (this.cellPadding.t + this.cellPadding.b);
|
|
160
|
+
for (let k = 1; k < cell.cellHeight; ++k) {
|
|
161
|
+
diffY += this.heights[i + k] + (this.vAxis[i + k] ? 1 : 0);
|
|
162
|
+
}
|
|
163
|
+
const hAlign = getCellAlign(cell.align, 0) || this.options.hAlign[j] || 'left',
|
|
164
|
+
vAlign = getCellAlign(cell.align, 1) || this.options.vAlign[i] || 'top',
|
|
165
|
+
dx = hAlign === 'l' || hAlign == 'left' ? 0 : hAlign === 'r' || hAlign === 'right' ? diffX : diffX >> 1,
|
|
166
|
+
dy = vAlign === 't' || vAlign == 'top' ? 0 : vAlign === 'b' || vAlign === 'bottom' ? diffY : diffY >> 1;
|
|
167
|
+
panel.put(x + dx, y + dy, cell.box);
|
|
168
|
+
}
|
|
169
|
+
x += hAxis[2 * j + 1] + (this.lineTheme['w_' + hAxis[2 * j + 2]] || 0);
|
|
170
|
+
}
|
|
171
|
+
y += vAxis[2 * i + 1] + (vAxis[2 * i + 2] ? 1 : 0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return panel;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
toPanel(options) {
|
|
178
|
+
return this.draw(options);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
toBox(options) {
|
|
182
|
+
return this.toPanel(options).toBox(options);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
toStrings(options) {
|
|
186
|
+
return this.toBox(options).toStrings();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
isVisible(x, y) {
|
|
190
|
+
const i = 2 * y + 1,
|
|
191
|
+
j = 2 * x + 1;
|
|
192
|
+
for (const rect of this.skipList) {
|
|
193
|
+
if (rect.x === j && rect.y === i) return true;
|
|
194
|
+
if (rect.x <= j && j < rect.x + rect.width && rect.y <= i && i < rect.y + rect.height) return false;
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static generateAxes(
|
|
200
|
+
width,
|
|
201
|
+
height,
|
|
202
|
+
{
|
|
203
|
+
hTheme = '1',
|
|
204
|
+
vTheme = '1',
|
|
205
|
+
borderTop,
|
|
206
|
+
borderRight,
|
|
207
|
+
borderLeft,
|
|
208
|
+
borderBottom,
|
|
209
|
+
rowFirst,
|
|
210
|
+
rowLast,
|
|
211
|
+
columnFirst,
|
|
212
|
+
columnLast,
|
|
213
|
+
hDataSep,
|
|
214
|
+
vDataSep,
|
|
215
|
+
|
|
216
|
+
hAlignDefault = 'l',
|
|
217
|
+
hLeft = [],
|
|
218
|
+
hCenter = [],
|
|
219
|
+
hRight = [],
|
|
220
|
+
|
|
221
|
+
vAlignDefault = 't',
|
|
222
|
+
vTop = [],
|
|
223
|
+
vCenter = [],
|
|
224
|
+
vBottom = [],
|
|
225
|
+
|
|
226
|
+
hMinDefault = 0,
|
|
227
|
+
hMin = {},
|
|
228
|
+
|
|
229
|
+
vMinDefault = 0,
|
|
230
|
+
vMin = {}
|
|
231
|
+
}
|
|
232
|
+
) {
|
|
233
|
+
const hAxis = new Array(width + 1).fill(hTheme);
|
|
234
|
+
if (borderLeft !== undefined) hAxis[0] = borderLeft;
|
|
235
|
+
if (borderRight !== undefined) hAxis[width] = borderRight;
|
|
236
|
+
{
|
|
237
|
+
let dataFrom = 1,
|
|
238
|
+
dataTo = width - 1;
|
|
239
|
+
if (columnFirst !== undefined && dataFrom <= dataTo) hAxis[dataFrom++] = columnFirst;
|
|
240
|
+
if (columnLast !== undefined && dataFrom <= dataTo) hAxis[dataTo--] = columnLast;
|
|
241
|
+
if (vDataSep !== undefined) {
|
|
242
|
+
for (let i = dataFrom; i <= dataTo; ++i) hAxis[i] = vDataSep;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const vAxis = new Array(height + 1).fill(vTheme);
|
|
247
|
+
if (borderTop !== undefined) vAxis[0] = borderTop;
|
|
248
|
+
if (borderBottom !== undefined) vAxis[height] = borderBottom;
|
|
249
|
+
{
|
|
250
|
+
let dataFrom = 1,
|
|
251
|
+
dataTo = height - 1;
|
|
252
|
+
if (rowFirst !== undefined && dataFrom <= dataTo) vAxis[dataFrom++] = rowFirst;
|
|
253
|
+
if (rowLast !== undefined && dataFrom <= dataTo) vAxis[dataTo--] = rowLast;
|
|
254
|
+
if (hDataSep !== undefined) {
|
|
255
|
+
for (let i = dataFrom; i <= dataTo; ++i) vAxis[i] = hDataSep;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const hAlign = new Array(width).fill(hAlignDefault);
|
|
260
|
+
for (const i of hLeft) hAlign[i] = 'l';
|
|
261
|
+
for (const i of hCenter) hAlign[i] = 'c';
|
|
262
|
+
for (const i of hRight) hAlign[i] = 'r';
|
|
263
|
+
|
|
264
|
+
const vAlign = new Array(height).fill(vAlignDefault);
|
|
265
|
+
for (const i of vTop) vAlign[i] = 't';
|
|
266
|
+
for (const i of vCenter) vAlign[i] = 'c';
|
|
267
|
+
for (const i of vBottom) vAlign[i] = 'b';
|
|
268
|
+
|
|
269
|
+
const hMinArray = new Array(width).fill(hMinDefault);
|
|
270
|
+
for (const [i, value] of Object.entries(hMin)) hMinArray[i] = value;
|
|
271
|
+
|
|
272
|
+
const vMinArray = new Array(height).fill(vMinDefault);
|
|
273
|
+
for (const [i, value] of Object.entries(vMin)) vMinArray[i] = value;
|
|
274
|
+
|
|
275
|
+
return {hAxis, vAxis, hAlign, vAlign, hMin: hMinArray, vMin: vMinArray};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static processData(data, options) {
|
|
279
|
+
if (!options) return data;
|
|
280
|
+
|
|
281
|
+
const available = dataInstructions.filter(name => options[name] !== undefined);
|
|
282
|
+
if (!available.length) return data;
|
|
283
|
+
|
|
284
|
+
const height = data.length,
|
|
285
|
+
width = height && data[0].length,
|
|
286
|
+
states = {};
|
|
287
|
+
available.forEach(name => (states[name] = options[name] || RESET_STATE));
|
|
288
|
+
|
|
289
|
+
const rowOdd = states.rowOdd || states.data,
|
|
290
|
+
rowEven = states.rowEven || states.data,
|
|
291
|
+
columnOdd = states.columnOdd || states.data,
|
|
292
|
+
columnEven = states.columnEven || states.data;
|
|
293
|
+
|
|
294
|
+
return data.map((row, i) => {
|
|
295
|
+
return row.map((data, j) => {
|
|
296
|
+
if (data === null) return null;
|
|
297
|
+
const isObject = data?.hasOwnProperty('value');
|
|
298
|
+
let datum = isObject ? data.value : data;
|
|
299
|
+
if (j === 0 && states.columnFirst) datum = style.addState(states.columnFirst).text(datum);
|
|
300
|
+
if (j === width - 1 && states.columnLast) datum = style.addState(states.columnLast).text(datum);
|
|
301
|
+
if (i === 0 && states.rowFirst) datum = style.addState(states.rowFirst).text(datum);
|
|
302
|
+
if (i === height - 1 && states.rowLast) datum = style.addState(states.rowLast).text(datum);
|
|
303
|
+
if (columnOdd || columnEven) {
|
|
304
|
+
if (j % 2) {
|
|
305
|
+
if (columnOdd) datum = style.addState(columnOdd).text(datum);
|
|
306
|
+
} else {
|
|
307
|
+
if (columnEven) datum = style.addState(columnEven).text(datum);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (rowOdd || rowEven) {
|
|
311
|
+
if (i % 2) {
|
|
312
|
+
if (rowOdd) datum = style.addState(rowOdd).text(datum);
|
|
313
|
+
} else {
|
|
314
|
+
if (rowEven) datum = style.addState(rowEven).text(datum);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return isObject ? {...data, value: datum} : datum;
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
static make(data, lineTheme, options, overrides) {
|
|
323
|
+
return new Table(Table.processData(data, options?.states), lineTheme, {
|
|
324
|
+
...(options && Table.generateAxes(data.length && data[0].length, data.length, options)),
|
|
325
|
+
...overrides
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export default Table;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const table11 = {t: ' ', m: ' ', b: ' ', v: ' ', h: '---'},
|
|
6
|
+
table21 = {t: ' ', m: ' ', b: ' ', v: ' ', h: '==='};
|
|
7
|
+
|
|
8
|
+
populateTheme(lineTheme, table11, 1, 1);
|
|
9
|
+
populateTheme(lineTheme, table21, 2, 1);
|
|
10
|
+
|
|
11
|
+
export default lineTheme;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const markdownGithub11 = {t: '|||', m: '|||', b: '|||', v: '|||', h: '---'},
|
|
6
|
+
markdownGithub21 = {t: '|||', m: '|||', b: '|||', v: '|||', h: '==='};
|
|
7
|
+
|
|
8
|
+
populateTheme(lineTheme, markdownGithub11, 1, 1);
|
|
9
|
+
populateTheme(lineTheme, markdownGithub21, 2, 1);
|
|
10
|
+
|
|
11
|
+
export default lineTheme;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const markdownReddit11 = {t: ' | ', m: ' | ', b: ' | ', v: ' | ', h: '---'},
|
|
6
|
+
markdownReddit21 = {t: ' | ', m: ' | ', b: ' | ', v: ' | ', h: '==='};
|
|
7
|
+
|
|
8
|
+
populateTheme(lineTheme, markdownReddit11, 1, 1);
|
|
9
|
+
populateTheme(lineTheme, markdownReddit21, 2, 1);
|
|
10
|
+
|
|
11
|
+
export default lineTheme;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const rounded11 = {t: '...', m: ':+:', b: "'''", v: '|||', h: '---'},
|
|
6
|
+
rounded21 = {t: '...', m: ':+:', b: "'''", v: '|||', h: '==='};
|
|
7
|
+
|
|
8
|
+
populateTheme(lineTheme, rounded11, 1, 1);
|
|
9
|
+
populateTheme(lineTheme, rounded21, 2, 1);
|
|
10
|
+
|
|
11
|
+
export default lineTheme;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const table11 = {t: '+++', m: '+++', b: '+++', v: '|||', h: '---'},
|
|
6
|
+
table21 = {t: '+++', m: '+++', b: '+++', v: '|||', h: '==='};
|
|
7
|
+
|
|
8
|
+
populateTheme(lineTheme, table11, 1, 1);
|
|
9
|
+
populateTheme(lineTheme, table21, 2, 1);
|
|
10
|
+
|
|
11
|
+
export default lineTheme;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {populateTheme} from '../utils.js';
|
|
2
|
+
|
|
3
|
+
export const lineTheme = {};
|
|
4
|
+
|
|
5
|
+
const table11 = {t: '┌┬┐', m: '├┼┤', b: '└┴┘', v: '│││', h: '───'},
|
|
6
|
+
table12 = {t: '┎┰┒', m: '┠╂┨', b: '┖┸┚', v: '┃┃┃', h: '───'},
|
|
7
|
+
table21 = {t: '┍┯┑', m: '┝┿┥', b: '┕┷┙', v: '│││', h: '━━━'},
|
|
8
|
+
table22 = {t: '┏┳┓', m: '┣╋┫', b: '┗┻┛', v: '┃┃┃', h: '━━━'};
|
|
9
|
+
|
|
10
|
+
populateTheme(lineTheme, table11, 1, 1);
|
|
11
|
+
populateTheme(lineTheme, table12, 1, 2);
|
|
12
|
+
populateTheme(lineTheme, table21, 2, 1);
|
|
13
|
+
populateTheme(lineTheme, table22, 2, 2);
|
|
14
|
+
|
|
15
|
+
export default lineTheme;
|