{"id":18735659,"url":"https://github.com/rdmurphy/node-copytext","last_synced_at":"2025-04-12T19:21:05.612Z","repository":{"id":30463557,"uuid":"34017466","full_name":"rdmurphy/node-copytext","owner":"rdmurphy","description":":ledger::scissors: A module for accessing a XLSX spreadsheet as a JavaScript object.","archived":false,"fork":false,"pushed_at":"2019-08-25T21:42:52.000Z","size":189,"stargazers_count":16,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T13:38:19.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/copytext","language":"JavaScript","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/rdmurphy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2015-04-15T20:40:11.000Z","updated_at":"2019-01-16T16:46:55.000Z","dependencies_parsed_at":"2022-09-08T17:01:43.697Z","dependency_job_id":null,"html_url":"https://github.com/rdmurphy/node-copytext","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdmurphy%2Fnode-copytext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdmurphy%2Fnode-copytext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdmurphy%2Fnode-copytext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rdmurphy%2Fnode-copytext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rdmurphy","download_url":"https://codeload.github.com/rdmurphy/node-copytext/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248618629,"owners_count":21134273,"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":[],"created_at":"2024-11-07T15:17:39.935Z","updated_at":"2025-04-12T19:21:05.587Z","avatar_url":"https://github.com/rdmurphy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-copytext\n\nA node library for accessing a XLSX spreadsheet as a JavaScript object. Inspired by the NPR visuals team's [copytext](https://github.com/nprapps/copytext) Python library. Works great coupled with a group-edited Google Spreadsheet exported as a XLSX file.\n\n[![build status](https://img.shields.io/travis/rdmurphy/node-copytext/master.svg?style=flat-square)](https://travis-ci.org/rdmurphy/node-copytext)\n[![Coveralls branch](https://img.shields.io/coveralls/rdmurphy/node-copytext/master.svg?style=flat-square)](https://coveralls.io/github/rdmurphy/node-copytext)\n[![npm version](https://img.shields.io/npm/v/copytext.svg?style=flat-square)](https://www.npmjs.com/package/copytext)\n[![npm](https://img.shields.io/npm/dm/copytext.svg?style=flat-square)](https://www.npmjs.com/package/copytext)\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n- [In Practice](#in-practice)\n- [API Docs](#api-docs)\n  - [process](#process)\n- [License](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Features\n\n-   Access an XLSX spreadsheet as a JavaScript object\n-   Great for passing into templates, saving to a file, etc.\n-   XLSX spreadsheets can be loaded via path or [`Buffer`](https://nodejs.org/api/buffer.html)\n-   Can process both **key/value** sheets and **table** layouts\n\n## Requirements\n\n-   [node.js](https://nodejs.org/) \u003e= 4\n\n## Installation\n\n```sh\nnpm install --save-dev copytext\n```\n\nIf you're looking to do some work on `node-copytext` itself, clone the repo instead:\n\n```sh\ngit clone https://github.com/rdmurphy/node-copytext.git\ncd node-copytext\nnpm install\nnpm test # make sure everything already works!\n```\n\nAnd you're good to go!\n\n## Usage\n\n`copytext` can work with both **key/value** and **table** layouts. By default, it assumes you're passing **key/value** sheets.\n\n_Note: With **key/value** sheets, the processor will only care about content in the first **two** columns. Anything else will be ignored. (Meaning the other columns are a great place to leave notes!)_\n\n**corgis_keyvalue.xlsx**  \n_Sheet name: CORGIS_\n\n| -                     | -                                      |\n| --------------------- | -------------------------------------- |\n| **name**              | Poky                                   |\n| **instagram_account** | \u003chttps://instagram.com/tibbythecorgi/\u003e |\n\n```js\nvar copytext = require('copytext');\n\nvar data = copytext.process('./corgis_keyvalue.xlsx');\n\nconsole.log(data);\n\n// {\n//   'CORGIS': {\n//     'name': 'Poky',\n//     'instagram_account': 'https://instagram.com/poky_corgi/'\n//   }\n// }\n```\n\nTo tell `copytext` to use the **table** parser instead, pass an object as the second argument to `copytext` with `processor` set to `table`.\n\n**corgis_table.xlsx**  \n_Sheet name: CORGIS_\n\n| name  | instagram_account                      |\n| ----- | -------------------------------------- |\n| Poky  | \u003chttps://instagram.com/poky_corgi/\u003e    |\n| Tibby | \u003chttps://instagram.com/tibbythecorgi/\u003e |\n\n```js\nvar copytext = require('copytext');\n\nvar data = copytext.process('./corgis_table.xlsx', {\n  'processor': 'table'\n});\n\nconsole.log(data);\n\n// {\n//   'CORGIS': [{\n//     'name': 'Poky',\n//     'instagram_account': 'https://instagram.com/poky_corgi/'\n//   },{\n//     'name': 'Tibby',\n//     'instagram_account': 'https://instagram.com/tibbythecorgi/'\n//   }]\n// }\n```\n\nHave a spreadsheet that uses both layouts? No problem! Tell `copytext` which sheets are the exception. Overrides are passed in as a list to the options object on the `overrides` key. Each override should have the name of the sheet as the key, and the name of the processor as the value.\n\nAssume we have the previous example's `CORGIS` sheet in a spreadsheet plus this sheet:\n\n_Sheet name: SHIBA_\n\n| -                     | -                                      |\n| --------------------- | -------------------------------------- |\n| **name**              | Maru                                   |\n| **instagram_account** | \u003chttps://instagram.com/marutaro/\u003e      |\n\n```js\nvar copytext = require('copytext');\n\nvar data = copytext.process('./husky_keyvalue_corgis_table.xlsx', {\n  'processor': 'table',\n  'overrides': {\n    'SHIBA': 'keyvalue'\n  }\n});\n\nconsole.log(data);\n\n// {\n//   'CORGIS': [{\n//     'name': 'Poky',\n//     'instagram_account': 'https://instagram.com/poky_corgi/'\n//   },\n//   {\n//     'name': 'Tibby',\n//     'instagram_account': 'https://instagram.com/tibbythecorgi/'\n//   }],\n//   'SHIBAS': {\n//     'name': 'Maru',\n//     'instagram_account': 'https://instagram.com/marutaro/'\n//   }\n// }\n```\n\nThe override works in both directions — this would have produced the same result:\n\n```js\nvar data = copytext.process('./husky_keyvalue_corgis_table.xlsx', {\n  'processor': 'keyvalue',\n  'overrides': {\n    'CORGIS': 'table'\n  }\n});\n```\n\nIt's also possible to include or exclude entire sheets. This is useful if you only want one sheet to be converted (for example, the other sheets may be supplying data to the master sheet), or want to exclude certain sheets.\n\n```js\nvar copytext = require('copytext');\n\nvar data = copytext.process('./husky_keyvalue_corgis_table.xlsx', {\n  'processor': 'table',\n  'includeSheets': ['CORGI']\n});\n```\n\n```js\nvar copytext = require('copytext');\n\nvar data = copytext.process('./husky_keyvalue_corgis_table.xlsx', {\n  'processor': 'table',\n  'excludeSheets': ['HUSKY']\n});\n```\n\n## In Practice\n\nThis is most useful when working with templates. Here's an example with the excellent [Nunjucks](http://mozilla.github.io/nunjucks/) library.\n\n```js\nvar fs = require('fs');\nvar copytext = require('copytext');\nvar nunjucks = require('nunjucks');\n\nvar data = copytext.process('./data/contacts.xlsx');  // a key/value sheet named CONTACTS\nvar res = nunjucks.render('index.html', {DATA: data});\n```\n\n**index.html**\n\n```html\n\u003cul\u003e\n  \u003cli\u003e{{ DATA.CONTACTS.name }}\u003c/li\u003e\n  \u003cli\u003e{{ DATA.CONTACTS.address }}\u003c/li\u003e\n  \u003cli\u003e{{ DATA.CONTACTS.phone }}\u003c/li\u003e\n\u003c/ul\u003e\n```\n\nIf you pass in a **table** sheet, you can loop through it! (Assume `CONTACTS` is a `table`.)\n\n**index.html**\n\n```html\n\u003cul\u003e\n  {% for contact in DATA.CONTACTS %}\n  \u003cli\u003e{{ contact.name }} | {{ contact.address }} | {{ contact.phone }}\u003c/li\u003e\n  {% endfor %}\n\u003c/ul\u003e\n```\n\n## API Docs\n\n### process\n\nAccepts a raw XLSX file and options that determine how `copytext` should\nprocess it.\n\n**Parameters**\n\n-   `rawXLSX` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \\| [Buffer](https://nodejs.org/api/buffer.html))** A Buffer of, or path to, an XLSX file\n-   `options` **\\[[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)]** \n    -   `options.processor` **\\[[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)]** The processor used on all sheets without overrides (optional, default `'keyvalue'`)\n    -   `options.includeSheets` **\\[([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)\u0026lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)\u003e | [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))]** Sheets to include (optional, default `undefined`)\n    -   `options.excludeSheets` **\\[([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)\u0026lt;[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)\u003e | [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))]** Sheets to exclude (optional, default `undefined`)\n    -   `options.overrides` **\\[[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)]** Key value pairs of the sheet name and processor that should be used (optional, default `undefined`)\n\nReturns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** \n\n## License\n\nBy [Ryan Murphy](https://twitter.com/rdmurphy).\n\nAvailable under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frdmurphy%2Fnode-copytext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frdmurphy%2Fnode-copytext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frdmurphy%2Fnode-copytext/lists"}