table-string
TypeScript icon, indicating that this package has built-in type declarations

1.2.1 • Public • Published

table-string

Originally, I was looking for a replacement for console.table() because I missed this function in Cloudflare workers.

So tableString() is a function originally inspired by console.table() but with the following main differences:

  • First, it doesn't output anything to the console, but returns a string.
  • More importantly, its output looks less technical. It aims to simplify the creation of meaningful tables for CLIs.

Purpose

We will generate a table for this array:

const data = [
  { price: 1.99, fruit: chalk.green("Apples") },
  { price: 3.99, fruit: chalk.red("Strawberries") },
  { price: 0.99, fruit: chalk.bgBlue.yellow("Bananas") },
  { price: 12.99, fruit: chalk.blue.bgWhite("Bilberries") },
],

What you get without tableString

On node.js console.table(data) produces a table that looks very debug-like:

console.table output

What you might be looking for

The same structure with tableString(data) looks much cleaner: tableString output

What else tableString can do

By adding two parameters we can control the columns and table options: tableString output with options

tableString(data,
  [{ price: "Price in $" }, { fruit: "Fruit" }],
  {
    frameChalk: chalk.white.bgBlack(" "),
  }
);

Geared for CLI output, not debugging

As I was looking into this, I noticed that the output of console.table() looks pretty technical. It's more appropriate for developers debugging their code than for users of a CLI expecting informative tables.

Less technical

I've intentionally omitted some functions from console.table() because they give the output a more technical, debugger-like look:

  • there is no coloring of values based on their JavaScript type
  • there are no quotes around strings or 'm' after BigInts
  • null values and values of type "function" are not rendered
  • for arrays, the index column is included only if explicitly specified
  • the index column has no header by default

More functionality

The table-string package supports more options compared to console.table:

  • It provides full control over table headings and alignment.
  • It is compatible with ANSI color sequences. For example, you can use the chalk package to colorize strings without affecting the layout. Even better, padding recognizes background colors and extends them. You can even define a chalk for the table's border.

Non-goals:

There are other table packages with different targets. The table-string package does not share them all. Here are explicit non-goals

  • No support for emojis. Currently, emojis do not seem to be well supported in monospace fonts. Emojis tend to break table spacing.
  • No dynamic effects on TTYs based on cursor repositioning. The result of the tableString function is a simple string that can be printed to a text file.

Usage

tableString

tableString generates a multiline string that renders as a table when printed to a tty. The data for the table is typically provided as an array of objects. The properties of those objects define the columns of the table, the array entries are the rows. The look of the table can be controlled by additional option parameters:

tableString(data, columnOptions, tableOptions) takes three parameters:

  1. The data to be displayed
  2. Column Options describing the order, headings and alignment of the columns
  3. Table Options that specify global characteristics of the table, such as alignment of headings or a chalk for the border.

The options are typically simple values or key-value pairs. But sometimes it is also helpful to use JavaScript functions to compute option.

flatten

Newlines in your data will break the output of tableString. Multiple lines of text in a table cell are not supported. But it is possible to substitute multiline strings with multiple rows. The flatten function will do that for you:

flatten([{a:"one line", b: "two\nlines"}]) == [{a:"one line", b:"two"}, {a:"", b:"lines"}]

Printing tableString(flatten([{a:"one line", b: "two\nlines"}])) will look like this:

flatten

With flatten, it is also possible to use tabelString results as values in tableString tables 😏

flatten

Configuration

Data

In general, tableString is called with an array1. The elements of the array are used to populate the rows of the table. Values that are not strings, numbers, or objects are ignored. Strings can contain ANSI color escapes. If they occur at the beginning or the end of the string, they will be automatically extended if the string needs to be padded to fill the column width.

If the array contains primitive values, i.e. strings, numbers, or BigInts, those are shown in a column called "Values". Non primitive values are objects. These objects have properties. Each property defines a column of the table and the property value of an row's object is the value in the column for that row. Columns values should be primitive values. More complex values are likely show as "[object Object]". String values with newlines break the table layout. To use multiline strings as values, first flatten the table.

There is one special property called "<hr>". If the "<hr>" property is defined in the object for a row, e.g. { .... "<hr>": true}, an horizontal line is included after that row.

Column Options

The main purpose of column options is to tell the layout which columns to show and in what order. They are also used to specify alignments and headings of columns.

An entry of the columnOptions array defines up to 5 values for a column:

  • name
  • heading
  • minWidth, maxWidth, width
  • padding
  • align
  • alignHeading Of these values, only the name is mandatory.

If no column options are specified, the table shows all columns available in the underlying data. If column options are defined, only those columns are shown in the table.

Example: [ {name: "firstName" }, {name: "lastName" } ]2 will show these two columns in that order. The values are taken from the properties of the same name (from the objects that form the rows of the table).

name

A string. The name selects a single data column of the table. It is the name of this column. Possible values are the property names (keys) of the objects specified as table data. These include '0', '1', ... if the values in the data object are arrays. In addition, two special column names may exist:

  • "Values" is the name of the column of primitive values. If the data object for the table is an array, this column contains all strings and numbers that are direct elements of this array.
  • "" is the name of the index column. Unlike console.table(), this column is not included by default. To add an index column, you must explicitly specify the values for the index column using the index table option.
heading

A string. Sets the heading of the column. If not specified, the column name is used as the heading.

minWidth

A positive integer. The minimal width of a column is derived from the heading and the widest values. The width option can be used to explicitly set a minimum width for the column.

maxWidth

A positive integer. If set, truncates too long output in this column to n characters. It is an error to set maxWidth < minWidth.

width

A positive integer. Can be used as an abbreviation for setting minWidth and maxWidth to the same value.

padding

A positive integer. Adds spaces to the left and to the right of a value in a column. Default is 1 space.

align

Possible values are left, center, and right. Sets the alignment for the values of the column. The default is left for most values. If no alignment is specified for the column, number values will be right aligned by default. This also affects how the heading of the column is aligned. If you want a different alignment for the column heading, use the alignHeading column option. By default, column headings are all center aligned. This can be changed globally with the alignTableHeadings table option.

alignHeading

Possible values are left, center, and right. If the align column option is defined, this will also align the heading. The option alignHeading allows a different alignment of the heading. The default is center if not overridden by the table option alignTableHeadings.

Shortened Notation

Often, you do not need to specify all options for a column. For these cases, two abbreviations are supported:

  • The tuple { column: "name", heading: "Column Heading" } can be abbreviated to { name: "Column Heading" }\
  • The { name: "prop2" } object can be abbreviated to a single string "prop2".

All forms can be mixed: [ { prop1: "Column Name" }, "prop2", { name: "prop3", align: "center" } ]

Table Options

While column options refer to individual columns, there are a few options that affect the entire table:

  • alignTableHeadings
  • frameChalk, headerChalk, alternativeChalk
  • propertyCompareFunction
  • index

alignTableHeadings

Possible values are left, center, and right. This overrides the default "center" alignment of column headings. The align and alignHeading values for individual columns take precedence over this option.

frameChalk

A string. Want an alternative color for the table's border? Just define a string value with opening and closing ANSI color escapes. As an example: { frameChalk: "\x1B[37m\x1B[40m \x1B[49m\x1B[39m"}

headerChalk

Specific setting for the header rows. Default is frameChalk.

alternativeChalk

Alternative chalk for every second table row. Default is frameChalk.

propertyCompareFunction

A function. Normally, the data object for tableString() is an array. However, you can also pass an object. The properties of this object are then used to form the rows of the table. If the order of the rows is important to you, you can specify a comparison function to sort them. By default, the properties ar sorted alphabetically. If you do not want sorting, specify: propertyCompareFunction: null.

index

An array of values. To add an index column, define values for that column. This can look like this: index: ["A", "B", "C"] or index: [...data.keys()]. The column is named "" (the empty string) and its heading is also "". You can change heading and alignment with a column option for "": { name: "", heading: "(index)", align: "right" }.

Using Functions in Options

The examples for the index table option also include an example for a computed option value: [...data.keys()] computes an index from the data array. There are other examples where using functions for option values greatly simplifies configuration and improves readability.

For example, the table option frameChalk could also be set with the chalk package as follows: { frameChalk: chalk.red.bgBlue("x") }. Here the string itself is not important, but it should have a non-zero length. Otherwise, chalk optimizes the colors away.

As another example, if you just want the columns to show up in alphabetical order:
tableString(data = [{ z: 3, y: 4, x:2 }]), [...Object.keys(data[0])].sort()) renders as sorted columns

  1. You can also pass an object instead of an array, see the table option propertyCompareFunction.

  2. Or shorter: [ "firstName", "lastName" ], see shortened notation

Package Sidebar

Install

npm i table-string

Weekly Downloads

3

Version

1.2.1

License

MIT

Unpacked Size

55 kB

Total Files

47

Last publish

Collaborators

  • ergberg