{"id":16347724,"url":"https://github.com/privatenumber/terminal-columns","last_synced_at":"2025-04-06T06:06:39.307Z","repository":{"id":45157260,"uuid":"442337995","full_name":"privatenumber/terminal-columns","owner":"privatenumber","description":"Render readable \u0026 responsive tables in the terminal","archived":false,"fork":false,"pushed_at":"2025-02-11T12:25:52.000Z","size":1884,"stargazers_count":53,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-03-30T05:03:32.191Z","etag":null,"topics":["cli","columns","readable","responsive","table","typescript","wrapping"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/privatenumber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-28T03:27:56.000Z","updated_at":"2025-03-29T13:29:48.000Z","dependencies_parsed_at":"2022-09-07T17:22:17.089Z","dependency_job_id":null,"html_url":"https://github.com/privatenumber/terminal-columns","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/privatenumber%2Fterminal-columns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/privatenumber%2Fterminal-columns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/privatenumber%2Fterminal-columns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/privatenumber%2Fterminal-columns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/privatenumber","download_url":"https://codeload.github.com/privatenumber/terminal-columns/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441042,"owners_count":20939239,"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":["cli","columns","readable","responsive","table","typescript","wrapping"],"created_at":"2024-10-11T00:45:18.896Z","updated_at":"2025-04-06T06:06:39.282Z","avatar_url":"https://github.com/privatenumber.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# terminal-columns \u003c!-- \u003ca href=\"https://npm.im/terminal-columns\"\u003e\u003cimg src=\"https://badgen.net/npm/v/terminal-columns\"\u003e\u003c/a\u003e \u003ca href=\"https://npm.im/terminal-columns\"\u003e\u003cimg src=\"https://badgen.net/npm/dm/terminal-columns\"\u003e\u003c/a\u003e \u003ca href=\"https://packagephobia.now.sh/result?p=terminal-columns\"\u003e\u003cimg src=\"https://packagephobia.now.sh/badge?p=terminal-columns\"\u003e\u003c/a\u003e --\u003e\n\nReadable tables for the terminal.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\".github/demo.gif\" width=\"450\"\u003e\n    \u003cbr\u003e\n    \u003cem\u003eTables can be automatically responsive!\u003c/em\u003e\n\u003c/p\u003e\n\n### Features\n- Content wrapped to fit column width\n- Column widths `auto`, `content-width`, viewport percents \u0026 static values\n- Align left \u0026 right\n- Horizontal \u0026 vertical padding\n- Rows can overflow into multiple rows\n- Easy to make responsive tables\n\n→ [Try it out online](https://stackblitz.com/edit/terminal-columns-demo?devtoolsheight=50\u0026file=examples/responsive-table.js\u0026view=editor)\n\n\u003csub\u003eSupport this project by ⭐️ starring and sharing it. [Follow me](https://github.com/privatenumber) to see what other cool projects I'm working on! ❤️\u003c/sub\u003e\n\n## 🚀 Install\n\n```bash\nnpm i terminal-columns\n```\n\n## 🚦 Quick start\nRender a table by passing table data into `terminal-columns` and writing it to stdout.\n\n```ts\nimport { terminalColumns } from 'terminal-columns'\n\n// Create table data\nconst tableData = [\n    ['Cell A1', 'Cell B1', 'Cell C1'],\n    ['Cell A2', 'Cell B2', 'Cell C2'],\n    ['Cell A3', 'Cell B3', 'Cell C3']\n]\n\n// Render table\nconst tableString = terminalColumns(tableData)\nconsole.log(tableString)\n```\n\nBy 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.\n\n```ts\nconst tableString = terminalColumns(\n    tableData,\n\n    // Configure column widths\n    [\n        'content-width', // Use the width of the content\n        '50%', // Fill 50% of viewport width\n        'auto' // Fill remaining width\n    ]\n)\n```\n\n## 📖 Examples\n\n### Fixed width table\nYou can set a fixed width for each column by passing in a the number of columns.\n\nHowever, note that this will wrap the row to the next line if the viewport width is smaller than the table width.\n\n```ts\nterminalColumns(\n    tableData,\n    [\n        30,\n        30,\n        30\n    ]\n)\n```\n\n### Fixed width table with no row-wrapping\nYou 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.\n\n```ts\nterminalColumns(\n    tableData,\n    {\n        stdoutColumns: Number.POSITIVE_INFINITY,\n        columns: [\n            30,\n            30,\n            30\n        ]\n    }\n)\n```\n\n### Padding\nYou can add padding to each column by setting `paddingLeft`, `paddingRight`, `paddingTop`, or `paddingBottom` on the column.\n\n```ts\nterminalColumns(\n    tableData,\n    [\n        {\n            paddingLeft: 2 // Pad the left side of the cell with 2 spaces\n        },\n        {\n            paddingRight: 2 // Pad the right side of the cell with 2 spaces\n        },\n        {\n            paddingTop: 2 // Pad the top of the cell with 2 lines\n        },\n        {\n            paddingBottom: 2 // Pad the bottom of the cell with 2 lines\n        }\n    ]\n)\n```\n\n### Right align text\nYou can align the content of the column by setting `align: 'right'`.\n\n```ts\nterminalColumns(\n    tableData,\n    [\n        {\n            align: 'right'\n        }\n    ]\n)\n```\n\n### Responsive table with breakpoints function\nDefine breakpoints declaratively with the `breakpoints` function.\n\n```ts\nimport { terminalColumns, breakpoints } from 'terminal-columns'\n\nterminalColumns(\n    tableData,\n    breakpoints({\n        // Large screens\n        '\u003e= 90': ['content-width', 'auto'],\n\n        // Small screens\n        '\u003e= 25': ['100%', '100%'],\n\n        // Tiny screens - remove responsiveness\n        '\u003e= 0': {\n            columns: ['content-width', 'content-width'],\n            stdoutColumns: Number.POSITIVE_INFINITY\n        }\n    })\n)\n```\n\n### Preprocess / Postprocess\nPreprocessing 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.\n\nIn this example, the first column spans the entire screen and is transformed to be uppercase on screens smaller than 80 columns.\n\n```ts\nterminalColumns(\n    tableData,\n    breakpoints({\n        // Small screens\n        '\u003c 80': [\n            {\n                width: '100%',\n                preprocess: text =\u003e text.toUpperCase()\n            },\n            '100%'\n        ]\n    })\n)\n```\n\n### Responsive table with custom function\nYou can make the table responsive by passing in a function that computes the column width allocation based on the detected viewport width.\n\nFor a working example, see [this example](/examples/responsive-table.ts).\n\n```ts\nterminalColumns(\n    tableData,\n    (stdoutColumns) =\u003e {\n        /**\n         * For large viewports\n         * Split screen automatically\n         */\n        if (stdoutColumns \u003e 100) {\n            return [\n                {\n                    width: 'auto',\n                    paddingRight: 1\n                },\n                {\n                    width: 'auto'\n                }\n            ]\n        }\n\n        /**\n         * For medium viewports\n         * Break table row into two rows, and add vertical padding to create\n         * a divider between rows\n         */\n        if (stdoutColumns \u003e 30) {\n            return [\n                {\n                    width: '100%'\n                },\n                {\n                    width: '100%',\n                    paddingBottom: 1\n                }\n            ]\n        }\n\n        /**\n         * For viewports smaller than or equal to 30 columns\n         * In this case, the screen is too small to render anything.\n         * Simply remove responsiveness and assume the viewport width\n         * is actually 1000 columns.\n         */\n        return {\n            // Remove responsiveness\n            stdoutColumns: 1000,\n            columns: [\n                {\n                    width: 'content-width',\n                    paddingRight: 1\n                },\n                {\n                    width: 'content-width'\n                }\n            ]\n        }\n    }\n)\n```\n\n\n## ⚙️ API\n\n### terminalColumns(tableData, options?)\nReturn type: `string`\n\nTakes in table data and outputs a string that represents the table within the current terminal width (`process.stdout.columns`).\n\n#### tableData\nType: `string[][]`\n\nRequired\n\nA nested array where the first-level are \"rows\", and the second-level are \"columns\".\n\n#### options\nType: `OptionsObject | (stdoutColumns: number) =\u003e OptionsObject | ColumnMetasArray`\n\nSchema:\n```ts\ntype Options = OptionsObject | OptionsFunction\n\ntype OptionsObject = ColumnMetasArray | {\n    columns: ColumnMetasArray\n    stdoutColumns?: number\n}\n\ntype OptionsFunction = (stdoutColumns: number) =\u003e OptionsObject\n\ntype ColumnMetasArray = (ColumnWidth | ColumnMeta)[]\n\ntype ColumnWidth = number | 'content-width' | 'auto' | string\n\ntype ColumnMeta = {\n    width: ColumnWidth\n    paddingRight?: number\n    paddingLeft?: number\n    paddingTop?: number\n    paddingBottom?: number\n    align?: 'left' | 'right'\n}\n```\n\nOptions to define the column widths (default is `auto`) and the stdout columns to use.\n\n#### stdoutColumns\nType: `number`\n\nDefault: `process.stdout.columns`\n\nThe 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.\n#### columns\n\nType: `Object`\n\n##### width\nType: `number | 'content-width' | 'auto' | string`\n\n- `number`: number of columns to span\n- `'content-width'`: The width of the content in the column\n- `'auto'`: Allocate the remaining width of the row to the column\n- `string`: Percentage of the viewport width to use (e.g. `'50%'`)\n\nFor all of these values, the max width is `stdoutColumns`.\n\n\n##### paddingLeft\nType: `number`\n\nHow many spaces to the left the column should have\n\n##### paddingRight\nType: `number`\n\nHow many spaces to the right the column should have\n\n##### paddingTop\nType: `number`\n\nHow many new lines to the top the column should have\n\n##### paddingBottom\nType: `number`\n\nHow many new lines to the bottom the column should have\n\n##### align\nType: `'left' | 'right'`\n\nDefault: `'left'`\n\nWhether to align the text to the left or right.\n\n##### preprocess\nType: `(cellValue: string) =\u003e string`\n\nFunction to preprocess the cell value before it is wrapped to the column width.\n\n##### postprocess\nType: `(line: string, lineNumber: number) =\u003e string`\n\nFunction to postprocess the individual lines of a cell after it has been wrapped to the column width.\n\n### breakpoints(breakpointsMap)\n\nA function to declaratively define breakpoints. Returns a function pass into terminal-columns.\n\n#### breakpointsMap\n\nType: `Record\u003cstring, Options\u003e`\n\nAn object mapping breakpoints to options. The key must be in the format: `\u003coperator\u003e \u003cstdout-columns\u003e`. For example, `\u003e= 90` will match if the terminal width is 90 or more.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprivatenumber%2Fterminal-columns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprivatenumber%2Fterminal-columns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprivatenumber%2Fterminal-columns/lists"}