{"id":19778228,"url":"https://github.com/a-x-/table-builder","last_synced_at":"2025-07-11T15:44:36.625Z","repository":{"id":57376301,"uuid":"55315379","full_name":"a-x-/table-builder","owner":"a-x-","description":"Isomorphic (universal) Powerful HTML table builder based on the JSON.","archived":false,"fork":false,"pushed_at":"2017-07-02T10:13:19.000Z","size":280,"stargazers_count":19,"open_issues_count":2,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-19T21:53:02.769Z","etag":null,"topics":["html-table","table","table-builder"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/table-builder","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/a-x-.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-02T20:45:34.000Z","updated_at":"2025-05-15T13:02:46.000Z","dependencies_parsed_at":"2022-09-05T19:12:59.800Z","dependency_job_id":null,"html_url":"https://github.com/a-x-/table-builder","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/a-x-/table-builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-x-%2Ftable-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-x-%2Ftable-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-x-%2Ftable-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-x-%2Ftable-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/a-x-","download_url":"https://codeload.github.com/a-x-/table-builder/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/a-x-%2Ftable-builder/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264843491,"owners_count":23672214,"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":["html-table","table","table-builder"],"created_at":"2024-11-12T05:28:32.265Z","updated_at":"2025-07-11T15:44:36.579Z","avatar_url":"https://github.com/a-x-.png","language":"JavaScript","readme":"table-builder [![Build Status](https://travis-ci.org/a-x-/table-builder.svg?branch=master)](https://travis-ci.org/a-x-/table-builder)\n============\n\nCreate HTML tables from a JSON in a both Node.js (0.10+) and browsers enviroments.\n\n#### Installation\n\n```sh\nyarn add --production table-builder\n```\n\nor\n\n```sh\nnpm i --production table-builder\n```\n\n`--production` flag skips devDependencies of the table-builder (testing framework).\n\n#### Usage\n\n##### node.js and webpack\n```js\nimport TableBuilder from 'table-builder'\n```\n\n##### browser (without build tool)\n1. Copy built UMD module:\n   `cp node_modules/table-builder/tablebuilder.js dist/tablebuilder.js`\n\n2. Insert tag:\n   `\u003cscript src=\"/dist/tablebuilder.js\"\u003e\u003c/script\u003e`\n\n#### Simple Example\n\nEach object represents one row in the data array.\n```json\n[\n  { \"name\":\"Larry Wall\", \"age\":57, \"link\": \"\u003ca href='http://www.wall.org/~larry/'\u003ewww.wall.org/~larry/\u003c/a\u003e\" },\n  { \"name\":\"Bill Gates\", \"age\":56, \"link\": \"\u003ca href='http://www.microsoft.com'\u003ewww.microsoft.com\u003c/a\u003e\" },\n  { \"name\":\"Daffy Duck\", \"age\":75, \"link\": \"\" }\n]\n```\n\n```javascript\nvar data = [/* see data section above */];\n\n// You can put key-value pairs if you strongly want keep headers order:\n// [['name', 'User name'], ['age', 'User age'], ['link', 'Homepage']]\nvar headers = { \"name\" : \"User name\", \"age\": \"User age\", \"link\": \"Homepage\" };\n\nvar Table = require('table-builder');\nconsole.log(\n  (new Table({'class': 'some-table'}))\n    .setHeaders(headers) // see above json headers section\n    .setData(data) // see above json data section\n    .render()\n);\n```\n\nRendered to:\n```html\n\u003ctable class='some-table'\u003e\n  \u003cthead\u003e \u003ctr\u003e \u003cth\u003eUser name\u003c/th\u003e \u003cth\u003eUser age\u003c/th\u003e \u003cth\u003eHomepage\u003c/th\u003e \u003c/tr\u003e \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd class=\"name-td\"\u003eLarry Wall\u003c/td\u003e\n      \u003ctd class=\"age-td\"\u003e57\u003c/td\u003e\n      \u003ctd class=\"link-td\"\u003e\u003ca href=\"http://www.wall.org/~larry/\"\u003ewww.wall.org/~larry/\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd class=\"name-td\"\u003eBill Gates\u003c/td\u003e\n      \u003ctd class=\"age-td\"\u003e56\u003c/td\u003e\n      \u003ctd class=\"link-td\"\u003e\u003ca href=\"http://www.microsoft.com\"\u003ewww.microsoft.com\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd class=\"name-td\"\u003eDaffy Duck\u003c/td\u003e\n      \u003ctd class=\"age-td\"\u003e75\u003c/td\u003e\n      \u003ctd class=\"link-td\"\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n```\n\n#### Example of simple scrapper with tablebuilder result representation\n\n```js\nconst process = require('process')\nconst TableBuilder = require('table-builder')\n    const table = new TableBuilder({class: 'avito'})\n    const headers = {price: 'Price', title: 'Title'}\nconst thrw = require('throw')\nconst fetch = require('isomorphic-fetch')\n    const getHttp = (uri) =\u003e fetch(uri).then(r =\u003e r.status \u003e= 400 ? thrw (r.status) : r.text())\nconst parseHtml = html =\u003e require('jsdom').jsdom(html)\n\nconst uri = process.argv[2] || 'https://www.avito.ru/moskva/telefony/iphone?q=iphone+se'\n\nconst retreiveData = (document) =\u003e Array.from(document.querySelectorAll('.js-catalog_after-ads .item')).map(i=\u003e({title:i.querySelector('.title'), price:i.querySelector('.about')})).map(({title,price})=\u003e({title:title.textContent.trim(),price:price.textContent.trim()}))\n\nconst main = () =\u003e\n    getHttp(uri)\n    .then(html =\u003e parseHtml(html))\n    .then(document =\u003e retreiveData(document))\n    .then(data =\u003e table.setHeaders(headers).setData(data).render())\n\nconst style = `\u003cstyle\u003ebody { text-align: center; } .avito {width: 100%;} thead { text-align: left; } .price-td { text-align: right; }\u003c/style\u003e`\nmain().then(r=\u003econsole.log(style, r))\n```\n\n![example result](https://cloud.githubusercontent.com/assets/6201068/20455981/216d347c-ae7a-11e6-83bf-572d410ef6e8.png)\n\n\n## API\n\n#### Prisms\nPrism are callbacks-preprocessors for specified fields.\n\n```javascript\nvar data = [ // Look the previous case differences: link format changed and name splitted into firstname and surname\n  { \"firstname\":\"Larry\", \"surname\":\"Wall\", \"age\":57, \"link\": \"www.wall.org/~larry/\" },\n  { \"firstname\":\"Bill\", \"surname\":\"Gates\", \"age\":56, \"link\": \"www.microsoft.com\" },\n  { \"firstname\":\"Daffy\", \"surname\":\"Duck\", \"age\":75, \"link\": \"\" }\n];\n\n(new Table({'class': 'some-table'}))\n  .setPrism('link', function (cellData) {\n    return cellData \u0026\u0026 '\u003ca href=\"http://'+cellData+'\"\u003e'+cellData+'\u003c/a\u003e' || 'N/A';\n  })\n  .setPrism('name', function (cellData, row) {\n    return row.surname + ' ' + row.firstname;\n  })\n  .setHeaders({ \"name\": \"User name\", \"age\": \"User age\", \"link\": \"Homepage\" })\n  .setData(data)\n  .render()\n```\n\nRender output is equal the previous case.\n\nAlso, prism callback may return `{presentation: '...', raw: '...'}` object\nfor splitting html wrapped cell values and raw values.\nFor example, raw values uses in [totals](#totals).\n\n#### Totals\nSee following code:\n\n```js\ntable.setTotal('age', function (columnCellsCollection, rowsCollection) {\n  // Calc average age\n  return Math.round(\n    columnCellsCollection\n      .reduce(function (prev, val) { return +prev + val; })\n      / columnCellsCollection.length\n  );\n});\n```\n\nIt adds `tfoot` in the table with average age:\n```html\n\u003ctfoot\u003e\u003ctr\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003e62\u003c/td\u003e\u003c/tr\u003e\u003c/tfoot\u003e\n```\n\n#### Grouping\n\nGrouping fields util (`setGroup`).\n\n```js\n// ...\ntable\n  .setGroup('product_category', function (value, recordsCount, totals) {\n    // ...\n  })\n  // ...\n  .render();\n```\n\nGroup removes the field (`product_category`) from the table \nand adds row-separators with the field's values (group names). and referenced items.\n\nBody of the setGroup callback may contains processor of group name. \nAdditionaly processor may use the group's `recordsCount` and `totals` collection for group\nif `setTotal` for whole table have installed.\n\nIf callback is not defined then tableBuilder uses group name without processing, as is.\n\n## Empty data collection\n\n```js\n// Show table replacer block if data set is empty\n// ...\ntable\n  // ...\n  .render()\n  || 'Data collection is empty!';\n```\n\n## Client side sorting, filtering\n\nYou can use [list.js](https://github.com/javve/list.js) with table builder.\n\n## TODO\n\n* [x] Unit tests, CI\n* [x] Decompose methods\n* [ ] More unit tests\n* [ ] Run building and another activity only in the render() method, push intermediate methods into preordered list\n* [ ] Framefork agnostic: possibility to use with React and another frameworks\n  * `tagBuilder` as a dependency injection (for compatibility with either: `innerHTML`, `createElement`, `React.Component`)\n* [ ] Internal type constructors with asserts\n* [ ] Data model, changing/accessing data api\n* [ ] Client-side filters, multisort\n* [ ] Plural versions of methods: `setPrisms`, `setTotals`\n* [ ] Plugins system (call hooks for different cells)\n* [ ] N/A maps\n* [ ] Escaping\n* [ ] Complex 2-level headers feature\n* [ ] Sticky headers feature\n* [ ] Vertical header feature\n* [ ] Simplify prisms api: callback must returns presentation data only instead of `{raw, presentation}`\n\n## See also another solutions\n\n**React based**:\n* [react-data-grid](https://github.com/adazzle/react-data-grid) - I did not use it still\n* [react-table](https://github.com/tannerlinsley/react-table) - I revealed problems with custom styles and stability\n* _suggestions are welcome_\n\n**Framework agnostic**:\n* _suggestions are welcome_\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-x-%2Ftable-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa-x-%2Ftable-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa-x-%2Ftable-builder/lists"}