UNPKG

terminal-columns

Version:
356 lines (275 loc) 9.27 kB
# terminal-columns <!-- <a href="https://npm.im/terminal-columns"><img src="https://badgen.net/npm/v/terminal-columns"></a> <a href="https://npm.im/terminal-columns"><img src="https://badgen.net/npm/dm/terminal-columns"></a> <a href="https://packagephobia.now.sh/result?p=terminal-columns"><img src="https://packagephobia.now.sh/badge?p=terminal-columns"></a> --> Readable tables for the terminal. <p align="center"> <img src=".github/demo.gif" width="450"> <br> <em>Tables can be automatically responsive!</em> </p> ### Features - Content wrapped to fit column width - Column widths `auto`, `content-width`, viewport percents & static values - Align left & right - Horizontal & vertical padding - Rows can overflow into multiple rows - Easy to make responsive tables → [Try it out online](https://stackblitz.com/edit/terminal-columns-demo?devtoolsheight=50&file=examples/responsive-table.js&view=editor) <sub>Support this project by ⭐️ starring and sharing it. [Follow me](https://github.com/privatenumber) to see what other cool projects I'm working on! ❤️</sub> ## 🚀 Install ```bash npm i terminal-columns ``` ## 🚦 Quick start Render a table by passing table data into `terminal-columns` and writing it to stdout. ```ts import { terminalColumns } from 'terminal-columns' // Create table data const tableData = [ ['Cell A1', 'Cell B1', 'Cell C1'], ['Cell A2', 'Cell B2', 'Cell C2'], ['Cell A3', 'Cell B3', 'Cell C3'] ] // Render table const tableString = terminalColumns(tableData) console.log(tableString) ``` By default, the columns will be rendered with the `auto` width, which splits the available width with other `auto` columns. To configure the width of each column, pass them in as the second argument. ```ts const tableString = terminalColumns( tableData, // Configure column widths [ 'content-width', // Use the width of the content '50%', // Fill 50% of viewport width 'auto' // Fill remaining width ] ) ``` ## 📖 Examples ### Fixed width table You can set a fixed width for each column by passing in a the number of columns. However, note that this will wrap the row to the next line if the viewport width is smaller than the table width. ```ts terminalColumns( tableData, [ 30, 30, 30 ] ) ``` ### Fixed width table with no row-wrapping You can change the row-wrapping behavior by telling terminal-columns to use a different viewport width via the `stdoutColumns` option. For example, passing in `Infinity` will trick it into thinking the table is never overflowing the viewport width. ```ts terminalColumns( tableData, { stdoutColumns: Number.POSITIVE_INFINITY, columns: [ 30, 30, 30 ] } ) ``` ### Padding You can add padding to each column by setting `paddingLeft`, `paddingRight`, `paddingTop`, or `paddingBottom` on the column. ```ts terminalColumns( tableData, [ { paddingLeft: 2 // Pad the left side of the cell with 2 spaces }, { paddingRight: 2 // Pad the right side of the cell with 2 spaces }, { paddingTop: 2 // Pad the top of the cell with 2 lines }, { paddingBottom: 2 // Pad the bottom of the cell with 2 lines } ] ) ``` ### Right align text You can align the content of the column by setting `align: 'right'`. ```ts terminalColumns( tableData, [ { align: 'right' } ] ) ``` ### Responsive table with breakpoints function Define breakpoints declaratively with the `breakpoints` function. ```ts import { terminalColumns, breakpoints } from 'terminal-columns' terminalColumns( tableData, breakpoints({ // Large screens '>= 90': ['content-width', 'auto'], // Small screens '>= 25': ['100%', '100%'], // Tiny screens - remove responsiveness '>= 0': { columns: ['content-width', 'content-width'], stdoutColumns: Number.POSITIVE_INFINITY } }) ) ``` ### Preprocess / Postprocess Preprocessing and postprocessing can be used to modify the table data before it is rendered. It's primarily designed for formatting purposes and can be useful to style text in a declarative manner. In this example, the first column spans the entire screen and is transformed to be uppercase on screens smaller than 80 columns. ```ts terminalColumns( tableData, breakpoints({ // Small screens '< 80': [ { width: '100%', preprocess: text => text.toUpperCase() }, '100%' ] }) ) ``` ### Responsive table with custom function You can make the table responsive by passing in a function that computes the column width allocation based on the detected viewport width. For a working example, see [this example](/examples/responsive-table.ts). ```ts terminalColumns( tableData, (stdoutColumns) => { /** * For large viewports * Split screen automatically */ if (stdoutColumns > 100) { return [ { width: 'auto', paddingRight: 1 }, { width: 'auto' } ] } /** * For medium viewports * Break table row into two rows, and add vertical padding to create * a divider between rows */ if (stdoutColumns > 30) { return [ { width: '100%' }, { width: '100%', paddingBottom: 1 } ] } /** * For viewports smaller than or equal to 30 columns * In this case, the screen is too small to render anything. * Simply remove responsiveness and assume the viewport width * is actually 1000 columns. */ return { // Remove responsiveness stdoutColumns: 1000, columns: [ { width: 'content-width', paddingRight: 1 }, { width: 'content-width' } ] } } ) ``` ## ⚙️ API ### terminalColumns(tableData, options?) Return type: `string` Takes in table data and outputs a string that represents the table within the current terminal width (`process.stdout.columns`). #### tableData Type: `string[][]` Required A nested array where the first-level are "rows", and the second-level are "columns". #### options Type: `OptionsObject | (stdoutColumns: number) => OptionsObject | ColumnMetasArray` Schema: ```ts type Options = OptionsObject | OptionsFunction type OptionsObject = ColumnMetasArray | { columns: ColumnMetasArray stdoutColumns?: number } type OptionsFunction = (stdoutColumns: number) => OptionsObject type ColumnMetasArray = (ColumnWidth | ColumnMeta)[] type ColumnWidth = number | 'content-width' | 'auto' | string type ColumnMeta = { width: ColumnWidth paddingRight?: number paddingLeft?: number paddingTop?: number paddingBottom?: number align?: 'left' | 'right' } ``` Options to define the column widths (default is `auto`) and the stdout columns to use. #### stdoutColumns Type: `number` Default: `process.stdout.columns` The number of columns in the terminal. Autodetected by default. This is used to calculate the max-width of the table and can be overriden to force a specific width. #### columns Type: `Object` ##### width Type: `number | 'content-width' | 'auto' | string` - `number`: number of columns to span - `'content-width'`: The width of the content in the column - `'auto'`: Allocate the remaining width of the row to the column - `string`: Percentage of the viewport width to use (e.g. `'50%'`) For all of these values, the max width is `stdoutColumns`. ##### paddingLeft Type: `number` How many spaces to the left the column should have ##### paddingRight Type: `number` How many spaces to the right the column should have ##### paddingTop Type: `number` How many new lines to the top the column should have ##### paddingBottom Type: `number` How many new lines to the bottom the column should have ##### align Type: `'left' | 'right'` Default: `'left'` Whether to align the text to the left or right. ##### preprocess Type: `(cellValue: string) => string` Function to preprocess the cell value before it is wrapped to the column width. ##### postprocess Type: `(line: string, lineNumber: number) => string` Function to postprocess the individual lines of a cell after it has been wrapped to the column width. ### breakpoints(breakpointsMap) A function to declaratively define breakpoints. Returns a function pass into terminal-columns. #### breakpointsMap Type: `Record<string, Options>` An object mapping breakpoints to options. The key must be in the format: `<operator> <stdout-columns>`. For example, `>= 90` will match if the terminal width is 90 or more.