tty-table 4.2.3 → 6.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 +39 -229
- package/adapters/automattic-cli-table.js +1 -1
- package/adapters/default-adapter.js +1 -1
- package/adapters/terminal-adapter.js +3 -2
- package/dist/browser/tty-table.global.js +4411 -0
- package/dist/browser/tty-table.global.js.map +1 -0
- package/dist/browser-BC4npgub.d.mts +128 -0
- package/dist/browser-BC4npgub.d.ts +128 -0
- package/dist/browser.d.mts +1 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +1020 -0
- package/dist/browser.js.map +1 -0
- package/dist/browser.mjs +1016 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1113 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +1118 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1020 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1016 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -59
- package/src/defaults.js +0 -71
- package/src/factory.d.ts +0 -67
- package/src/factory.js +0 -137
- package/src/format.js +0 -282
- package/src/main.js +0 -8
- package/src/render.js +0 -398
- package/src/style.js +0 -58
package/src/format.js
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
const stripAnsi = require("strip-ansi")
|
|
2
|
-
const smartwrap = require("smartwrap")
|
|
3
|
-
const wcwidth = require("wcwidth")
|
|
4
|
-
|
|
5
|
-
const addPadding = (config, width) => {
|
|
6
|
-
return width + config.paddingLeft + config.paddingRight
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Returns the widest cell give a collection of rows
|
|
11
|
-
*
|
|
12
|
-
* @param object columnOptions
|
|
13
|
-
* @param array rows
|
|
14
|
-
* @param integer columnIndex
|
|
15
|
-
* @returns string
|
|
16
|
-
*/
|
|
17
|
-
const getMaxLength = (columnOptions, rows, columnIndex) => {
|
|
18
|
-
let iterable
|
|
19
|
-
|
|
20
|
-
// add header value, alias to calculate width when applicable
|
|
21
|
-
if (columnOptions && (columnOptions.value || columnOptions.alias)) {
|
|
22
|
-
// string we use from header
|
|
23
|
-
let val = columnOptions.alias || columnOptions.value
|
|
24
|
-
val = val.toString()
|
|
25
|
-
// create a row with value in the current columnIndex
|
|
26
|
-
const headerRow = Array(rows[0].length)
|
|
27
|
-
headerRow[columnIndex] = val
|
|
28
|
-
// add header row to new array we will check for max value width
|
|
29
|
-
iterable = rows.slice()
|
|
30
|
-
iterable.push(headerRow)
|
|
31
|
-
} else {
|
|
32
|
-
// no header value, just use rows to derive max width
|
|
33
|
-
iterable = rows
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const widest = iterable.reduce((prev, row) => {
|
|
37
|
-
if (row[columnIndex]) {
|
|
38
|
-
// check cell value is object or scalar
|
|
39
|
-
const value = (row[columnIndex].value) ? row[columnIndex].value : row[columnIndex]
|
|
40
|
-
const width = Math.max(
|
|
41
|
-
...stripAnsi(value.toString()).split(/[\n\r]/).map((s) => wcwidth(s))
|
|
42
|
-
)
|
|
43
|
-
return (width > prev) ? width : prev
|
|
44
|
-
}
|
|
45
|
-
return prev
|
|
46
|
-
}, 0)
|
|
47
|
-
|
|
48
|
-
return widest
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Get total width available to this table instance
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*/
|
|
56
|
-
const getAvailableWidth = config => {
|
|
57
|
-
if (process && ((process.stdout && process.stdout.columns) || (process.env && process.env.COLUMNS))) {
|
|
58
|
-
// forked calls that do not inherit process.stdout must use process.env
|
|
59
|
-
let viewport = (process.stdout && process.stdout.columns) ? process.stdout.columns : process.env.COLUMNS
|
|
60
|
-
viewport = viewport - config.marginLeft
|
|
61
|
-
|
|
62
|
-
// table width percentage of (viewport less margin)
|
|
63
|
-
if (config.width !== "auto" && /^\d+%$/.test(config.width)) {
|
|
64
|
-
return Math.min(1, (config.width.slice(0, -1) * 0.01)) * viewport
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// table width fixed
|
|
68
|
-
if (config.width !== "auto" && /^\d+$/.test(config.width)) {
|
|
69
|
-
config.FIXED_WIDTH = true
|
|
70
|
-
return config.width
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// table width equals viewport less margin
|
|
74
|
-
// @TODO deprecate and remove "auto", which was never documented so should not be
|
|
75
|
-
// an issue
|
|
76
|
-
return viewport
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// browser
|
|
80
|
-
/* istanbul ignore next */
|
|
81
|
-
if (typeof window !== "undefined") return window.innerWidth // eslint-disable-line
|
|
82
|
-
|
|
83
|
-
// process.stdout.columns does not exist. assume redirecting to write stream
|
|
84
|
-
// use 80 columns, which is VT200 standard
|
|
85
|
-
return config.COLUMNS - config.marginLeft
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
module.exports.getStringLength = string => {
|
|
89
|
-
// stripAnsi(string.replace(/[^\x00-\xff]/g,'XX')).length
|
|
90
|
-
return wcwidth(stripAnsi(string))
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
module.exports.wrapCellText = (
|
|
94
|
-
config,
|
|
95
|
-
cellValue,
|
|
96
|
-
columnIndex,
|
|
97
|
-
cellOptions,
|
|
98
|
-
rowType
|
|
99
|
-
) => {
|
|
100
|
-
// ANSI chararacters that demarcate the start/end of a line
|
|
101
|
-
const startAnsiRegexp = /^(\033\[[0-9;]*m)+/
|
|
102
|
-
const endAnsiRegexp = /(\033\[[0-9;]*m)+$/
|
|
103
|
-
|
|
104
|
-
// coerce cell value to string
|
|
105
|
-
let string = cellValue.toString()
|
|
106
|
-
|
|
107
|
-
// store matching ANSI characters
|
|
108
|
-
const startMatches = string.match(startAnsiRegexp) || [""]
|
|
109
|
-
|
|
110
|
-
// remove ANSI start-of-line chars
|
|
111
|
-
string = string.replace(startAnsiRegexp, "")
|
|
112
|
-
|
|
113
|
-
// store matching ANSI characters so can be later re-attached
|
|
114
|
-
const endMatches = string.match(endAnsiRegexp) || [""]
|
|
115
|
-
|
|
116
|
-
// remove ANSI end-of-line chars
|
|
117
|
-
string = string.replace(endAnsiRegexp, "")
|
|
118
|
-
|
|
119
|
-
let alignTgt
|
|
120
|
-
|
|
121
|
-
switch (rowType) {
|
|
122
|
-
case ("header"):
|
|
123
|
-
alignTgt = "headerAlign"
|
|
124
|
-
break
|
|
125
|
-
case ("body"):
|
|
126
|
-
alignTgt = "align"
|
|
127
|
-
break
|
|
128
|
-
default:
|
|
129
|
-
alignTgt = "footerAlign"
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// equalize padding for centered lines
|
|
133
|
-
if (cellOptions[alignTgt] === "center") {
|
|
134
|
-
cellOptions.paddingLeft = cellOptions.paddingRight = Math.max(
|
|
135
|
-
cellOptions.paddingRight,
|
|
136
|
-
cellOptions.paddingLeft,
|
|
137
|
-
0
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const columnWidth = config.table.columnWidths[columnIndex]
|
|
142
|
-
|
|
143
|
-
// innerWidth is the width available for text within the cell
|
|
144
|
-
const innerWidth = columnWidth
|
|
145
|
-
- cellOptions.paddingLeft
|
|
146
|
-
- cellOptions.paddingRight
|
|
147
|
-
- config.GUTTER
|
|
148
|
-
|
|
149
|
-
if (typeof config.truncate === "string") {
|
|
150
|
-
string = exports.truncate(string, cellOptions, innerWidth)
|
|
151
|
-
} else {
|
|
152
|
-
string = exports.wrap(string, cellOptions, innerWidth)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// format each line
|
|
156
|
-
const cell = string.split("\n").map(line => {
|
|
157
|
-
line = line.trim()
|
|
158
|
-
|
|
159
|
-
const lineLength = exports.getStringLength(line)
|
|
160
|
-
|
|
161
|
-
// alignment
|
|
162
|
-
if (lineLength < columnWidth) {
|
|
163
|
-
let emptySpace = columnWidth - lineLength
|
|
164
|
-
|
|
165
|
-
switch (true) {
|
|
166
|
-
case (cellOptions[alignTgt] === "center"):
|
|
167
|
-
emptySpace--
|
|
168
|
-
const padBoth = Math.floor(emptySpace / 2)
|
|
169
|
-
const padRemainder = emptySpace % 2
|
|
170
|
-
line = Array(padBoth + 1).join(" ")
|
|
171
|
-
+ line
|
|
172
|
-
+ Array(padBoth + 1 + padRemainder).join(" ")
|
|
173
|
-
break
|
|
174
|
-
|
|
175
|
-
case (cellOptions[alignTgt] === "right"):
|
|
176
|
-
line = Array(emptySpace - cellOptions.paddingRight).join(" ")
|
|
177
|
-
+ line
|
|
178
|
-
+ Array(cellOptions.paddingRight + 1).join(" ")
|
|
179
|
-
break
|
|
180
|
-
|
|
181
|
-
default:
|
|
182
|
-
line = Array(cellOptions.paddingLeft + 1).join(" ")
|
|
183
|
-
+ line
|
|
184
|
-
+ Array(emptySpace - cellOptions.paddingLeft).join(" ")
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// put ANSI color codes BACK on the beginning and end of string
|
|
189
|
-
return startMatches[0] + line + endMatches[0]
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
return { cell, innerWidth }
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
module.exports.truncate = (string, cellOptions, maxWidth) => {
|
|
196
|
-
const stringWidth = wcwidth(string)
|
|
197
|
-
|
|
198
|
-
if (maxWidth < stringWidth) {
|
|
199
|
-
// @TODO give user option to decide if they want to break words on wrapping
|
|
200
|
-
string = smartwrap(string, {
|
|
201
|
-
width: maxWidth - cellOptions.truncate.length,
|
|
202
|
-
breakword: true
|
|
203
|
-
}).split("\n")[0]
|
|
204
|
-
string = string + cellOptions.truncate
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return string
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
module.exports.wrap = (string, cellOptions, innerWidth) => {
|
|
211
|
-
const outstring = smartwrap(string, {
|
|
212
|
-
errorChar: cellOptions.defaultErrorValue,
|
|
213
|
-
minWidth: 1,
|
|
214
|
-
trim: true,
|
|
215
|
-
width: innerWidth
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
return outstring
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
module.exports.getColumnWidths = (config, rows) => {
|
|
222
|
-
const availableWidth = getAvailableWidth(config)
|
|
223
|
-
|
|
224
|
-
// iterate over the header if we have it, iterate over the first row
|
|
225
|
-
// if we do not (to step through the correct number of columns)
|
|
226
|
-
const iterable = (config.table.header[0] && config.table.header[0].length > 0)
|
|
227
|
-
? config.table.header[0] : rows[0]
|
|
228
|
-
|
|
229
|
-
let widths = iterable.map((column, columnIndex) => {
|
|
230
|
-
let result
|
|
231
|
-
|
|
232
|
-
switch (true) {
|
|
233
|
-
// column width is a percentage of table width specified in column header
|
|
234
|
-
case (typeof column === "object" && (/^\d+%$/.test(column.width))):
|
|
235
|
-
result = (column.width.slice(0, -1) * 0.01) * availableWidth
|
|
236
|
-
result = addPadding(config, result)
|
|
237
|
-
break
|
|
238
|
-
|
|
239
|
-
// column width is specified in column header
|
|
240
|
-
case (typeof column === "object" && (/^\d+$/.test(column.width))):
|
|
241
|
-
result = column.width
|
|
242
|
-
break
|
|
243
|
-
|
|
244
|
-
// 'auto' sets column width to its longest value in the initial data set
|
|
245
|
-
default:
|
|
246
|
-
const columnOptions = (config.table.header[0][columnIndex])
|
|
247
|
-
? config.table.header[0][columnIndex] : {}
|
|
248
|
-
const measurableRows = (rows.length) ? rows : config.table.header[0]
|
|
249
|
-
|
|
250
|
-
result = getMaxLength(columnOptions, measurableRows, columnIndex)
|
|
251
|
-
|
|
252
|
-
// add spaces for padding if not centered
|
|
253
|
-
// @TODO test with if not centered conditional
|
|
254
|
-
result = addPadding(config, result)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// add space for gutter
|
|
258
|
-
result = result + config.GUTTER
|
|
259
|
-
return result
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
// calculate sum of all column widths (including marginLeft)
|
|
263
|
-
const totalWidth = widths.reduce((prev, current) => prev + current)
|
|
264
|
-
|
|
265
|
-
// proportionately resize columns when necessary
|
|
266
|
-
if (totalWidth > availableWidth || config.FIXED_WIDTH) {
|
|
267
|
-
// proportion wont be exact fit, but this method keeps us safe
|
|
268
|
-
const proportion = (availableWidth / totalWidth).toFixed(2) - 0.01
|
|
269
|
-
const relativeWidths = widths.map(value => Math.max(2, Math.floor(proportion * value)))
|
|
270
|
-
if (config.FIXED_WIDTH) return relativeWidths
|
|
271
|
-
|
|
272
|
-
// when proportion < 0 column cant be resized and totalWidth must overflow viewport
|
|
273
|
-
if (proportion > 0) {
|
|
274
|
-
const totalRelativeWidths = relativeWidths.reduce((prev, current) => prev + current)
|
|
275
|
-
widths = (totalRelativeWidths < totalWidth) ? relativeWidths : widths
|
|
276
|
-
}
|
|
277
|
-
} else {
|
|
278
|
-
widths = widths.map(Math.floor)
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return widths
|
|
282
|
-
}
|
package/src/main.js
DELETED
package/src/render.js
DELETED
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
const Style = require("./style.js")
|
|
2
|
-
const Format = require("./format.js")
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Converts arrays of data into arrays of cell strings
|
|
6
|
-
* @param {TtyTable.Config} config
|
|
7
|
-
* @param {Array<Array<string>|object|TtyTable.Formatter>} inputData
|
|
8
|
-
* @returns {Array<string>}
|
|
9
|
-
*/
|
|
10
|
-
module.exports.stringifyData = (config, inputData) => {
|
|
11
|
-
const sections = {
|
|
12
|
-
header: [],
|
|
13
|
-
body: [],
|
|
14
|
-
footer: []
|
|
15
|
-
}
|
|
16
|
-
const marginLeft = Array(config.marginLeft + 1).join(" ")
|
|
17
|
-
const borderStyle = config.borderCharacters[config.borderStyle]
|
|
18
|
-
const borders = []
|
|
19
|
-
|
|
20
|
-
// support backwards compatibility cli-table's multiple constructor geometries
|
|
21
|
-
// @TODO deprecate and support only a single format
|
|
22
|
-
const constructorType = exports.getConstructorGeometry(inputData[0] || [], config)
|
|
23
|
-
const rows = exports.coerceConstructorGeometry(config, inputData, constructorType)
|
|
24
|
-
|
|
25
|
-
// when streaming values to tty-table, we don't want column widths to change
|
|
26
|
-
// from one rows set to the next, so we save the first set of widths and reuse
|
|
27
|
-
if (!global.columnWidths) {
|
|
28
|
-
global.columnWidths = {}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (global.columnWidths[config.tableId]) {
|
|
32
|
-
config.table.columnWidths = global.columnWidths[config.tableId]
|
|
33
|
-
} else {
|
|
34
|
-
global.columnWidths[config.tableId] = config.table.columnWidths = Format.getColumnWidths(config, rows)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// stringify header cells
|
|
38
|
-
// hide header if no column names or if specified in config
|
|
39
|
-
switch (true) {
|
|
40
|
-
case (config.showHeader !== null && !config.showHeader): // explicitly false, hide
|
|
41
|
-
sections.header = []
|
|
42
|
-
break
|
|
43
|
-
|
|
44
|
-
case (config.showHeader === true): // explicitly true, show
|
|
45
|
-
case (!!config.table.header[0].find(obj => obj.value || obj.alias)): // atleast one named column, show header
|
|
46
|
-
sections.header = config.table.header.map(row => {
|
|
47
|
-
return exports.buildRow(config, row, "header", null, rows, inputData)
|
|
48
|
-
})
|
|
49
|
-
break
|
|
50
|
-
|
|
51
|
-
default: // no named columns, hide
|
|
52
|
-
sections.header = []
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// stringify body cells
|
|
56
|
-
sections.body = rows.map((row, rowIndex) => {
|
|
57
|
-
return exports.buildRow(config, row, "body", rowIndex, rows, inputData)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// stringify footer cells
|
|
61
|
-
sections.footer = (config.table.footer instanceof Array && config.table.footer.length > 0) ? [config.table.footer] : []
|
|
62
|
-
|
|
63
|
-
sections.footer = sections.footer.map(row => {
|
|
64
|
-
return exports.buildRow(config, row, "footer", null, rows, inputData)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
// apply borders
|
|
68
|
-
// 0=top, 1=middle, 2=bottom
|
|
69
|
-
for (let a = 0; a < 3; a++) {
|
|
70
|
-
// add left border
|
|
71
|
-
borders[a] = borderStyle[a].l
|
|
72
|
-
|
|
73
|
-
// add joined borders for each column
|
|
74
|
-
config.table.columnWidths.forEach((columnWidth, index, arr) => {
|
|
75
|
-
// Math.max because otherwise columns 1 wide wont have horizontal border
|
|
76
|
-
borders[a] += Array(Math.max(columnWidth, 2)).join(borderStyle[a].h)
|
|
77
|
-
borders[a] += ((index + 1 < arr.length) ? borderStyle[a].j : "")
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
// add right border
|
|
81
|
-
borders[a] += borderStyle[a].r
|
|
82
|
-
|
|
83
|
-
// no trailing space on footer
|
|
84
|
-
borders[a] = (a < 2) ? `${marginLeft + borders[a]}\n` : marginLeft + borders[a]
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// top horizontal border
|
|
88
|
-
let output = borders[0]
|
|
89
|
-
|
|
90
|
-
// for each section (header,body,footer)
|
|
91
|
-
Object.keys(sections).forEach((p, i) => {
|
|
92
|
-
// for each row in the section
|
|
93
|
-
while (sections[p].length) {
|
|
94
|
-
const row = sections[p].shift()
|
|
95
|
-
|
|
96
|
-
// if(row.length === 0) {break}
|
|
97
|
-
|
|
98
|
-
row.forEach(line => {
|
|
99
|
-
// vertical row borders
|
|
100
|
-
output = `${output
|
|
101
|
-
+ marginLeft
|
|
102
|
-
// left vertical border
|
|
103
|
-
+ borderStyle[1].v
|
|
104
|
-
// join cells on vertical border
|
|
105
|
-
+ line.join(borderStyle[1].v)
|
|
106
|
-
// right vertical border
|
|
107
|
-
+ borderStyle[1].v
|
|
108
|
-
// end of line
|
|
109
|
-
}\n`
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
// bottom horizontal row border
|
|
113
|
-
switch (true) {
|
|
114
|
-
// skip if end of body and no footer
|
|
115
|
-
case (sections[p].length === 0
|
|
116
|
-
&& i === 1
|
|
117
|
-
&& sections.footer.length === 0):
|
|
118
|
-
break
|
|
119
|
-
|
|
120
|
-
// skip if end of footer
|
|
121
|
-
case (sections[p].length === 0
|
|
122
|
-
&& i === 2):
|
|
123
|
-
break
|
|
124
|
-
|
|
125
|
-
// skip if compact
|
|
126
|
-
case (config.compact && p === "body" && !row.empty):
|
|
127
|
-
break
|
|
128
|
-
|
|
129
|
-
// skip if border style is "none"
|
|
130
|
-
case (config.borderStyle === "none" && config.compact):
|
|
131
|
-
break
|
|
132
|
-
|
|
133
|
-
default:
|
|
134
|
-
output += borders[1]
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
// bottom horizontal border
|
|
140
|
-
output += borders[2]
|
|
141
|
-
|
|
142
|
-
const finalOutput = Array(config.marginTop + 1).join("\n") + output
|
|
143
|
-
|
|
144
|
-
// record the height of the output
|
|
145
|
-
config.height = finalOutput.split(/\r\n|\r|\n/).length
|
|
146
|
-
|
|
147
|
-
return finalOutput
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
module.exports.buildRow = (config, row, rowType, rowIndex, rowData, inputData) => {
|
|
151
|
-
let minRowHeight = 0
|
|
152
|
-
|
|
153
|
-
// tag row as empty if empty, used for `compact` option
|
|
154
|
-
if (row.length === 0 && config.compact) {
|
|
155
|
-
row.empty = true
|
|
156
|
-
return row
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// force row to have correct number of columns
|
|
160
|
-
const lengthDifference = config.table.columnWidths.length - row.length
|
|
161
|
-
if (lengthDifference > 0) {
|
|
162
|
-
// array (row) lacks elements, add until equal
|
|
163
|
-
row = row.concat(Array.apply(null, new Array(lengthDifference)).map(() => null))
|
|
164
|
-
} else if (lengthDifference < 0) {
|
|
165
|
-
// array (row) has too many elements, remove until equal
|
|
166
|
-
row.length = config.table.columnWidths.length
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// convert each element in row to cell format
|
|
170
|
-
row = row.map((elem, elemIndex) => {
|
|
171
|
-
const cell = exports.buildCell(config, elem, elemIndex, rowType, rowIndex, rowData, inputData)
|
|
172
|
-
minRowHeight = (minRowHeight < cell.length) ? cell.length : minRowHeight
|
|
173
|
-
return cell
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
// apply top and bottom padding to row
|
|
177
|
-
minRowHeight = (rowType === "header") ? minRowHeight
|
|
178
|
-
: minRowHeight + (config.paddingBottom + config.paddingTop)
|
|
179
|
-
|
|
180
|
-
const linedRow = Array.apply(null, { length: minRowHeight })
|
|
181
|
-
.map(Function.call, () => [])
|
|
182
|
-
|
|
183
|
-
row.forEach(function (cell, a) {
|
|
184
|
-
const whitespace = Array(config.table.columnWidths[a]).join(" ")
|
|
185
|
-
|
|
186
|
-
if (rowType === "body") {
|
|
187
|
-
// add whitespace for top padding
|
|
188
|
-
for (let i = 0; i < config.paddingTop; i++) {
|
|
189
|
-
cell.unshift(whitespace)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// add whitespace for bottom padding
|
|
193
|
-
for (let i = 0; i < config.paddingBottom; i++) {
|
|
194
|
-
cell.push(whitespace)
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// a `row` is divided by columns (horizontally)
|
|
199
|
-
// a `linedRow` becomes the row divided instead into an array of vertical lines
|
|
200
|
-
// each nested line divided by columns
|
|
201
|
-
for (let i = 0; i < minRowHeight; i++) {
|
|
202
|
-
linedRow[i].push((typeof cell[i] !== "undefined")
|
|
203
|
-
? cell[i] : whitespace)
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
return linedRow
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
module.exports.buildCell = (config, elem, columnIndex, rowType, rowIndex, rowData, inputData) => {
|
|
211
|
-
let cellValue = null
|
|
212
|
-
|
|
213
|
-
const cellOptions = Object.assign(
|
|
214
|
-
{ reset: false },
|
|
215
|
-
config,
|
|
216
|
-
(rowType === "body") ? config.columnSettings[columnIndex] : {}, // ignore columnSettings for footer
|
|
217
|
-
(typeof elem === "object") ? elem : {}
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
if (rowType === "header") {
|
|
221
|
-
config.table.columns.push(cellOptions)
|
|
222
|
-
cellValue = cellOptions.alias || cellOptions.value || ""
|
|
223
|
-
} else {
|
|
224
|
-
// set cellValue
|
|
225
|
-
switch (true) {
|
|
226
|
-
case (typeof elem === "undefined" || elem === null):
|
|
227
|
-
// replace undefined/null elem values with placeholder
|
|
228
|
-
cellValue = (config.errorOnNull) ? config.defaultErrorValue : config.defaultValue
|
|
229
|
-
// @TODO add to elem defaults
|
|
230
|
-
cellOptions.isNull = true
|
|
231
|
-
break
|
|
232
|
-
|
|
233
|
-
case (typeof elem === "object" && elem !== null && typeof elem.value !== "undefined"):
|
|
234
|
-
cellValue = elem.value
|
|
235
|
-
break
|
|
236
|
-
|
|
237
|
-
case (typeof elem === "function"):
|
|
238
|
-
cellValue = elem.bind({
|
|
239
|
-
configure: function (object) {
|
|
240
|
-
return Object.assign(cellOptions, object)
|
|
241
|
-
},
|
|
242
|
-
style: Style.style,
|
|
243
|
-
resetStyle: Style.resetStyle
|
|
244
|
-
})(
|
|
245
|
-
(!cellOptions.isNull) ? cellValue : "",
|
|
246
|
-
columnIndex,
|
|
247
|
-
rowIndex,
|
|
248
|
-
rowData,
|
|
249
|
-
inputData
|
|
250
|
-
)
|
|
251
|
-
break
|
|
252
|
-
|
|
253
|
-
default:
|
|
254
|
-
// elem is assumed to be a scalar
|
|
255
|
-
cellValue = elem
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// run formatter
|
|
259
|
-
if (typeof cellOptions.formatter === "function") {
|
|
260
|
-
cellValue = cellOptions.formatter
|
|
261
|
-
.bind({
|
|
262
|
-
configure: function (object) {
|
|
263
|
-
return Object.assign(cellOptions, object)
|
|
264
|
-
},
|
|
265
|
-
style: Style.style,
|
|
266
|
-
resetStyle: Style.resetStyle
|
|
267
|
-
})(
|
|
268
|
-
(!cellOptions.isNull) ? cellValue : "",
|
|
269
|
-
columnIndex,
|
|
270
|
-
rowIndex,
|
|
271
|
-
rowData,
|
|
272
|
-
inputData
|
|
273
|
-
)
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// colorize cellValue
|
|
278
|
-
// we don't want the formatter to pass a styled cell value with ANSI codes
|
|
279
|
-
// (in case user wants to do math or string operations to cell value), so
|
|
280
|
-
// we apply default styles to the cell after it runs through the formatter
|
|
281
|
-
// and omit those default styles if the user applied `this.resetStyle`
|
|
282
|
-
if (!cellOptions.reset) {
|
|
283
|
-
cellValue = Style.colorizeCell(cellValue, cellOptions, rowType)
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// textwrap cellValue
|
|
287
|
-
const { cell, innerWidth } = Format.wrapCellText(cellOptions, cellValue, columnIndex, cellOptions, rowType)
|
|
288
|
-
|
|
289
|
-
if (rowType === "header") {
|
|
290
|
-
config.table.columnInnerWidths.push(innerWidth)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return cell
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Check for a backwards compatible (cli-table) constructor
|
|
298
|
-
*/
|
|
299
|
-
module.exports.getConstructorGeometry = (row, config) => {
|
|
300
|
-
let type
|
|
301
|
-
|
|
302
|
-
// rows passed as an object
|
|
303
|
-
if (typeof row === "object" && !(row instanceof Array)) {
|
|
304
|
-
const keys = Object.keys(row)
|
|
305
|
-
|
|
306
|
-
if (config.adapter === "automattic") {
|
|
307
|
-
// detected cross table
|
|
308
|
-
const key = keys[0]
|
|
309
|
-
|
|
310
|
-
if (row[key] instanceof Array) {
|
|
311
|
-
type = "automattic-cross"
|
|
312
|
-
} else {
|
|
313
|
-
// detected vertical table
|
|
314
|
-
type = "automattic-vertical"
|
|
315
|
-
}
|
|
316
|
-
} else {
|
|
317
|
-
// detected horizontal table
|
|
318
|
-
type = "o-horizontal"
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
// rows passed as an array
|
|
322
|
-
type = "a-horizontal"
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return type
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Coerce backwards compatible constructor styles
|
|
330
|
-
*/
|
|
331
|
-
module.exports.coerceConstructorGeometry = (config, rows, constructorType) => {
|
|
332
|
-
let output = []
|
|
333
|
-
switch (constructorType) {
|
|
334
|
-
case ("automattic-cross"):
|
|
335
|
-
// assign header styles to first column
|
|
336
|
-
config.columnSettings[0] = config.columnSettings[0] || {}
|
|
337
|
-
config.columnSettings[0].color = config.headerColor
|
|
338
|
-
|
|
339
|
-
output = rows.map(obj => {
|
|
340
|
-
const arr = []
|
|
341
|
-
const key = Object.keys(obj)[0]
|
|
342
|
-
arr.push(key)
|
|
343
|
-
return arr.concat(obj[key])
|
|
344
|
-
})
|
|
345
|
-
break
|
|
346
|
-
|
|
347
|
-
case ("automattic-vertical"):
|
|
348
|
-
// assign header styles to first column
|
|
349
|
-
config.columnSettings[0] = config.columnSettings[0] || {}
|
|
350
|
-
config.columnSettings[0].color = config.headerColor
|
|
351
|
-
|
|
352
|
-
output = rows.map(function (value) {
|
|
353
|
-
const key = Object.keys(value)[0]
|
|
354
|
-
return [key, value[key]]
|
|
355
|
-
})
|
|
356
|
-
break
|
|
357
|
-
|
|
358
|
-
case ("o-horizontal"):
|
|
359
|
-
// cell property names are specified in header columns
|
|
360
|
-
if (config.table.header[0].length
|
|
361
|
-
&& config.table.header[0].every(obj => obj.value)) {
|
|
362
|
-
output = rows.map(row => config.table.header[0]
|
|
363
|
-
.map(obj => row[obj.value]))
|
|
364
|
-
} // eslint-disable-line brace-style
|
|
365
|
-
// no property names given, default to object property order
|
|
366
|
-
else {
|
|
367
|
-
output = rows.map(obj => Object.values(obj))
|
|
368
|
-
}
|
|
369
|
-
break
|
|
370
|
-
|
|
371
|
-
case ("a-horizontal"):
|
|
372
|
-
output = rows
|
|
373
|
-
break
|
|
374
|
-
|
|
375
|
-
default:
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
return output
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// @TODO For rotating horizontal data into a vertical table
|
|
382
|
-
// assumes all rows are same length
|
|
383
|
-
// module.exports.verticalizeMatrix = (config, inputArray) => {
|
|
384
|
-
//
|
|
385
|
-
// // grow to # arrays equal to number of columns in input array
|
|
386
|
-
// let outputArray = []
|
|
387
|
-
// let headers = config.table.columns
|
|
388
|
-
//
|
|
389
|
-
// // create a row for each heading, and prepend the row
|
|
390
|
-
// // with the heading name
|
|
391
|
-
// headers.forEach(name => outputArray.push([name]))
|
|
392
|
-
//
|
|
393
|
-
// inputArray.forEach(row => {
|
|
394
|
-
// row.forEach((element, index) => outputArray[index].push(element))
|
|
395
|
-
// })
|
|
396
|
-
//
|
|
397
|
-
// return outputArray
|
|
398
|
-
// }
|