11import detectEOL from 'detect-eol' ;
2+ import { tryRegexToString , splitIgnoringChar } from './utils' ;
23
34type CSVToXMLOptions = {
45 eol ?: string ;
@@ -7,7 +8,7 @@ type CSVToXMLOptions = {
78 headerList ?: string [ ] ;
89 header ?: boolean ;
910 indentation ?: number | string ;
10- quotes ?: 'single' | 'double' | 'none' ;
11+ quote ?: 'single' | 'double' | 'all' | ' none' | RegExp ;
1112} ;
1213
1314const defaultOptions : CSVToXMLOptions = {
@@ -17,7 +18,7 @@ const defaultOptions: CSVToXMLOptions = {
1718 header : true ,
1819 headerList : [ ] ,
1920 indentation : 4 ,
20- quotes : 'none' ,
21+ quote : 'none' ,
2122} ;
2223
2324export default function csvToXml (
@@ -29,12 +30,35 @@ export default function csvToXml(
2930 const csvData = csvString . split ( eol ! ) . map ( ( row ) => row . trim ( ) ) ;
3031 const separator = usedOptions . separator ! ;
3132
32- const firstRow = csvData [ 0 ] . split ( separator ) ;
33+ let quote ;
34+ if ( usedOptions . quote instanceof RegExp ) {
35+ quote = usedOptions . quote ;
36+ } else if ( usedOptions . quote ) {
37+ quote = usedOptions . quote ;
38+ quote = { single : "'" , double : '"' , all : / (?: ' | " ) / , none : undefined } [
39+ usedOptions . quote
40+ ] ;
41+ }
42+
43+ const split = ( str : string ) => {
44+ return splitIgnoringChar ( { str, separator, charToIgnore : quote } ) . map (
45+ ( ch ) =>
46+ ch . replace (
47+ new RegExp (
48+ String . raw `${ tryRegexToString ( quote ) ?? '' } (.*?)${
49+ tryRegexToString ( quote ) ?? ''
50+ } `
51+ ) ,
52+ '$1'
53+ )
54+ ) ;
55+ } ;
56+
57+ const firstRow = split ( csvData [ 0 ] ) ;
58+
3359 const colCount = firstRow . length ;
3460
35- const foundHeaders = usedOptions . header
36- ? csvData [ 0 ] . split ( separator )
37- : [ ...Array ( colCount ) ] ;
61+ const foundHeaders = usedOptions . header ? firstRow : [ ...Array ( colCount ) ] ;
3862 const specifiedHeaders : ( string | undefined ) [ ] = [ ...usedOptions . headerList ! ] ;
3963
4064 const usedHeaders : string [ ] = [ ] ;
@@ -69,7 +93,7 @@ export default function csvToXml(
6993 : usedOptions . indentation ;
7094
7195 for ( let i = rowStartLine ; i < csvData . length ; i ++ ) {
72- const details = csvData [ i ] . split ( separator ) ;
96+ const details = split ( csvData [ i ] ) ;
7397
7498 if ( details . length < colCount ) {
7599 warn ( 'rows found without enough columns.' ) ;
@@ -79,13 +103,6 @@ export default function csvToXml(
79103 xml += `<${ usedOptions . rowName } >\n` ;
80104 for ( let j = 0 ; j < colCount ; j ++ ) {
81105 let colValue = details [ j ] ;
82- if ( ! usedOptions . quotes || usedOptions . quotes !== 'none' ) {
83- const quoteRemovingRegex = {
84- double : / " ( .* ?) " / ,
85- single : / ' ( .* ?) ' / ,
86- } [ usedOptions . quotes ! ] ;
87- colValue = colValue . replace ( quoteRemovingRegex , '$1' ) ;
88- }
89106 xml += `${ spaces } <${ usedHeaders [ j ] } >${ colValue } </${ usedHeaders [ j ] } >\n` ;
90107 }
91108 xml += `</${ usedOptions . rowName } >\n` ;
0 commit comments