Added Types and Unit tests

This commit is contained in:
2020-12-24 07:44:13 +11:00
parent 992e025e6b
commit d13c712be8
7 changed files with 3784 additions and 6 deletions

61
.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next

View File

@ -5,10 +5,26 @@ efficient and no dependencies.
## Usage
Only one method is provided;
```js
const csv = 'Name,Age,Location\nDom,26,Sydney\nSteve,30,New York';
const csv = 'Name,Age,Location\nDom,26,"Sydney, Australia"\nSteve,30,"New York, USA"';
parseCSV(csv, function(headers, line, index) {
console.log(index, '-', line[headers.indexOf('Name')]);//1 - Dom
return true;//Return false to break loop
})
```
To stay efficient we ask for a callback that is fired for every line parsed.
## Options
Options can be provided if necessary;
```js
parseCSV(csv, (headers,line,index) => true, {
skipBlanks: false
});
```
Current Options;
```
skipBlanks - True or False, whether or not to skip blank lines
```
## Testing
Tests are written in jest. Run `yarn test`

9
index.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
type CSVOptions = {
skipBlanks?:boolean;
};
type CSVCallback = (headers:string[], line:string[], index:number) => boolean;
type CSVParser = (csv:string, onLine:CSVCallback, options?:CSVOptions)=>void;
export const { parseCSV:CSVParser }

17
package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "micro-csv",
"version": "1.0.0",
"main": "src/index.js",
"repository": "https://github.com/YourWishes/Micro-CSV.git",
"author": "Dominic Masters <dominic@domsplace.com>",
"license": "MIT",
"scripts": {
"test": "jest"
},
"dependencies": {
"jest": "^26.6.3"
},
"jest": {
"testMatch": [ "**/test/**/*.js" ]
}
}

View File

@ -1,15 +1,25 @@
function parseCSV(csv, onLine) {
/**
* Parses a CSV string and runs a callback for each line found.
*
* @param csv CSV string to parse
* @param onLine Callback to be fired for each line in the CSV
* @param options Modify how the callback is called
*/
function parseCSV(csv, onLine, options) {
//Split lines by delim, don't worry about \r here
const lines = csv.split('\n');
let headers = null;
let index = 0;
options = options || {
skipBlanks: true
};
//For each line...
for(let i = 0; i < lines.length; i++) {
//Shave off trailing whitespaces
let line = lines[i].trim();
if(!line.replace(/\s/g, '').length) continue;//Skip blank lines
index++;//Count real lines
if(options.skipBlanks && !line.replace(/\s/g, '').length) continue;//Skip blank lines
//Setup line array
let lineArray;
@ -39,15 +49,20 @@ function parseCSV(csv, onLine) {
} else {
lineArray = line.split(',');
}
if(options.skipBlanks && (!lineArray.length || lineArray.every(e => !e.length))) continue;
//Is this the headers line?
if(!headers) {
headers = lineArray;
continue;
}
index++;//Count real lines
//Callback
let r = onLine(headers, lineArray, index);
if(!r) break;//If r != true then break loop
}
}
//CommonJS only, don't copy this into google script
module.exports = { parseCSV };

75
test/index.js Normal file
View File

@ -0,0 +1,75 @@
const { expect, it } = require('@jest/globals');
const { parseCSV } = require('./../src/index');
describe('parseCSV', () => {
it('should parse a csv file', () => {
const csv = 'Name,Age,Location\nDom,26,"Sydney, Australia"\nSteve,30,"New York, USA"';
parseCSV(csv, (headers,line,index) => {
//Headers are parsed as arrays of strings
expect(headers).toEqual([ 'Name', 'Age', 'Location' ]);
switch(index) {
case 1:
expect(line).toEqual([ 'Dom', '26', 'Sydney, Australia' ]);
break;
case 2:
expect(line).toEqual([ 'Steve', '30', 'New York, USA' ]);
break;
}
return true;
});
});
it('should skip blank lines', () => {
//Line 2 is blank, Line 3 ends with a return carraige
const csv = 'Name,Age,Location\n,,\nSteve,30,"New York, USA"\n\rDom,26,"Sydney, Australia"';
parseCSV(csv, (headers,line,index) => {
expect(headers).toEqual([ 'Name', 'Age', 'Location' ]);
switch(index) {
case 1:
expect(line).toEqual([ 'Steve', '30', 'New York, USA' ]);
break;
case 2:
expect(line).toEqual([ 'Dom', '26', 'Sydney, Australia' ]);
break;
}
return;
});
});
it('should break when returning false', () => {
const csv = 'Name,Age,Location\nDom,26,"Sydney, Australia"\nSteve,30,"New York, USA"';
parseCSV(csv, (headers,line,index) => {
expect(line).toEqual([ 'Dom', '26', 'Sydney, Australia' ]);
expect(index).not.toEqual(2);
return false;
});
});
it('should be allowed to not skip blanks', () => {
//Line 2 is blank, Line 3 ends with a return carraige
const csv = 'Name,Age,Location\n,,\nSteve,30,"New York, USA"\n\rDom,26,"Sydney, Australia"';
parseCSV(csv, (headers,line,index) => {
expect(headers).toEqual([ 'Name', 'Age', 'Location' ]);
switch(index) {
case 1:
expect(line).toEqual([ '', '', '' ]);
break;
case 2:
expect(line).toEqual([ 'Steve', '30', 'New York, USA' ]);
break;
}
return;
}, { skipBlanks: false });
});
});

3585
yarn.lock Normal file

File diff suppressed because it is too large Load Diff