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.
Files changed (78) hide show
  1. package/LICENSE +34 -0
  2. package/README.md +92 -0
  3. package/package.json +59 -0
  4. package/src/alphanumeric/arrows.js +31 -0
  5. package/src/alphanumeric/fractions.js +82 -0
  6. package/src/alphanumeric/number-formatters.js +131 -0
  7. package/src/alphanumeric/roman.js +86 -0
  8. package/src/alphanumeric/unicode-cultural-numbers.js +68 -0
  9. package/src/alphanumeric/unicode-letters.js +63 -0
  10. package/src/alphanumeric/unicode-numbers.js +75 -0
  11. package/src/alphanumeric/utils.js +44 -0
  12. package/src/ansi/csi.js +67 -0
  13. package/src/ansi/index.js +20 -0
  14. package/src/ansi/sgr-constants.js +99 -0
  15. package/src/ansi/sgr-state.js +398 -0
  16. package/src/ansi/sgr.js +214 -0
  17. package/src/box.js +253 -0
  18. package/src/charts/bars/block-frac-grouped.js +6 -0
  19. package/src/charts/bars/block-frac.js +36 -0
  20. package/src/charts/bars/block-grouped.js +6 -0
  21. package/src/charts/bars/block.js +43 -0
  22. package/src/charts/bars/draw-grouped.js +39 -0
  23. package/src/charts/bars/draw-stacked.js +24 -0
  24. package/src/charts/bars/frac-grouped.js +33 -0
  25. package/src/charts/bars/plain-grouped.js +6 -0
  26. package/src/charts/bars/plain.js +63 -0
  27. package/src/charts/columns/block-frac-grouped.js +6 -0
  28. package/src/charts/columns/block-frac.js +30 -0
  29. package/src/charts/columns/block-grouped.js +6 -0
  30. package/src/charts/columns/block.js +37 -0
  31. package/src/charts/columns/draw-grouped.js +48 -0
  32. package/src/charts/columns/draw-stacked.js +31 -0
  33. package/src/charts/columns/frac-grouped.js +27 -0
  34. package/src/charts/columns/plain-grouped.js +6 -0
  35. package/src/charts/columns/plain.js +39 -0
  36. package/src/charts/themes/default.js +12 -0
  37. package/src/charts/themes/rainbow-reversed.js +5 -0
  38. package/src/charts/themes/rainbow.js +8 -0
  39. package/src/charts/utils.js +75 -0
  40. package/src/draw-block-frac.js +33 -0
  41. package/src/draw-block.js +55 -0
  42. package/src/meta.js +41 -0
  43. package/src/output/show.js +40 -0
  44. package/src/output/updater.js +82 -0
  45. package/src/output/writer.js +131 -0
  46. package/src/panel.js +748 -0
  47. package/src/plot/bitmap.js +108 -0
  48. package/src/plot/draw-line.js +26 -0
  49. package/src/plot/draw-rect.js +216 -0
  50. package/src/plot/index.js +24 -0
  51. package/src/plot/to-quads.js +32 -0
  52. package/src/spinner/index.js +8 -0
  53. package/src/spinner/spin.js +51 -0
  54. package/src/spinner/spinner.js +75 -0
  55. package/src/spinner/spinners.js +65 -0
  56. package/src/strings.js +72 -0
  57. package/src/style.js +620 -0
  58. package/src/symbols.js +131 -0
  59. package/src/table/draw-borders.js +87 -0
  60. package/src/table/index.js +7 -0
  61. package/src/table/table.js +330 -0
  62. package/src/themes/blocks/unicode-half.js +9 -0
  63. package/src/themes/blocks/unicode-thin.js +9 -0
  64. package/src/themes/lines/ascii-compact.js +11 -0
  65. package/src/themes/lines/ascii-dots.js +9 -0
  66. package/src/themes/lines/ascii-girder.js +9 -0
  67. package/src/themes/lines/ascii-github.js +11 -0
  68. package/src/themes/lines/ascii-reddit.js +11 -0
  69. package/src/themes/lines/ascii-rounded.js +11 -0
  70. package/src/themes/lines/ascii.js +11 -0
  71. package/src/themes/lines/unicode-bold.js +15 -0
  72. package/src/themes/lines/unicode-rounded.js +15 -0
  73. package/src/themes/lines/unicode.js +15 -0
  74. package/src/themes/utils.js +38 -0
  75. package/src/turtle/draw-line-art.js +46 -0
  76. package/src/turtle/draw-unicode.js +33 -0
  77. package/src/turtle/index.js +12 -0
  78. package/src/turtle/turtle.js +286 -0
@@ -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;
@@ -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;
@@ -0,0 +1,38 @@
1
+ // A table definition matrix should define the following properties:
2
+ // - 't': top row (3 symbols),
3
+ // - 'm': middle row (3 symbols),
4
+ // - 'b': bottom row (3 symbols),
5
+ // - 'v': vertical separators (3 symbols) - left border, internal, right border,
6
+ // - 'h': horizontal separators (3 symbol) - top border, internal, bottom border,
7
+ // - 'w': (optional) width of individual t/m/b/v symbols.
8
+ // t/m/b/v lines should have the same width for each symbol.
9
+ // h should have 3 symbols of length 1.
10
+
11
+ // The default value for 'w': 1
12
+
13
+ export const populateTheme = (lineTheme, tableDefinition, hTheme, vTheme) => {
14
+ const w = tableDefinition.w || 1,
15
+ s = [0, w, w << 1],
16
+ e = [s[0] + w, s[1] + w, s[2] + w],
17
+ theme = (lineTheme['t_' + hTheme + '_' + vTheme] = [
18
+ tableDefinition.m.substring(s[1], e[1]),
19
+ tableDefinition.t.substring(s[1], e[1]), // before
20
+ tableDefinition.b.substring(s[1], e[1]), // after
21
+ tableDefinition.h[1].repeat(w),
22
+ tableDefinition.m.substring(s[0], e[0]),
23
+ tableDefinition.t.substring(s[0], e[0]), // before
24
+ tableDefinition.b.substring(s[0], e[0]), // after
25
+ tableDefinition.h[0].repeat(w),
26
+ tableDefinition.m.substring(s[2], e[2]),
27
+ tableDefinition.t.substring(s[2], e[2]), // before
28
+ tableDefinition.b.substring(s[2], e[2]), // after
29
+ tableDefinition.h[2].repeat(w),
30
+ tableDefinition.v.substring(s[1], e[1]),
31
+ tableDefinition.v.substring(s[0], e[0]), // before
32
+ tableDefinition.v.substring(s[2], e[2]) // after
33
+ ]);
34
+ lineTheme['h_' + hTheme] = [tableDefinition.h[1], tableDefinition.h[0], tableDefinition.h[2]];
35
+ lineTheme['v_' + vTheme] = theme.slice(12);
36
+ lineTheme['w_' + vTheme] = w;
37
+ lineTheme.f = tableDefinition.f || ' ';
38
+ };
@@ -0,0 +1,46 @@
1
+ import Box from '../box.js';
2
+
3
+ const BEFORE = 1,
4
+ AFTER = 2,
5
+ BOTH = 3;
6
+
7
+ const getIndex = cell => {
8
+ if (!cell) return {skipFlag: true};
9
+
10
+ const hTheme = cell.l || cell.r,
11
+ vTheme = cell.u || cell.d,
12
+ hIndex = (cell.l ? 0 : BEFORE) | (cell.r ? 0 : AFTER),
13
+ vIndex = (cell.u ? 0 : BEFORE) | (cell.d ? 0 : AFTER),
14
+ skipFlag = hIndex == BOTH && vIndex == BOTH;
15
+ return {skipFlag, hTheme, vTheme, hIndex, vIndex};
16
+ };
17
+
18
+ export const draw = (turtle, lineTheme, {ignore = ' '} = {}) =>
19
+ new Box(
20
+ turtle.cells.map(row =>
21
+ row
22
+ .map(cell => {
23
+ const {skipFlag, hTheme, vTheme, hIndex, vIndex} = getIndex(cell);
24
+ if (skipFlag) return ignore;
25
+ if (!hTheme) {
26
+ if (lineTheme['w_' + vTheme] !== 1)
27
+ throw new TypeError(`Vertical theme "${vTheme}" should have width of 1 for all vertical elements`);
28
+ if (!lineTheme['v_' + vTheme]) throw new TypeError(`Style has no "v_${vTheme}" property`);
29
+ return lineTheme['v_' + vTheme][vIndex];
30
+ }
31
+ if (!vTheme) {
32
+ if (!lineTheme['h_' + hTheme]) throw new TypeError(`Style has no "h_${hTheme}" property`);
33
+ return lineTheme['h_' + hTheme][hIndex];
34
+ }
35
+ if (lineTheme['w_' + vTheme] !== 1)
36
+ throw new TypeError(`Vertical theme "${vTheme}" should have width of 1 for all vertical elements`);
37
+ if (!lineTheme['t_' + hTheme + '_' + vTheme])
38
+ throw new TypeError(`Style has no "t_${hTheme}_${vTheme}" property`);
39
+ return lineTheme['t_' + hTheme + '_' + vTheme][4 * hIndex + vIndex];
40
+ })
41
+ .join('')
42
+ ),
43
+ true
44
+ );
45
+
46
+ export default draw;
@@ -0,0 +1,33 @@
1
+ import Box from '../box.js';
2
+
3
+ const symbols =
4
+ ' ╵╹╶└┖╺┕┗' +
5
+ '╷│╿┌├┞┍┝┡' +
6
+ '╻╽┃┎┟┠┏┢┣' +
7
+ '╴┘┚─┴┸╼┶┺' +
8
+ '┐┤┦┬┼╀┮┾╄' +
9
+ '┒┧┨┰╁╂┲╆╊' +
10
+ '╸┙┛╾┵┹━┷┻' +
11
+ '┑┥┩┭┽╃┯┿╇' +
12
+ '┓┪┫┱╅╉┳╈╋';
13
+
14
+ const arcs = {4: '╰', 12: '╭', 28: '╯', 36: '╮'};
15
+
16
+ const getIndex = cell => (cell ? (((+cell.l || 0) * 3 + (+cell.d || 0)) * 3 + (+cell.r || 0)) * 3 + (+cell.u || 0) : 0);
17
+
18
+ export const draw = (turtle, {ignore = ' ', useArcs} = {}) =>
19
+ new Box(
20
+ turtle.cells.map(row =>
21
+ row
22
+ .map(cell => {
23
+ const index = getIndex(cell);
24
+ if (isNaN(index) || index < 0 || index >= symbols.length)
25
+ throw new Error('Wrong theme. It can be either 1 or 2');
26
+ return index ? (useArcs ? arcs[index] || symbols[index] : symbols[index]) : ignore;
27
+ })
28
+ .join('')
29
+ ),
30
+ true
31
+ );
32
+
33
+ export default draw;
@@ -0,0 +1,12 @@
1
+ import Turtle from './turtle.js';
2
+ import draw from './draw-unicode.js';
3
+
4
+ Turtle.prototype.toBox = function (options) {
5
+ return draw(this, options);
6
+ };
7
+ Turtle.prototype.toStrings = function (options) {
8
+ return this.toBox(options).toStrings();
9
+ };
10
+
11
+ export {Turtle, draw};
12
+ export default Turtle;
@@ -0,0 +1,286 @@
1
+ import {addAliases} from '../meta.js';
2
+
3
+ export class Turtle {
4
+ static RIGHT = 0;
5
+ static DOWN = 1;
6
+ static LEFT = 2;
7
+ static UP = 3;
8
+
9
+ static EAST = 0;
10
+ static SOUTH = 1;
11
+ static WEST = 2;
12
+ static NORTH = 3;
13
+
14
+ constructor(width, height, theme = 1) {
15
+ this.cells = new Array(height);
16
+ for (let i = 0; i < height; ++i) {
17
+ this.cells[i] = new Array(width).fill(null);
18
+ }
19
+
20
+ this.width = width;
21
+ this.height = height;
22
+ this.direction = Turtle.RIGHT;
23
+ this.position = {x: 0, y: 0};
24
+ this.theme = theme;
25
+ this.stack = [];
26
+ }
27
+
28
+ reset() {
29
+ this.position.x = this.position.y = 0;
30
+ return this;
31
+ }
32
+ set(x, y) {
33
+ this.position.x = Math.max(0, Math.min(this.width - 1, x));
34
+ this.position.y = Math.max(0, Math.min(this.height - 1, y));
35
+ return this;
36
+ }
37
+ setX(x) {
38
+ this.position.x = Math.max(0, Math.min(this.width - 1, x));
39
+ return this;
40
+ }
41
+ setY(y) {
42
+ this.position.y = Math.max(0, Math.min(this.height - 1, y));
43
+ return this;
44
+ }
45
+ add(dx, dy) {
46
+ return this.set(x + dx, y + dy);
47
+ }
48
+ addX(dx) {
49
+ return this.setX(x + dx);
50
+ }
51
+ addY(dy) {
52
+ return this.setY(y + dy);
53
+ }
54
+
55
+ setTheme(theme) {
56
+ this.theme = theme;
57
+ return this;
58
+ }
59
+
60
+ setDirection(direction) {
61
+ this.direction = direction % 4;
62
+ return this;
63
+ }
64
+ setUp() {
65
+ return this.setDirection(Turtle.UP);
66
+ }
67
+ setDown() {
68
+ return this.setDirection(Turtle.DOWN);
69
+ }
70
+ setLeft() {
71
+ return this.setDirection(Turtle.LEFT);
72
+ }
73
+ setRight() {
74
+ return this.setDirection(Turtle.RIGHT);
75
+ }
76
+ left() {
77
+ return this.setDirection((this.direction + 3) % 4);
78
+ }
79
+ right() {
80
+ return this.setDirection((this.direction + 1) % 4);
81
+ }
82
+
83
+ save() {
84
+ this.stack.push([this.position.x, this.position.y, this.direction, this.theme]);
85
+ return this;
86
+ }
87
+ restore() {
88
+ if (!this.stack) throw new ReferenceError('Unmatched restore');
89
+ [this.position.x, this.position.y, this.direction, this.theme] = this.stack.pop();
90
+ return this;
91
+ }
92
+
93
+ moveUp(distance) {
94
+ if (!distance) return this;
95
+ if (distance < 0) return this.moveDown(-distance);
96
+
97
+ const last = Math.max(0, this.position.y - distance);
98
+ if (this.position.y === last) return this;
99
+
100
+ for (let i = this.position.y; i >= last; --i) {
101
+ let cell = this.cells[i][this.position.x];
102
+ if (!cell) cell = this.cells[i][this.position.x] = {};
103
+ switch (i) {
104
+ case this.position.y:
105
+ cell.u = this.theme;
106
+ break;
107
+ case last:
108
+ cell.d = this.theme;
109
+ break;
110
+ default:
111
+ cell.u = cell.d = this.theme;
112
+ break;
113
+ }
114
+ }
115
+
116
+ this.position.y = last;
117
+ return this;
118
+ }
119
+ moveDown(distance) {
120
+ if (!distance) return this;
121
+ if (distance < 0) return this.moveUp(-distance);
122
+
123
+ const last = Math.min(this.height - 1, this.position.y + distance);
124
+ if (this.position.y === last) return this;
125
+
126
+ for (let i = this.position.y; i <= last; ++i) {
127
+ let cell = this.cells[i][this.position.x];
128
+ if (!cell) cell = this.cells[i][this.position.x] = {};
129
+ switch (i) {
130
+ case this.position.y:
131
+ cell.d = this.theme;
132
+ break;
133
+ case last:
134
+ cell.u = this.theme;
135
+ break;
136
+ default:
137
+ cell.u = cell.d = this.theme;
138
+ break;
139
+ }
140
+ }
141
+
142
+ this.position.y = last;
143
+ return this;
144
+ }
145
+ moveLeft(distance) {
146
+ if (!distance) return this;
147
+ if (distance < 0) return this.moveRight(-distance);
148
+
149
+ const last = Math.max(0, this.position.x - distance);
150
+ if (this.position.x === last) return this;
151
+
152
+ for (let j = this.position.x; j >= last; --j) {
153
+ let cell = this.cells[this.position.y][j];
154
+ if (!cell) cell = this.cells[this.position.y][j] = {};
155
+ switch (j) {
156
+ case this.position.x:
157
+ cell.l = this.theme;
158
+ break;
159
+ case last:
160
+ cell.r = this.theme;
161
+ break;
162
+ default:
163
+ cell.r = cell.l = this.theme;
164
+ break;
165
+ }
166
+ }
167
+
168
+ this.position.x = last;
169
+ return this;
170
+ }
171
+ moveRight(distance) {
172
+ if (!distance) return this;
173
+ if (distance < 0) return this.moveLeft(-distance);
174
+
175
+ const last = Math.min(this.width - 1, this.position.x + distance);
176
+ if (this.position.x === last) return this;
177
+
178
+ for (let j = this.position.x; j <= last; ++j) {
179
+ let cell = this.cells[this.position.y][j];
180
+ if (!cell) cell = this.cells[this.position.y][j] = {};
181
+ switch (j) {
182
+ case this.position.x:
183
+ cell.r = this.theme;
184
+ break;
185
+ case last:
186
+ cell.l = this.theme;
187
+ break;
188
+ default:
189
+ cell.r = cell.l = this.theme;
190
+ break;
191
+ }
192
+ }
193
+
194
+ this.position.x = last;
195
+ return this;
196
+ }
197
+ move(direction, distance) {
198
+ switch (direction) {
199
+ case Turtle.UP:
200
+ return this.moveUp(distance);
201
+ case Turtle.DOWN:
202
+ return this.moveDown(distance);
203
+ case Turtle.RIGHT:
204
+ return this.moveRight(distance);
205
+ case Turtle.LEFT:
206
+ return this.moveLeft(distance);
207
+ }
208
+ return this;
209
+ }
210
+ forward(distance) {
211
+ return this.move(this.direction, distance);
212
+ }
213
+ backward(distance) {
214
+ return this.move((this.direction + 2) % 4, distance);
215
+ }
216
+
217
+ markHalf(direction) {
218
+ let cell = this.cells[this.position.y][this.position.x];
219
+ if (!cell) cell = this.cells[this.position.y][this.position.x] = {};
220
+ switch (direction) {
221
+ case Turtle.UP:
222
+ cell.u = this.theme;
223
+ break;
224
+ case Turtle.DOWN:
225
+ cell.d = this.theme;
226
+ break;
227
+ case Turtle.RIGHT:
228
+ cell.r = this.theme;
229
+ break;
230
+ case Turtle.LEFT:
231
+ cell.l = this.theme;
232
+ break;
233
+ }
234
+ return this;
235
+ }
236
+ markHalfForward() {
237
+ return this.markHalf(this.direction);
238
+ }
239
+ markHalfBackward() {
240
+ return this.markHalf((this.direction + 2) % 4);
241
+ }
242
+ markHalfUp() {
243
+ return this.markHalf(Turtle.UP);
244
+ }
245
+ markHalfDown() {
246
+ return this.markHalf(Turtle.DOWN);
247
+ }
248
+ markHalfLeft() {
249
+ return this.markHalf(Turtle.LEFT);
250
+ }
251
+ markHalfRight() {
252
+ return this.markHalf(Turtle.RIGHT);
253
+ }
254
+ }
255
+
256
+ addAliases(Turtle, {
257
+ home: 'reset',
258
+ goto: 'set',
259
+ setPos: 'set',
260
+ setPosition: 'set',
261
+ advance: 'add',
262
+ lt: 'left',
263
+ rt: 'right',
264
+ fd: 'forward',
265
+ fwd: 'forward',
266
+ bk: 'backward',
267
+ back: 'backward',
268
+ bwd: 'backward',
269
+ setPen: 'setTheme',
270
+ setWidth: 'setTheme',
271
+ setDir: 'setDirection',
272
+ setNorth: 'setUp',
273
+ setSouth: 'setDown',
274
+ setWest: 'setLeft',
275
+ setEast: 'setRight',
276
+ moveNorth: 'moveUp',
277
+ moveSouth: 'moveDown',
278
+ moveWest: 'moveLeft',
279
+ moveEast: 'moveRight',
280
+ markHalfNorth: 'markHalfUp',
281
+ markHalfSouth: 'markHalfDown',
282
+ markHalfWest: 'markHalfLeft',
283
+ markHalfEast: 'markHalfRight'
284
+ });
285
+
286
+ export default Turtle;