From 631ef53aa17f49a83ae89a72f9b7bd208adbd2e6 Mon Sep 17 00:00:00 2001 From: hparkertt Date: Fri, 6 Sep 2019 15:45:19 -0400 Subject: [PATCH 1/3] Adding undefined/null check for `container.lat` scenarios. --- geojson.js | 4 ++-- geojson.min.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/geojson.js b/geojson.js index 8550a87..df807a4 100644 --- a/geojson.js +++ b/geojson.js @@ -230,7 +230,7 @@ var paths = val[i].split('.'); var itemClone = item; for (var j = 0; j < paths.length; j++) { - if (!itemClone.hasOwnProperty(paths[j])) { + if (itemClone == undefined || !itemClone.hasOwnProperty(paths[j])) { return false; } itemClone = itemClone[paths[j]]; // Iterate deeper into the object @@ -248,7 +248,7 @@ var paths = val[i].split('.'); var itemClone = item; for (var j = 0; j < paths.length; j++) { - if (!itemClone.hasOwnProperty(paths[j])) { + if (itemClone == undefined || !itemClone.hasOwnProperty(paths[j])) { return false; } itemClone = itemClone[paths[j]]; // Iterate deeper into the object diff --git a/geojson.min.js b/geojson.min.js index e727334..1a4548b 100644 --- a/geojson.min.js +++ b/geojson.min.js @@ -1,3 +1,4 @@ // geojson.js - v0.4.1 -// (c) 2016 Casey Thomas, MIT License -!function(a){function b(){var a=1<=arguments.length?[].slice.call(arguments,0):[],b=a.shift(),c=a.shift();Error.apply(this,a),this.message=this.message||"Invalid Geometry: item: "+JSON.stringify(b)+", params: "+JSON.stringify(c)}function c(a,b){var c=a||{};for(var d in b)b.hasOwnProperty(d)&&!c[d]&&(c[d]=b[d]);return c}function d(a,b){if(b.crs&&e(b.crs)&&(b.isPostgres?a.geometry.crs=b.crs:a.crs=b.crs),b.bbox&&(a.bbox=b.bbox),b.extraGlobal){a.properties={};for(var c in b.extraGlobal)a.properties[c]=b.extraGlobal[c]}}function e(a){if("name"===a.type){if(a.properties&&a.properties.name)return!0;throw new Error('Invalid CRS. Properties must contain "name" key')}if("link"===a.type){if(a.properties&&a.properties.href&&a.properties.type)return!0;throw new Error('Invalid CRS. Properties must contain "href" and "type" key')}throw new Error('Invald CRS. Type attribute must be "name" or "link"')}function f(a){a.geom={};for(var b in a)a.hasOwnProperty(b)&&-1!==m.indexOf(b)&&(a.geom[b]=a[b],delete a[b]);g(a.geom)}function g(a){for(var b in a)a.hasOwnProperty(b)&&("string"==typeof a[b]?n.push(a[b]):"object"==typeof a[b]&&(n.push(a[b][0]),n.push(a[b][1])));if(0===n.length)throw new Error("No geometry attributes specified")}function h(a){var b=a.item,c=a.params,d=a.propFunc,e={type:"Feature"};return e.geometry=j(b,c),e.properties=d.call(b),e}function i(a){return/^.+\..+$/.test(a)}function j(c,d){var e={};for(var f in d.geom){var g=d.geom[f];if("string"==typeof g&&c.hasOwnProperty(g))"GeoJSON"===f?e=c[g]:(e.type=f,e.coordinates=c[g]);else if("object"!=typeof g||Array.isArray(g))if(Array.isArray(g)&&c.hasOwnProperty(g[0])&&c.hasOwnProperty(g[1]))e.type=f,e.coordinates=[Number(c[g[1]]),Number(c[g[0]])];else if(Array.isArray(g)&&i(g[0])&&i(g[1])){for(var h=[],k=0;k Date: Mon, 30 Sep 2019 16:51:09 -0400 Subject: [PATCH 2/3] Adjusting variable names and definitions to resolve jshint task warnings. --- geojson.js | 23 ++++++++++++----------- geojson.min.js | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/geojson.js b/geojson.js index df807a4..6bf8391 100644 --- a/geojson.js +++ b/geojson.js @@ -180,6 +180,9 @@ for(var gtype in params.geom) { var val = params.geom[gtype]; + var coordinates = []; + var itemClone; + var paths; // Geometry parameter specified as: {Point: 'coords'} if(typeof val === 'string' && item.hasOwnProperty(val)) { @@ -225,10 +228,9 @@ // Geometry parameter specified as: {Point: ['container.lat', 'container.lng', 'container.alt']} else if(Array.isArray(val) && isNested(val[0]) && isNested(val[1]) && isNested(val[2])){ - var coordinates = []; for (var i = 0; i < val.length; i++) { // i.e. 0 and 1 - var paths = val[i].split('.'); - var itemClone = item; + paths = val[i].split('.'); + itemClone = item; for (var j = 0; j < paths.length; j++) { if (itemClone == undefined || !itemClone.hasOwnProperty(paths[j])) { return false; @@ -243,17 +245,16 @@ // Geometry parameter specified as: {Point: ['container.lat', 'container.lng']} else if(Array.isArray(val) && isNested(val[0]) && isNested(val[1])){ - var coordinates = []; - for (var i = 0; i < val.length; i++) { // i.e. 0 and 1 - var paths = val[i].split('.'); - var itemClone = item; - for (var j = 0; j < paths.length; j++) { - if (itemClone == undefined || !itemClone.hasOwnProperty(paths[j])) { + for (var k = 0; k < val.length; k++) { // i.e. 0 and 1 + paths = val[k].split('.'); + itemClone = item; + for (var l = 0; l < paths.length; l++) { + if (itemClone == undefined || !itemClone.hasOwnProperty(paths[l])) { return false; } - itemClone = itemClone[paths[j]]; // Iterate deeper into the object + itemClone = itemClone[paths[l]]; // Iterate deeper into the object } - coordinates[i] = itemClone; + coordinates[k] = itemClone; } geom.type = gtype; geom.coordinates = [Number(coordinates[1]), Number(coordinates[0])]; diff --git a/geojson.min.js b/geojson.min.js index 1a4548b..c000d1b 100644 --- a/geojson.min.js +++ b/geojson.min.js @@ -1,4 +1,4 @@ // geojson.js - v0.4.1 // (c) 2019 Casey Cesari, MIT License -!function(y){function l(){var r=1<=arguments.length?[].slice.call(arguments,0):[],e=r.shift(),t=r.shift();Error.apply(this,r),this.message=this.message||"Invalid Geometry: item: "+JSON.stringify(e)+", params: "+JSON.stringify(t)}y.version="0.4.1",y.defaults={doThrows:{invalidGeometry:!1}},l.prototype=Error,y.errors={InvalidGeometryError:l},y.isGeometryValid=function(r){return!(!r||!Object.keys(r).length)&&(!!r.type&&!!r.coordinates&&Array.isArray(r.coordinates)&&!!r.coordinates.length)},y.parse=function(r,e,t){var o,n,i=function(r,e){var t=r||{};for(var o in e)e.hasOwnProperty(o)&&!t[o]&&(t[o]=e[o]);return t}(e,this.defaults);if(s.length=0,function(r){for(var e in r.geom={},r)r.hasOwnProperty(e)&&-1!==a.indexOf(e)&&(r.geom[e]=r[e],delete r[e]);!function(r){for(var e in r)r.hasOwnProperty(e)&&("string"==typeof r[e]?s.push(r[e]):"object"==typeof r[e]&&(s.push(r[e][0]),s.push(r[e][1])));if(0===s.length)throw new Error("No geometry attributes specified")}(r.geom)}(i),n=function(t){var e;t.exclude||t.include?t.include?e=function(e){t.include.forEach(function(r){e[r]=this[r]},this)}:t.exclude&&(e=function(r){for(var e in this)this.hasOwnProperty(e)&&-1===s.indexOf(e)&&-1===t.exclude.indexOf(e)&&(r[e]=this[e])}):e=function(r){for(var e in this)this.hasOwnProperty(e)&&-1===s.indexOf(e)&&(r[e]=this[e])};return function(){var r={};return e.call(this,r),t.extra&&function(r,e){for(var t in e)e.hasOwnProperty(t)&&(r[t]=e[t])}(r,t.extra),r}}(i),Array.isArray(r)?(o={type:"FeatureCollection",features:[]},r.forEach(function(r){o.features.push(p({item:r,params:i,propFunc:n}))}),u(o,i)):u(o=p({item:r,params:i,propFunc:n}),i),!t||"function"!=typeof t)return o;t(o)};var a=["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","GeoJSON"],s=[];function u(r,e){if(e.crs&&function(r){{if("name"===r.type){if(r.properties&&r.properties.name)return!0;throw new Error('Invalid CRS. Properties must contain "name" key')}if("link"!==r.type)throw new Error('Invald CRS. Type attribute must be "name" or "link"');if(r.properties&&r.properties.href&&r.properties.type)return!0;throw new Error('Invalid CRS. Properties must contain "href" and "type" key')}}(e.crs)&&(e.isPostgres?r.geometry.crs=e.crs:r.crs=e.crs),e.bbox&&(r.bbox=e.bbox),e.extraGlobal)for(var t in r.properties={},e.extraGlobal)r.properties[t]=e.extraGlobal[t]}function p(r){var e=r.item,t=r.params,o=r.propFunc,n={type:"Feature"};return n.geometry=function o(n,r){var e={};for(var t in r.geom){var i=r.geom[t];if("string"==typeof i&&n.hasOwnProperty(i))"GeoJSON"===t?e=n[i]:(e.type=t,e.coordinates=n[i]);else if("object"!=typeof i||Array.isArray(i))if(Array.isArray(i)&&n.hasOwnProperty(i[0])&&n.hasOwnProperty(i[1])&&n.hasOwnProperty(i[2]))e.type=t,e.coordinates=[Number(n[i[1]]),Number(n[i[0]]),Number(n[i[2]])];else if(Array.isArray(i)&&n.hasOwnProperty(i[0])&&n.hasOwnProperty(i[1]))e.type=t,e.coordinates=[Number(n[i[1]]),Number(n[i[0]])];else if(Array.isArray(i)&&h(i[0])&&h(i[1])&&h(i[2])){for(var a=[],s=0;s Date: Tue, 1 Oct 2019 12:39:08 -0400 Subject: [PATCH 3/3] Adding tests for nested point arguments and undefined geometry values. --- test/test.js | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/test.js b/test/test.js index d321452..9ea2ba9 100644 --- a/test/test.js +++ b/test/test.js @@ -481,6 +481,57 @@ describe('GeoJSON', function() { }); }); + it('can accept nested arguments for Point', function(done) { + var data = [ + { name: 'Location A', category: 'Store', location: { point: { lat: 39.984, lng: -75.343 } } } + ]; + + GeoJSON.parse(data, { Point: ['location.point.lat', 'location.point.lng'] }, function(geojson) { + expect(geojson.type).to.be('FeatureCollection'); + expect(geojson.features).to.be.an('array'); + expect(geojson.features.length).to.be(1); + expect(geojson.features[0].geometry.coordinates[0]).to.equal(-75.343); + expect(geojson.features[0].geometry.coordinates[1]).to.equal(39.984); + done(); + }); + }); + + it('can handle null or undefined values when parsing nested arguments', function(done) { + var data = [ + { geo: null }, + { geo: { line: [[102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0] ] } }, + { geo: { polygon: [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] } }, + { geo: { multipoint: [ [100.0, 0.0], [101.0, 1.0] ] } }, + { geo: { multipolygon: [ + [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]], + [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]], + [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]] + ]}}, + { geo: { multilinestring: [ [ [100.0, 0.0], [101.0, 1.0] ], [ [102.0, 2.0], [103.0, 3.0] ] ] } } + ]; + + GeoJSON.parse(data, { + Point: ['geo.nope.point.lng', 'geo.nope.point.lat'], + LineString: 'geo.nope.line', + Polygon: 'geo.nope.polygon', + MultiPoint: 'geo.nope.multipoint', + MultiPolygon: 'geo.nope.multipolygon', + MultiLineString: 'geo.nope.multilinestring' + }, function(geojson) { + expect(geojson.type).to.be('FeatureCollection'); + expect(geojson.features).to.be.an('array'); + expect(geojson.features.length).to.be(6); + expect(geojson.features[0].geometry).to.be(false); + expect(geojson.features[1].geometry).to.be(false); + expect(geojson.features[2].geometry).to.be(false); + expect(geojson.features[3].geometry).to.be(false); + expect(geojson.features[4].geometry).to.be(false); + expect(geojson.features[5].geometry).to.be(false); + done(); + }); + + }); + it('can accept up to three arguments for Point in a nested structure', function(done) { var data = [ { name: 'Location A', category: 'Store', location: { lat: 39.984, lng: -75.343, alt: 22026.46 }, street: 'Market' },