Popularity
4.7
Growing
Activity
6.7
Declining
587
9
71

Description

Produces a string that represents array data in a text table.

Code Quality Rank: L5
Monthly Downloads: 0
Programming language: TypeScript
License: GNU General Public License v3.0 or later
Tags: Ascii     Table     Ansi     Text     Align    
Latest version: v6.0.4

Table alternatives and similar modules

Based on the "Text" category.
Alternatively, view Table alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of Table or a related project?

Add another 'Text' Module

README

Table

Produces a string that represents array data in a text table.

Travis build status Coveralls NPM version Canonical Code Style Twitter Follow

[Demo of table displaying a list of missions to the Moon.](./.README/demo.png)

Features

  • Works with strings containing fullwidth characters.
  • Works with strings containing ANSI escape codes.
  • Configurable border characters.
  • Configurable content alignment per column.
  • Configurable content padding per column.
  • Configurable column width.
  • Text wrapping.

Install

npm install table

Buy Me A Coffee Become a Patron

Usage

import { table } from 'table';

// Using commonjs?
// const { table } = require('table');

const data = [
    ['0A', '0B', '0C'],
    ['1A', '1B', '1C'],
    ['2A', '2B', '2C']
];

console.log(table(data));
╔════╀════╀════╗
β•‘ 0A β”‚ 0B β”‚ 0C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 1A β”‚ 1B β”‚ 1C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 2A β”‚ 2B β”‚ 2C β•‘
β•šβ•β•β•β•β•§β•β•β•β•β•§β•β•β•β•β•

API

table

Returns the string in the table format

Parameters:

  • data: The data to display

    • Type: any[][]
    • Required: true
  • config: Table configuration

    • Type: object
    • Required: false
config.border

Type: { [type: string]: string }\ Default: honeywell template

Custom borders. The keys are any of:

  • topLeft, topRight, topBody,topJoin
  • bottomLeft, bottomRight, bottomBody, bottomJoin
  • joinLeft, joinRight, joinBody, joinJoin
  • bodyLeft, bodyRight, bodyJoin
  • headerJoin
const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C']
];

const config = {
  border: {
    topBody: `─`,
    topJoin: `┬`,
    topLeft: `β”Œ`,
    topRight: `┐`,

    bottomBody: `─`,
    bottomJoin: `β”΄`,
    bottomLeft: `β””`,
    bottomRight: `β”˜`,

    bodyLeft: `β”‚`,
    bodyRight: `β”‚`,
    bodyJoin: `β”‚`,

    joinBody: `─`,
    joinLeft: `β”œ`,
    joinRight: `─`,
    joinJoin: `β”Ό`
  }
};

console.log(table(data, config));
β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”
β”‚ 0A β”‚ 0B β”‚ 0C β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€
β”‚ 1A β”‚ 1B β”‚ 1C β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€
β”‚ 2A β”‚ 2B β”‚ 2C β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”˜
config.drawVerticalLine

Type: (lineIndex: number, columnCount: number) => boolean\ Default: () => true

It is used to tell whether to draw a vertical line. This callback is called for each vertical border of the table. If the table has n columns, then the index parameter is alternatively received all numbers in range [0, n] inclusively.

const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C'],
  ['3A', '3B', '3C'],
  ['4A', '4B', '4C']
];

const config = {
  drawVerticalLine: (lineIndex, columnCount) => {
    return lineIndex === 0 || lineIndex === columnCount;
  }
};

console.log(table(data, config));

╔════════════╗
β•‘ 0A  0B  0C β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 1A  1B  1C β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 2A  2B  2C β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 3A  3B  3C β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 4A  4B  4C β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•

config.drawHorizontalLine

Type: (lineIndex: number, rowCount: number) => boolean\ Default: () => true

It is used to tell whether to draw a horizontal line. This callback is called for each horizontal border of the table. If the table has n rows, then the index parameter is alternatively received all numbers in range [0, n] inclusively. If the table has n rows and contains the header, then the range will be [0, n+1] inclusively.

const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C'],
  ['3A', '3B', '3C'],
  ['4A', '4B', '4C']
];

const config = {
  drawHorizontalLine: (lineIndex, rowCount) => {
    return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount - 1 || lineIndex === rowCount;
  }
};

console.log(table(data, config));

╔════╀════╀════╗
β•‘ 0A β”‚ 0B β”‚ 0C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 1A β”‚ 1B β”‚ 1C β•‘
β•‘ 2A β”‚ 2B β”‚ 2C β•‘
β•‘ 3A β”‚ 3B β”‚ 3C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 4A β”‚ 4B β”‚ 4C β•‘
β•šβ•β•β•β•β•§β•β•β•β•β•§β•β•β•β•β•

config.singleLine

Type: boolean\ Default: false

If true, horizontal lines inside the table are not drawn. This option also overrides the config.drawHorizontalLine if specified.

const data = [
  ['-rw-r--r--', '1', 'pandorym', 'staff', '1529', 'May 23 11:25', 'LICENSE'],
  ['-rw-r--r--', '1', 'pandorym', 'staff', '16327', 'May 23 11:58', 'README.md'],
  ['drwxr-xr-x', '76', 'pandorym', 'staff', '2432', 'May 23 12:02', 'dist'],
  ['drwxr-xr-x', '634', 'pandorym', 'staff', '20288', 'May 23 11:54', 'node_modules'],
  ['-rw-r--r--', '1,', 'pandorym', 'staff', '525688', 'May 23 11:52', 'package-lock.json'],
  ['[email protected]', '1', 'pandorym', 'staff', '2440', 'May 23 11:25', 'package.json'],
  ['drwxr-xr-x', '27', 'pandorym', 'staff', '864', 'May 23 11:25', 'src'],
  ['drwxr-xr-x', '20', 'pandorym', 'staff', '640', 'May 23 11:25', 'test'],
];

const config = {
  singleLine: true
};

console.log(table(data, config));
╔═════════════╀═════╀══════════╀═══════╀════════╀══════════════╀═══════════════════╗
β•‘ -rw-r--r--  β”‚ 1   β”‚ pandorym β”‚ staff β”‚ 1529   β”‚ May 23 11:25 β”‚ LICENSE           β•‘
β•‘ -rw-r--r--  β”‚ 1   β”‚ pandorym β”‚ staff β”‚ 16327  β”‚ May 23 11:58 β”‚ README.md         β•‘
β•‘ drwxr-xr-x  β”‚ 76  β”‚ pandorym β”‚ staff β”‚ 2432   β”‚ May 23 12:02 β”‚ dist              β•‘
β•‘ drwxr-xr-x  β”‚ 634 β”‚ pandorym β”‚ staff β”‚ 20288  β”‚ May 23 11:54 β”‚ node_modules      β•‘
β•‘ -rw-r--r--  β”‚ 1,  β”‚ pandorym β”‚ staff β”‚ 525688 β”‚ May 23 11:52 β”‚ package-lock.json β•‘
β•‘ [email protected] β”‚ 1   β”‚ pandorym β”‚ staff β”‚ 2440   β”‚ May 23 11:25 β”‚ package.json      β•‘
β•‘ drwxr-xr-x  β”‚ 27  β”‚ pandorym β”‚ staff β”‚ 864    β”‚ May 23 11:25 β”‚ src               β•‘
β•‘ drwxr-xr-x  β”‚ 20  β”‚ pandorym β”‚ staff β”‚ 640    β”‚ May 23 11:25 β”‚ test              β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
config.columns

Type: Column[] | { [columnIndex: number]: Column }

Column specific configurations.

config.columns[*].width

Type: number\ Default: the maximum cell widths of the column

Column width (excluding the paddings).


const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C']
];

const config = {
  columns: {
    1: { width: 10 }
  }
};

console.log(table(data, config));
╔════╀════════════╀════╗
β•‘ 0A β”‚ 0B         β”‚ 0C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 1A β”‚ 1B         β”‚ 1C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 2A β”‚ 2B         β”‚ 2C β•‘
β•šβ•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•
config.columns[*].alignment

Type: 'center' | 'justify' | 'left' | 'right'\ Default: 'left'

Cell content horizontal alignment

const data = [
  ['0A', '0B', '0C', '0D 0E 0F'],
  ['1A', '1B', '1C', '1D 1E 1F'],
  ['2A', '2B', '2C', '2D 2E 2F'],
];

const config = {
  columnDefault: {
    width: 10,
  },
  columns: [
    { alignment: 'left' },
    { alignment: 'center' },
    { alignment: 'right' },
    { alignment: 'justify' }
  ],
};

console.log(table(data, config));
╔════════════╀════════════╀════════════╀════════════╗
β•‘ 0A         β”‚     0B     β”‚         0C β”‚ 0D  0E  0F β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 1A         β”‚     1B     β”‚         1C β”‚ 1D  1E  1F β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 2A         β”‚     2B     β”‚         2C β”‚ 2D  2E  2F β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•
config.columns[*].verticalAlignment

Type: 'top' | 'middle' | 'bottom'\ Default: 'top'

Cell content vertical alignment

const data = [
  ['A', 'B', 'C', 'DEF'],
];

const config = {
  columnDefault: {
    width: 1,
  },
  columns: [
    { verticalAlignment: 'top' },
    { verticalAlignment: 'middle' },
    { verticalAlignment: 'bottom' },
  ],
};

console.log(table(data, config));
╔═══╀═══╀═══╀═══╗
β•‘ A β”‚   β”‚   β”‚ D β•‘
β•‘   β”‚ B β”‚   β”‚ E β•‘
β•‘   β”‚   β”‚ C β”‚ F β•‘
β•šβ•β•β•β•§β•β•β•β•§β•β•β•β•§β•β•β•β•
config.columns[*].paddingLeft

Type: number\ Default: 1

The number of whitespaces used to pad the content on the left.

config.columns[*].paddingRight

Type: number\ Default: 1

The number of whitespaces used to pad the content on the right.

The paddingLeft and paddingRight options do not count on the column width. So the column has width = 5, paddingLeft = 2 and paddingRight = 2 will have the total width is 9.

const data = [
  ['0A', 'AABBCC', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C']
];

const config = {
  columns: [
    {
      paddingLeft: 3
    },
    {
      width: 2,
      paddingRight: 3
    }
  ]
};

console.log(table(data, config));
╔══════╀══════╀════╗
β•‘   0A β”‚ AA   β”‚ 0C β•‘
β•‘      β”‚ BB   β”‚    β•‘
β•‘      β”‚ CC   β”‚    β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘   1A β”‚ 1B   β”‚ 1C β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘   2A β”‚ 2B   β”‚ 2C β•‘
β•šβ•β•β•β•β•β•β•§β•β•β•β•β•β•β•§β•β•β•β•β•
config.columns[*].truncate

Type: number\ Default: Infinity

The number of characters is which the content will be truncated. To handle a content that overflows the container width, table package implements text wrapping. However, sometimes you may want to truncate content that is too long to be displayed in the table.

const data = [
  ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']
];

const config = {
  columns: [
    {
      width: 20,
      truncate: 100
    }
  ]
};

console.log(table(data, config));
╔══════════════════════╗
β•‘ Lorem ipsum dolor si β•‘
β•‘ t amet, consectetur  β•‘
β•‘ adipiscing elit. Pha β•‘
β•‘ sellus pulvinar nibh β•‘
β•‘ sed mauris convall…  β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
config.columns[*].wrapWord

Type: boolean\ Default: false

The table package implements auto text wrapping, i.e., text that has the width greater than the container width will be separated into multiple lines at the nearest space or one of the special characters: \|/_.,;-.

When wrapWord is false:

const data = [
    ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']
];

const config = {
  columns: [ { width: 20 } ]
};

console.log(table(data, config));
╔══════════════════════╗
β•‘ Lorem ipsum dolor si β•‘
β•‘ t amet, consectetur  β•‘
β•‘ adipiscing elit. Pha β•‘
β•‘ sellus pulvinar nibh β•‘
β•‘ sed mauris convallis β•‘
β•‘ dapibus. Nunc venena β•‘
β•‘ tis tempus nulla sit β•‘
β•‘ amet viverra.        β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

When wrapWord is true:

╔══════════════════════╗
β•‘ Lorem ipsum dolor    β•‘
β•‘ sit amet,            β•‘
β•‘ consectetur          β•‘
β•‘ adipiscing elit.     β•‘
β•‘ Phasellus pulvinar   β•‘
β•‘ nibh sed mauris      β•‘
β•‘ convallis dapibus.   β•‘
β•‘ Nunc venenatis       β•‘
β•‘ tempus nulla sit     β•‘
β•‘ amet viverra.        β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

config.columnDefault

Type: Column\ Default: {}

The default configuration for all columns. Column-specific settings will overwrite the default values.

config.header

Type: object

Header configuration.

The header configuration inherits the most of the column's, except:

  • content {string}: the header content.
  • width: calculate based on the content width automatically.
  • alignment: center be default.
  • verticalAlignment: is not supported.
  • config.border.topJoin will be config.border.topBody for prettier.
const data = [
      ['0A', '0B', '0C'],
      ['1A', '1B', '1C'],
      ['2A', '2B', '2C'],
    ];

const config = {
  columnDefault: {
    width: 10,
  },
  header: {
    alignment: 'center',
    content: 'THE HEADER\nThis is the table about something',
  },
}

console.log(table(data, config));
╔══════════════════════════════════════╗
β•‘              THE HEADER              β•‘
β•‘  This is the table about something   β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 0A         β”‚ 0B         β”‚ 0C         β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 1A         β”‚ 1B         β”‚ 1C         β•‘
β•Ÿβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β•’
β•‘ 2A         β”‚ 2B         β”‚ 2C         β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•

createStream

table package exports createStream function used to draw a table and append rows.

Parameter:

  • config: the same as table's, except config.columnDefault.width and config.columnCount must be provided.
import { createStream } from 'table';

const config = {
  columnDefault: {
    width: 50
  },
  columnCount: 1
};

const stream = createStream(config);

setInterval(() => {
  stream.write([new Date()]);
}, 500);

[Streaming current date.](./.README/api/stream/streaming.gif)

table package uses ANSI escape codes to overwrite the output of the last line when a new row is printed.

The underlying implementation is explained in this Stack Overflow answer.

Streaming supports all of the configuration properties and functionality of a static table (such as auto text wrapping, alignment and padding), e.g.

import { createStream } from 'table';

import _ from 'lodash';

const config = {
  columnDefault: {
    width: 50
  },
  columnCount: 3,
  columns: [
    {
      width: 10,
      alignment: 'right'
    },
    { alignment: 'center' },
    { width: 10 }

  ]
};

const stream = createStream(config);

let i = 0;

setInterval(() => {
  let random;

  random = _.sample('abcdefghijklmnopqrstuvwxyz', _.random(1, 30)).join('');

  stream.write([i++, new Date(), random]);
}, 500);

[Streaming random data.](./.README/api/stream/streaming-random.gif)

getBorderCharacters

Parameter:

  • template
    • Type: 'honeywell' | 'norc' | 'ramac' | 'void'
    • Required: true

You can load one of the predefined border templates using getBorderCharacters function.

import { table, getBorderCharacters } from 'table';

const data = [
  ['0A', '0B', '0C'],
  ['1A', '1B', '1C'],
  ['2A', '2B', '2C']
];

const config = {
  border: getBorderCharacters(`name of the template`)
};

console.log(table(data, config));
# honeywell

╔════╀════╀════╗
β•‘ 0A β”‚ 0B β”‚ 0C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 1A β”‚ 1B β”‚ 1C β•‘
β•Ÿβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β•’
β•‘ 2A β”‚ 2B β”‚ 2C β•‘
β•šβ•β•β•β•β•§β•β•β•β•β•§β•β•β•β•β•

# norc

β”Œβ”€β”€β”€β”€β”¬β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”
β”‚ 0A β”‚ 0B β”‚ 0C β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€
β”‚ 1A β”‚ 1B β”‚ 1C β”‚
β”œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€
β”‚ 2A β”‚ 2B β”‚ 2C β”‚
β””β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”˜

# ramac (ASCII; for use in terminals that do not support Unicode characters)

+----+----+----+
| 0A | 0B | 0C |
|----|----|----|
| 1A | 1B | 1C |
|----|----|----|
| 2A | 2B | 2C |
+----+----+----+

# void (no borders; see "borderless table" section of the documentation)

 0A  0B  0C

 1A  1B  1C

 2A  2B  2C

Raise an issue if you'd like to contribute a new border template.

Borderless Table

Simply using void border character template creates a table with a lot of unnecessary spacing.

To create a more pleasant to the eye table, reset the padding and remove the joining rows, e.g.


const output = table(data, {
    border: getBorderCharacters('void'),
    columnDefault: {
        paddingLeft: 0,
        paddingRight: 1
    },
    drawHorizontalLine: () => false
    }
);

console.log(output);
0A 0B 0C
1A 1B 1C
2A 2B 2C


*Note that all licence references and agreements mentioned in the Table README section above are relevant to that project's source code only.