{"_id":"@zkochan/table","_rev":"950109","name":"@zkochan/table","description":"Formats data into a string table.","dist-tags":{"latest":"1.0.0"},"maintainers":[{"name":"npm:zkochan","email":""}],"time":{"modified":"2021-09-23T02:23:21.000Z","created":"2020-10-28T20:34:59.396Z","1.0.0":"2020-10-28T20:34:59.396Z"},"users":{},"author":{"name":"Gajus Kuizinas","email":"gajus@gajus.com","url":"http://gajus.com"},"repository":{"type":"git","url":"git+https://github.com/gajus/table.git"},"versions":{"1.0.0":{"author":{"name":"Gajus Kuizinas","email":"gajus@gajus.com","url":"http://gajus.com"},"dependencies":{"@arcanis/slice-ansi":"^1.0.2","ajv":"^6.12.4","lodash":"^4.17.20","string-width":"^4.2.0"},"description":"Formats data into a string table.","devDependencies":{"@babel/cli":"^7.10.5","@babel/core":"^7.11.4","@babel/node":"^7.10.5","@babel/plugin-transform-flow-strip-types":"^7.10.4","@babel/preset-env":"^7.11.0","@babel/register":"^7.10.5","ajv-cli":"^3.2.1","ajv-keywords":"^3.5.2","babel-plugin-istanbul":"^6.0.0","babel-plugin-lodash":"^3.3.4","babel-plugin-transform-export-default-name":"^2.0.4","chai":"^4.2.0","chalk":"^4.1.0","coveralls":"^3.1.0","eslint":"^7.7.0","eslint-config-canonical":"^23.0.1","flow-bin":"^0.132.0","flow-copy-source":"^2.0.9","gitdown":"^3.1.3","husky":"^4.2.5","mocha":"^8.1.3","nyc":"^15.1.0","semantic-release":"^17.1.1","sinon":"^9.0.3"},"engines":{"node":">=10.0.0"},"husky":{"hooks":{"post-commit":"npm run create-readme && git add README.md && git commit -m 'docs: generate docs' --no-verify","pre-commit":"npm run lint && npm run test && npm run build"}},"keywords":["ascii","text","table","align","ansi"],"license":"BSD-3-Clause","main":"./dist/index.js","name":"@zkochan/table","nyc":{"include":["src/**/*.js"],"instrument":false,"reporter":["text-lcov"],"require":["@babel/register"],"sourceMap":false},"repository":{"type":"git","url":"git+https://github.com/gajus/table.git"},"scripts":{"build":"rm -fr ./dist && NODE_ENV=production babel ./src --out-dir ./dist --copy-files --source-maps && npm run create-validators && flow-copy-source src dist","create-readme":"gitdown ./.README/README.md --output-file ./README.md","create-validators":"ajv compile --all-errors --inline-refs=false -s src/schemas/config -c ajv-keywords/keywords/typeof -o dist/validateConfig.js && ajv compile --all-errors --inline-refs=false -s src/schemas/streamConfig -c ajv-keywords/keywords/typeof -o dist/validateStreamConfig.js","lint":"npm run build && eslint ./src ./test && flow","test":"mocha --require @babel/register"},"version":"1.0.0","gitHead":"9c4b12673ab733d313c55f332db7ccc197c63e6c","bugs":{"url":"https://github.com/gajus/table/issues"},"homepage":"https://github.com/gajus/table#readme","_id":"@zkochan/table@1.0.0","_nodeVersion":"12.18.3","_npmVersion":"7.0.6","dist":{"shasum":"8f23361b74773db632c3cf1000883e41c7a50100","size":116955,"noattachment":false,"key":"/@zkochan/table/-/@zkochan/table-1.0.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/@zkochan/table/download/@zkochan/table-1.0.0.tgz"},"maintainers":[{"name":"npm:zkochan","email":""}],"_npmUser":{"name":"zkochan","email":"z@kochan.io"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/table_1.0.0_1603917299164_0.11768611437076326"},"_hasShrinkwrap":false,"publish_time":1603917299396,"_cnpm_publish_time":1603917299396}},"readme":"<a name=\"table\"></a>\n# Table\n\n[![GitSpo Mentions](https://gitspo.com/badges/mentions/gajus/table?style=flat-square)](https://gitspo.com/mentions/gajus/table)\n[![Travis build status](http://img.shields.io/travis/gajus/table/master.svg?style=flat-square)](https://travis-ci.org/gajus/table)\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&label=Follow)](https://twitter.com/kuizinas)\n\n* [Table](#table)\n    * [Features](#table-features)\n    * [Install](#table-install)\n    * [Usage](#table-usage)\n        * [Cell Content Alignment](#table-usage-cell-content-alignment)\n        * [Column Width](#table-usage-column-width)\n        * [Custom Border](#table-usage-custom-border)\n        * [Draw Horizontal Line](#table-usage-draw-horizontal-line)\n        * [Single Line Mode](#table-usage-single-line-mode)\n        * [Padding Cell Content](#table-usage-padding-cell-content)\n        * [Predefined Border Templates](#table-usage-predefined-border-templates)\n        * [Streaming](#table-usage-streaming)\n        * [Text Truncation](#table-usage-text-truncation)\n        * [Text Wrapping](#table-usage-text-wrapping)\n\n\nProduces a string that represents array data in a text table.\n\n![Demo of table displaying a list of missions to the Moon.](./.README/demo.png)\n\n<a name=\"table-features\"></a>\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<a name=\"table-install\"></a>\n## Install\n\n```bash\nnpm install table\n\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<a name=\"table-usage\"></a>\n## Usage\n\nTable data is described using an array (rows) of array (cells).\n\n```js\nimport {\n  table\n} from 'table';\n\n// Using commonjs?\n// const {table} = require('table');\n\nlet data,\n    output;\n\ndata = [\n    ['0A', '0B', '0C'],\n    ['1A', '1B', '1C'],\n    ['2A', '2B', '2C']\n];\n\n/**\n * @typedef {string} table~cell\n */\n\n/**\n * @typedef {table~cell[]} table~row\n */\n\n/**\n * @typedef {Object} table~columns\n * @property {string} alignment Cell content alignment (enum: left, center, right) (default: left).\n * @property {number} width Column width (default: auto).\n * @property {number} truncate Number of characters are which the content will be truncated (default: Infinity).\n * @property {number} paddingLeft Cell content padding width left (default: 1).\n * @property {number} paddingRight Cell content padding width right (default: 1).\n */\n\n/**\n * @typedef {Object} table~border\n * @property {string} topBody\n * @property {string} topJoin\n * @property {string} topLeft\n * @property {string} topRight\n * @property {string} bottomBody\n * @property {string} bottomJoin\n * @property {string} bottomLeft\n * @property {string} bottomRight\n * @property {string} bodyLeft\n * @property {string} bodyRight\n * @property {string} bodyJoin\n * @property {string} joinBody\n * @property {string} joinLeft\n * @property {string} joinRight\n * @property {string} joinJoin\n */\n\n/**\n * Used to dynamically tell table whether to draw a line separating rows or not.\n * The default behavior is to always return true.\n *\n * @typedef {function} drawHorizontalLine\n * @param {number} index\n * @param {number} size\n * @return {boolean}\n */\n\n/**\n * @typedef {Object} table~config\n * @property {table~border} border\n * @property {table~columns[]} columns Column specific configuration.\n * @property {table~columns} columnDefault Default values for all columns. Column specific settings overwrite the default values.\n * @property {table~drawHorizontalLine} drawHorizontalLine\n */\n\n/**\n * Generates a text table.\n *\n * @param {table~row[]} rows\n * @param {table~config} config\n * @return {String}\n */\noutput = table(data);\n\nconsole.log(output);\n```\n\n```\n╔════╤════╤════╗\n║ 0A │ 0B │ 0C ║\n╟────┼────┼────╢\n║ 1A │ 1B │ 1C ║\n╟────┼────┼────╢\n║ 2A │ 2B │ 2C ║\n╚════╧════╧════╝\n\n```\n\n\n<a name=\"table-usage-cell-content-alignment\"></a>\n### Cell Content Alignment\n\n`{string} config.columns[{number}].alignment` property controls content horizontal alignment within a cell.\n\nValid values are: \"left\", \"right\" and \"center\".\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconfig = {\n  columns: {\n    0: {\n      alignment: 'left',\n      width: 10\n    },\n    1: {\n      alignment: 'center',\n      width: 10\n    },\n    2: {\n      alignment: 'right',\n      width: 10\n    }\n  }\n};\n\noutput = table(data, config);\n\nconsole.log(output);\n```\n\n```\n╔════════════╤════════════╤════════════╗\n║ 0A         │     0B     │         0C ║\n╟────────────┼────────────┼────────────╢\n║ 1A         │     1B     │         1C ║\n╟────────────┼────────────┼────────────╢\n║ 2A         │     2B     │         2C ║\n╚════════════╧════════════╧════════════╝\n```\n\n<a name=\"table-usage-column-width\"></a>\n### Column Width\n\n`{number} config.columns[{number}].width` property restricts column width to a fixed width.\n\n```js\nlet data,\n  output,\n  options;\n\ndata = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\noptions = {\n  columns: {\n    1: {\n      width: 10\n    }\n  }\n};\n\noutput = table(data, options);\n\nconsole.log(output);\n```\n\n```\n╔════╤════════════╤════╗\n║ 0A │ 0B         │ 0C ║\n╟────┼────────────┼────╢\n║ 1A │ 1B         │ 1C ║\n╟────┼────────────┼────╢\n║ 2A │ 2B         │ 2C ║\n╚════╧════════════╧════╝\n```\n\n<a name=\"table-usage-custom-border\"></a>\n### Custom Border\n\n`{object} config.border` property describes characters used to draw the table border.\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconfig = {\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\noutput = table(data, config);\n\nconsole.log(output);\n```\n\n```\n┌────┬────┬────┐\n│ 0A │ 0B │ 0C │\n├────┼────┼────┤\n│ 1A │ 1B │ 1C │\n├────┼────┼────┤\n│ 2A │ 2B │ 2C │\n└────┴────┴────┘\n```\n\n<a name=\"table-usage-draw-horizontal-line\"></a>\n### Draw Horizontal Line\n\n`{function} config.drawHorizontalLine` property is a function that is called for every non-content row in the table. The result of the function `{boolean}` determines whether a row is drawn.\n\n```js\nlet data,\n  output,\n  options;\n\ndata = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C'],\n  ['3A', '3B', '3C'],\n  ['4A', '4B', '4C']\n];\n\noptions = {\n  /**\n    * @typedef {function} drawHorizontalLine\n    * @param {number} index\n    * @param {number} size\n    * @return {boolean}\n    */\n  drawHorizontalLine: (index, size) => {\n    return index === 0 || index === 1 || index === size - 1 || index === size;\n  }\n};\n\noutput = table(data, options);\n\nconsole.log(output);\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<a name=\"table-usage-single-line-mode\"></a>\n### Single Line Mode\n\nHorizontal lines inside the table are not drawn.\n\n```js\nimport {\n  table,\n  getBorderCharacters\n} from 'table';\n\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\nconst output = table(data, config);\nconsole.log(output);\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<a name=\"table-usage-padding-cell-content\"></a>\n### Padding Cell Content\n\n`{number} config.columns[{number}].paddingLeft` and `{number} config.columns[{number}].paddingRight` properties control content padding within a cell. Property value represents a number of whitespaces used to pad the content.\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\n  ['0A', 'AABBCC', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconfig = {\n  columns: {\n    0: {\n      paddingLeft: 3\n    },\n    1: {\n      width: 2,\n      paddingRight: 3\n    }\n  }\n};\n\noutput = table(data, config);\n\nconsole.log(output);\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<a name=\"table-usage-predefined-border-templates\"></a>\n### Predefined Border Templates\n\nYou can load one of the predefined border templates using `getBorderCharacters` function.\n\n```js\nimport {\n  table,\n  getBorderCharacters\n} from 'table';\n\nlet config,\n  data;\n\ndata = [\n  ['0A', '0B', '0C'],\n  ['1A', '1B', '1C'],\n  ['2A', '2B', '2C']\n];\n\nconfig = {\n  border: getBorderCharacters(`name of the template`)\n};\n\ntable(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 \"bordless 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<a name=\"table-usage-predefined-border-templates-borderless-table\"></a>\n#### Borderless Table\n\nSimply using \"void\" border character template creates a table with a lot of unnecessary spacing.\n\nTo create a more plesant to the eye table, reset the padding and remove the joining rows, e.g.\n\n```js\nlet output;\n\noutput = table(data, {\n    border: getBorderCharacters(`void`),\n    columnDefault: {\n        paddingLeft: 0,\n        paddingRight: 1\n    },\n    drawHorizontalLine: () => {\n        return false\n    }\n});\n\nconsole.log(output);\n```\n\n```\n0A 0B 0C\n1A 1B 1C\n2A 2B 2C\n```\n\n<a name=\"table-usage-streaming\"></a>\n### Streaming\n\n`table` package exports `createStream` function used to draw a table and append rows.\n\n`createStream` requires `{number} columnDefault.width` and `{number} columnCount` configuration properties.\n\n```js\nimport {\n  createStream\n} from 'table';\n\nlet config,\n  stream;\n\nconfig = {\n  columnDefault: {\n    width: 50\n  },\n  columnCount: 1\n};\n\nstream = createStream(config);\n\nsetInterval(() => {\n  stream.write([new Date()]);\n}, 500);\n```\n\n![Streaming current date.](./.README/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 {\n  createStream\n} from 'table';\n\nimport _ from 'lodash';\n\nlet config,\n  stream,\n  i;\n\nconfig = {\n  columnDefault: {\n    width: 50\n  },\n  columnCount: 3,\n  columns: {\n    0: {\n      width: 10,\n      alignment: 'right'\n    },\n    1: {\n      alignment: 'center',\n    },\n    2: {\n      width: 10\n    }\n  }\n};\n\nstream = createStream(config);\n\ni = 0;\n\nsetInterval(() => {\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/streaming-random.gif)\n\n<a name=\"table-usage-text-truncation\"></a>\n### Text Truncation\n\nTo handle a content that overflows the container width, `table` package implements [text wrapping](#table-usage-text-wrapping). However, sometimes you may want to truncate content that is too long to be displayed in the table.\n\n`{number} config.columns[{number}].truncate` property (default: `Infinity`) truncates the text at the specified length.\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\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\nconfig = {\n  columns: {\n    0: {\n      width: 20,\n      truncate: 100\n    }\n  }\n};\n\noutput = table(data, config);\n\nconsole.log(output);\n```\n\n```\n╔══════════════════════╗\n║ Lorem ipsum dolor si ║\n║ t amet, consectetur  ║\n║ adipiscing elit. Pha ║\n║ sellus pulvinar nibh ║\n║ sed mauris conva...  ║\n╚══════════════════════╝\n```\n\n<a name=\"table-usage-text-wrapping\"></a>\n### Text Wrapping\n\n`table` package implements auto text wrapping, i.e. text that has width greater than the container width will be separated into multiple lines, e.g.\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\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\nconfig = {\n  columns: {\n    0: {\n      width: 20\n    }\n  }\n};\n\noutput = table(data, config);\n\nconsole.log(output);\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` the text is broken at the nearest space or one of the special characters (\"-\", \"_\", \"\\\", \"/\", \".\", \",\", \";\"), e.g.\n\n```js\nlet config,\n  data,\n  output;\n\ndata = [\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\nconfig = {\n  columns: {\n    0: {\n      width: 20,\n      wrapWord: true\n    }\n  }\n};\n\noutput = table(data, config);\n\nconsole.log(output);\n```\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","_attachments":{},"homepage":"https://github.com/gajus/table#readme","bugs":{"url":"https://github.com/gajus/table/issues"},"license":"BSD-3-Clause"}