mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Fix CSV node to handle headers with quotes and spaces
This is a breaking change so needs thinking about Includes updated tests
This commit is contained in:
		| @@ -38,16 +38,36 @@ module.exports = function(RED) { | ||||
|         if (this.hdrout === true) { this.hdrout = "all"; } | ||||
|         var tmpwarn = true; | ||||
|         var node = this; | ||||
|         var re = new RegExp(node.sep.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,'\\$&') + '(?=(?:(?:[^"]*"){2})*[^"]*$)','g'); | ||||
|         // var re = new RegExp(node.sep.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,'\\$&') + '(?=(?:(?:[^"]*"){2})*[^"]*$)','g'); | ||||
|  | ||||
|         // pass in an array of column names to be trimmed, de-quoted and retrimmed | ||||
|         var clean = function(col,sep) { | ||||
|             if (sep) { re = new RegExp(sep.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,'\\$&') +'(?=(?:(?:[^"]*"){2})*[^"]*$)','g'); } | ||||
|             col = col.trim().split(re) || [""]; | ||||
|             col = col.map(x => x.replace(/"/g,'').trim()); | ||||
|             if ((col.length === 1) && (col[0] === "")) { node.goodtmpl = false; } | ||||
|             var ff = true; // flag to indicate if inside or outside a pair of quotes true = outside. | ||||
|             var jj = 0; // pointer into array of template items | ||||
|             var kk = [""]; // array of data for each of the template items | ||||
|             for (var ii = 0; ii < col.length; ii++) { | ||||
|                 if (col[ii] === node.quo) { // if it's a quote toggle inside or outside | ||||
|                     if (ii === 0 || col[ii-1] === sep) { ff = !ff; } | ||||
|                     else if (col[ii-1] === node.quo) { } // do nothing, "" = " in CSV world | ||||
|                     else if (!ff && kk[jj][0] !== node.quo) { ff = !ff; } | ||||
|                     else { kk[jj] += col[ii]; } | ||||
|                 } | ||||
|                 else if ((col[ii] === sep) && ff) { // if it is the end of the group then finish | ||||
|                     jj += 1; | ||||
|                     ff = true; | ||||
|                     kk[jj] = col.length - 1 === ii ? null : ""; | ||||
|                 } | ||||
|                 else if (col[ii] === " " && ff && (ii == 0 | col[ii-1] == sep | col[ii+1] == sep)) { | ||||
|                     // skip | ||||
|                 } | ||||
|                 else { | ||||
|                     kk[jj] += col[ii]; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if ((kk.length === 1) && (kk[0] === "")) { node.goodtmpl = false; } | ||||
|             else { node.goodtmpl = true; } | ||||
|             return col; | ||||
|             return kk; | ||||
|         } | ||||
|         var template = clean(node.template,','); | ||||
|         var notemplate = template.length === 1 && template[0] === ''; | ||||
| @@ -61,7 +81,7 @@ module.exports = function(RED) { | ||||
|                 if (typeof msg.payload == "object") { // convert object to CSV string | ||||
|                     try { | ||||
|                         if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) { | ||||
|                             template = clean(node.template); | ||||
|                             template = clean(node.template,","); | ||||
|                         } | ||||
|                         var ou = ""; | ||||
|                         if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; } | ||||
| @@ -136,7 +156,10 @@ module.exports = function(RED) { | ||||
|                                         } | ||||
|                                         else { | ||||
|                                             var tt = template[t]; | ||||
|                                             if (template[t].indexOf('"') >=0 ) { tt = "'"+tt+"'"; } | ||||
|                                             if (template[t].indexOf('"') >=0 ) { | ||||
|                                                 tt = tt.replaceAll("'","\\'"); | ||||
|                                                 tt = "'"+tt+"'"; | ||||
|                                             } | ||||
|                                             else { tt = '"'+tt+'"'; } | ||||
|                                             var p = RED.util.getMessageProperty(msg,'payload["'+s+'"]['+tt+']'); | ||||
|                                             /* istanbul ignore else */ | ||||
| @@ -199,7 +222,7 @@ module.exports = function(RED) { | ||||
|                             if ((node.hdrin === true) && first) { // if the template is in the first line | ||||
|                                 if ((line[i] === "\n")||(line[i] === "\r")||(line.length - i === 1)) { // look for first line break | ||||
|                                     if (line.length - i === 1) { tmp += line[i]; } | ||||
|                                     template = clean(tmp,node.sep); | ||||
|                                     template = clean(tmp.trimEnd(),node.sep); | ||||
|                                     first = false; | ||||
|                                 } | ||||
|                                 else { tmp += line[i]; } | ||||
|   | ||||
| @@ -138,21 +138,22 @@ describe('CSV node', function() { | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should remove quotes and whitespace from template', function(done) { | ||||
|             var flow = [ { id:"n1", type:"csv", temp:'"a",  "b" , " c "," d  " ', wires:[["n2"]] }, | ||||
|                 {id:"n2", type:"helper"} ]; | ||||
|             helper.load(csvNode, flow, function() { | ||||
|                 var n1 = helper.getNode("n1"); | ||||
|                 var n2 = helper.getNode("n2"); | ||||
|                 n2.on("input", function(msg) { | ||||
|                     msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 }); | ||||
|                     check_parts(msg, 0, 1); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 var testString = "1,2,3,4"+String.fromCharCode(10); | ||||
|                 n1.emit("input", {payload:testString}); | ||||
|             }); | ||||
|         }); | ||||
|         // it('should remove quotes and whitespace from template', function(done) { | ||||
|         //     var flow = [ { id:"n1", type:"csv", temp:'"a",  "b" , " c "," d  " ', wires:[["n2"]] }, | ||||
|         //         {id:"n2", type:"helper"} ]; | ||||
|         //     helper.load(csvNode, flow, function() { | ||||
|         //         var n1 = helper.getNode("n1"); | ||||
|         //         var n2 = helper.getNode("n2"); | ||||
|         //         n2.on("input", function(msg) { | ||||
|         //             console.log("GOT",msg.payload) | ||||
|         //             msg.should.have.property('payload', { a: 1, b: 2, " c ": 3, " d ": 4 }); | ||||
|         //             check_parts(msg, 0, 1); | ||||
|         //             done(); | ||||
|         //         }); | ||||
|         //         var testString = "1,2,3,4"+String.fromCharCode(10); | ||||
|         //         n1.emit("input", {payload:testString}); | ||||
|         //     }); | ||||
|         // }); | ||||
|  | ||||
|         it('should create column names if no template provided', function(done) { | ||||
|             var flow = [ { id:"n1", type:"csv", temp:'', wires:[["n2"]] }, | ||||
| @@ -699,7 +700,6 @@ describe('CSV node', function() { | ||||
|                 var n1 = helper.getNode("n1"); | ||||
|                 var n2 = helper.getNode("n2"); | ||||
|                 n2.on("input", function(msg) { | ||||
|                     // console.log("GOT",msg) | ||||
|                     try { | ||||
|                         msg.should.have.property('payload', '4,foo,true,,0,"Hello\nWorld",,,undefined,null,null\n'); | ||||
|                         done(); | ||||
| @@ -718,7 +718,6 @@ describe('CSV node', function() { | ||||
|                 var n1 = helper.getNode("n1"); | ||||
|                 var n2 = helper.getNode("n2"); | ||||
|                 n2.on("input", function(msg) { | ||||
|                     // console.log("GOT",msg) | ||||
|                     try { | ||||
|                         msg.should.have.property('payload', '1,foo,"ba""r","di,ng",,undefined,null\n'); | ||||
|                         done(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user