{"id":13457639,"url":"https://github.com/gajus/table","last_synced_at":"2025-05-12T13:15:03.856Z","repository":{"id":37663524,"uuid":"42323222","full_name":"gajus/table","owner":"gajus","description":"Formats data into a string table.","archived":false,"fork":false,"pushed_at":"2025-02-17T12:14:39.000Z","size":2488,"stargazers_count":935,"open_issues_count":28,"forks_count":77,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-08T10:48:41.046Z","etag":null,"topics":["ansi","ascii","cli","text-table"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gajus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"gajus","patreon":"gajus"}},"created_at":"2015-09-11T17:41:56.000Z","updated_at":"2025-05-06T05:52:42.000Z","dependencies_parsed_at":"2024-03-26T08:31:05.832Z","dependency_job_id":"0ec8cbb9-6b68-4c00-ae98-5aa76c27eda4","html_url":"https://github.com/gajus/table","commit_stats":{"total_commits":256,"total_committers":34,"mean_commits":7.529411764705882,"dds":0.62890625,"last_synced_commit":"1a39e0c54989ca1417c5bf8797d2dd896ffa5848"},"previous_names":[],"tags_count":78,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Ftable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Ftable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Ftable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gajus%2Ftable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gajus","download_url":"https://codeload.github.com/gajus/table/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253312097,"owners_count":21888573,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansi","ascii","cli","text-table"],"created_at":"2024-07-31T09:00:32.624Z","updated_at":"2025-05-12T13:15:03.714Z","avatar_url":"https://github.com/gajus.png","language":"TypeScript","readme":"\u003ca name=\"table\"\u003e\u003c/a\u003e\n# Table\n\n\u003e Produces a string that represents array data in a text table.\n\n[![Github action status](https://github.com/gajus/table/actions/workflows/main.yml/badge.svg)](https://github.com/gajus/table/actions)\n[![Coveralls](https://img.shields.io/coveralls/gajus/table.svg?style=flat-square)](https://coveralls.io/github/gajus/table)\n[![NPM version](http://img.shields.io/npm/v/table.svg?style=flat-square)](https://www.npmjs.org/package/table)\n[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)\n[![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social\u0026label=Follow)](https://twitter.com/kuizinas)\n\n* [Table](#table)\n    * [Features](#table-features)\n    * [Install](#table-install)\n    * [Usage](#table-usage)\n    * [API](#table-api)\n        * [table](#table-api-table-1)\n        * [createStream](#table-api-createstream)\n        * [getBorderCharacters](#table-api-getbordercharacters)\n\n\n![Demo of table displaying a list of missions to the Moon.](./.README/demo.png)\n\n\u003ca name=\"table-features\"\u003e\u003c/a\u003e\n## Features\n\n* Works with strings containing [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) characters.\n* Works with strings containing [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code).\n* Configurable border characters.\n* Configurable content alignment per column.\n* Configurable content padding per column.\n* Configurable column width.\n* Text wrapping.\n\n\u003ca name=\"table-install\"\u003e\u003c/a\u003e\n## Install\n\n```bash\nnpm install table\n```\n\n[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/gajus)\n[![Become a Patron](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/gajus)\n\n\n\u003ca name=\"table-usage\"\u003e\u003c/a\u003e\n## Usage\n\n```js\nimport { table } from 'table';\n\n// Using commonjs?\n// const { table } = require('table');\n\nconst data = [\n    ['0A', '0B', '0C'],\n    ['1A', '1B', '1C'],\n    ['2A', '2B', '2C']\n];\n\nconsole.log(table(data));\n```\n\n```\n╔════╤════╤════╗\n║ 0A │ 0B │ 0C ║\n╟────┼────┼────╢\n║ 1A │ 1B │ 1C ║\n╟────┼────┼────╢\n║ 2A │ 2B │ 2C ║\n╚════╧════╧════╝\n\n```\n\n\n\u003ca name=\"table-api\"\u003e\u003c/a\u003e\n## API\n\n\u003ca name=\"table-api-table-1\"\u003e\u003c/a\u003e\n### table\n\nReturns the string in the table format\n\n**Parameters:**\n- **_data_:** The data to display\n  - Type: `any[][]`\n  - Required: `true`\n\n- **_config_:** Table configuration\n  - Type: `object`\n  - Required: `false`\n\n\u003ca name=\"table-api-table-1-config-border\"\u003e\u003c/a\u003e\n##### config.border\n\nType: `{ [type: string]: string }`\\\nDefault: `honeywell` [template](#getbordercharacters)\n\nCustom borders. The keys are any of:\n- `topLeft`, `topRight`, `topBody`,`topJoin`\n- `bottomLeft`, `bottomRight`, `bottomBody`, `bottomJoin`\n- `joinLeft`, `joinRight`, `joinBody`, `joinJoin`\n- `bodyLeft`, `bodyRight`, `bodyJoin`\n- `headerJoin`\n\n```js\nconst data = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconst config = {\n  border: {\n    topBody: `─`,\n    topJoin: `┬`,\n    topLeft: `┌`,\n    topRight: `┐`,\n\n    bottomBody: `─`,\n    bottomJoin: `┴`,\n    bottomLeft: `└`,\n    bottomRight: `┘`,\n\n    bodyLeft: `│`,\n    bodyRight: `│`,\n    bodyJoin: `│`,\n\n    joinBody: `─`,\n    joinLeft: `├`,\n    joinRight: `┤`,\n    joinJoin: `┼`\n  }\n};\n\nconsole.log(table(data, config));\n```\n\n```\n┌────┬────┬────┐\n│ 0A │ 0B │ 0C │\n├────┼────┼────┤\n│ 1A │ 1B │ 1C │\n├────┼────┼────┤\n│ 2A │ 2B │ 2C │\n└────┴────┴────┘\n```\n\n\u003ca name=\"table-api-table-1-config-drawverticalline\"\u003e\u003c/a\u003e\n##### config.drawVerticalLine\n\nType: `(lineIndex: number, columnCount: number) =\u003e boolean`\\\nDefault: `() =\u003e true`\n\nIt is used to tell whether to draw a vertical line. This callback is called for each vertical border of the table.\nIf the table has `n` columns, then the `index` parameter is alternatively received all numbers in range `[0, n]` inclusively.\n\n```js\nconst data = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C'],\n  ['3A', '3B', '3C'],\n  ['4A', '4B', '4C']\n];\n\nconst config = {\n  drawVerticalLine: (lineIndex, columnCount) =\u003e {\n    return lineIndex === 0 || lineIndex === columnCount;\n  }\n};\n\nconsole.log(table(data, config));\n\n```\n\n```\n╔════════════╗\n║ 0A  0B  0C ║\n╟────────────╢\n║ 1A  1B  1C ║\n╟────────────╢\n║ 2A  2B  2C ║\n╟────────────╢\n║ 3A  3B  3C ║\n╟────────────╢\n║ 4A  4B  4C ║\n╚════════════╝\n\n```\n\n\u003ca name=\"table-api-table-1-config-drawhorizontalline\"\u003e\u003c/a\u003e\n##### config.drawHorizontalLine\n\nType: `(lineIndex: number, rowCount: number) =\u003e boolean`\\\nDefault: `() =\u003e true`\n\nIt is used to tell whether to draw a horizontal line. This callback is called for each horizontal border of the table.\nIf the table has `n` rows, then the `index` parameter is alternatively received all numbers in range `[0, n]` inclusively.\nIf the table has `n` rows and contains the header, then the range will be `[0, n+1]` inclusively.\n\n```js\nconst data = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C'],\n  ['3A', '3B', '3C'],\n  ['4A', '4B', '4C']\n];\n\nconst config = {\n  drawHorizontalLine: (lineIndex, rowCount) =\u003e {\n    return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount - 1 || lineIndex === rowCount;\n  }\n};\n\nconsole.log(table(data, config));\n\n```\n\n```\n╔════╤════╤════╗\n║ 0A │ 0B │ 0C ║\n╟────┼────┼────╢\n║ 1A │ 1B │ 1C ║\n║ 2A │ 2B │ 2C ║\n║ 3A │ 3B │ 3C ║\n╟────┼────┼────╢\n║ 4A │ 4B │ 4C ║\n╚════╧════╧════╝\n\n```\n\n\u003ca name=\"table-api-table-1-config-singleline\"\u003e\u003c/a\u003e\n##### config.singleLine\n\nType: `boolean`\\\nDefault: `false`\n\nIf `true`, horizontal lines inside the table are not drawn. This option also overrides the `config.drawHorizontalLine` if specified.\n\n```js\nconst data = [\n  ['-rw-r--r--', '1', 'pandorym', 'staff', '1529', 'May 23 11:25', 'LICENSE'],\n  ['-rw-r--r--', '1', 'pandorym', 'staff', '16327', 'May 23 11:58', 'README.md'],\n  ['drwxr-xr-x', '76', 'pandorym', 'staff', '2432', 'May 23 12:02', 'dist'],\n  ['drwxr-xr-x', '634', 'pandorym', 'staff', '20288', 'May 23 11:54', 'node_modules'],\n  ['-rw-r--r--', '1,', 'pandorym', 'staff', '525688', 'May 23 11:52', 'package-lock.json'],\n  ['-rw-r--r--@', '1', 'pandorym', 'staff', '2440', 'May 23 11:25', 'package.json'],\n  ['drwxr-xr-x', '27', 'pandorym', 'staff', '864', 'May 23 11:25', 'src'],\n  ['drwxr-xr-x', '20', 'pandorym', 'staff', '640', 'May 23 11:25', 'test'],\n];\n\nconst config = {\n  singleLine: true\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔═════════════╤═════╤══════════╤═══════╤════════╤══════════════╤═══════════════════╗\n║ -rw-r--r--  │ 1   │ pandorym │ staff │ 1529   │ May 23 11:25 │ LICENSE           ║\n║ -rw-r--r--  │ 1   │ pandorym │ staff │ 16327  │ May 23 11:58 │ README.md         ║\n║ drwxr-xr-x  │ 76  │ pandorym │ staff │ 2432   │ May 23 12:02 │ dist              ║\n║ drwxr-xr-x  │ 634 │ pandorym │ staff │ 20288  │ May 23 11:54 │ node_modules      ║\n║ -rw-r--r--  │ 1,  │ pandorym │ staff │ 525688 │ May 23 11:52 │ package-lock.json ║\n║ -rw-r--r--@ │ 1   │ pandorym │ staff │ 2440   │ May 23 11:25 │ package.json      ║\n║ drwxr-xr-x  │ 27  │ pandorym │ staff │ 864    │ May 23 11:25 │ src               ║\n║ drwxr-xr-x  │ 20  │ pandorym │ staff │ 640    │ May 23 11:25 │ test              ║\n╚═════════════╧═════╧══════════╧═══════╧════════╧══════════════╧═══════════════════╝\n```\n\n\n\u003ca name=\"table-api-table-1-config-columns\"\u003e\u003c/a\u003e\n##### config.columns\n\nType: `Column[] | { [columnIndex: number]: Column }`\n\nColumn specific configurations.\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-width\"\u003e\u003c/a\u003e\n###### config.columns[*].width\n\nType: `number`\\\nDefault: the maximum cell widths of the column\n\nColumn width (excluding the paddings).\n\n```js\n\nconst data = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconst config = {\n  columns: {\n    1: { width: 10 }\n  }\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔════╤════════════╤════╗\n║ 0A │ 0B         │ 0C ║\n╟────┼────────────┼────╢\n║ 1A │ 1B         │ 1C ║\n╟────┼────────────┼────╢\n║ 2A │ 2B         │ 2C ║\n╚════╧════════════╧════╝\n```\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-alignment\"\u003e\u003c/a\u003e\n###### config.columns[*].alignment\n\nType: `'center' | 'justify' | 'left' | 'right'`\\\nDefault: `'left'`\n\nCell content horizontal alignment\n\n```js\nconst data = [\n  ['0A', '0B', '0C', '0D 0E 0F'],\n  ['1A', '1B', '1C', '1D 1E 1F'],\n  ['2A', '2B', '2C', '2D 2E 2F'],\n];\n\nconst config = {\n  columnDefault: {\n    width: 10,\n  },\n  columns: [\n    { alignment: 'left' },\n    { alignment: 'center' },\n    { alignment: 'right' },\n    { alignment: 'justify' }\n  ],\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔════════════╤════════════╤════════════╤════════════╗\n║ 0A         │     0B     │         0C │ 0D  0E  0F ║\n╟────────────┼────────────┼────────────┼────────────╢\n║ 1A         │     1B     │         1C │ 1D  1E  1F ║\n╟────────────┼────────────┼────────────┼────────────╢\n║ 2A         │     2B     │         2C │ 2D  2E  2F ║\n╚════════════╧════════════╧════════════╧════════════╝\n```\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-verticalalignment\"\u003e\u003c/a\u003e\n###### config.columns[*].verticalAlignment\n\nType: `'top' | 'middle' | 'bottom'`\\\nDefault: `'top'`\n\nCell content vertical alignment\n\n```js\nconst data = [\n  ['A', 'B', 'C', 'DEF'],\n];\n\nconst config = {\n  columnDefault: {\n    width: 1,\n  },\n  columns: [\n    { verticalAlignment: 'top' },\n    { verticalAlignment: 'middle' },\n    { verticalAlignment: 'bottom' },\n  ],\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔═══╤═══╤═══╤═══╗\n║ A │   │   │ D ║\n║   │ B │   │ E ║\n║   │   │ C │ F ║\n╚═══╧═══╧═══╧═══╝\n```\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-paddingleft\"\u003e\u003c/a\u003e\n###### config.columns[*].paddingLeft\n\nType: `number`\\\nDefault: `1`\n\nThe number of whitespaces used to pad the content on the left.\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-paddingright\"\u003e\u003c/a\u003e\n###### config.columns[*].paddingRight\n\nType: `number`\\\nDefault: `1`\n\nThe number of whitespaces used to pad the content on the right.\n\nThe `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`.\n\n\n```js\nconst data = [\n  ['0A', 'AABBCC', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconst config = {\n  columns: [\n    {\n      paddingLeft: 3\n    },\n    {\n      width: 2,\n      paddingRight: 3\n    }\n  ]\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔══════╤══════╤════╗\n║   0A │ AA   │ 0C ║\n║      │ BB   │    ║\n║      │ CC   │    ║\n╟──────┼──────┼────╢\n║   1A │ 1B   │ 1C ║\n╟──────┼──────┼────╢\n║   2A │ 2B   │ 2C ║\n╚══════╧══════╧════╝\n```\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-truncate\"\u003e\u003c/a\u003e\n###### config.columns[*].truncate\n\nType: `number`\\\nDefault: `Infinity`\n\nThe number of characters is which the content will be truncated.\nTo handle a content that overflows the container width, `table` package implements [text wrapping](#config.columns[*].wrapWord). However, sometimes you may want to truncate content that is too long to be displayed in the table.\n\n```js\nconst data = [\n  ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']\n];\n\nconst config = {\n  columns: [\n    {\n      width: 20,\n      truncate: 100\n    }\n  ]\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔══════════════════════╗\n║ Lorem ipsum dolor si ║\n║ t amet, consectetur  ║\n║ adipiscing elit. Pha ║\n║ sellus pulvinar nibh ║\n║ sed mauris convall…  ║\n╚══════════════════════╝\n```\n\n\u003ca name=\"table-api-table-1-config-columns-config-columns-wrapword\"\u003e\u003c/a\u003e\n###### config.columns[*].wrapWord\n\nType: `boolean`\\\nDefault: `false`\n\nThe `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: `\\|/_.,;-`.\n\nWhen `wrapWord` is `false`:\n\n```js\nconst data = [\n    ['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']\n];\n\nconst config = {\n  columns: [ { width: 20 } ]\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔══════════════════════╗\n║ Lorem ipsum dolor si ║\n║ t amet, consectetur  ║\n║ adipiscing elit. Pha ║\n║ sellus pulvinar nibh ║\n║ sed mauris convallis ║\n║ dapibus. Nunc venena ║\n║ tis tempus nulla sit ║\n║ amet viverra.        ║\n╚══════════════════════╝\n```\n\nWhen `wrapWord` is `true`:\n\n```\n╔══════════════════════╗\n║ Lorem ipsum dolor    ║\n║ sit amet,            ║\n║ consectetur          ║\n║ adipiscing elit.     ║\n║ Phasellus pulvinar   ║\n║ nibh sed mauris      ║\n║ convallis dapibus.   ║\n║ Nunc venenatis       ║\n║ tempus nulla sit     ║\n║ amet viverra.        ║\n╚══════════════════════╝\n\n```\n\n\n\u003ca name=\"table-api-table-1-config-columndefault\"\u003e\u003c/a\u003e\n##### config.columnDefault\n\nType: `Column`\\\nDefault: `{}`\n\nThe default configuration for all columns. Column-specific settings will overwrite the default values.\n\n\n\u003ca name=\"table-api-table-1-config-header\"\u003e\u003c/a\u003e\n##### config.header\n\nType: `object`\n\nHeader configuration.\n\n*Deprecated in favor of the new spanning cells API.*\n\nThe header configuration inherits the most of the column's, except:\n- `content` **{string}**: the header content.\n- `width:` calculate based on the content width automatically.\n- `alignment:` `center` be default.\n- `verticalAlignment:` is not supported.\n- `config.border.topJoin` will be `config.border.topBody` for prettier.\n\n```js\nconst data = [\n      ['0A', '0B', '0C'],\n      ['1A', '1B', '1C'],\n      ['2A', '2B', '2C'],\n    ];\n\nconst config = {\n  columnDefault: {\n    width: 10,\n  },\n  header: {\n    alignment: 'center',\n    content: 'THE HEADER\\nThis is the table about something',\n  },\n}\n\nconsole.log(table(data, config));\n```\n\n```\n╔══════════════════════════════════════╗\n║              THE HEADER              ║\n║  This is the table about something   ║\n╟────────────┬────────────┬────────────╢\n║ 0A         │ 0B         │ 0C         ║\n╟────────────┼────────────┼────────────╢\n║ 1A         │ 1B         │ 1C         ║\n╟────────────┼────────────┼────────────╢\n║ 2A         │ 2B         │ 2C         ║\n╚════════════╧════════════╧════════════╝\n```\n\n\n\u003ca name=\"table-api-table-1-config-spanningcells\"\u003e\u003c/a\u003e\n##### config.spanningCells\n\nType: `SpanningCellConfig[]`\n\nSpanning cells configuration.\n\nThe configuration should be straightforward: just specify an array of minimal cell configurations including the position of top-left cell\nand the number of columns and/or rows will be expanded from it.\n\nThe content of overlap cells will be ignored to make the `data` shape be consistent.\n\nBy default, the configuration of column that the top-left cell belongs to will be applied to the whole spanning cell, except:\n* The `width` will be summed up of all spanning columns.\n* The `paddingRight` will be received from the right-most column intentionally.\n\nAdvances customized column-like styles can be configurable to each spanning cell to overwrite the default behavior.\n\n```js\nconst data = [\n  ['Test Coverage Report', '', '', '', '', ''],\n  ['Module', 'Component', 'Test Cases', 'Failures', 'Durations', 'Success Rate'],\n  ['Services', 'User', '50', '30', '3m 7s', '60.0%'],\n  ['', 'Payment', '100', '80', '7m 15s', '80.0%'],\n  ['Subtotal', '', '150', '110', '10m 22s', '73.3%'],\n  ['Controllers', 'User', '24', '18', '1m 30s', '75.0%'],\n  ['', 'Payment', '30', '24', '50s', '80.0%'],\n  ['Subtotal', '', '54', '42', '2m 20s', '77.8%'],\n  ['Total', '', '204', '152', '12m 42s', '74.5%'],\n];\n\nconst config = {\n  columns: [\n    { alignment: 'center', width: 12 },\n    { alignment: 'center', width: 10 },\n    { alignment: 'right' },\n    { alignment: 'right' },\n    { alignment: 'right' },\n    { alignment: 'right' }\n  ],\n  spanningCells: [\n    { col: 0, row: 0, colSpan: 6 },\n    { col: 0, row: 2, rowSpan: 2, verticalAlignment: 'middle'},\n    { col: 0, row: 4, colSpan: 2, alignment: 'right'},\n    { col: 0, row: 5, rowSpan: 2, verticalAlignment: 'middle'},\n    { col: 0, row: 7, colSpan: 2, alignment: 'right' },\n    { col: 0, row: 8, colSpan: 2, alignment: 'right' }\n  ],\n};\n\nconsole.log(table(data, config));\n```\n\n```\n╔══════════════════════════════════════════════════════════════════════════════╗\n║                             Test Coverage Report                             ║\n╟──────────────┬────────────┬────────────┬──────────┬───────────┬──────────────╢\n║    Module    │ Component  │ Test Cases │ Failures │ Durations │ Success Rate ║\n╟──────────────┼────────────┼────────────┼──────────┼───────────┼──────────────╢\n║              │    User    │         50 │       30 │     3m 7s │        60.0% ║\n║   Services   ├────────────┼────────────┼──────────┼───────────┼──────────────╢\n║              │  Payment   │        100 │       80 │    7m 15s │        80.0% ║\n╟──────────────┴────────────┼────────────┼──────────┼───────────┼──────────────╢\n║                  Subtotal │        150 │      110 │   10m 22s │        73.3% ║\n╟──────────────┬────────────┼────────────┼──────────┼───────────┼──────────────╢\n║              │    User    │         24 │       18 │    1m 30s │        75.0% ║\n║ Controllers  ├────────────┼────────────┼──────────┼───────────┼──────────────╢\n║              │  Payment   │         30 │       24 │       50s │        80.0% ║\n╟──────────────┴────────────┼────────────┼──────────┼───────────┼──────────────╢\n║                  Subtotal │         54 │       42 │    2m 20s │        77.8% ║\n╟───────────────────────────┼────────────┼──────────┼───────────┼──────────────╢\n║                     Total │        204 │      152 │   12m 42s │        74.5% ║\n╚═══════════════════════════╧════════════╧══════════╧═══════════╧══════════════╝\n```\n\n\n\u003ca name=\"table-api-createstream\"\u003e\u003c/a\u003e\n### createStream\n\n`table` package exports `createStream` function used to draw a table and append rows.\n\n**Parameter:**\n - _**config:**_ the same as `table`'s, except `config.columnDefault.width` and `config.columnCount` must be provided.\n\n\n```js\nimport { createStream } from 'table';\n\nconst config = {\n  columnDefault: {\n    width: 50\n  },\n  columnCount: 1\n};\n\nconst stream = createStream(config);\n\nsetInterval(() =\u003e {\n  stream.write([new Date()]);\n}, 500);\n```\n\n![Streaming current date.](./.README/api/stream/streaming.gif)\n\n`table` package uses ANSI escape codes to overwrite the output of the last line when a new row is printed.\n\nThe underlying implementation is explained in this [Stack Overflow answer](http://stackoverflow.com/a/32938658/368691).\n\nStreaming supports all of the configuration properties and functionality of a static table (such as auto text wrapping, alignment and padding), e.g.\n\n```js\nimport { createStream } from 'table';\n\nimport _ from 'lodash';\n\nconst config = {\n  columnDefault: {\n    width: 50\n  },\n  columnCount: 3,\n  columns: [\n    {\n      width: 10,\n      alignment: 'right'\n    },\n    { alignment: 'center' },\n    { width: 10 }\n\n  ]\n};\n\nconst stream = createStream(config);\n\nlet i = 0;\n\nsetInterval(() =\u003e {\n  let random;\n\n  random = _.sample('abcdefghijklmnopqrstuvwxyz', _.random(1, 30)).join('');\n\n  stream.write([i++, new Date(), random]);\n}, 500);\n```\n\n![Streaming random data.](./.README/api/stream/streaming-random.gif)\n\n\n\u003ca name=\"table-api-getbordercharacters\"\u003e\u003c/a\u003e\n### getBorderCharacters\n\n**Parameter:**\n - **_template_**\n   - Type: `'honeywell' | 'norc' | 'ramac' | 'void'`\n   - Required: `true`\n\nYou can load one of the predefined border templates using `getBorderCharacters` function.\n\n```js\nimport { table, getBorderCharacters } from 'table';\n\nconst data = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconst config = {\n  border: getBorderCharacters(`name of the template`)\n};\n\nconsole.log(table(data, config));\n```\n\n```\n# honeywell\n\n╔════╤════╤════╗\n║ 0A │ 0B │ 0C ║\n╟────┼────┼────╢\n║ 1A │ 1B │ 1C ║\n╟────┼────┼────╢\n║ 2A │ 2B │ 2C ║\n╚════╧════╧════╝\n\n# norc\n\n┌────┬────┬────┐\n│ 0A │ 0B │ 0C │\n├────┼────┼────┤\n│ 1A │ 1B │ 1C │\n├────┼────┼────┤\n│ 2A │ 2B │ 2C │\n└────┴────┴────┘\n\n# ramac (ASCII; for use in terminals that do not support Unicode characters)\n\n+----+----+----+\n| 0A | 0B | 0C |\n|----|----|----|\n| 1A | 1B | 1C |\n|----|----|----|\n| 2A | 2B | 2C |\n+----+----+----+\n\n# void (no borders; see \"borderless table\" section of the documentation)\n\n 0A  0B  0C\n\n 1A  1B  1C\n\n 2A  2B  2C\n\n```\n\nRaise [an issue](https://github.com/gajus/table/issues) if you'd like to contribute a new border template.\n\n\u003ca name=\"table-api-getbordercharacters-borderless-table\"\u003e\u003c/a\u003e\n#### Borderless Table\n\nSimply using `void` border character template creates a table with a lot of unnecessary spacing.\n\nTo create a more pleasant to the eye table, reset the padding and remove the joining rows, e.g.\n\n```js\n\nconst output = table(data, {\n    border: getBorderCharacters('void'),\n    columnDefault: {\n        paddingLeft: 0,\n        paddingRight: 1\n    },\n    drawHorizontalLine: () =\u003e false\n    }\n);\n\nconsole.log(output);\n```\n\n```\n0A 0B 0C\n1A 1B 1C\n2A 2B 2C\n```\n\n","funding_links":["https://github.com/sponsors/gajus","https://patreon.com/gajus","https://www.buymeacoffee.com/gajus","https://www.patreon.com/gajus"],"categories":["TypeScript","Utilities","Uncategorized","JavaScript"],"sub_categories":["React Components","Uncategorized","Node"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Ftable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgajus%2Ftable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgajus%2Ftable/lists"}