@enspirit/bmg-js 1.1.0 → 1.1.1
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/dist/bmg.cjs +1 -1
- package/dist/bmg.cjs.map +1 -1
- package/dist/bmg.modern.js +1 -1
- package/dist/bmg.modern.js.map +1 -1
- package/dist/bmg.module.js +1 -1
- package/dist/bmg.module.js.map +1 -1
- package/dist/bmg.umd.js +1 -1
- package/dist/bmg.umd.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/writer/Text.d.ts +28 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/writer/Text.ts +125 -15
package/src/writer/Text.ts
CHANGED
|
@@ -1,6 +1,102 @@
|
|
|
1
1
|
import { Relation, Tuple } from '../types';
|
|
2
2
|
import { isRelation } from '../sync/operators/isRelation';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Characters used for table borders
|
|
6
|
+
*/
|
|
7
|
+
export interface BorderChars {
|
|
8
|
+
topLeft: string;
|
|
9
|
+
topCenter: string;
|
|
10
|
+
topRight: string;
|
|
11
|
+
midLeft: string;
|
|
12
|
+
midCenter: string;
|
|
13
|
+
midRight: string;
|
|
14
|
+
bottomLeft: string;
|
|
15
|
+
bottomCenter: string;
|
|
16
|
+
bottomRight: string;
|
|
17
|
+
horizontal: string;
|
|
18
|
+
vertical: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** ASCII border style (default) - maximum compatibility */
|
|
22
|
+
export const ASCII_BORDER: BorderChars = {
|
|
23
|
+
topLeft: '+',
|
|
24
|
+
topCenter: '+',
|
|
25
|
+
topRight: '+',
|
|
26
|
+
midLeft: '+',
|
|
27
|
+
midCenter: '+',
|
|
28
|
+
midRight: '+',
|
|
29
|
+
bottomLeft: '+',
|
|
30
|
+
bottomCenter: '+',
|
|
31
|
+
bottomRight: '+',
|
|
32
|
+
horizontal: '-',
|
|
33
|
+
vertical: '|',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Unicode single-line border style */
|
|
37
|
+
export const SINGLE_BORDER: BorderChars = {
|
|
38
|
+
topLeft: '┌',
|
|
39
|
+
topCenter: '┬',
|
|
40
|
+
topRight: '┐',
|
|
41
|
+
midLeft: '├',
|
|
42
|
+
midCenter: '┼',
|
|
43
|
+
midRight: '┤',
|
|
44
|
+
bottomLeft: '└',
|
|
45
|
+
bottomCenter: '┴',
|
|
46
|
+
bottomRight: '┘',
|
|
47
|
+
horizontal: '─',
|
|
48
|
+
vertical: '│',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Unicode double-line border style */
|
|
52
|
+
export const DOUBLE_BORDER: BorderChars = {
|
|
53
|
+
topLeft: '╔',
|
|
54
|
+
topCenter: '╦',
|
|
55
|
+
topRight: '╗',
|
|
56
|
+
midLeft: '╠',
|
|
57
|
+
midCenter: '╬',
|
|
58
|
+
midRight: '╣',
|
|
59
|
+
bottomLeft: '╚',
|
|
60
|
+
bottomCenter: '╩',
|
|
61
|
+
bottomRight: '╝',
|
|
62
|
+
horizontal: '═',
|
|
63
|
+
vertical: '║',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** Unicode rounded corners border style */
|
|
67
|
+
export const ROUNDED_BORDER: BorderChars = {
|
|
68
|
+
topLeft: '╭',
|
|
69
|
+
topCenter: '┬',
|
|
70
|
+
topRight: '╮',
|
|
71
|
+
midLeft: '├',
|
|
72
|
+
midCenter: '┼',
|
|
73
|
+
midRight: '┤',
|
|
74
|
+
bottomLeft: '╰',
|
|
75
|
+
bottomCenter: '┴',
|
|
76
|
+
bottomRight: '╯',
|
|
77
|
+
horizontal: '─',
|
|
78
|
+
vertical: '│',
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** Border style preset names */
|
|
82
|
+
export type BorderStyleName = 'ascii' | 'single' | 'double' | 'rounded';
|
|
83
|
+
|
|
84
|
+
const BORDER_PRESETS: Record<BorderStyleName, BorderChars> = {
|
|
85
|
+
ascii: ASCII_BORDER,
|
|
86
|
+
single: SINGLE_BORDER,
|
|
87
|
+
double: DOUBLE_BORDER,
|
|
88
|
+
rounded: ROUNDED_BORDER,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/** Resolve border option to BorderChars */
|
|
92
|
+
const resolveBorder = (
|
|
93
|
+
border: BorderStyleName | BorderChars | undefined
|
|
94
|
+
): BorderChars => {
|
|
95
|
+
if (border === undefined) return ASCII_BORDER;
|
|
96
|
+
if (typeof border === 'string') return BORDER_PRESETS[border];
|
|
97
|
+
return border;
|
|
98
|
+
};
|
|
99
|
+
|
|
4
100
|
/**
|
|
5
101
|
* Options for text rendering
|
|
6
102
|
*/
|
|
@@ -9,6 +105,8 @@ export interface TextOptions {
|
|
|
9
105
|
floatPrecision?: number;
|
|
10
106
|
/** Maximum width to trim output at */
|
|
11
107
|
trimAt?: number;
|
|
108
|
+
/** Border style: preset name or custom BorderChars object */
|
|
109
|
+
border?: BorderStyleName | BorderChars;
|
|
12
110
|
}
|
|
13
111
|
|
|
14
112
|
// Type guards
|
|
@@ -138,7 +236,8 @@ class Row {
|
|
|
138
236
|
return this.cells.map(cell => cell.minWidth);
|
|
139
237
|
}
|
|
140
238
|
|
|
141
|
-
renderingLines(sizes: number[]): string[] {
|
|
239
|
+
renderingLines(sizes: number[], border: BorderChars): string[] {
|
|
240
|
+
const v = border.vertical;
|
|
142
241
|
let nbLines = 0;
|
|
143
242
|
const byCell = this.cells.map((cell, i) => {
|
|
144
243
|
const lines = cell.renderingLines(sizes[i]);
|
|
@@ -150,11 +249,11 @@ class Row {
|
|
|
150
249
|
for (let lineI = 0; lineI < nbLines; lineI++) {
|
|
151
250
|
const lineContent = byCell
|
|
152
251
|
.map((cellLines, i) => cellLines[lineI] ?? ' '.repeat(sizes[i]))
|
|
153
|
-
.join(
|
|
154
|
-
grid.push(
|
|
252
|
+
.join(` ${v} `);
|
|
253
|
+
grid.push(`${v} ` + lineContent + ` ${v}`);
|
|
155
254
|
}
|
|
156
255
|
|
|
157
|
-
return grid.length === 0 ? [
|
|
256
|
+
return grid.length === 0 ? [`${v} ${v}`] : grid;
|
|
158
257
|
}
|
|
159
258
|
}
|
|
160
259
|
|
|
@@ -163,13 +262,14 @@ class Row {
|
|
|
163
262
|
*/
|
|
164
263
|
class Table {
|
|
165
264
|
private renderer: TextWriter;
|
|
265
|
+
private border: BorderChars;
|
|
166
266
|
private header: Row;
|
|
167
267
|
private rows: Row[];
|
|
168
268
|
private _sizes: number[] | null = null;
|
|
169
|
-
private _sep: string | null = null;
|
|
170
269
|
|
|
171
270
|
constructor(renderer: TextWriter, records: unknown[][], attributes: string[]) {
|
|
172
271
|
this.renderer = renderer;
|
|
272
|
+
this.border = resolveBorder(renderer.options.border);
|
|
173
273
|
this.header = new Row(renderer, attributes);
|
|
174
274
|
this.rows = records.map(r => new Row(renderer, r));
|
|
175
275
|
}
|
|
@@ -185,11 +285,21 @@ class Table {
|
|
|
185
285
|
return this._sizes;
|
|
186
286
|
}
|
|
187
287
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
288
|
+
private makeSep(left: string, center: string, right: string): string {
|
|
289
|
+
const h = this.border.horizontal;
|
|
290
|
+
return left + h + this.sizes.map(s => h.repeat(s)).join(h + center + h) + h + right;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
get topSep(): string {
|
|
294
|
+
return this.makeSep(this.border.topLeft, this.border.topCenter, this.border.topRight);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
get midSep(): string {
|
|
298
|
+
return this.makeSep(this.border.midLeft, this.border.midCenter, this.border.midRight);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
get bottomSep(): string {
|
|
302
|
+
return this.makeSep(this.border.bottomLeft, this.border.bottomCenter, this.border.bottomRight);
|
|
193
303
|
}
|
|
194
304
|
|
|
195
305
|
*eachLine(): Generator<string> {
|
|
@@ -205,15 +315,15 @@ class Table {
|
|
|
205
315
|
}
|
|
206
316
|
|
|
207
317
|
private *eachLineRaw(): Generator<string> {
|
|
208
|
-
yield this.
|
|
209
|
-
yield this.header.renderingLines(this.sizes)[0];
|
|
210
|
-
yield this.
|
|
318
|
+
yield this.topSep;
|
|
319
|
+
yield this.header.renderingLines(this.sizes, this.border)[0];
|
|
320
|
+
yield this.midSep;
|
|
211
321
|
for (const row of this.rows) {
|
|
212
|
-
for (const line of row.renderingLines(this.sizes)) {
|
|
322
|
+
for (const line of row.renderingLines(this.sizes, this.border)) {
|
|
213
323
|
yield line;
|
|
214
324
|
}
|
|
215
325
|
}
|
|
216
|
-
yield this.
|
|
326
|
+
yield this.bottomSep;
|
|
217
327
|
}
|
|
218
328
|
|
|
219
329
|
*[Symbol.iterator](): Generator<string> {
|