mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Added YAML parser node (#1034)
Thanks @natcl - (sorry pressed closed by mistake !) * Added YAML parser node * Added YAML error strings in messages.json * Change location of YAML library import * Remove copyright * Remove copyright * Change order of yaml in Template node * Add YAML test * Add working test
This commit is contained in:
		
				
					committed by
					
						 Dave Conway-Jones
						Dave Conway-Jones
					
				
			
			
				
	
			
			
			
						parent
						
							b1ab26e3ad
						
					
				
				
					commit
					9bbc8eda9d
				
			
							
								
								
									
										
											BIN
										
									
								
								editor/icons/parser-yaml.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								editor/icons/parser-yaml.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 423 B | 
| @@ -37,6 +37,7 @@ | |||||||
|                 <option value="css">CSS</option> |                 <option value="css">CSS</option> | ||||||
|                 <option value="markdown">Markdown</option> |                 <option value="markdown">Markdown</option> | ||||||
|                 <option value="text">none</option> |                 <option value="text">none</option> | ||||||
|  |                 <option value="yaml">YAML</option> | ||||||
|             </select> |             </select> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -614,6 +614,13 @@ | |||||||
|             "dropped-error": "Failed to convert payload" |             "dropped-error": "Failed to convert payload" | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |     "yaml": { | ||||||
|  |         "errors": { | ||||||
|  |             "dropped-object": "Ignored non-object payload", | ||||||
|  |             "dropped": "Ignored unsupported payload type", | ||||||
|  |             "dropped-error": "Failed to convert payload" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|     "xml": { |     "xml": { | ||||||
|         "label": { |         "label": { | ||||||
|             "represent": "Represent XML tag attributes as a property named", |             "represent": "Represent XML tag attributes as a property named", | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								nodes/core/parsers/70-YAML.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								nodes/core/parsers/70-YAML.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | <script type="text/x-red" data-template-name="yaml"> | ||||||
|  |     <div class="form-row"> | ||||||
|  |         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||||
|  |         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"> | ||||||
|  |     </div> | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <script type="text/x-red" data-help-name="yaml"> | ||||||
|  |     <p>A function that parses the <code>msg.payload</code> to convert a YAML string to/from a javascript object. Places the result back into the payload.</p> | ||||||
|  |     <p>If the input is a YAML string it tries to parse it to a javascript object.</p> | ||||||
|  |     <p>If the input is a javascript object it creates a YAML string.</p> | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <script type="text/javascript"> | ||||||
|  |     RED.nodes.registerType('yaml',{ | ||||||
|  |         category: 'function', | ||||||
|  |         color:"#DEBD5C", | ||||||
|  |         defaults: { | ||||||
|  |             name: {value:""} | ||||||
|  |         }, | ||||||
|  |         inputs:1, | ||||||
|  |         outputs:1, | ||||||
|  |         icon: "parser-yaml.png", | ||||||
|  |         label: function() { | ||||||
|  |             return this.name||"yaml"; | ||||||
|  |         }, | ||||||
|  |         labelStyle: function() { | ||||||
|  |             return this.name?"node_label_italic":""; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | </script> | ||||||
							
								
								
									
										34
									
								
								nodes/core/parsers/70-YAML.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								nodes/core/parsers/70-YAML.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | module.exports = function(RED) { | ||||||
|  |     "use strict"; | ||||||
|  |     var yaml = require('js-yaml'); | ||||||
|  |     function YAMLNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         var node = this; | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |             if (msg.hasOwnProperty("payload")) { | ||||||
|  |                 if (typeof msg.payload === "string") { | ||||||
|  |                     try { | ||||||
|  |                         msg.payload = yaml.load(msg.payload); | ||||||
|  |                         node.send(msg); | ||||||
|  |                     } | ||||||
|  |                     catch(e) { node.error(e.message,msg); } | ||||||
|  |                 } | ||||||
|  |                 else if (typeof msg.payload === "object") { | ||||||
|  |                     if (!Buffer.isBuffer(msg.payload)) { | ||||||
|  |                         try { | ||||||
|  |                             msg.payload = yaml.dump(msg.payload); | ||||||
|  |                             node.send(msg); | ||||||
|  |                         } | ||||||
|  |                         catch(e) { | ||||||
|  |                             node.error(RED._("yaml.errors.dropped-error")); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else { node.warn(RED._("yaml.errors.dropped-object")); } | ||||||
|  |                 } | ||||||
|  |                 else { node.warn(RED._("yaml.errors.dropped")); } | ||||||
|  |             } | ||||||
|  |             else { node.send(msg); } // If no payload - just pass it on. | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("yaml",YAMLNode); | ||||||
|  | }; | ||||||
| @@ -40,6 +40,7 @@ | |||||||
|         "fs.notify":"0.0.4", |         "fs.notify":"0.0.4", | ||||||
|         "i18next":"1.10.6", |         "i18next":"1.10.6", | ||||||
|         "is-utf8":"0.2.1", |         "is-utf8":"0.2.1", | ||||||
|  |         "js-yaml": "3.6.1", | ||||||
|         "media-typer": "0.3.0", |         "media-typer": "0.3.0", | ||||||
|         "mqtt": "1.14.1", |         "mqtt": "1.14.1", | ||||||
|         "mustache": "2.2.1", |         "mustache": "2.2.1", | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								test/nodes/core/parsers/70-YAML_spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								test/nodes/core/parsers/70-YAML_spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright 2014 IBM Corp. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * | ||||||
|  |  * http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  * | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  **/ | ||||||
|  |  | ||||||
|  | var should = require("should"); | ||||||
|  | var yamlNode = require("../../../../nodes/core/parsers/70-YAML.js"); | ||||||
|  | var helper = require("../../helper.js"); | ||||||
|  |  | ||||||
|  | describe('YAML node', function() { | ||||||
|  |  | ||||||
|  |     before(function(done) { | ||||||
|  |         helper.startServer(done); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     afterEach(function() { | ||||||
|  |         helper.unload(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should be loaded', function(done) { | ||||||
|  |         var flow = [{id:"yamlNode1", type:"yaml", name: "yamlNode" }]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yamlNode1 = helper.getNode("yamlNode1"); | ||||||
|  |             yamlNode1.should.have.property('name', 'yamlNode'); | ||||||
|  |             done(); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should convert a valid yaml string to a javascript object', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yn1 = helper.getNode("yn1"); | ||||||
|  |             var yn2 = helper.getNode("yn2"); | ||||||
|  |             yn2.on("input", function(msg) { | ||||||
|  |                 console.log('msg', msg); | ||||||
|  |                 console.log('payload', msg.payload.employees[0]); | ||||||
|  |                 msg.should.have.property('topic', 'bar'); | ||||||
|  |                 msg.payload.should.have.property('employees'); | ||||||
|  |                 msg.payload.employees[0].should.have.property('firstName', 'John'); | ||||||
|  |                 msg.payload.employees[0].should.have.property('lastName', 'Smith'); | ||||||
|  |                 done(); | ||||||
|  |             }); | ||||||
|  |             var yamlString = "employees:\n  - firstName: John\n    lastName: Smith\n"; | ||||||
|  |             yn1.receive({payload:yamlString,topic: "bar"}); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should convert a javascript object to a yaml string', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yn1 = helper.getNode("yn1"); | ||||||
|  |             var yn2 = helper.getNode("yn2"); | ||||||
|  |             yn2.on("input", function(msg) { | ||||||
|  |                 should.equal(msg.payload, "employees:\n  - firstName: John\n    lastName: Smith\n"); | ||||||
|  |                 done(); | ||||||
|  |             }); | ||||||
|  |             var obj = {employees:[{firstName:"John", lastName:"Smith"}]}; | ||||||
|  |             yn1.receive({payload:obj}); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should convert an array to a yaml string', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yn1 = helper.getNode("yn1"); | ||||||
|  |             var yn2 = helper.getNode("yn2"); | ||||||
|  |             yn2.on("input", function(msg) { | ||||||
|  |                 should.equal(msg.payload, "- 1\n- 2\n- 3\n"); | ||||||
|  |                 done(); | ||||||
|  |             }); | ||||||
|  |             var obj = [1,2,3]; | ||||||
|  |             yn1.receive({payload:obj}); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should log an error if asked to parse an invalid yaml string', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             try { | ||||||
|  |                 var yn1 = helper.getNode("yn1"); | ||||||
|  |                 var yn2 = helper.getNode("yn2"); | ||||||
|  |                 yn1.receive({payload:'employees:\n-firstName: John\n- lastName: Smith\n',topic: "bar"}); | ||||||
|  |                 var logEvents = helper.log().args.filter(function(evt) { | ||||||
|  |                     return evt[0].type == "yaml"; | ||||||
|  |                 }); | ||||||
|  |                 logEvents.should.have.length(1); | ||||||
|  |                 logEvents[0][0].should.have.a.property('msg'); | ||||||
|  |                 logEvents[0][0].msg.should.startWith("end of the stream"); | ||||||
|  |                 logEvents[0][0].should.have.a.property('level',helper.log().ERROR); | ||||||
|  |                 done(); | ||||||
|  |             } catch(err) { | ||||||
|  |                 done(err); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should log an error if asked to parse something thats not yaml or js', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yn1 = helper.getNode("yn1"); | ||||||
|  |             var yn2 = helper.getNode("yn2"); | ||||||
|  |             setTimeout(function() { | ||||||
|  |                 try { | ||||||
|  |                     var logEvents = helper.log().args.filter(function(evt) { | ||||||
|  |                         return evt[0].type == "yaml"; | ||||||
|  |                     }); | ||||||
|  |                     logEvents.should.have.length(3); | ||||||
|  |                     logEvents[0][0].should.have.a.property('msg'); | ||||||
|  |                     logEvents[0][0].msg.toString().should.eql('yaml.errors.dropped'); | ||||||
|  |                     logEvents[1][0].should.have.a.property('msg'); | ||||||
|  |                     logEvents[1][0].msg.toString().should.eql('yaml.errors.dropped'); | ||||||
|  |                     logEvents[2][0].should.have.a.property('msg'); | ||||||
|  |                     logEvents[2][0].msg.toString().should.eql('yaml.errors.dropped-object'); | ||||||
|  |                     done(); | ||||||
|  |                 } catch(err) { | ||||||
|  |                     done(err); | ||||||
|  |                 } | ||||||
|  |             },150); | ||||||
|  |             yn1.receive({payload:true}); | ||||||
|  |             yn1.receive({payload:1}); | ||||||
|  |             yn1.receive({payload:new Buffer("a")}); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('should pass straight through if no payload set', function(done) { | ||||||
|  |         var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"}, | ||||||
|  |                     {id:"yn2", type:"helper"}]; | ||||||
|  |         helper.load(yamlNode, flow, function() { | ||||||
|  |             var yn1 = helper.getNode("yn1"); | ||||||
|  |             var yn2 = helper.getNode("yn2"); | ||||||
|  |             yn2.on("input", function(msg) { | ||||||
|  |                 msg.should.have.property('topic', 'bar'); | ||||||
|  |                 msg.should.not.have.property('payload'); | ||||||
|  |                 done(); | ||||||
|  |             }); | ||||||
|  |             yn1.receive({topic: "bar"}); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | }); | ||||||
		Reference in New Issue
	
	Block a user