(array, options = {}, replacer = v => v)
| 130 | } |
| 131 | |
| 132 | export function stringify (array, options = {}, replacer = v => v) { |
| 133 | const ctx = Object.create(null); |
| 134 | ctx.options = options; |
| 135 | ctx.options.eof = ctx.options.eof !== undefined ? ctx.options.eof : true; |
| 136 | ctx.row = 1; |
| 137 | ctx.col = 1; |
| 138 | ctx.output = ''; |
| 139 | |
| 140 | ctx.options.delimiter = ctx.options.delimiter === undefined ? '"' : options.delimiter; |
| 141 | if(ctx.options.delimiter.length > 1 || ctx.options.delimiter.length === 0) |
| 142 | throw Error(`CSVError: delimiter must be one character [${ctx.options.separator}]`); |
| 143 | |
| 144 | ctx.options.separator = ctx.options.separator === undefined ? ',' : options.separator; |
| 145 | if(ctx.options.separator.length > 1 || ctx.options.separator.length === 0) |
| 146 | throw Error(`CSVError: separator must be one character [${ctx.options.separator}]`); |
| 147 | |
| 148 | const needsDelimiters = new RegExp(`${escapeRegExp(ctx.options.delimiter)}|${escapeRegExp(ctx.options.separator)}|\r\n|\n|\r`); |
| 149 | |
| 150 | array.forEach((row, rIdx) => { |
| 151 | let entry = ''; |
| 152 | ctx.col = 1; |
| 153 | row.forEach((col, cIdx) => { |
| 154 | if (typeof col === 'string') { |
| 155 | col = col.replace(new RegExp(ctx.options.delimiter, 'g'), `${ctx.options.delimiter}${ctx.options.delimiter}`); |
| 156 | col = needsDelimiters.test(col) ? `${ctx.options.delimiter}${col}${ctx.options.delimiter}` : col; |
| 157 | } |
| 158 | entry += replacer(col, ctx.row, ctx.col); |
| 159 | if (cIdx !== row.length - 1) { |
| 160 | entry += ctx.options.separator; |
| 161 | } |
| 162 | ctx.col++; |
| 163 | }); |
| 164 | switch (true) { |
| 165 | case ctx.options.eof: |
| 166 | case !ctx.options.eof && rIdx !== array.length - 1: |
| 167 | ctx.output += `${entry}\n`; |
| 168 | break; |
| 169 | default: |
| 170 | ctx.output += `${entry}`; |
| 171 | break; |
| 172 | } |
| 173 | ctx.row++; |
| 174 | }); |
| 175 | |
| 176 | return ctx.output; |
| 177 | } |
| 178 | |
| 179 | function valueEnd (ctx) { |
| 180 | const value = ctx.options.typed ? inferType(ctx.value) : ctx.value; |
no test coverage detected