Comparing version 2.8.9 to 2.8.10
@@ -8,5 +8,5 @@ var Factory = require("../src/factory.js") | ||
//translations | ||
// translations | ||
//header | ||
// header | ||
var header = [] | ||
@@ -21,3 +21,3 @@ if(options.head && options.head instanceof Array) { | ||
//colWidths | ||
// colWidths | ||
if(options.colWidths) { | ||
@@ -29,3 +29,3 @@ options.colWidths.forEach(function(val, i) { | ||
//colAligns | ||
// colAligns | ||
if(options.colAligns) { | ||
@@ -38,6 +38,6 @@ options.colAligns.forEach(function(val, i) { | ||
//style | ||
// style | ||
options.style = options.style || {} | ||
//style - padding | ||
// style - padding | ||
if(options.style["padding-left"]) { | ||
@@ -51,3 +51,3 @@ options.paddingLeft = options.style["padding-left"] | ||
//style - colors | ||
// style - colors | ||
if(options.style.head && options.style.head instanceof Array) { | ||
@@ -61,3 +61,3 @@ options.headerColor = options.style.head[0] | ||
//style - compact | ||
// style - compact | ||
if(options.style.compact) { | ||
@@ -67,5 +67,5 @@ options.compact = true | ||
//@todo style - border color | ||
// @todo style - border color | ||
//inherited from prototype | ||
// inherited from prototype | ||
let t = Factory(header, [], [], options) | ||
@@ -72,0 +72,0 @@ t.toString = t.render |
#!/usr/bin/env node | ||
const path = require("path") | ||
const fs = require("fs") | ||
const Csv = require("csv") | ||
const Chalk = require("chalk") | ||
let Yargs = require("yargs") | ||
const csv = require("csv") | ||
const chalk = require("chalk") | ||
let yargs = require("yargs") | ||
Yargs.epilog("Copyright github.com/tecfu 2018") | ||
yargs.epilog("Copyright github.com/tecfu 2018") | ||
Yargs.option("config", { | ||
yargs.option("config", { | ||
describe: "Specify the configuration for your table." | ||
}) | ||
Yargs.option("csv-delimiter", { | ||
yargs.option("csv-delimiter", { | ||
describe: "Set the field delimiter. One character only.", | ||
@@ -19,7 +19,7 @@ default: "," | ||
Yargs.option("csv-escape", { | ||
yargs.option("csv-escape", { | ||
describe: "Set the escape character. One character only." | ||
}) | ||
Yargs.option("csv-rowDelimiter", { | ||
yargs.option("csv-rowDelimiter", { | ||
describe: "String used to delimit record rows. You can also use a special constant: \"auto\",\"unix\",\"max\",\"windows\",\"unicode\".", | ||
@@ -29,3 +29,3 @@ default: "\n" | ||
Yargs.option("format", { | ||
yargs.option("format", { | ||
describe: "Set input data format", | ||
@@ -36,15 +36,15 @@ choices: ["json", "csv"], | ||
Yargs.option("options\u2010\u002A", { | ||
yargs.option("options\u2010\u002A", { | ||
describe: "Specify an optional setting where * is the setting name. See README.md for a complete list." | ||
}) | ||
//run help only at the end | ||
Yargs = Yargs.help("h").argv | ||
// run help only at the end | ||
yargs = yargs.help("h").argv | ||
let emitError = function(type, detail) { | ||
console.log(`\n${ Chalk.bgRed.white(type) }\n\n${ Chalk.bold(detail)}`) | ||
console.log(`\n${ chalk.bgRed.white(type) }\n\n${ chalk.bold(detail)}`) | ||
process.exit(1) | ||
} | ||
//note that this is the first run | ||
// note that this is the first run | ||
let alreadyRendered = false | ||
@@ -55,5 +55,5 @@ let previousHeight = 0 | ||
switch(true) { | ||
case(typeof Yargs.format === "undefined"): | ||
case(typeof yargs.format === "undefined"): | ||
break | ||
case(Yargs.format.toString().match(/json/i) !== null): | ||
case(yargs.format.toString().match(/json/i) !== null): | ||
dataFormat = "json" | ||
@@ -64,28 +64,28 @@ break | ||
//look for individually flagged options-* | ||
// look for individually flagged options-* | ||
let options = {} | ||
Object.keys(Yargs).forEach(function(key) { | ||
Object.keys(yargs).forEach(function(key) { | ||
let keyParts = key.split("-") | ||
if(keyParts[0]==="options") { | ||
options[keyParts[1]]=Yargs[key] | ||
options[keyParts[1]]=yargs[key] | ||
} | ||
}) | ||
//look for options passed via config file | ||
// look for options passed via config file | ||
let header = [] | ||
if(Yargs.header) { | ||
if(!fs.existsSync(path.resolve(Yargs.header))) { | ||
if(yargs.header) { | ||
if(!fs.existsSync(path.resolve(yargs.header))) { | ||
emitError( | ||
"Invalid file path", | ||
`Cannot find config file at: ${ Yargs.header }.` | ||
`Cannot find config file at: ${ yargs.header }.` | ||
) | ||
} | ||
//merge with any individually flagged options | ||
header = require(path.resolve(Yargs.header)) | ||
// merge with any individually flagged options | ||
header = require(path.resolve(yargs.header)) | ||
} | ||
//because different dataFormats | ||
// because different dataFormats | ||
let runTable = function(header, body) { | ||
//footer = [], | ||
// footer = [], | ||
let Table = require("../src/factory.js") | ||
@@ -95,13 +95,13 @@ options.terminalAdapter = true | ||
//hide cursor | ||
// hide cursor | ||
console.log("\u001b[?25l") | ||
//wipe existing if already rendered | ||
// wipe existing if already rendered | ||
if(alreadyRendered) { | ||
//move cursor up number to the top of the previous print | ||
//before deleting | ||
// move cursor up number to the top of the previous print | ||
// before deleting | ||
console.log(`\u001b[${previousHeight+3}A`) | ||
//delete to end of terminal | ||
// delete to end of terminal | ||
console.log("\u001b[0J") | ||
@@ -114,4 +114,4 @@ } else{ | ||
//reset the previous height to the height of this output | ||
//for when we next clear the print | ||
// reset the previous height to the height of this output | ||
// for when we next clear the print | ||
previousHeight = t1.height | ||
@@ -125,3 +125,3 @@ | ||
//handle dataFormats | ||
// handle dataFormats | ||
switch(true) { | ||
@@ -142,10 +142,10 @@ case(dataFormat==="json"): | ||
let formatterOptions = {} | ||
Object.keys(Yargs).forEach(function(key) { | ||
if(key.slice(0, 4) === "csv-" && typeof(Yargs[key]) !== "undefined") { | ||
formatterOptions[key.slice(4)] = Yargs[key] | ||
Object.keys(yargs).forEach(function(key) { | ||
if(key.slice(0, 4) === "csv-" && typeof(yargs[key]) !== "undefined") { | ||
formatterOptions[key.slice(4)] = yargs[key] | ||
} | ||
}) | ||
Csv.parse(chunk, formatterOptions, function(err, data) { | ||
//validate csv | ||
csv.parse(chunk, formatterOptions, function(err, data) { | ||
// validate csv | ||
if(typeof data === "undefined") { | ||
@@ -176,3 +176,3 @@ emitError( | ||
process.on("SIGINT", function () { | ||
//graceful shutdown | ||
// graceful shutdown | ||
process.exit() | ||
@@ -182,4 +182,4 @@ }) | ||
process.on("exit", function() { | ||
//show cursor | ||
// show cursor | ||
console.log("\u001b[?25h") | ||
}) |
{ | ||
"name": "tty-table", | ||
"version": "2.8.9", | ||
"version": "2.8.10", | ||
"description": "Node cli table", | ||
@@ -54,3 +54,3 @@ "main": "src/main.js", | ||
"csv": "^5.3.1", | ||
"smartwrap": "^1.2.2", | ||
"smartwrap": "^1.2.3", | ||
"strip-ansi": "^6.0.0", | ||
@@ -69,3 +69,3 @@ "wcwidth": "^1.0.1", | ||
"doctoc": "^1.4.0", | ||
"eslint": "^6.6.0", | ||
"eslint": "^6.8.0", | ||
"glob": "^7.1.4", | ||
@@ -72,0 +72,0 @@ "grunt": "^1.0.4", |
@@ -30,3 +30,3 @@ const defaults = { | ||
defaultErrorValue: "�", | ||
//defaultValue: "\u001b[31m?\u001b[39m", | ||
// defaultValue: "\u001b[31m?\u001b[39m", | ||
defaultValue: "[32m[37m[41m ?[49m[32m[39m", | ||
@@ -48,6 +48,6 @@ errorOnNull: false, | ||
width: "auto", | ||
GUTTER: 1, //undocumented | ||
GUTTER: 1, // undocumented | ||
columnSettings: [], | ||
headerEmpty: false, | ||
//save so cell options can be merged into column options | ||
// save so cell options can be merged into column options | ||
table: { | ||
@@ -59,8 +59,9 @@ body: "", | ||
footer: "", | ||
header: "", //post-rendered strings. | ||
header: "", // post-rendered strings. | ||
height: 0, | ||
typeLocked: false //once a table type is selected can't switch | ||
typeLocked: false // once a table type is selected can't switch | ||
} | ||
} | ||
// support deprecated border style values | ||
@@ -71,2 +72,3 @@ defaults.borderCharacters["0"] = defaults.borderCharacters["none"] | ||
module.exports = defaults |
@@ -1,6 +0,7 @@ | ||
const Defaults = require("./defaults.js") | ||
const Render = require("./render.js") | ||
const Chalk = require("chalk") | ||
let Counter = 0 | ||
const defaults = require("./defaults.js") | ||
const render = require("./render.js") | ||
const chalk = require("chalk") | ||
let counter = 0 | ||
/** | ||
@@ -34,3 +35,3 @@ * @class Table | ||
* Removes horizontal lines when true. | ||
* @param {mixed} options.defaultErrorValue - default: 'ERROR!' | ||
* @param {mixed} options.defaultErrorValue - default: '�' | ||
* @param {mixed} options.defaultValue - default: '?' | ||
@@ -66,9 +67,9 @@ * @param {boolean} options.errorOnNull - default: false | ||
//handle different parameter scenarios | ||
// handle different parameter scenarios | ||
switch(true) { | ||
//header, rows, footer, and options | ||
// header, rows, footer, and options | ||
case(paramsArr.length === 4): | ||
header = paramsArr[0] | ||
body.push(...paramsArr[1]) //creates new array to store our rows (body) | ||
body.push(...paramsArr[1]) // creates new array to store our rows (body) | ||
footer = paramsArr[2] | ||
@@ -78,29 +79,29 @@ options = paramsArr[3] | ||
//header, rows, footer | ||
// header, rows, footer | ||
case(paramsArr.length === 3 && paramsArr[2] instanceof Array): | ||
header = paramsArr[0] | ||
body.push(...paramsArr[1]) //creates new array to store our rows | ||
body.push(...paramsArr[1]) // creates new array to store our rows | ||
footer = paramsArr[2] | ||
break | ||
//header, rows, options | ||
// header, rows, options | ||
case(paramsArr.length === 3 && typeof paramsArr[2] === "object"): | ||
header = paramsArr[0] | ||
body.push(...paramsArr[1]) //creates new array to store our rows | ||
body.push(...paramsArr[1]) // creates new array to store our rows | ||
options = paramsArr[2] | ||
break | ||
//header, rows (rows, footer is not an option) | ||
// header, rows (rows, footer is not an option) | ||
case(paramsArr.length === 2 && paramsArr[1] instanceof Array): | ||
header = paramsArr[0] | ||
body.push(...paramsArr[1]) //creates new array to store our rows | ||
body.push(...paramsArr[1]) // creates new array to store our rows | ||
break | ||
//rows, options | ||
// rows, options | ||
case(paramsArr.length === 2 && typeof paramsArr[1] === "object"): | ||
body.push(...paramsArr[0]) //creates new array to store our rows | ||
body.push(...paramsArr[0]) // creates new array to store our rows | ||
options = paramsArr[1] | ||
break | ||
//rows | ||
// rows | ||
case(paramsArr.length === 1 && paramsArr[0] instanceof Array): | ||
@@ -110,3 +111,3 @@ body.push(...paramsArr[0]) | ||
//adapter called i.e. require('tty-table')('automattic-cli') | ||
// adapter called: i.e. `require('tty-table')('automattic-cli')` | ||
case(paramsArr.length === 1 && typeof paramsArr[0] === "string"): | ||
@@ -121,14 +122,13 @@ return require(`../adapters/${ paramsArr[0]}`) | ||
// For "deep" copy, use JSON.parse | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Deep_Clone | ||
const clonedDefaults = JSON.parse(JSON.stringify(Defaults)) | ||
let config = Object.assign({}, clonedDefaults, options) | ||
const cloneddefaults = JSON.parse(JSON.stringify(defaults)) | ||
let config = Object.assign({}, cloneddefaults, options) | ||
//backfixes for shortened option names | ||
// backfixes for shortened option names | ||
config.align = config.alignment || config.align | ||
config.headerAlign = config.headerAlignment || config.headerAlign | ||
//for truncate true is equivalent to empty string | ||
// for truncate true is equivalent to empty string | ||
if(config.truncate === true) config.truncate = "" | ||
//if borderColor customized, color the border character set | ||
// if borderColor customized, color the border character set | ||
if(config.borderColor) { | ||
@@ -138,3 +138,3 @@ config.borderCharacters[config.borderStyle] = | ||
Object.keys(obj).forEach(function(key) { | ||
obj[key] = Chalk[config.borderColor](obj[key]) | ||
obj[key] = chalk[config.borderColor](obj[key]) | ||
}) | ||
@@ -145,26 +145,26 @@ return obj | ||
//save a copy for merging columnSettings into cell options | ||
// save a copy for merging columnSettings into cell options | ||
config.columnSettings = header.slice(0) | ||
//header | ||
// header | ||
config.table.header = header | ||
config.headerEmpty = (header.length === 0) ? true : false | ||
//match header geometry with body array | ||
// match header geometry with body array | ||
config.table.header = [config.table.header] | ||
//footer | ||
// footer | ||
config.table.footer = footer | ||
//counting table enables fixed column widths for streams, | ||
//variable widths for multiple tables simulateously | ||
// counting table enables fixed column widths for streams, | ||
// variable widths for multiple tables simulateously | ||
if(config.terminalAdapter !== true) { | ||
Counter++ //fix columnwidths for streams | ||
counter++ // fix columnwidths for streams | ||
} | ||
config.tableId = Counter | ||
config.tableId = counter | ||
//create a new object with an Array prototype | ||
// create a new object with an Array prototype | ||
let tableObject = Object.create(body) | ||
//save configuration to new object | ||
// save configuration to new object | ||
tableObject[_configKey] = config | ||
@@ -183,5 +183,3 @@ | ||
tableObject.render = function() { | ||
//let configCopy = JSON.parse(JSON.stringify(this[_configKey])); | ||
//return Render.stringifyData(configCopy,this.slice(0)); //get string output | ||
let output = Render.stringifyData(this[_configKey], this.slice(0)) //get string output | ||
let output = render.stringifyData(this[_configKey], this.slice(0)) // get string output | ||
tableObject.height = this[_configKey].height | ||
@@ -194,4 +192,5 @@ return output | ||
module.exports = function() { | ||
return new Factory(arguments) | ||
} |
@@ -1,12 +0,13 @@ | ||
const StripAnsi = require("strip-ansi") | ||
const Smartwrap = require("smartwrap") | ||
const Wcwidth = require("wcwidth") | ||
const Format = {} | ||
const stripAnsi = require("strip-ansi") | ||
const smartwrap = require("smartwrap") | ||
const wcwidth = require("wcwidth") | ||
Format.calculateLength = line => { | ||
//return StripAnsi(line.replace(/[^\x00-\xff]/g,'XX')).length; | ||
return Wcwidth(StripAnsi(line)) | ||
module.exports.calculateLength = line => { | ||
// return stripAnsi(line.replace(/[^\x00-\xff]/g,'XX')).length | ||
return wcwidth(stripAnsi(line)) | ||
} | ||
Format.wrapCellContent = ( | ||
module.exports.wrapCellContent = ( | ||
config, | ||
@@ -19,19 +20,19 @@ cellValue, | ||
//ANSI chararacters that demarcate the start/end of a line | ||
// ANSI chararacters that demarcate the start/end of a line | ||
const startAnsiRegexp = /^(\033\[[0-9;]*m)+/ | ||
const endAnsiRegexp = /(\033\[[0-9;]*m)+$/ | ||
//coerce cell value to string | ||
// coerce cell value to string | ||
let string = cellValue.toString() | ||
//store matching ANSI characters | ||
// store matching ANSI characters | ||
let startMatches = string.match(startAnsiRegexp) || [""] | ||
//remove ANSI start-of-line chars | ||
// remove ANSI start-of-line chars | ||
string = string.replace(startAnsiRegexp, "") | ||
//store matching ANSI characters so can be later re-attached | ||
// store matching ANSI characters so can be later re-attached | ||
let endMatches = string.match(endAnsiRegexp) || [""] | ||
//remove ANSI end-of-line chars | ||
// remove ANSI end-of-line chars | ||
string = string.replace(endAnsiRegexp, "") | ||
@@ -50,9 +51,11 @@ | ||
alignTgt = "footerAlign" | ||
break | ||
} | ||
//equalize padding for centered lines | ||
// equalize padding for centered lines | ||
if(cellOptions[alignTgt] === "center") { | ||
cellOptions.paddingLeft = cellOptions.paddingRight = | ||
Math.max(cellOptions.paddingRight, cellOptions.paddingLeft, 0) | ||
cellOptions.paddingLeft = cellOptions.paddingRight = Math.max( | ||
cellOptions.paddingRight, | ||
cellOptions.paddingLeft, | ||
0 | ||
) | ||
} | ||
@@ -62,21 +65,24 @@ | ||
//innerWidth is the width available for text within the cell | ||
const innerWidth = columnWidth -cellOptions.paddingLeft -cellOptions.paddingRight -config.GUTTER | ||
// innerWidth is the width available for text within the cell | ||
const innerWidth = columnWidth | ||
- cellOptions.paddingLeft | ||
- cellOptions.paddingRight | ||
- config.GUTTER | ||
if(typeof config.truncate === "string") { | ||
string = Format.truncate(string, cellOptions, innerWidth) | ||
string = exports.truncate(string, cellOptions, innerWidth) | ||
} else { | ||
string = Format.wrap(string, cellOptions, innerWidth) | ||
string = exports.wrap(string, cellOptions, innerWidth) | ||
} | ||
//format each line | ||
// format each line | ||
let strArr = string.split("\n").map( line => { | ||
line = line.trim() | ||
const lineLength = Format.calculateLength(line) | ||
const lineLength = exports.calculateLength(line) | ||
//alignment | ||
// alignment | ||
if(lineLength < columnWidth) { | ||
let emptySpace = columnWidth - lineLength | ||
switch(true) { | ||
@@ -91,2 +97,3 @@ case(cellOptions[alignTgt] === "center"): | ||
break | ||
case(cellOptions[alignTgt] === "right"): | ||
@@ -97,2 +104,3 @@ line = Array(emptySpace - cellOptions.paddingRight).join(" ") | ||
break | ||
default: | ||
@@ -105,3 +113,3 @@ line = Array(cellOptions.paddingLeft + 1).join(" ") | ||
//put ANSI color codes BACK on the beginning and end of string | ||
// put ANSI color codes BACK on the beginning and end of string | ||
return startMatches[0] + line + endMatches[0] | ||
@@ -116,8 +124,10 @@ }) | ||
Format.truncate = (string, cellOptions, maxWidth) => { | ||
const stringWidth = Wcwidth(string) | ||
module.exports.truncate = (string, cellOptions, maxWidth) => { | ||
const stringWidth = wcwidth(string) | ||
if(maxWidth < stringWidth) { | ||
string = Smartwrap(string, { | ||
// @todo give use option to decide if they want to break words on wrapping | ||
string = smartwrap(string, { | ||
width: maxWidth - cellOptions.truncate.length, | ||
//@todo give use option to decide if they want to break words on wrapping | ||
breakword: true | ||
@@ -127,7 +137,9 @@ }).split("\n")[0] | ||
} | ||
return string | ||
} | ||
Format.wrap = (string, cellOptions, innerWidth) => { | ||
let outstring = Smartwrap(string, { | ||
module.exports.wrap = (string, cellOptions, innerWidth) => { | ||
let outstring = smartwrap(string, { | ||
errorChar: cellOptions.defaultErrorValue, | ||
@@ -137,4 +149,2 @@ minWidth: 1, | ||
width: innerWidth | ||
//indent : '', | ||
//cut : true | ||
}) | ||
@@ -145,2 +155,3 @@ | ||
/** | ||
@@ -153,57 +164,61 @@ * Returns the widest cell give a collection of rows | ||
*/ | ||
Format.inferColumnWidth = (columnOptions, rows, columnIndex) => { | ||
module.exports.inferColumnWidth = (columnOptions, rows, columnIndex) => { | ||
let iterable | ||
let widest = 0 | ||
//add a row that contains the header value, so we use that width too | ||
// add a row that contains the header value, so we use that width too | ||
if(typeof columnOptions === "object" && columnOptions.value) { | ||
iterable = rows.slice() | ||
let z = new Array(iterable[0].length) //create a new empty row | ||
let z = new Array(iterable[0].length) // create a new empty row | ||
z[columnIndex] = columnOptions.value.toString() | ||
iterable.push(z) | ||
} else{ | ||
//no header value, just use rows to derive max width | ||
} else { | ||
// no header value, just use rows to derive max width | ||
iterable = rows | ||
} | ||
let widest = 0 | ||
iterable.forEach( row => { | ||
if(row[columnIndex] && row[columnIndex].toString().length > widest) { | ||
//widest = row[columnIndex].toString().length; | ||
widest = Wcwidth(row[columnIndex].toString()) | ||
widest = wcwidth(row[columnIndex].toString()) | ||
} | ||
}) | ||
return widest | ||
} | ||
Format.getColumnWidths = (config, rows) => { | ||
//iterate over the header if we have it, iterate over the first row | ||
//if we do not (to step through the correct number of columns) | ||
module.exports.getColumnWidths = (config, rows) => { | ||
// iterate over the header if we have it, iterate over the first row | ||
// if we do not (to step through the correct number of columns) | ||
let iterable = (config.table.header[0] && config.table.header[0].length > 0) | ||
? config.table.header[0] : rows[0] | ||
let widths = iterable.map((column, columnIndex) => { //iterate through column settings | ||
let widths = iterable.map((column, columnIndex) => { | ||
let result | ||
switch(true) { | ||
//column width specified in header | ||
// column width specified in header | ||
case(typeof column === "object" && typeof column.width === "number"): | ||
result = column.width | ||
break | ||
//global column width set in config | ||
// global column width set in config | ||
case(config.width && config.width !== "auto"): | ||
result = config.width | ||
break | ||
default: | ||
//'auto' sets column width to longest value in initial data set | ||
// 'auto' sets column width to longest value in initial data set | ||
let columnOptions = (config.table.header[0][columnIndex]) | ||
? config.table.header[0][columnIndex] : {} | ||
let measurableRows = (rows.length) ? rows : config.table.header[0] | ||
result = Format.inferColumnWidth(columnOptions, measurableRows, columnIndex) | ||
result = exports.inferColumnWidth(columnOptions, measurableRows, columnIndex) | ||
//add spaces for padding if not centered | ||
// add spaces for padding if not centered | ||
result = result + config.paddingLeft + config.paddingRight | ||
} | ||
//add space for gutter | ||
// add space for gutter | ||
result = result + config.GUTTER | ||
@@ -214,21 +229,16 @@ | ||
//calculate sum of all column widths (including marginLeft) | ||
let totalWidth = widths.reduce((prev, curr) => { | ||
return prev + curr | ||
}) | ||
// calculate sum of all column widths (including marginLeft) | ||
let totalWidth = widths.reduce((prev, curr) => prev + curr) | ||
//if sum of all widths exceeds viewport, resize proportionately to fit | ||
// if sum of all widths exceeds viewport, resize proportionately to fit | ||
if(process && process.stdout && totalWidth > process.stdout.columns) { | ||
//recalculate proportionately to fit size | ||
// recalculate proportionately to fit | ||
let prop = (process.stdout.columns - config.marginLeft) / totalWidth | ||
prop = prop.toFixed(2)-0.01 | ||
prop = prop.toFixed(2) - 0.01 | ||
// when process.stdout.columns is 0, width will be negative | ||
if (prop > 0) { | ||
widths = widths.map(value => { | ||
return Math.floor(prop*value) | ||
}) | ||
widths = widths.map(value => Math.floor(prop * value)) | ||
} | ||
} | ||
@@ -238,3 +248,1 @@ | ||
} | ||
module.exports = Format |
if(require.main === module) { | ||
//called directly in terminal | ||
// called directly in terminal | ||
/* istanbul ignore next */ | ||
require("./../adapters/terminal-adapter.js") | ||
} else { | ||
//called as a module | ||
// called as a module | ||
module.exports = require("./../adapters/default-adapter.js") | ||
} |
const Style = require("./style.js") | ||
const Format = require("./format.js") | ||
const Render = {} | ||
/** | ||
* Converts arrays of data into arrays of cell strings | ||
*/ | ||
Render.stringifyData = function(config, inputData) { | ||
module.exports.stringifyData = (config, inputData) => { | ||
const sections = { | ||
@@ -18,11 +18,11 @@ header: [], | ||
//because automattic/cli-table syntax infers table type based on | ||
//how rows are passed (array of arrays, objects, etc) | ||
config.rowFormat = Render.getRowFormat(inputData[0] || [], config) | ||
// because automattic/cli-table syntax infers table type based on | ||
// how rows are passed (array of arrays, objects, etc) | ||
config.rowFormat = exports.getRowFormat(inputData[0] || [], config) | ||
//now translate them | ||
const rowData = Render.transformRows(config, inputData) | ||
// now translate them | ||
const rowData = exports.transformRows(config, inputData) | ||
//when streaming values to tty-table, we don't want column widths to change | ||
//from one rowData set to the next, so we save the first set of widths and reuse | ||
// when streaming values to tty-table, we don't want column widths to change | ||
// from one rowData set to the next, so we save the first set of widths and reuse | ||
if(!global.columnWidths) { | ||
@@ -34,32 +34,32 @@ global.columnWidths = {} | ||
config.table.columnWidths = global.columnWidths[config.tableId] | ||
} else{ | ||
} else { | ||
global.columnWidths[config.tableId] = config.table.columnWidths = Format.getColumnWidths(config, rowData) | ||
} | ||
//stringify header cells | ||
// stringify header cells | ||
if(!config.headerEmpty) { | ||
sections.header = config.table.header.map(function(row) { | ||
return buildRow(config, row, "header", null, rowData, inputData) | ||
sections.header = config.table.header.map(row => { | ||
return exports.buildRow(config, row, "header", null, rowData, inputData) | ||
}) | ||
} else{ | ||
} else { | ||
sections.header = [] | ||
} | ||
//stringify body cells | ||
sections.body = rowData.map(function(row, rowIndex) { | ||
return buildRow(config, row, "body", rowIndex, rowData, inputData) | ||
// stringify body cells | ||
sections.body = rowData.map((row, rowIndex) => { | ||
return exports.buildRow(config, row, "body", rowIndex, rowData, inputData) | ||
}) | ||
//stringify footer cells | ||
// stringify footer cells | ||
sections.footer = (config.table.footer instanceof Array && config.table.footer.length > 0) ? [config.table.footer] : [] | ||
sections.footer = sections.footer.map(function(row) { | ||
return buildRow(config, row, "footer", null, rowData, inputData) | ||
sections.footer = sections.footer.map(row => { | ||
return exports.buildRow(config, row, "footer", null, rowData, inputData) | ||
}) | ||
//add borders | ||
//0=header, 1=body, 2=footer | ||
for(let a=0; a<3; a++) { | ||
// add borders | ||
// 0=header, 1=body, 2=footer | ||
for (let a=0; a<3; a++) { | ||
borders.push("") | ||
config.table.columnWidths.forEach(function(w, i, arr) { | ||
config.table.columnWidths.forEach(function (w, i, arr) { | ||
borders[a] += Array(w).join(borderStyle[a].h) + | ||
@@ -72,14 +72,14 @@ ((i+1 !== arr.length) ? borderStyle[a].j : borderStyle[a].r) | ||
borders[a] = borders[a].join("") | ||
//no trailing space on footer | ||
// no trailing space on footer | ||
borders[a] = (a<2) ? `${marginLeft + borders[a] }\n` : marginLeft + borders[a] | ||
} | ||
//top horizontal border | ||
// top horizontal border | ||
let output = "" | ||
output += borders[0] | ||
//for each section (header,body,footer) | ||
Object.keys(sections).forEach(function(p, i) { | ||
// for each section (header,body,footer) | ||
Object.keys(sections).forEach((p, i) => { | ||
//for each row in the section | ||
// for each row in the section | ||
while(sections[p].length) { | ||
@@ -89,21 +89,21 @@ | ||
//if(row.length === 0) {break} | ||
// if(row.length === 0) {break} | ||
row.forEach(function(line) { | ||
//vertical row borders | ||
row.forEach(line => { | ||
// vertical row borders | ||
output = `${output | ||
+ marginLeft | ||
//left vertical border | ||
// left vertical border | ||
+ borderStyle[1].v | ||
//join cells on vertical border | ||
// join cells on vertical border | ||
+ line.join(borderStyle[1].v) | ||
//right vertical border | ||
// right vertical border | ||
+ borderStyle[1].v | ||
//end of line | ||
// end of line | ||
}\n` | ||
}) | ||
//bottom horizontal row border | ||
// bottom horizontal row border | ||
switch(true) { | ||
//skip if end of body and no footer | ||
// skip if end of body and no footer | ||
case(sections[p].length === 0 | ||
@@ -113,12 +113,16 @@ && i === 1 | ||
break | ||
//skip if end of footer | ||
// skip if end of footer | ||
case(sections[p].length === 0 | ||
&& i === 2): | ||
break | ||
//skip if compact | ||
// skip if compact | ||
case(config.compact && p === "body" && !row.empty): | ||
break | ||
//skip if border style is "none" | ||
// skip if border style is "none" | ||
case(config.borderStyle === "none" && config.compact): | ||
break | ||
default: | ||
@@ -130,3 +134,3 @@ output += borders[1] | ||
//bottom horizontal border | ||
// bottom horizontal border | ||
output += borders[2] | ||
@@ -136,13 +140,14 @@ | ||
//record the height of the output | ||
// record the height of the output | ||
config.height = finalOutput.split(/\r\n|\r|\n/).length | ||
return finalOutput | ||
} | ||
const buildRow = function(config, row, rowType, rowIndex, rowData, inputData) { | ||
module.exports.buildRow = (config, row, rowType, rowIndex, rowData, inputData) => { | ||
let minRowHeight = 0 | ||
//tag row as empty if empty | ||
//(used) for compact tables | ||
// tag row as empty if empty | ||
// (used) for compact tables | ||
if(row.length === 0 && config.compact) { | ||
@@ -153,23 +158,22 @@ row.empty = true | ||
//force row to have correct number of columns | ||
// force row to have correct number of columns | ||
let difL = config.table.columnWidths.length - row.length | ||
if(difL > 0) { | ||
//add empty element to array | ||
row = row.concat(Array.apply(null, new Array(difL)) | ||
.map(function() { | ||
return null | ||
})) | ||
} else if(difL < 0) { | ||
//truncate array | ||
// add empty element to array | ||
row = row.concat(Array.apply(null, new Array(difL)).map(() => null)) | ||
} else if (difL < 0) { | ||
// truncate array | ||
row.length = config.table.columnWidths.length | ||
} | ||
//get row as array of cell arrays | ||
//can't use es5 row functions (map, forEach because i.e. | ||
//[1,,3] will only iterate 1,3 | ||
// get row as array of cell arrays | ||
// can't use es5 row functions (map, forEach because i.e. | ||
// [1,,3] will only iterate 1,3 | ||
let cArrs = [] | ||
let rowLength = row.length | ||
for(let index=0; index<rowLength; index++) { | ||
let c = Render.buildCell(config, row[index], index, rowType, rowIndex, rowData, inputData) | ||
let c = exports.buildCell(config, row[index], index, rowType, rowIndex, rowData, inputData) | ||
let cellArr = c.cellArr | ||
@@ -187,11 +191,9 @@ | ||
//adjust minRowHeight to reflect vertical row padding | ||
// adjust minRowHeight to reflect vertical row padding | ||
minRowHeight = (rowType === "header") ? minRowHeight : | ||
minRowHeight + (config.paddingBottom + config.paddingTop) | ||
//convert array of cell arrays to array of lines | ||
// convert array of cell arrays to array of lines | ||
let lines = Array.apply(null, {length: minRowHeight}) | ||
.map(Function.call, function() { | ||
return [] | ||
}) | ||
.map(Function.call, () => []) | ||
@@ -202,3 +204,3 @@ cArrs.forEach(function(cellArr, a) { | ||
if(rowType ==="body") { | ||
//add whitespace for top padding | ||
// add whitespace for top padding | ||
for(let i=0; i<config.paddingTop; i++) { | ||
@@ -208,3 +210,3 @@ cellArr.unshift(whiteline) | ||
//add whitespace for bottom padding | ||
// add whitespace for bottom padding | ||
for(let i=0; i<config.paddingBottom; i++) { | ||
@@ -223,4 +225,4 @@ cellArr.push(whiteline) | ||
Render.buildCell = function(config, cell, columnIndex, rowType, rowIndex, rowData, inputData) { | ||
module.exports.buildCell = (config, cell, columnIndex, rowType, rowIndex, rowData, inputData) => { | ||
let cellValue | ||
@@ -230,3 +232,3 @@ let cellOptions = Object.assign( | ||
config, | ||
(rowType === "body") ? config.columnSettings[columnIndex] : {}, //ignore columnSettings for footer | ||
(rowType === "body") ? config.columnSettings[columnIndex] : {}, // ignore columnSettings for footer | ||
(typeof cell === "object") ? cell : {} | ||
@@ -238,21 +240,24 @@ ) | ||
cellValue = cellOptions.alias || cellOptions.value || "" | ||
} else{ | ||
//set cellValue | ||
} else { | ||
// set cellValue | ||
switch(true) { | ||
case(typeof cell === "undefined" || cell === null): | ||
//replace undefined/null cell values with placeholder | ||
// replace undefined/null cell values with placeholder | ||
cellValue = (config.errorOnNull) ? config.defaultErrorValue : config.defaultValue | ||
break | ||
case(typeof cell === "object" && typeof cell.value !== "undefined"): | ||
cellValue = cell.value | ||
break | ||
case(typeof cell === "function"): | ||
cellValue = cell(cellValue, columnIndex, rowIndex, rowData, inputData) | ||
break | ||
default: | ||
//cell is assumed to be a scalar | ||
// cell is assumed to be a scalar | ||
cellValue = cell | ||
} | ||
//run header formatter | ||
// run header formatter | ||
if(typeof cellOptions.formatter === "function") { | ||
@@ -263,37 +268,39 @@ cellValue = cellOptions.formatter(cellValue, columnIndex, rowIndex, rowData, inputData) | ||
//colorize cellValue | ||
// colorize cellValue | ||
cellValue = Style.colorizeCell(cellValue, cellOptions, rowType) | ||
//textwrap cellValue | ||
let WrapObj = Format.wrapCellContent(config, cellValue, columnIndex, cellOptions, rowType) | ||
//cellValue = WrapObj.output.join('\n'); | ||
// textwrap cellValue | ||
let wrapObj = Format.wrapCellContent(config, cellValue, columnIndex, cellOptions, rowType) | ||
//return as array of lines | ||
// return as array of lines | ||
return { | ||
cellArr: WrapObj.output, | ||
width: WrapObj.width | ||
cellArr: wrapObj.output, | ||
width: wrapObj.width | ||
} | ||
} | ||
Render.getRowFormat = function(row, config) { | ||
module.exports.getRowFormat = (row, config) => { | ||
let type | ||
//rows passed as an object | ||
// rows passed as an object | ||
if(typeof row === "object" && !(row instanceof Array)) { | ||
let keys = Object.keys(row) | ||
if(config.adapter === "automattic") { | ||
//detected cross table | ||
// detected cross table | ||
let key = keys[0] | ||
if(row[key] instanceof Array) { | ||
type = "automattic-cross" | ||
} else{ | ||
//detected vertical table | ||
} else { | ||
// detected vertical table | ||
type = "automattic-vertical" | ||
} | ||
} else { | ||
//detected horizontal table | ||
// detected horizontal table | ||
type = "o-horizontal" | ||
} | ||
} else{ | ||
//rows passed as an array | ||
} else { | ||
// rows passed as an array | ||
type = "a-horizontal" | ||
@@ -305,20 +312,17 @@ } | ||
//@todo For rotating horizontal data into a vertical table | ||
//assumes all rows are same length | ||
Render.verticalizeMatrix = function(config, inputArray) { | ||
//grow to # arrays equal to number of columns in input array | ||
// @todo For rotating horizontal data into a vertical table | ||
// assumes all rows are same length | ||
module.exports.verticalizeMatrix = (config, inputArray) => { | ||
// grow to # arrays equal to number of columns in input array | ||
let outputArray = [] | ||
let headers = config.table.columns | ||
//create a row for each heading, and prepend the row | ||
//with the heading name | ||
headers.forEach(function(name) { | ||
outputArray.push([name]) | ||
}) | ||
// create a row for each heading, and prepend the row | ||
// with the heading name | ||
headers.forEach(name => outputArray.push([name])) | ||
inputArray.forEach(function(row) { | ||
row.forEach(function(element, index) { | ||
outputArray[index].push(element) | ||
}) | ||
inputArray.forEach(row => { | ||
row.forEach((element, index) => outputArray[index].push(element)) | ||
}) | ||
@@ -329,6 +333,7 @@ | ||
/** | ||
* Transforms input data arrays to base rendering structure. | ||
*/ | ||
Render.transformRows = function(config, rows) { | ||
module.exports.transformRows = (config, rows) => { | ||
@@ -338,7 +343,7 @@ let output = [] | ||
case("automattic-cross"): | ||
//assign header styles to first column | ||
// assign header styles to first column | ||
config.columnSettings[0] = config.columnSettings[0] || {} | ||
config.columnSettings[0].color = config.headerColor | ||
output = rows.map(function(obj) { | ||
output = rows.map(obj => { | ||
let arr = [] | ||
@@ -350,4 +355,5 @@ let key = Object.keys(obj)[0] | ||
break | ||
case("automattic-vertical"): | ||
//assign header styles to first column | ||
// assign header styles to first column | ||
config.columnSettings[0] = config.columnSettings[0] || {} | ||
@@ -361,22 +367,20 @@ config.columnSettings[0].color = config.headerColor | ||
break | ||
case("o-horizontal"): | ||
//cell property names are specified in header columns | ||
// cell property names are specified in header columns | ||
if (config.table.header[0].length | ||
&& config.table.header[0].every( obj => obj.value )) { | ||
output = rows.map(function(row) { | ||
return config.table.header[0].map(function(object) { | ||
return row[object.value] | ||
}) | ||
}) | ||
} //eslint-disable-line brace-style | ||
//no property names given, default to object property order | ||
&& config.table.header[0].every(obj => obj.value)) { | ||
output = rows.map(row => config.table.header[0] | ||
.map(obj => row[obj.value])) | ||
} // eslint-disable-line brace-style | ||
// no property names given, default to object property order | ||
else { | ||
output = rows.map(function(obj) { | ||
return Object.values(obj) | ||
}) | ||
output = rows.map(obj => Object.values(obj)) | ||
} | ||
break | ||
case("a-horizontal"): | ||
output = rows | ||
break | ||
default: | ||
@@ -387,3 +391,1 @@ } | ||
} | ||
module.exports = Render |
@@ -1,7 +0,8 @@ | ||
const Chalk = require("chalk") | ||
const chalk = require("chalk") | ||
exports.colorizeCell = function(str, cellOptions, rowType) { | ||
let color = false //false will keep terminal default | ||
module.exports.colorizeCell = (str, cellOptions, rowType) => { | ||
let color = false // false will keep terminal default | ||
switch(true) { | ||
@@ -11,5 +12,7 @@ case(rowType === "body"): | ||
break | ||
case(rowType === "header"): | ||
color = cellOptions.headerColor || color | ||
break | ||
default: | ||
@@ -20,3 +23,3 @@ color = cellOptions.footerColor || color | ||
if (color) { | ||
str = Chalk[color](str) | ||
str = chalk[color](str) | ||
} | ||
@@ -27,7 +30,8 @@ | ||
/* | ||
exports.colorizeAllWords = function(color,str){ | ||
module.exports.colorizeAllWords = function(color,str){ | ||
//color each word in the cell so that line breaks don't break color | ||
let arr = str.replace(/(\S+)/gi,function(match){ | ||
return Chalk[color](match)+'\ '; | ||
return chalk[color](match)+'\ '; | ||
}); | ||
@@ -34,0 +38,0 @@ return arr; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
0
42215
938
Updatedsmartwrap@^1.2.3