Skip to content

Commit

Permalink
chore: add rollup-plugin-dsv (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
shellscape authored Oct 31, 2019
1 parent 8121cd1 commit 9bc503a
Show file tree
Hide file tree
Showing 17 changed files with 376 additions and 1 deletion.
25 changes: 25 additions & 0 deletions packages/dsv/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# rollup-plugin-dsv changelog

## 1.2.0

* Pass `id` to `processRow`

## 1.1.2

* Return a `name`

## 1.1.1

* Add missing dependencies

## 1.1.0

* Support `options.processRow`

## 1.0.1

* Include correct files in package

## 1.0.0

* First release
100 changes: 100 additions & 0 deletions packages/dsv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
[cover]: https://codecov.io/gh/rollup/plugins/replace/branch/master/graph/badge.svg
[cover-url]: https://codecov.io/gh/rollup/plugins
[size]: https://packagephobia.now.sh/badge?p=@rollup/plugin-dsv
[size-url]: https://packagephobia.now.sh/result?p=@rollup/plugin-dsv
[tests]: https://img.shields.io/circleci/project/github/rollup/plugins.svg
[tests-url]: https://circleci.com/gh/rollup/plugins

[![tests][tests]][tests-url]
[![cover][cover]][cover-url]
[![size][size]][size-url]
[![libera manifesto](https://img.shields.io/badge/libera-manifesto-lightgrey.svg)](https://liberamanifesto.com)

# @rollup/plugin-dsv

🍣 A Rollup plugin which converts `.csv` and `.tsv` files into JavaScript modules with [d3-dsv](https://github.com/d3/d3-dsv).

WebAssembly Modules are imported asynchronous as base64 strings. Small modules [can be imported synchronously](#synchronous-modules).

## Requirements

This plugin requires an [LTS](https://github.com/nodejs/Release) Node version (v8.0.0+) and Rollup v1.20.0+.

## Install

Using npm:

```console
npm install @rollup/plugin-dsv --save-dev
```

## Usage

Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin:

```js
import dsv from '@rollup/plugin-dsv';

export default {
input: 'src/index.js',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [dsv()]
};
```

Then call `rollup` either via the [CLI](https://www.rollupjs.org/guide/en/#command-line-reference) or the [API](https://www.rollupjs.org/guide/en/#javascript-api).

## Practical Example

Suppose that you have a CSV (or TSV!) file which contains some information on delicious fruits:

```csv
type,count
apples,7
pears,4
bananas,5
```

And suppose you'd like to import that CSV as an `Array` within some part of your code. After adding the plugin (as shown above), you may `import` (or `require`) the CSV file directly. The import will provide an `Array` of `Objects` representing rows from the CSV file:

```js
import fruit from './fruit.csv';

console.log(fruit);
// [
// { type: 'apples', count: '7' },
// { type: 'pears', count: '4' },
// { type: 'bananas', count: '5' }
// ]
```

## Options

### `processRow`

Type: `Function`<br>
Default: `null`

Specifies a function which processes each row in the parsed array. The function can either manipulate the passed `row`, or return an entirely new row object.

This option could be used for converting numeric `string` values into `Number` values. – for example turning numeric values into numbers, e.g.

```js
dsv({
processRow: (row, id) => {
Object.keys(row).forEach(key => {
var value = row[key];
row[key] = isNaN(+value) ? value : +value;
});
}
});
```

## Meta

[CONTRIBUTING](./.github/CONTRIBUTING.md)

[LICENSE (MIT)](./LICENSE)
53 changes: 53 additions & 0 deletions packages/dsv/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "@rollup/plugin-dsv",
"version": "2.0.0",
"description": "Convert .csv and .tsv files into JavaScript modules with d3-dsv",
"license": "MIT",
"repository": "rollup/plugins",
"author": "Rich Harris",
"homepage": "https://github.com/rollup/plugins",
"bugs": "https://github.com/rollup/plugins/issues",
"main": "dist/index.js",
"scripts": {
"build": "rollup -c",
"ci:coverage": "nyc pnpm run test && nyc report --reporter=text-lcov > coverage.lcov",
"ci:coverage:submit": "curl -s https://codecov.io/bash | bash -s - -F dsv",
"ci:lint": "pnpm run build && pnpm run lint && pnpm run security",
"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}",
"ci:test": "pnpm run test -- --verbose",
"lint": "pnpm run lint:js && pnpm run lint:docs && pnpm run lint:package",
"lint:docs": "prettier --single-quote --write README.md",
"lint:js": "eslint --fix --cache src test",
"lint:package": "prettier --write package.json --plugin=prettier-plugin-package",
"prebuild": "del-cli dist",
"prepare": "npm run build",
"prepublishOnly": "npm run lint",
"pretest": "npm run build",
"security": "echo 'pnpm needs `npm audit` support'",
"test": "ava"
},
"files": [
"dist",
"README.md",
"LICENSE"
],
"dependencies": {
"d3-dsv": "^0.1.14",
"rollup-pluginutils": "^2.8.2",
"tosource": "^1.0.0"
},
"devDependencies": {
"del-cli": "^3.0.0",
"rollup": "^1.20.0"
},
"ava": {
"files": [
"!**/fixtures/**",
"!**/helpers/**",
"!**/recipes/**",
"!**/types.ts"
]
},
"jsnext:main": "dist/index.es.js",
"module": "dist/index.es.js"
}
6 changes: 6 additions & 0 deletions packages/dsv/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import pkg from './package.json';

export default {
input: 'src/index.js',
output: [{ file: pkg.main, format: 'cjs' }, { file: pkg.module, format: 'es' }]
};
33 changes: 33 additions & 0 deletions packages/dsv/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { extname } from 'path';

import { csv, tsv } from 'd3-dsv';
import toSource from 'tosource';
import { createFilter } from 'rollup-pluginutils';

const parsers = { '.csv': csv, '.tsv': tsv };

export default function dsv(options = {}) {
const filter = createFilter(options.include, options.exclude);

return {
name: 'dsv',

transform(code, id) {
if (!filter(id)) return null;

const ext = extname(id);
if (!(ext in parsers)) return null;

let rows = parsers[ext].parse(code);

if (options.processRow) {
rows = rows.map((row) => options.processRow(row, id) || row);
}

return {
code: `export default ${toSource(rows)};`,
map: { mappings: '' }
};
}
};
}
5 changes: 5 additions & 0 deletions packages/dsv/test/fixtures/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"globals": {
"t": "readonly"
}
}
4 changes: 4 additions & 0 deletions packages/dsv/test/fixtures/basic-csv/fruit.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type,count
apples,7
pears,4
bananas,5
7 changes: 7 additions & 0 deletions packages/dsv/test/fixtures/basic-csv/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import fruit from './fruit.csv';

t.deepEqual(fruit, [
{ type: 'apples', count: '7' },
{ type: 'pears', count: '4' },
{ type: 'bananas', count: '5' }
]);
4 changes: 4 additions & 0 deletions packages/dsv/test/fixtures/basic-tsv/fruit.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type count
apples 7
pears 4
bananas 5
7 changes: 7 additions & 0 deletions packages/dsv/test/fixtures/basic-tsv/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import fruit from './fruit.tsv';

t.deepEqual(fruit, [
{ type: 'apples', count: '7' },
{ type: 'pears', count: '4' },
{ type: 'bananas', count: '5' }
]);
4 changes: 4 additions & 0 deletions packages/dsv/test/fixtures/process-id/lower.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type,count
Apples,7
Pears,4
Bananas,5
14 changes: 14 additions & 0 deletions packages/dsv/test/fixtures/process-id/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import lower from './lower.csv';
import upper from './upper.csv';

t.deepEqual(lower, [
{ type: 'apples', count: 7 },
{ type: 'pears', count: 4 },
{ type: 'bananas', count: 5 }
]);

t.deepEqual(upper, [
{ type: 'APPLES', count: 7 },
{ type: 'PEARS', count: 4 },
{ type: 'BANANAS', count: 5 }
]);
4 changes: 4 additions & 0 deletions packages/dsv/test/fixtures/process-id/upper.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type,count
Apples,7
Pears,4
Bananas,5
4 changes: 4 additions & 0 deletions packages/dsv/test/fixtures/process/fruit.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type,count
apples,7
pears,4
bananas,5
7 changes: 7 additions & 0 deletions packages/dsv/test/fixtures/process/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import fruit from './fruit.csv';

t.deepEqual(fruit, [
{ type: 'apples', count: 7 },
{ type: 'pears', count: 4 },
{ type: 'bananas', count: 5 }
]);
69 changes: 69 additions & 0 deletions packages/dsv/test/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const test = require('ava');
const { rollup } = require('rollup');

const dsv = require('..');

process.chdir(__dirname);

const testBundle = async (t, bundle) => {
const { output } = await bundle.generate({ format: 'cjs' });
const [{ code }] = output;
const func = new Function('t', code); // eslint-disable-line no-new-func

return func(t);
};

test('converts a csv file', async (t) => {
const bundle = await rollup({
input: 'fixtures/basic-csv/main.js',
plugins: [dsv()]
});
t.plan(1);
return testBundle(t, bundle);
});

test('converts a tsv file', async (t) => {
const bundle = await rollup({
input: 'fixtures/basic-tsv/main.js',
plugins: [dsv()]
});
t.plan(1);
return testBundle(t, bundle);
});

test('uses a custom processor', async (t) => {
const parse = (value) => (isNaN(+value) ? value : +value);

const bundle = await rollup({
input: 'fixtures/process/main.js',
plugins: [
dsv({
processRow(row) {
Object.keys(row).forEach((key) => {
row[key] = parse(row[key]); // eslint-disable-line no-param-reassign
});
}
})
]
});
t.plan(1);
return testBundle(t, bundle);
});

test('uses a custom processor with id', async (t) => {
const bundle = await rollup({
input: 'fixtures/process-id/main.js',
plugins: [
dsv({
processRow(row, id) {
return {
type: row.type[/lower/.test(id) ? 'toLowerCase' : 'toUpperCase'](),
count: +row.count
};
}
})
]
});
t.plan(2);
return testBundle(t, bundle);
});
Loading

0 comments on commit 9bc503a

Please sign in to comment.