@flyingrobots/bijou 5.0.0 → 7.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/README.md +62 -0
- package/dist/core/active-binding-collection.d.ts +49 -0
- package/dist/core/active-binding-collection.d.ts.map +1 -0
- package/dist/core/active-binding-collection.js +264 -0
- package/dist/core/active-binding-collection.js.map +1 -0
- package/dist/core/app-shell-composition.d.ts +44 -0
- package/dist/core/app-shell-composition.d.ts.map +1 -0
- package/dist/core/app-shell-composition.js +123 -0
- package/dist/core/app-shell-composition.js.map +1 -0
- package/dist/core/binding-frame-update.d.ts +18 -0
- package/dist/core/binding-frame-update.d.ts.map +1 -0
- package/dist/core/binding-frame-update.js +133 -0
- package/dist/core/binding-frame-update.js.map +1 -0
- package/dist/core/binding-lifecycle.d.ts +65 -0
- package/dist/core/binding-lifecycle.d.ts.map +1 -0
- package/dist/core/binding-lifecycle.js +357 -0
- package/dist/core/binding-lifecycle.js.map +1 -0
- package/dist/core/binding.d.ts +192 -0
- package/dist/core/binding.d.ts.map +1 -0
- package/dist/core/binding.js +587 -0
- package/dist/core/binding.js.map +1 -0
- package/dist/core/block-metadata.d.ts +113 -0
- package/dist/core/block-metadata.d.ts.map +1 -0
- package/dist/core/block-metadata.js +376 -0
- package/dist/core/block-metadata.js.map +1 -0
- package/dist/core/block-tree-render.d.ts +17 -0
- package/dist/core/block-tree-render.d.ts.map +1 -0
- package/dist/core/block-tree-render.js +186 -0
- package/dist/core/block-tree-render.js.map +1 -0
- package/dist/core/component-metadata.d.ts +63 -0
- package/dist/core/component-metadata.d.ts.map +1 -0
- package/dist/core/component-metadata.js +158 -0
- package/dist/core/component-metadata.js.map +1 -0
- package/dist/core/components/dag-edges.d.ts +9 -3
- package/dist/core/components/dag-edges.d.ts.map +1 -1
- package/dist/core/components/dag-edges.js +41 -10
- package/dist/core/components/dag-edges.js.map +1 -1
- package/dist/core/components/dag-render.d.ts +1 -1
- package/dist/core/components/dag-render.d.ts.map +1 -1
- package/dist/core/components/dag-render.js +193 -72
- package/dist/core/components/dag-render.js.map +1 -1
- package/dist/core/components/dag-source.d.ts +4 -0
- package/dist/core/components/dag-source.d.ts.map +1 -1
- package/dist/core/components/dag-source.js +10 -0
- package/dist/core/components/dag-source.js.map +1 -1
- package/dist/core/components/dag.d.ts +13 -0
- package/dist/core/components/dag.d.ts.map +1 -1
- package/dist/core/components/dag.js.map +1 -1
- package/dist/core/components/index.d.ts +2 -2
- package/dist/core/components/index.d.ts.map +1 -1
- package/dist/core/components/index.js.map +1 -1
- package/dist/core/components/table-v3.d.ts +1 -1
- package/dist/core/components/table-v3.d.ts.map +1 -1
- package/dist/core/components/table-v3.js +136 -21
- package/dist/core/components/table-v3.js.map +1 -1
- package/dist/core/components/table.d.ts +36 -6
- package/dist/core/components/table.d.ts.map +1 -1
- package/dist/core/components/table.js +530 -74
- package/dist/core/components/table.js.map +1 -1
- package/dist/core/fixture-promotion.d.ts +33 -0
- package/dist/core/fixture-promotion.d.ts.map +1 -0
- package/dist/core/fixture-promotion.js +62 -0
- package/dist/core/fixture-promotion.js.map +1 -0
- package/dist/core/layout/envelope.d.ts +174 -0
- package/dist/core/layout/envelope.d.ts.map +1 -0
- package/dist/core/layout/envelope.js +336 -0
- package/dist/core/layout/envelope.js.map +1 -0
- package/dist/core/mode-lowering.d.ts +48 -0
- package/dist/core/mode-lowering.d.ts.map +1 -0
- package/dist/core/mode-lowering.js +176 -0
- package/dist/core/mode-lowering.js.map +1 -0
- package/dist/core/schema-block.d.ts +63 -0
- package/dist/core/schema-block.d.ts.map +1 -0
- package/dist/core/schema-block.js +361 -0
- package/dist/core/schema-block.js.map +1 -0
- package/dist/core/selection.d.ts +127 -0
- package/dist/core/selection.d.ts.map +1 -0
- package/dist/core/selection.js +350 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/standard-blocks.d.ts +264 -0
- package/dist/core/standard-blocks.d.ts.map +1 -0
- package/dist/core/standard-blocks.js +2518 -0
- package/dist/core/standard-blocks.js.map +1 -0
- package/dist/core/story-capture.d.ts +48 -0
- package/dist/core/story-capture.d.ts.map +1 -0
- package/dist/core/story-capture.js +64 -0
- package/dist/core/story-capture.js.map +1 -0
- package/dist/core/text/wrap.d.ts.map +1 -1
- package/dist/core/text/wrap.js +37 -20
- package/dist/core/text/wrap.js.map +1 -1
- package/dist/core/theme/doctor.d.ts +37 -0
- package/dist/core/theme/doctor.d.ts.map +1 -0
- package/dist/core/theme/doctor.js +175 -0
- package/dist/core/theme/doctor.js.map +1 -0
- package/dist/core/theme/dtcg.d.ts.map +1 -1
- package/dist/core/theme/dtcg.js +10 -1
- package/dist/core/theme/dtcg.js.map +1 -1
- package/dist/core/theme/index.d.ts +2 -0
- package/dist/core/theme/index.d.ts.map +1 -1
- package/dist/core/theme/index.js +2 -0
- package/dist/core/theme/index.js.map +1 -1
- package/dist/core/theme/presets.d.ts.map +1 -1
- package/dist/core/theme/presets.js +4 -0
- package/dist/core/theme/presets.js.map +1 -1
- package/dist/core/theme/tokens.d.ts +1 -1
- package/dist/core/theme/tokens.d.ts.map +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { RESET_SGR } from '../ansi.js';
|
|
2
|
-
import { ANSI_OSC8_RE, ANSI_SGR_RE, graphemeClusterWidth, segmentGraphemes, stripAnsi } from '../text/grapheme.js';
|
|
2
|
+
import { ANSI_OSC8_RE, ANSI_SGR_RE, graphemeClusterWidth, segmentGraphemes, stripAnsi, } from '../text/grapheme.js';
|
|
3
|
+
import { wrapToWidth } from '../text/wrap.js';
|
|
3
4
|
import { resolveCtx } from '../resolve-ctx.js';
|
|
4
5
|
import { renderByMode } from '../mode-render.js';
|
|
5
6
|
import { makeBgFill } from '../bg-fill.js';
|
|
7
|
+
import { sanitizeNonNegativeInt, sanitizeOptionalNonNegativeInt, sanitizeOptionalPositiveInt, sanitizePositiveInt, } from '../numeric.js';
|
|
6
8
|
import { resolveOverflowBehavior } from './overflow.js';
|
|
7
9
|
/**
|
|
8
10
|
* Structural width added by the interactive table frame for a given column count.
|
|
@@ -24,10 +26,10 @@ function isTableOptions(value) {
|
|
|
24
26
|
return !Array.isArray(value);
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
|
-
* Calculate the visible (non-ANSI)
|
|
29
|
+
* Calculate the visible (non-ANSI) display width of a string.
|
|
28
30
|
*
|
|
29
31
|
* @param str - Input string potentially containing ANSI codes.
|
|
30
|
-
* @returns The number of visible
|
|
32
|
+
* @returns The number of visible terminal columns.
|
|
31
33
|
*/
|
|
32
34
|
function visibleLength(str) {
|
|
33
35
|
let width = 0;
|
|
@@ -47,21 +49,181 @@ function padRight(str, width) {
|
|
|
47
49
|
const visible = visibleLength(str);
|
|
48
50
|
return visible >= width ? str : str + ' '.repeat(width - visible);
|
|
49
51
|
}
|
|
52
|
+
function padLeft(str, width) {
|
|
53
|
+
const visible = visibleLength(str);
|
|
54
|
+
return visible >= width ? str : ' '.repeat(width - visible) + str;
|
|
55
|
+
}
|
|
56
|
+
function padCenter(str, width) {
|
|
57
|
+
const visible = visibleLength(str);
|
|
58
|
+
if (visible >= width)
|
|
59
|
+
return str;
|
|
60
|
+
const remaining = width - visible;
|
|
61
|
+
const left = Math.floor(remaining / 2);
|
|
62
|
+
return ' '.repeat(left) + str + ' '.repeat(remaining - left);
|
|
63
|
+
}
|
|
64
|
+
function alignCell(str, width, align) {
|
|
65
|
+
if (align === 'right')
|
|
66
|
+
return padLeft(str, width);
|
|
67
|
+
if (align === 'center')
|
|
68
|
+
return padCenter(str, width);
|
|
69
|
+
return padRight(str, width);
|
|
70
|
+
}
|
|
50
71
|
function normalizeColumnWidth(width) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
return sanitizeOptionalNonNegativeInt(width);
|
|
73
|
+
}
|
|
74
|
+
function normalizePositiveWeight(weight) {
|
|
75
|
+
if (weight == null || !Number.isFinite(weight))
|
|
76
|
+
return 1;
|
|
77
|
+
return Math.max(0, Math.floor(weight));
|
|
78
|
+
}
|
|
79
|
+
function maxVisibleLineWidth(value) {
|
|
80
|
+
const lines = String(value ?? '').split('\n');
|
|
81
|
+
return lines.reduce((max, line) => Math.max(max, visibleLength(line)), 0);
|
|
82
|
+
}
|
|
83
|
+
function normalizeRows(rows) {
|
|
84
|
+
return (rows ?? []).map(row => (row ?? []).map(cell => String(cell ?? '')));
|
|
85
|
+
}
|
|
86
|
+
function resolveColumns(suppliedColumns, rows, variant) {
|
|
87
|
+
const columns = suppliedColumns ?? [];
|
|
88
|
+
if (columns.length > 0)
|
|
89
|
+
return [...columns];
|
|
90
|
+
if (variant === 'definition') {
|
|
91
|
+
return [
|
|
92
|
+
{ header: 'Field', minWidth: 5 },
|
|
93
|
+
{ header: 'Value', minWidth: 5, weight: 3 },
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
const inferredCount = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
97
|
+
return Array.from({ length: inferredCount }, () => ({ header: '' }));
|
|
56
98
|
}
|
|
57
|
-
function
|
|
99
|
+
function normalizeTable(options) {
|
|
100
|
+
const rows = normalizeRows(options.rows);
|
|
101
|
+
const variant = options.variant ?? 'box';
|
|
102
|
+
const columns = resolveColumns(options.columns, rows, variant);
|
|
103
|
+
return {
|
|
104
|
+
columns,
|
|
105
|
+
rows,
|
|
106
|
+
showHeader: variant === 'definition' || columns.some(column => (column.header ?? '').length > 0),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function structuralOverhead(variant, columnCount, columnGap) {
|
|
110
|
+
if (columnCount <= 0)
|
|
111
|
+
return variant === 'box' || variant === 'ascii-grid' ? 2 : 0;
|
|
112
|
+
if (variant === 'box' || variant === 'ascii-grid') {
|
|
113
|
+
return interactiveTableBorderOverhead(columnCount);
|
|
114
|
+
}
|
|
115
|
+
if (variant === 'markdown') {
|
|
116
|
+
return columnCount * 3 + 1;
|
|
117
|
+
}
|
|
118
|
+
return Math.max(0, columnCount - 1) * columnGap;
|
|
119
|
+
}
|
|
120
|
+
function resolveTargetWidth(options, ctx, layout) {
|
|
121
|
+
const explicitWidth = sanitizeOptionalPositiveInt(options.width);
|
|
122
|
+
if (explicitWidth !== undefined)
|
|
123
|
+
return explicitWidth;
|
|
124
|
+
const explicitMaxWidth = sanitizeOptionalPositiveInt(options.maxWidth);
|
|
125
|
+
if (layout === 'intrinsic')
|
|
126
|
+
return explicitMaxWidth;
|
|
127
|
+
const runtimeWidth = sanitizePositiveInt(ctx.runtime.columns, 80);
|
|
128
|
+
return explicitMaxWidth === undefined ? runtimeWidth : Math.min(runtimeWidth, explicitMaxWidth);
|
|
129
|
+
}
|
|
130
|
+
function columnPreferredWidth(column, rows, columnIndex) {
|
|
131
|
+
const fixedWidth = normalizeColumnWidth(column.width);
|
|
132
|
+
if (fixedWidth !== undefined)
|
|
133
|
+
return fixedWidth;
|
|
134
|
+
let preferred = Math.max(1, maxVisibleLineWidth(column.header ?? ''));
|
|
135
|
+
for (const row of rows) {
|
|
136
|
+
preferred = Math.max(preferred, maxVisibleLineWidth(row[columnIndex] ?? ''));
|
|
137
|
+
}
|
|
138
|
+
const maxWidth = sanitizeOptionalNonNegativeInt(column.maxWidth);
|
|
139
|
+
if (maxWidth !== undefined)
|
|
140
|
+
preferred = Math.min(preferred, maxWidth);
|
|
141
|
+
const minWidth = sanitizeOptionalNonNegativeInt(column.minWidth);
|
|
142
|
+
if (minWidth !== undefined)
|
|
143
|
+
preferred = Math.max(preferred, Math.min(minWidth, maxWidth ?? minWidth));
|
|
144
|
+
return preferred;
|
|
145
|
+
}
|
|
146
|
+
function columnMinWidth(column, preferredWidth) {
|
|
147
|
+
const fixedWidth = normalizeColumnWidth(column.width);
|
|
148
|
+
if (fixedWidth !== undefined)
|
|
149
|
+
return fixedWidth;
|
|
150
|
+
const maxWidth = sanitizeOptionalNonNegativeInt(column.maxWidth);
|
|
151
|
+
const rawMinWidth = sanitizeOptionalNonNegativeInt(column.minWidth) ?? Math.min(1, preferredWidth);
|
|
152
|
+
const constrainedMin = Math.min(rawMinWidth, maxWidth ?? rawMinWidth);
|
|
153
|
+
return Math.min(preferredWidth, constrainedMin);
|
|
154
|
+
}
|
|
155
|
+
function fitColumnWidths(columns, rows, variant, layout, targetWidth, columnGap) {
|
|
156
|
+
const preferred = columns.map((column, index) => columnPreferredWidth(column, rows, index));
|
|
157
|
+
if (layout === 'intrinsic' && targetWidth === undefined)
|
|
158
|
+
return preferred;
|
|
159
|
+
const contentTarget = targetWidth === undefined
|
|
160
|
+
? undefined
|
|
161
|
+
: Math.max(0, targetWidth - structuralOverhead(variant, columns.length, columnGap));
|
|
162
|
+
if (contentTarget === undefined)
|
|
163
|
+
return preferred;
|
|
164
|
+
const preferredTotal = preferred.reduce((sum, width) => sum + width, 0);
|
|
165
|
+
if (preferredTotal <= contentTarget)
|
|
166
|
+
return preferred;
|
|
167
|
+
const minimum = columns.map((column, index) => columnMinWidth(column, preferred[index]));
|
|
168
|
+
const minimumTotal = minimum.reduce((sum, width) => sum + width, 0);
|
|
169
|
+
if (minimumTotal >= contentTarget)
|
|
170
|
+
return minimum;
|
|
171
|
+
const widths = [...minimum];
|
|
172
|
+
const remainingCapacity = preferred.map((width, index) => Math.max(0, width - minimum[index]));
|
|
173
|
+
let remainingBudget = contentTarget - minimumTotal;
|
|
174
|
+
while (remainingBudget > 0) {
|
|
175
|
+
const active = remainingCapacity
|
|
176
|
+
.map((capacity, index) => ({ capacity, index }))
|
|
177
|
+
.filter(entry => entry.capacity > 0);
|
|
178
|
+
if (active.length === 0)
|
|
179
|
+
break;
|
|
180
|
+
const totalWeight = active.reduce((sum, entry) => {
|
|
181
|
+
return sum + Math.max(1, normalizePositiveWeight(columns[entry.index]?.weight));
|
|
182
|
+
}, 0);
|
|
183
|
+
let used = 0;
|
|
184
|
+
const remainders = [];
|
|
185
|
+
for (const entry of active) {
|
|
186
|
+
const weight = Math.max(1, normalizePositiveWeight(columns[entry.index]?.weight));
|
|
187
|
+
const exact = (remainingBudget * weight) / totalWeight;
|
|
188
|
+
const add = Math.min(entry.capacity, Math.floor(exact));
|
|
189
|
+
if (add > 0) {
|
|
190
|
+
widths[entry.index] += add;
|
|
191
|
+
remainingCapacity[entry.index] -= add;
|
|
192
|
+
used += add;
|
|
193
|
+
}
|
|
194
|
+
remainders.push({
|
|
195
|
+
index: entry.index,
|
|
196
|
+
remainder: exact - Math.floor(exact),
|
|
197
|
+
capacity: remainingCapacity[entry.index],
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (used === 0) {
|
|
201
|
+
const sortedRemainders = remainders
|
|
202
|
+
.filter(entry => entry.capacity > 0)
|
|
203
|
+
.sort((left, right) => {
|
|
204
|
+
if (right.remainder !== left.remainder)
|
|
205
|
+
return right.remainder - left.remainder;
|
|
206
|
+
return remainingCapacity[right.index] - remainingCapacity[left.index];
|
|
207
|
+
});
|
|
208
|
+
const next = sortedRemainders[0];
|
|
209
|
+
if (!next)
|
|
210
|
+
break;
|
|
211
|
+
widths[next.index]++;
|
|
212
|
+
remainingCapacity[next.index]--;
|
|
213
|
+
used = 1;
|
|
214
|
+
}
|
|
215
|
+
remainingBudget -= used;
|
|
216
|
+
}
|
|
217
|
+
return widths;
|
|
218
|
+
}
|
|
219
|
+
function formatCellLines(value, width, overflow, wrapMode) {
|
|
58
220
|
const safeValue = value ?? '';
|
|
59
|
-
if (!fixedWidth)
|
|
60
|
-
return safeValue.split('\n');
|
|
61
221
|
if (overflow === 'truncate') {
|
|
62
|
-
return safeValue.split('\n').map(
|
|
222
|
+
return safeValue.split('\n').map(line => clipCellToWidth(line, width));
|
|
63
223
|
}
|
|
64
|
-
|
|
224
|
+
if (wrapMode === 'word')
|
|
225
|
+
return wrapToWidth(safeValue, width);
|
|
226
|
+
return safeValue.split('\n').flatMap(line => wrapCellToWidth(line, width));
|
|
65
227
|
}
|
|
66
228
|
const TABLE_EMOJI_PRESENTATION_RE = /\p{Emoji_Presentation}/u;
|
|
67
229
|
function tableGraphemeWidth(grapheme) {
|
|
@@ -72,6 +234,11 @@ function tableGraphemeWidth(grapheme) {
|
|
|
72
234
|
function isOsc8Escape(raw) {
|
|
73
235
|
return raw.startsWith('\x1b]8;;');
|
|
74
236
|
}
|
|
237
|
+
const OSC8_CLOSE = '\x1b]8;;\x1b\\';
|
|
238
|
+
const OSC8_CLOSE_BEL = '\x1b]8;;\x07';
|
|
239
|
+
function isOsc8Close(raw) {
|
|
240
|
+
return raw === OSC8_CLOSE || raw === OSC8_CLOSE_BEL;
|
|
241
|
+
}
|
|
75
242
|
function isResetEscape(raw) {
|
|
76
243
|
return raw === RESET_SGR;
|
|
77
244
|
}
|
|
@@ -106,6 +273,19 @@ function tokenizeTableText(str) {
|
|
|
106
273
|
}
|
|
107
274
|
return tokens;
|
|
108
275
|
}
|
|
276
|
+
function activeTableAnsiPrefix(activeOsc8, activeStyle) {
|
|
277
|
+
return activeOsc8 + activeStyle;
|
|
278
|
+
}
|
|
279
|
+
function finalizeTableWrappedLine(raw, activeOsc8, activeStyle) {
|
|
280
|
+
let result = raw;
|
|
281
|
+
if (activeOsc8.length > 0 && !result.endsWith(OSC8_CLOSE) && !result.endsWith(OSC8_CLOSE_BEL)) {
|
|
282
|
+
result += OSC8_CLOSE;
|
|
283
|
+
}
|
|
284
|
+
if (activeStyle.length > 0 && !result.endsWith(RESET_SGR)) {
|
|
285
|
+
result += RESET_SGR;
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
109
289
|
function clipCellToWidth(str, maxWidth) {
|
|
110
290
|
if (maxWidth <= 0)
|
|
111
291
|
return '';
|
|
@@ -113,15 +293,21 @@ function clipCellToWidth(str, maxWidth) {
|
|
|
113
293
|
let visible = 0;
|
|
114
294
|
let result = '';
|
|
115
295
|
let hasStyle = false;
|
|
296
|
+
let activeOsc8 = '';
|
|
116
297
|
for (const token of tokens) {
|
|
117
298
|
if (token.kind === 'ansi') {
|
|
118
299
|
result += token.raw;
|
|
119
|
-
if (
|
|
120
|
-
|
|
300
|
+
if (isOsc8Escape(token.raw)) {
|
|
301
|
+
activeOsc8 = isOsc8Close(token.raw) ? '' : token.raw;
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
hasStyle = !isResetEscape(token.raw);
|
|
121
305
|
}
|
|
122
306
|
continue;
|
|
123
307
|
}
|
|
124
308
|
if (visible + token.width > maxWidth) {
|
|
309
|
+
if (activeOsc8.length > 0)
|
|
310
|
+
result += OSC8_CLOSE;
|
|
125
311
|
if (hasStyle && !result.endsWith(RESET_SGR))
|
|
126
312
|
result += RESET_SGR;
|
|
127
313
|
break;
|
|
@@ -129,7 +315,9 @@ function clipCellToWidth(str, maxWidth) {
|
|
|
129
315
|
result += token.raw;
|
|
130
316
|
visible += token.width;
|
|
131
317
|
}
|
|
132
|
-
return
|
|
318
|
+
return activeOsc8.length > 0 || hasStyle
|
|
319
|
+
? finalizeTableWrappedLine(result, activeOsc8, hasStyle ? RESET_SGR : '')
|
|
320
|
+
: result;
|
|
133
321
|
}
|
|
134
322
|
function wrapCellToWidth(str, maxWidth) {
|
|
135
323
|
if (maxWidth <= 0)
|
|
@@ -141,17 +329,20 @@ function wrapCellToWidth(str, maxWidth) {
|
|
|
141
329
|
let current = '';
|
|
142
330
|
let currentWidth = 0;
|
|
143
331
|
let activeStyle = '';
|
|
332
|
+
let activeOsc8 = '';
|
|
144
333
|
for (const token of tokens) {
|
|
145
334
|
if (token.kind === 'ansi') {
|
|
146
335
|
current += token.raw;
|
|
147
|
-
if (isOsc8Escape(token.raw))
|
|
336
|
+
if (isOsc8Escape(token.raw)) {
|
|
337
|
+
activeOsc8 = isOsc8Close(token.raw) ? '' : token.raw;
|
|
148
338
|
continue;
|
|
339
|
+
}
|
|
149
340
|
activeStyle = isResetEscape(token.raw) ? '' : activeStyle + token.raw;
|
|
150
341
|
continue;
|
|
151
342
|
}
|
|
152
343
|
if (currentWidth + token.width > maxWidth && currentWidth > 0) {
|
|
153
|
-
lines.push(
|
|
154
|
-
current = activeStyle + token.raw;
|
|
344
|
+
lines.push(finalizeTableWrappedLine(current, activeOsc8, activeStyle));
|
|
345
|
+
current = activeTableAnsiPrefix(activeOsc8, activeStyle) + token.raw;
|
|
155
346
|
currentWidth = token.width;
|
|
156
347
|
continue;
|
|
157
348
|
}
|
|
@@ -159,10 +350,320 @@ function wrapCellToWidth(str, maxWidth) {
|
|
|
159
350
|
currentWidth += token.width;
|
|
160
351
|
}
|
|
161
352
|
if (current.length > 0) {
|
|
162
|
-
lines.push(
|
|
353
|
+
lines.push(finalizeTableWrappedLine(current, activeOsc8, activeStyle));
|
|
163
354
|
}
|
|
164
355
|
return lines.length > 0 ? lines : [''];
|
|
165
356
|
}
|
|
357
|
+
function buildFittedTable(options, ctx, tableData, variant, optionsOverride = {}) {
|
|
358
|
+
const columns = optionsOverride.columns ?? tableData.columns;
|
|
359
|
+
const rows = optionsOverride.rows ?? tableData.rows;
|
|
360
|
+
const layout = optionsOverride.layout ?? options.layout ?? 'auto';
|
|
361
|
+
const columnGap = sanitizeNonNegativeInt(options.columnGap, 2);
|
|
362
|
+
const overflow = resolveOverflowBehavior(options.overflow, ctx.resolveBCSS({ type: 'Table', id: options.id, classes: options.class?.split(' ') }));
|
|
363
|
+
const wrapMode = options.wrap ?? 'word';
|
|
364
|
+
const widths = fitColumnWidths(columns, rows, variant, layout, resolveTargetWidth(options, ctx, layout), columnGap);
|
|
365
|
+
const headerToken = options.headerToken ?? ctx.ui('tableHeader');
|
|
366
|
+
const styleHeaders = optionsOverride.styleHeaders ?? true;
|
|
367
|
+
const headerLines = columns.map((column, index) => {
|
|
368
|
+
const header = column.header ?? '';
|
|
369
|
+
const value = styleHeaders ? ctx.style.styled(headerToken, header) : header;
|
|
370
|
+
return formatCellLines(value, widths[index] ?? 0, overflow, wrapMode);
|
|
371
|
+
});
|
|
372
|
+
const headerHeight = headerLines.reduce((max, lines) => Math.max(max, lines.length), 1);
|
|
373
|
+
const fittedRows = rows.map((row) => {
|
|
374
|
+
const cells = widths.map((width, index) => {
|
|
375
|
+
return formatCellLines(row[index] ?? '', width, overflow, wrapMode);
|
|
376
|
+
});
|
|
377
|
+
const height = cells.reduce((max, lines) => Math.max(max, lines.length), 1);
|
|
378
|
+
return { cells, height };
|
|
379
|
+
});
|
|
380
|
+
return {
|
|
381
|
+
columns: columns.map((column, index) => ({
|
|
382
|
+
header: column.header ?? '',
|
|
383
|
+
width: widths[index] ?? 0,
|
|
384
|
+
align: column.align ?? 'left',
|
|
385
|
+
})),
|
|
386
|
+
widths,
|
|
387
|
+
headerLines,
|
|
388
|
+
headerHeight,
|
|
389
|
+
rows: fittedRows,
|
|
390
|
+
columnGap,
|
|
391
|
+
showHeader: tableData.showHeader,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
function renderGridTable(model, options, ctx, variant, styled = true) {
|
|
395
|
+
const borderToken = options.borderToken ?? ctx.border('muted');
|
|
396
|
+
const bc = (s) => styled ? ctx.style.styled(borderToken, s) : s;
|
|
397
|
+
const chars = variant === 'box'
|
|
398
|
+
? {
|
|
399
|
+
h: '\u2500',
|
|
400
|
+
v: '\u2502',
|
|
401
|
+
topLeft: '\u250c',
|
|
402
|
+
topMid: '\u252c',
|
|
403
|
+
topRight: '\u2510',
|
|
404
|
+
midLeft: '\u251c',
|
|
405
|
+
midMid: '\u253c',
|
|
406
|
+
midRight: '\u2524',
|
|
407
|
+
bottomLeft: '\u2514',
|
|
408
|
+
bottomMid: '\u2534',
|
|
409
|
+
bottomRight: '\u2518',
|
|
410
|
+
}
|
|
411
|
+
: {
|
|
412
|
+
h: '-',
|
|
413
|
+
v: '|',
|
|
414
|
+
topLeft: '+',
|
|
415
|
+
topMid: '+',
|
|
416
|
+
topRight: '+',
|
|
417
|
+
midLeft: '+',
|
|
418
|
+
midMid: '+',
|
|
419
|
+
midRight: '+',
|
|
420
|
+
bottomLeft: '+',
|
|
421
|
+
bottomMid: '+',
|
|
422
|
+
bottomRight: '+',
|
|
423
|
+
};
|
|
424
|
+
const hLine = (left, mid, right) => {
|
|
425
|
+
const segments = model.widths.map(w => chars.h.repeat(w + 2));
|
|
426
|
+
return bc(left + segments.join(mid) + right);
|
|
427
|
+
};
|
|
428
|
+
const top = hLine(chars.topLeft, chars.topMid, chars.topRight);
|
|
429
|
+
const midSep = hLine(chars.midLeft, chars.midMid, chars.midRight);
|
|
430
|
+
const bottom = hLine(chars.bottomLeft, chars.bottomMid, chars.bottomRight);
|
|
431
|
+
const hdrBgFill = styled ? makeBgFill(options.headerBgToken, ctx) : undefined;
|
|
432
|
+
const headerRows = Array.from({ length: model.headerHeight }, (_row, rowIndex) => {
|
|
433
|
+
const headerCells = model.columns.map((column, i) => ' ' + alignCell(model.headerLines[i]?.[rowIndex] ?? '', column.width, column.align) + ' ');
|
|
434
|
+
const rawHeaderRow = bc(chars.v) + headerCells.join(bc(chars.v)) + bc(chars.v);
|
|
435
|
+
return hdrBgFill ? hdrBgFill(rawHeaderRow) : rawHeaderRow;
|
|
436
|
+
});
|
|
437
|
+
const dataRows = model.rows.flatMap((row) => {
|
|
438
|
+
return Array.from({ length: row.height }, (_line, lineIndex) => {
|
|
439
|
+
const cells = model.columns.map((column, i) => ' ' + alignCell(row.cells[i]?.[lineIndex] ?? '', column.width, column.align) + ' ');
|
|
440
|
+
return bc(chars.v) + cells.join(bc(chars.v)) + bc(chars.v);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
return model.showHeader
|
|
444
|
+
? [top, ...headerRows, midSep, ...dataRows, bottom].join('\n')
|
|
445
|
+
: [top, ...dataRows, bottom].join('\n');
|
|
446
|
+
}
|
|
447
|
+
function renderBorderlessRow(model, cells, rowIndex) {
|
|
448
|
+
const gap = ' '.repeat(model.columnGap);
|
|
449
|
+
return model.columns
|
|
450
|
+
.map((column, index) => alignCell(cells[index]?.[rowIndex] ?? '', column.width, column.align))
|
|
451
|
+
.join(gap)
|
|
452
|
+
.trimEnd();
|
|
453
|
+
}
|
|
454
|
+
function renderRule(model, char, ctx, options) {
|
|
455
|
+
const borderToken = options.borderToken ?? ctx.border('muted');
|
|
456
|
+
const line = model.widths.map(width => char.repeat(width)).join(' '.repeat(model.columnGap)).trimEnd();
|
|
457
|
+
return ctx.style.styled(borderToken, line);
|
|
458
|
+
}
|
|
459
|
+
function renderRuledTable(model, options, ctx, includeRowRules) {
|
|
460
|
+
const lines = model.showHeader
|
|
461
|
+
? [
|
|
462
|
+
...Array.from({ length: model.headerHeight }, (_row, index) => {
|
|
463
|
+
return renderBorderlessRow(model, model.headerLines, index);
|
|
464
|
+
}),
|
|
465
|
+
renderRule(model, '\u2501', ctx, options),
|
|
466
|
+
]
|
|
467
|
+
: [];
|
|
468
|
+
for (let rowIndex = 0; rowIndex < model.rows.length; rowIndex++) {
|
|
469
|
+
const row = model.rows[rowIndex];
|
|
470
|
+
for (let lineIndex = 0; lineIndex < row.height; lineIndex++) {
|
|
471
|
+
lines.push(renderBorderlessRow(model, row.cells, lineIndex));
|
|
472
|
+
}
|
|
473
|
+
if (includeRowRules && rowIndex < model.rows.length - 1) {
|
|
474
|
+
lines.push(renderRule(model, '\u2500', ctx, options));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return lines.join('\n');
|
|
478
|
+
}
|
|
479
|
+
function renderHeaderRuleTable(model) {
|
|
480
|
+
const lines = model.showHeader
|
|
481
|
+
? [
|
|
482
|
+
...Array.from({ length: model.headerHeight }, (_row, index) => {
|
|
483
|
+
return renderBorderlessRow(model, model.headerLines, index);
|
|
484
|
+
}),
|
|
485
|
+
model.widths.map(width => '-'.repeat(width)).join(' '.repeat(model.columnGap)).trimEnd(),
|
|
486
|
+
]
|
|
487
|
+
: [];
|
|
488
|
+
for (const row of model.rows) {
|
|
489
|
+
for (let lineIndex = 0; lineIndex < row.height; lineIndex++) {
|
|
490
|
+
lines.push(renderBorderlessRow(model, row.cells, lineIndex));
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return lines.join('\n');
|
|
494
|
+
}
|
|
495
|
+
function renderPlainTable(model) {
|
|
496
|
+
const lines = model.showHeader
|
|
497
|
+
? Array.from({ length: model.headerHeight }, (_row, index) => {
|
|
498
|
+
return renderBorderlessRow(model, model.headerLines, index);
|
|
499
|
+
})
|
|
500
|
+
: [];
|
|
501
|
+
for (const row of model.rows) {
|
|
502
|
+
for (let lineIndex = 0; lineIndex < row.height; lineIndex++) {
|
|
503
|
+
lines.push(renderBorderlessRow(model, row.cells, lineIndex));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return lines.join('\n');
|
|
507
|
+
}
|
|
508
|
+
function markdownSeparator(width, align) {
|
|
509
|
+
const segmentWidth = Math.max(3, width + 2);
|
|
510
|
+
if (align === 'right')
|
|
511
|
+
return '-'.repeat(segmentWidth - 1) + ':';
|
|
512
|
+
if (align === 'center')
|
|
513
|
+
return ':' + '-'.repeat(segmentWidth - 2) + ':';
|
|
514
|
+
return '-'.repeat(segmentWidth);
|
|
515
|
+
}
|
|
516
|
+
function renderMarkdownTable(model) {
|
|
517
|
+
const renderWidths = model.columns.map(column => Math.max(1, column.width));
|
|
518
|
+
const rowLine = (cells, lineIndex) => {
|
|
519
|
+
return '|' + model.columns.map((column, index) => {
|
|
520
|
+
const value = cells[index]?.[lineIndex] ?? '';
|
|
521
|
+
return ' ' + alignCell(value, renderWidths[index], column.align) + ' ';
|
|
522
|
+
}).join('|') + '|';
|
|
523
|
+
};
|
|
524
|
+
const headerRows = Array.from({ length: model.headerHeight }, (_row, index) => {
|
|
525
|
+
return rowLine(model.headerLines, index);
|
|
526
|
+
});
|
|
527
|
+
const separator = '|' + model.columns.map((column, index) => {
|
|
528
|
+
return markdownSeparator(renderWidths[index], column.align);
|
|
529
|
+
}).join('|') + '|';
|
|
530
|
+
const rows = model.rows.flatMap((row) => {
|
|
531
|
+
return Array.from({ length: row.height }, (_line, index) => rowLine(row.cells, index));
|
|
532
|
+
});
|
|
533
|
+
return model.showHeader ? [...headerRows, separator, ...rows].join('\n') : rows.join('\n');
|
|
534
|
+
}
|
|
535
|
+
function renderExpandedTable(tableData, options, ctx) {
|
|
536
|
+
const borderToken = options.borderToken ?? ctx.border('muted');
|
|
537
|
+
const lines = [];
|
|
538
|
+
const columnLabel = (index) => {
|
|
539
|
+
return tableData.showHeader ? tableData.columns[index]?.header ?? '' : `Column ${index + 1}`;
|
|
540
|
+
};
|
|
541
|
+
const preferredLabelWidth = tableData.columns.reduce((max, _column, index) => {
|
|
542
|
+
return Math.max(max, visibleLength(columnLabel(index)));
|
|
543
|
+
}, 0);
|
|
544
|
+
const layout = options.layout ?? 'auto';
|
|
545
|
+
const targetWidth = resolveTargetWidth(options, ctx, layout);
|
|
546
|
+
const ruleWidth = targetWidth ?? 40;
|
|
547
|
+
const separator = targetWidth === undefined || targetWidth >= 3
|
|
548
|
+
? ' | '
|
|
549
|
+
: ' '.repeat(Math.max(0, targetWidth - 1));
|
|
550
|
+
const availableContentWidth = targetWidth === undefined
|
|
551
|
+
? undefined
|
|
552
|
+
: Math.max(0, targetWidth - separator.length);
|
|
553
|
+
const labelWidth = targetWidth === undefined
|
|
554
|
+
? preferredLabelWidth
|
|
555
|
+
: Math.min(preferredLabelWidth, Math.floor((availableContentWidth ?? 0) / 2));
|
|
556
|
+
const valueWidth = targetWidth === undefined
|
|
557
|
+
? undefined
|
|
558
|
+
: Math.max(0, targetWidth - labelWidth - separator.length);
|
|
559
|
+
const overflow = resolveOverflowBehavior(options.overflow, ctx.resolveBCSS({ type: 'Table', id: options.id, classes: options.class?.split(' ') }));
|
|
560
|
+
const wrapMode = options.wrap ?? 'word';
|
|
561
|
+
for (let rowIndex = 0; rowIndex < tableData.rows.length; rowIndex++) {
|
|
562
|
+
const title = `-[ RECORD ${rowIndex + 1} ]`;
|
|
563
|
+
const clippedTitle = targetWidth === undefined ? title : clipCellToWidth(title, ruleWidth);
|
|
564
|
+
lines.push(ctx.style.styled(borderToken, clippedTitle + '-'.repeat(Math.max(0, ruleWidth - visibleLength(clippedTitle)))));
|
|
565
|
+
const row = tableData.rows[rowIndex];
|
|
566
|
+
for (let columnIndex = 0; columnIndex < tableData.columns.length; columnIndex++) {
|
|
567
|
+
const rawLabel = columnLabel(columnIndex);
|
|
568
|
+
const label = padRight(targetWidth === undefined ? rawLabel : clipCellToWidth(rawLabel, labelWidth), labelWidth);
|
|
569
|
+
const rawValue = row[columnIndex] ?? '';
|
|
570
|
+
const valueLines = valueWidth === undefined
|
|
571
|
+
? rawValue.split('\n')
|
|
572
|
+
: formatCellLines(rawValue, valueWidth, overflow, wrapMode);
|
|
573
|
+
for (let lineIndex = 0; lineIndex < valueLines.length; lineIndex++) {
|
|
574
|
+
const lineLabel = lineIndex === 0 ? label : ' '.repeat(labelWidth);
|
|
575
|
+
lines.push(`${lineLabel}${separator}${valueLines[lineIndex] ?? ''}`.trimEnd());
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return lines.join('\n');
|
|
580
|
+
}
|
|
581
|
+
function markdownEscapeCell(value) {
|
|
582
|
+
return stripAnsi(String(value ?? ''))
|
|
583
|
+
.replace(/\\/g, '\\\\')
|
|
584
|
+
.replace(/\|/g, '\\|')
|
|
585
|
+
.replace(/\r\n?/g, '\n')
|
|
586
|
+
.replace(/\n/g, '<br>');
|
|
587
|
+
}
|
|
588
|
+
function markdownTableData(tableData) {
|
|
589
|
+
return {
|
|
590
|
+
columns: tableData.columns.map(column => ({
|
|
591
|
+
...column,
|
|
592
|
+
header: markdownEscapeCell(column.header ?? ''),
|
|
593
|
+
})),
|
|
594
|
+
rows: tableData.rows.map(row => row.map(cell => markdownEscapeCell(cell))),
|
|
595
|
+
showHeader: tableData.showHeader,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function renderVisualTable(options, ctx, tableData, variant) {
|
|
599
|
+
if (variant === 'markdown') {
|
|
600
|
+
const markdownData = markdownTableData(tableData);
|
|
601
|
+
const markdownModel = buildFittedTable(options, ctx, markdownData, 'markdown', {
|
|
602
|
+
styleHeaders: false,
|
|
603
|
+
});
|
|
604
|
+
return renderMarkdownTable(markdownModel);
|
|
605
|
+
}
|
|
606
|
+
if (variant === 'expanded') {
|
|
607
|
+
return renderExpandedTable(tableData, options, ctx);
|
|
608
|
+
}
|
|
609
|
+
const model = buildFittedTable(options, ctx, tableData, variant);
|
|
610
|
+
switch (variant) {
|
|
611
|
+
case 'ascii-grid':
|
|
612
|
+
return renderGridTable(model, options, ctx, 'ascii-grid');
|
|
613
|
+
case 'ruled':
|
|
614
|
+
return renderRuledTable(model, options, ctx, true);
|
|
615
|
+
case 'header-rule':
|
|
616
|
+
return renderHeaderRuleTable(model);
|
|
617
|
+
case 'plain':
|
|
618
|
+
return renderPlainTable(model);
|
|
619
|
+
case 'definition':
|
|
620
|
+
return renderRuledTable(model, options, ctx, true);
|
|
621
|
+
case 'box':
|
|
622
|
+
default:
|
|
623
|
+
return renderGridTable(model, options, ctx, 'box');
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function escapeTsvCell(value) {
|
|
627
|
+
return String(value ?? '')
|
|
628
|
+
.replace(/\\/g, '\\\\')
|
|
629
|
+
.replace(/\t/g, '\\t')
|
|
630
|
+
.replace(/\r/g, '\\r')
|
|
631
|
+
.replace(/\n/g, '\\n');
|
|
632
|
+
}
|
|
633
|
+
function escapeCsvCell(value) {
|
|
634
|
+
const text = String(value ?? '');
|
|
635
|
+
if (!/[",\r\n]/.test(text))
|
|
636
|
+
return text;
|
|
637
|
+
return `"${text.replace(/"/g, '""')}"`;
|
|
638
|
+
}
|
|
639
|
+
function renderSeparatedPipe(tableData, separator, escapeCell) {
|
|
640
|
+
const headerLine = tableData.columns.map(column => escapeCell(column.header ?? '')).join(separator);
|
|
641
|
+
const dataLines = tableData.rows.map(row => row.map(escapeCell).join(separator));
|
|
642
|
+
if (!tableData.showHeader)
|
|
643
|
+
return dataLines.join('\n');
|
|
644
|
+
return [headerLine, ...dataLines].join('\n');
|
|
645
|
+
}
|
|
646
|
+
function renderPipeTable(options, ctx, tableData) {
|
|
647
|
+
const format = options.pipeFormat ?? 'tsv';
|
|
648
|
+
if (format === 'csv')
|
|
649
|
+
return renderSeparatedPipe(tableData, ',', escapeCsvCell);
|
|
650
|
+
if (format === 'markdown') {
|
|
651
|
+
const markdownData = markdownTableData(tableData);
|
|
652
|
+
const markdownModel = buildFittedTable(options, ctx, markdownData, 'markdown', {
|
|
653
|
+
layout: options.layout ?? (options.width !== undefined || options.maxWidth !== undefined ? 'auto' : 'intrinsic'),
|
|
654
|
+
styleHeaders: false,
|
|
655
|
+
});
|
|
656
|
+
return renderMarkdownTable(markdownModel);
|
|
657
|
+
}
|
|
658
|
+
if (format === 'ascii-grid') {
|
|
659
|
+
const model = buildFittedTable(options, ctx, tableData, 'ascii-grid', {
|
|
660
|
+
layout: options.layout ?? (options.width !== undefined || options.maxWidth !== undefined ? 'auto' : 'intrinsic'),
|
|
661
|
+
styleHeaders: false,
|
|
662
|
+
});
|
|
663
|
+
return renderGridTable(model, options, ctx, 'ascii-grid', false);
|
|
664
|
+
}
|
|
665
|
+
return renderSeparatedPipe(tableData, '\t', escapeTsvCell);
|
|
666
|
+
}
|
|
166
667
|
export function table(optionsOrColumns, rowData, context) {
|
|
167
668
|
let options;
|
|
168
669
|
if (isTableOptions(optionsOrColumns)) {
|
|
@@ -172,67 +673,22 @@ export function table(optionsOrColumns, rowData, context) {
|
|
|
172
673
|
options = { columns: [...optionsOrColumns], rows: rowData ?? [], ctx: context };
|
|
173
674
|
}
|
|
174
675
|
const ctx = resolveCtx(options.ctx);
|
|
175
|
-
const
|
|
176
|
-
const rows = (options.rows ?? []).map(row => (row ?? []).map(cell => cell ?? ''));
|
|
676
|
+
const tableData = normalizeTable(options);
|
|
177
677
|
return renderByMode(ctx.mode, {
|
|
178
|
-
pipe: () =>
|
|
179
|
-
const headerLine = columns.map((c) => c.header ?? '').join('\t');
|
|
180
|
-
const dataLines = rows.map((row) => row.join('\t'));
|
|
181
|
-
return [headerLine, ...dataLines].join('\n');
|
|
182
|
-
},
|
|
678
|
+
pipe: () => renderPipeTable(options, ctx, tableData),
|
|
183
679
|
accessible: () => {
|
|
184
680
|
const lines = [];
|
|
185
|
-
for (let i = 0; i < rows.length; i++) {
|
|
186
|
-
const row = rows[i];
|
|
187
|
-
const pairs = columns.map((col, j) =>
|
|
681
|
+
for (let i = 0; i < tableData.rows.length; i++) {
|
|
682
|
+
const row = tableData.rows[i];
|
|
683
|
+
const pairs = tableData.columns.map((col, j) => {
|
|
684
|
+
const label = tableData.showHeader ? col.header ?? '' : `Column ${j + 1}`;
|
|
685
|
+
return `${label}=${row[j] ?? ''}`;
|
|
686
|
+
});
|
|
188
687
|
lines.push(`Row ${i + 1}: ${pairs.join(', ')}`);
|
|
189
688
|
}
|
|
190
689
|
return lines.join('\n');
|
|
191
690
|
},
|
|
192
|
-
interactive: () =>
|
|
193
|
-
const headerToken = options.headerToken ?? ctx.ui('tableHeader');
|
|
194
|
-
const borderToken = options.borderToken ?? ctx.border('muted');
|
|
195
|
-
const overflow = resolveOverflowBehavior(options.overflow, ctx.resolveBCSS({ type: 'Table', id: options.id, classes: options.class?.split(' ') }));
|
|
196
|
-
const bc = (s) => ctx.style.styled(borderToken, s);
|
|
197
|
-
const colWidths = columns.map((col, i) => {
|
|
198
|
-
const normalizedWidth = normalizeColumnWidth(col.width);
|
|
199
|
-
if (normalizedWidth !== undefined)
|
|
200
|
-
return normalizedWidth;
|
|
201
|
-
let max = visibleLength(col.header ?? '');
|
|
202
|
-
for (const row of rows) {
|
|
203
|
-
const cell = row[i] ?? '';
|
|
204
|
-
max = Math.max(max, visibleLength(cell));
|
|
205
|
-
}
|
|
206
|
-
return max;
|
|
207
|
-
});
|
|
208
|
-
const h = '\u2500';
|
|
209
|
-
const v = '\u2502';
|
|
210
|
-
const hLine = (left, mid, right) => {
|
|
211
|
-
const segments = colWidths.map((w) => h.repeat(w + 2));
|
|
212
|
-
return bc(left + segments.join(mid) + right);
|
|
213
|
-
};
|
|
214
|
-
const top = hLine('\u250c', '\u252c', '\u2510');
|
|
215
|
-
const midSep = hLine('\u251c', '\u253c', '\u2524');
|
|
216
|
-
const bottom = hLine('\u2514', '\u2534', '\u2518');
|
|
217
|
-
const hdrBgFill = makeBgFill(options.headerBgToken, ctx);
|
|
218
|
-
const headerLinesByColumn = columns.map((col, i) => formatCellLines(ctx.style.styled(headerToken, col.header ?? ''), colWidths[i], overflow, col.width !== undefined));
|
|
219
|
-
const headerHeight = headerLinesByColumn.reduce((max, lines) => Math.max(max, lines.length), 1);
|
|
220
|
-
const headerRows = Array.from({ length: headerHeight }, (_row, rowIndex) => {
|
|
221
|
-
const headerCells = columns.map((_col, i) => ' ' + padRight(headerLinesByColumn[i][rowIndex] ?? '', colWidths[i]) + ' ');
|
|
222
|
-
const rawHeaderRow = bc(v) + headerCells.join(bc(v)) + bc(v);
|
|
223
|
-
return hdrBgFill ? hdrBgFill(rawHeaderRow) : rawHeaderRow;
|
|
224
|
-
});
|
|
225
|
-
const dataRows = rows.flatMap((row) => {
|
|
226
|
-
const cellLines = colWidths.map((w, i) => formatCellLines(row[i] ?? '', w, overflow, columns[i]?.width !== undefined));
|
|
227
|
-
const rowHeight = cellLines.reduce((max, lines) => Math.max(max, lines.length), 1);
|
|
228
|
-
return Array.from({ length: rowHeight }, (_line, lineIndex) => {
|
|
229
|
-
const cells = colWidths.map((w, i) => ' ' + padRight(cellLines[i][lineIndex] ?? '', w) + ' ');
|
|
230
|
-
return bc(v) + cells.join(bc(v)) + bc(v);
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
const lines = [top, ...headerRows, midSep, ...dataRows, bottom];
|
|
234
|
-
return lines.join('\n');
|
|
235
|
-
},
|
|
691
|
+
interactive: () => renderVisualTable(options, ctx, tableData, options.variant ?? 'box'),
|
|
236
692
|
}, options);
|
|
237
693
|
}
|
|
238
694
|
//# sourceMappingURL=table.js.map
|