npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nd-table

v1.2.2

Published

Table builder for console/terminal (ASCII, UTF, ANSI), MarkDown (MD), HTML, CSV, TSV, and custom

Downloads

641

Readme

nd-table

Node.js Table builder for:

  • console/terminal (ascii, utf8, ansi)
  • MarkDown (md)
  • HTML
  • JSON
  • CSV, TSV
  • pre-rendered data for your custom outputs

Supported features

Depending on the output format:

  • borders
  • multiline cells
  • horizontal and vertical cell alignments
  • styles: color, bold, italic See details at Configuration options

Install

npm install nd-table

In your code

import { Table } from 'nd-table';

Or, if you use require():

const Table = require('nd-table').Table;

Usage

const table = new Table('Column A', 'Column B'); // initialize table with optional column headers
table.addRowWithHead('First Row Head', 'abc def\nghi jkl mno pqr', 1); // add a row
table.addRowWithHead('Row Head', 'stu', 2); // add a row with row header
table.addRowWithHead('Another Row Head', { value: 'vwx', bold: true, color: 'red' }, 3); // Value is specified with options for "Column A"
table.addRow('yz', { value: 4, link: 'https://osnews.com/' }); // Specifies a link for "Column B". Supported in Markdown and HTML outputs
console.log(table.toString()); // print the table
//                    ┌──────────────────────────┐
//                    │ Column A        Column B │
// ┌──────────────────┼──────────────────────────┤
// │   First Row Head │ abc def                1 │
// │                  │ ghi jkl mno pqr          │
// │         Row Head │ stu                    2 │
// │ Another Row Head │ vwx                    3 │
// │                  │ yz                     4 │
// └──────────────────┴──────────────────────────┘

Builder API

Table.fromData(data[][]); // Builds a table from a 2-dimensional array of values
table.columns; // Current number of columns (the value of the highest 'x' position of any cells + 1)
table.rows; // Current number of rows (the value of the highest 'y' position of any cells + 1)
table.addRow(...values); // Append a row to the end of the table with values*
table.addRowWithHead(head, ...values); // Append a row to the end of the table with header and values*
table.addSeparator(); // Sets { borderBottom: true } on the last row's config
table.clear(); // Clear the entire table, including values, configs, headers
table.deleteColumn(x); // Removes a column
table.deleteColumns(x, count); // Removes a number of columns
table.deleteRow(y); // Removes a row
table.deleteRows(y, count); // Removes a number of rows
table.flip(); // Flips x and y axes
table.getCell(x, y); // Get cell value
table.getColumnHeaders(); // Get column headers
table.getRowHeaders(); // Get row headers
table.getSnapshot(); // A snapshot of the table's current state
table.insertColumn(x); // Inserts a column
table.insertColumns(x, count); // Inserts a number of columns
table.insertRow(y, ...values); // Inserts a row, adds cell values*
table.insertRowWithHead(y, head, ...values); // Inserts a row, adds head and cell values*
table.insertRows(y, count); // Inserts a number of empty rows
table.replaceRow(y, ...values); // Replaces a row's content with provided cell values*
table.replaceRowWithHead(y, head, ...values); // Replaces a row's content with provided header and cell values*
table.setCell(x, y, value); // Update cell value*
table.setColumnHeaders(newHeaders); // Update column headers (pass [] or null to delete headers)
table.setRowHeaders(newHeaders: CellValueOrValueWithOptions[] | null | undefined); // Update column headers (pass [] or null to delete headers)

Cell Value

  • Value can be any primitive: undefined, null, boolean, number, bigint, or string
  • Objects (including arrays), functions, and symbols will be stringified.
  • Values (marked with * above) can be passed directly, or in combination with config options, like this:
table.addRow({ value: 'My Cell Value', align: 'right', borderLeft: true }, 'Other Cell Value');

Coordinates: x, y

Columns and rows are in a 0-based index that excludes the optional headers x = -1 is the row header y = -1 is the column header

Config API

getCellConfig(x, y); // Get cell config
getCellRenderConfig(x, y); // Get meshed (cell > column > row > table) configuration for cell
getColumnConfig(x); // Get column config
getRowConfig(y); // Get row config
getTableConfig(); // Get table config
setCellConfig(x, y, config); // Update cell config
setColumnConfig(x, config); // Update column config
setRowConfig(y, config); // Update row config
setTableConfig(config); // Update table config

For setters (setCellConfig, setColumnConfig, setRowConfig) you may pass coordinate(s) for x and y:

  • an integer
  • string pattern that is a comma-separated list of indexes and/or ranges: '0..2,5' (from..to, to included)

Configuration options

interface ConfigValue {
  align?: 'left' | 'center' | 'right'; // horizontal alignment of cell content (undefined = 'left')
  bold?: boolean; // style: bold cell content (undefined = false)
  borderBottom?: boolean; // bottom border (cell, column, row, or table). NOTE: neighbors will overlap
  borderLeft?: boolean; // left border (cell, column, row, or table). NOTE: neighbors will overlap
  borderRight?: boolean; // right border (cell, column, row, or table). NOTE: neighbors will overlap
  borderTop?: boolean; // top border of scope (cell, column, row, or table). NOTE: neighbors will overlap
  color?: 'black' | 'blue' | 'cyan' | 'default' | 'green' | 'magenta' | 'red' | 'white' | 'yellow'; // style: ANSI 8-color
  height?: number; // fix cell content height (in line count)
  italic?: boolean; // style: italic cell content
  link?: string; // cell content link
  maxHeight?: number; // max cell content height (in line count)
  maxWidth?: number; // max cell content width (in character count)
  renderer?: (value: CellValue, x: number, y: number, config: ConfigValue, table: TableSnapshot) => string; // cell renderer function
  valign?: (typeof CONFIG_VALIGN)[number]; // vertical alignment of multiline cell content
  width?: number; // fixed cell content width (in character count)
}

// When setting configuration, you may use shorthands for border* properties:
interface IncomingConfigValue extends ConfigValue {
  border?: boolean; // top + right + bottom + left
  horizontalBorder?: boolean; // top + bottom
  verticalBorder?: boolean; // right + left
}

Preferences

Preferences for defaults can be set on both the Table static (ex: Table.setPreferences({ boldHeaders: true })) or for the instance (ex: const table = (new Table()).setPreferences({ verticalBorders: true })). You can check the current values by getting a copy of the preferences: table.getPreferences()

Default preferences
{
  align: 'left',
  boldHeaders: true,
  columnHeaderAlign: 'left',
  columnHeaderVAlign: 'bottom',
  headerBorders: true,
  horizontalBorders: false,
  numberAlign: 'right',
  rowHeaderAlign: 'right',
  rowHeaderVAlign: 'top',
  tableBorders: true,
  valign: 'top',
  verticalBorders: false
}

Output API

Output methods

// generic
table.toString(format?, options?); // Output Table string with selected (or default) format and options. Also triggered by String(table)
// or format-specific
table.toUTF8({ ansi: true, flavor: 'rounded', separatorSpaces: 3 }); // For terminal, uses UTF-8 box drowing characters for borders
table.toASCII({ ansi: true }); // For terminal with no UTF-8 support
table.toMarkdown(); // Markdown
table.toCSV(); // Excel compatbile CSV
table.toTSV(); // TSV (CSV with tab separation)
table.toHTML({ styles: true }); // HTML <table>
table.toJSON({ compact: true }); // JSON array of arrays

Default output format and options

If nothing is set, default format is utf8

Table.setOutputFormat(format, options?); // Sets default output format and options for all Table instances that don't have their own default
table.setOutputFormat(format, options?); // Sets default output format and options for the Table instance

Custom builder output

Get pre-processed render data and use it with your own custom output formatter.

myCustomOutput(table.toRenderData());

The render data is a mash of the TableSnapshot and these additional interfaces:

interface TableSnapshot {
  cellConfig: RenderConfig[][]; // copy of original cell config on (x, y) coordinates
  cellValue: CellValue[][]; // copy of original cell values on (x, y) coordinates
  columnConfig: ConfigValue[]; // copy of original column config on (x) coordinate
  columnHeaders?: CellValue[]; // column header values (or undefined for no headers)
  columns: number; // number of columns (excluding header)
  rowConfig: ConfigValue[]; // copy of original row config on (y) coordinate
  rowHeaders?: CellValue[]; // row header values (or undefined for no headers)
  rows: number; // row count (excluding header)
  startX: number; // -1 when row headers are present, 0 otherwise
  startY: number; // -1 when column headers are present, 0 otherwise
  tableConfig: ConfigValue; // copy of original table config
}

interface TableRenderData extends TableSnapshot {
  borders: TableRenderBorderData; // border information in a grid logic
  cellValueRendered: string[][] = []; // processed cell values on (x, y) coordinates
  cellValueRenderedMultiline: string[][][] = []; // processed cell values split into fixed-width lines on (x, y) coordinates
  columnWidth: number[] = []; // processed column width on (x) coordinate
  rowHeight: number[] = []; // processed row height (line count) on (y) coordinate
}

interface TableRenderBorderData {
  /**
   * border grid and content logical description (sep = TLBRSeparator, i.e [TRBL, multiplier])
   * [sep, sep,   sep,   sep, sep, enter]
   * [sep, sep, line[i], sep, sep, enter] x lines.length
   * [sep, sep,   sep,   sep, sep, enter]
   **/
  readonly grid: (TLBRSeparator | string)[][][][] = []; // border grid and content logical description (sep = TLBRSeparator, i.e [TRBL, multiplier])
  readonly horizontal: boolean[][] = []; // Map of horizontal (top/bottom) borders on (x, y) coordinates (+ 1 closing row)
  readonly horizontalSerparation: boolean[] = []; // Indication of at least 1 horizontal border for each y coordinate (+ 1 closing row)
  readonly vertical: boolean[][] = []; // Map of vertical (left/right) borders on (x, y) coordinates (+ 1 closing column)
  readonly verticalSerparation: boolean[] = []; // Indication of at least 1 vertical border for each x coordinate (+ 1 closing column)
}