Skip to content

Commit 27dd777

Browse files
committed
fix #266
1 parent 8e444d1 commit 27dd777

10 files changed

Lines changed: 68 additions & 25 deletions

File tree

bin/options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"type": "~object"
1414
},
1515
"--quote": {
16-
"desc": "quote surrounding a column content containing delimiters. default double quote (\"). e.g. --quote=# ",
16+
"desc": "quote surrounding a column content containing delimiters. To turn off quote, please use 'off' --quote=off. default double quote (\"). e.g. chage to hash: --quote=# ",
1717
"type": "string"
1818
},
1919
"--trim": {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,9 @@
297297
"test": "rm -Rf .ts-node && TS_NODE_CACHE_DIRECTORY=.ts-node mocha -r ts-node/register src/**/*.test.ts ./test/*.ts -R spec",
298298
"travis": "nyc --reporter lcov mocha -r ts-node/register src/**/*.test.ts ./test/*.ts -R spec",
299299
"test:debug": "mocha debug -r ts-node/register src/**/*.test.ts ./test/*.ts -R spec",
300+
"test:function":"mocha -r ts-node/register test/**/*.ts",
300301
"test-all": "mocha ./test -R spec && CSV_WORKER=3 mocha ./test -R spec ",
301-
"test:unit": "mocha -r ts-node/register src/**/*.test.ts",
302+
"test:unit": "mocha -r ts-node/register src/**/*.ts",
302303
"test:all:debug": "mocha debug ./testNew -R spec",
303304
"coverage": "nyc --reporter html mocha -r ts-node/register src/**/*.test.ts ./test/*.ts -R spec",
304305
"coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls"

src/Converter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { ProcessorLocal } from "./ProcessorLocal";
1313
import { Result } from "./Result";
1414
import CSVError from "./CSVError";
1515
import { bufFromString } from "./util";
16-
export class Converter extends Transform {
16+
export class Converter extends Transform implements PromiseLike<Array<any>> {
1717
preRawData(onRawData: PreRawDataCallback): Converter {
1818
this.runtime.preRawDataHook = onRawData;
1919
return this;

src/rowSplit.test.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,25 +106,38 @@ describe("RowSplit.parse function", function () {
106106
assert.equal(res.closed, true);
107107
assert.equal(res.cells[2], 'csvtojson,a"\nwesome');
108108
});
109-
it ("should allow blank quotes",()=>{
110-
const data="a|^^|^b^";
111-
109+
it("should allow blank quotes", () => {
110+
const data = "a|^^|^b^";
111+
112112
const rowSplit = new RowSplit(new Converter({
113113
delimiter: '|',
114114
quote: '^',
115115
noheader: true
116116
}));
117-
const res=rowSplit.parse(data);
118-
assert.equal(res.cells[1],"");
117+
const res = rowSplit.parse(data);
118+
assert.equal(res.cells[1], "");
119119
})
120-
it ("should allow blank quotes in quotes",()=>{
121-
const data='a,"hello,this,"", test"';
122-
120+
it("should allow blank quotes in quotes", () => {
121+
const data = 'a,"hello,this,"", test"';
122+
123123
const rowSplit = new RowSplit(new Converter({
124124
noheader: true
125125
}));
126-
const res=rowSplit.parse(data);
127-
assert.equal(res.cells[1],'hello,this,", test');
126+
const res = rowSplit.parse(data);
127+
assert.equal(res.cells[1], 'hello,this,", test');
128+
})
129+
it("should smart detect if an initial quote is only part of value ", () => {
130+
const data = '"Weight" (kg),Error code,"Height" (m)';
131+
const rowSplit = new RowSplit(new Converter({
132+
noheader: true
133+
}));
134+
const res = rowSplit.parse(data);
135+
console.log(res);
136+
assert.equal(res.cells.length, 3);
137+
assert(res.closed);
138+
assert.equal(res.cells[0],'"Weight" (kg)');
139+
assert.equal(res.cells[1],'Error code');
140+
assert.equal(res.cells[2],'"Height" (m)');
141+
128142
})
129-
130143
});

src/rowSplit.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { CSVParseParam } from "./Parameters";
22
import { Converter } from "./Converter";
33
import { Fileline } from "./fileline";
44
import getEol from "./getEol";
5-
import { filterArray,trimLeft,trimRight } from "./util";
5+
import { filterArray, trimLeft, trimRight } from "./util";
66

77
const defaulDelimiters = [",", "|", "\t", ";", ":"];
88
export class RowSplit {
@@ -24,7 +24,7 @@ export class RowSplit {
2424
this.escape = conv.parseParam.escape;
2525
}
2626
parse(fileline: Fileline): RowSplitResult {
27-
if (fileline.length ===0 ||(this.conv.parseParam.ignoreEmpty && fileline.trim().length===0) ) {
27+
if (fileline.length === 0 || (this.conv.parseParam.ignoreEmpty && fileline.trim().length === 0)) {
2828
return { cells: [], closed: true };
2929
}
3030
const quote = this.quote;
@@ -41,9 +41,9 @@ export class RowSplit {
4141
const delimiter = this.conv.parseRuntime.delimiter;
4242
const rowArr = fileline.split(delimiter);
4343
if (quote === "off") {
44-
if (trim){
45-
for (let i =0;i<rowArr.length;i++){
46-
rowArr[i]=rowArr[i].trim();
44+
if (trim) {
45+
for (let i = 0; i < rowArr.length; i++) {
46+
rowArr[i] = rowArr[i].trim();
4747
}
4848
}
4949
return { cells: rowArr, closed: true };
@@ -63,17 +63,24 @@ export class RowSplit {
6363
}
6464
const len = e.length;
6565
if (!inquote) {
66-
if (len === 2 && e ===this.quote+this.quote){
66+
if (len === 2 && e === this.quote + this.quote) {
6767
row.push("");
6868
continue;
69-
}else if (this.isQuoteOpen(e)) { //quote open
69+
} else if (this.isQuoteOpen(e)) { //quote open
7070
e = e.substr(1);
7171
if (this.isQuoteClose(e)) { //quote close
7272
e = e.substring(0, e.lastIndexOf(quote));
7373
e = this.escapeQuote(e);
7474
row.push(e);
7575
continue;
76-
} else {
76+
} else if (e.lastIndexOf(quote) !== 0) {
77+
if (trim) {
78+
e = trimRight(e);
79+
}
80+
row.push(quote+e);
81+
continue;
82+
}
83+
else {
7784
inquote = true;
7885
quoteBuff += e;
7986
continue;
@@ -175,7 +182,7 @@ export class RowSplit {
175182
while (lines.length) {
176183
const line = left + lines.shift();
177184
const row = this.parse(line);
178-
if (row.cells.length === 0 && this.conv.parseParam.ignoreEmpty){
185+
if (row.cells.length === 0 && this.conv.parseParam.ignoreEmpty) {
179186
continue;
180187
}
181188
if (row.closed || this.conv.parseParam.alwaysSplitAtEOL) {

test/data/csvWithUnclosedHeader

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Date and time,Sample no.,Status,Sample type,Patient ID,Last name,First name,Sex of patient,Patient birth date,Patient note,Patient department,Accession number,Sample site,Physician,Operator,Department,Note,Test order code,Draw time,Approval status,Approval time,Report layout,Patient account number,,Errors detected during measurement,"Age" (years),Error code,"Weight" (kg),Error code,"Height" (m),Error code,"HCG_Beta(P)" (mIU/mL),Error code,"Troponin_I(P)" (ng/mL),Error code,"CK_MB(P)" (ng/mL),Error code,"D-Dimer(P)" (ng/mL),Error code,"hsCRP(P)" (mg/L),Error code,"Myoglobin(P)" (ng/mL),Error code,"NT-proBNP" (pg/mL),Error code,"CRP" (mg/dL),Error code,"BNP" (ng/L),Error code,"TnT" (ng/mL),Error code,"Demo(P)" (AQT),Error code,"PCT" (ng/mL),Error code,
2+
"06/14/2018 10:34 AM","12669","OK","","4206454447","","","Unknown","","","","4206454447","","","Anonymous","","","400",,"Not reviewed","","New","",,"",,,,,,,,,,,,,,,,,,,168,"",,,,,,,,,,
3+
"06/14/2018 10:19 AM","12668","OK","","4206454403","","","Unknown","","","","4206454403","","","Anonymous","","","101",,"Not reviewed","","New","",,"",,,,,,,,,<0.010,"",4.2,"",,,,,,,,,,,,,,,,,,

test/testCSVConverter3.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,16 @@ describe("testCSVConverter3", function () {
228228
assert.equal(jsonObj[0].field2, "");
229229
});
230230
})
231+
it("should parse header with quotes correctly", function () {
232+
var testData = __dirname + "/data/csvWithUnclosedHeader";
233+
return csv({
234+
headers:["exam_date","sample_no","status","sample_type","patient_id","last_name","first_name","gender_of_patient","patient_birth_date","patient_note","patient_department","accession_number","sample_site","physician","operator","department","note","test_order_code","draw_time","approval_status","approval_time","report_layout","patient_account_number","none_1","errors_detected_during_measurement","age","error_code_01","weight","error_code_02","height","error_code_03","hcg_beta_p","error_code_04","troponin_i_p","error_code_05","ck_mb_p","error_code_06","d_dimer_p","error_code_07","hscrp_p","error_code_08","myoglobin_p","error_code_09","nt_probnp","error_code_10","crp","error_code_11","bnp","error_code_12","tnt","error_code_13","demo_p","error_code_14","pct","error_code_15"]
235+
})
236+
.fromFile(testData)
237+
.then((d)=>{
238+
assert.equal(d.length,2);
239+
assert.equal(d[0].sample_no,"12669");
240+
})
241+
242+
});
231243
});

v2/Converter.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Transform, TransformOptions, Readable } from "stream";
33
import { CSVParseParam } from "./Parameters";
44
import { ParseRuntime } from "./ParseRuntime";
55
import CSVError from "./CSVError";
6-
export declare class Converter extends Transform {
6+
export declare class Converter extends Transform implements PromiseLike<Array<any>> {
77
options: TransformOptions;
88
preRawData(onRawData: PreRawDataCallback): Converter;
99
preFileLine(onFileLine: PreFileLineCallback): Converter;

v2/rowSplit.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)