Skip to content

Commit

Permalink
Merge pull request mapbox#50 from mapbox/optional-precision
Browse files Browse the repository at this point in the history
[proposal] Make precision warning optional
  • Loading branch information
tmcw authored Aug 30, 2016
2 parents 4c13759 + 12d849d commit 571ce34
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 159 deletions.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ the GeoJSON standards and returns them as an array of errors. An example of the
}]
```

The options argument is optional and has one option: `noDuplicateMembers`.
The options argument is optional. It has these options:

`noDuplicateMembers`.

By default, geojsonhint will treat repeated properties as an error: you can
set noDuplicateMembers to false to allow them. For instance:

Expand All @@ -42,6 +45,36 @@ geojsonhint.hint('{"type":"invalid","type":"Feature","properties":{},"geometry":
The repeated `type` property in this input will be ignored with the option,
and flagged without it.


`precisionWarning`.

GeoJSON [now recommends six decimal places of accuracy](https://tools.ietf.org/html/rfc7946#section-11.2)
for coordinates (Section 11.2). This option adds a warning message when coordinates
contain over 6 decimal places of accuracy, up to 10 coordinates before the warning
message is truncated for performance.

```js
geojsonhint.hint('{ "type": "Point", "coordinates": [100.0000000001, 5.0000000001] }', {
precisionWarning: false
});
```

With this option enabled, geojsonhint will produce these warnings:

```js
[{
line: 1,
level: 'warn',
message: 'precision of coordinates should be reduced'
}, {
line: 1,
level: 'warn',
message: 'precision of coordinates should be reduced'
}]
```

Without this option, this input will pass without errors.

## Line Numbers

Note that the GeoJSON can be given as a **string or as an object**. Here's how
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var jsonlint = require('jsonlint-lines'),
* @param {boolean} [options.noDuplicateMembers=true] forbid repeated
* properties. This is only available for string input, becaused parsed
* Objects cannot have duplicate properties.
* @param {boolean} [options.precisionWarning=true] warn if GeoJSON contains
* unnecessary coordinate precision.
* @returns {Array<Object>} an array of errors
*/
function hint(str, options) {
Expand Down
53 changes: 28 additions & 25 deletions object.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ var rightHandRule = require('./rhr');
* @param {boolean} [options.noDuplicateMembers=true] forbid repeated
* properties. This is only available for string input, becaused parsed
* Objects cannot have duplicate properties.
* @param {boolean} [options.precisionWarning=true] warn if GeoJSON contains
* unnecessary coordinate precision.
* @returns {Array<Object>} an array of errors
*/
function hint(gj, options) {

var errors = [];
var precisionWarningCount = 0;
var maxPrecisionWarnings = 10;
var maxPrecision = 6;

function root(_) {

Expand Down Expand Up @@ -140,31 +144,30 @@ function hint(gj, options) {
});
}

var maxPrecisionWarnings = 10;
var maxPrecision = 6;
if (precisionWarningCount === maxPrecisionWarnings) {
precisionWarningCount += 1;
return errors.push({
message: 'truncated warnings: we\'ve encountered coordinate precision warning ' + maxPrecisionWarnings + ' times, no more warnings will be reported',
level: 'warn',
line: _.__line__ || line
});
} else if (precisionWarningCount < maxPrecisionWarnings) {
_.forEach(function(num) {
var precision = 0;
var decimalStr = String(num).split('.')[1];
if (decimalStr !== undefined)
precision = decimalStr.length;
if (precision > maxPrecision) {
precisionWarningCount += 1;
return errors.push({
message: 'precision of coordinates should be reduced',
level: 'warn',
line: _.__line__ || line
});
}

});
if (options && options.precisionWarning) {
if (precisionWarningCount === maxPrecisionWarnings) {
precisionWarningCount += 1;
return errors.push({
message: 'truncated warnings: we\'ve encountered coordinate precision warning ' + maxPrecisionWarnings + ' times, no more warnings will be reported',
level: 'warn',
line: _.__line__ || line
});
} else if (precisionWarningCount < maxPrecisionWarnings) {
_.forEach(function(num) {
var precision = 0;
var decimalStr = String(num).split('.')[1];
if (decimalStr !== undefined)
precision = decimalStr.length;
if (precision > maxPrecision) {
precisionWarningCount += 1;
return errors.push({
message: 'precision of coordinates should be reduced',
level: 'warn',
line: _.__line__ || line
});
}
});
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions test/data/bad/excessive_precision.cli-output-pretty

This file was deleted.

1 change: 0 additions & 1 deletion test/data/bad/excessive_precision.geojson

This file was deleted.

12 changes: 0 additions & 12 deletions test/data/bad/excessive_precision.result

This file was deleted.

10 changes: 0 additions & 10 deletions test/data/bad/excessive_precision.result-object

This file was deleted.

58 changes: 1 addition & 57 deletions test/data/bad/excessive_precision_truncated.result
Original file line number Diff line number Diff line change
@@ -1,57 +1 @@
[
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 2
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 2
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 3
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 3
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 4
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 4
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 5
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 5
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 6
},
{
"message": "precision of coordinates should be reduced",
"level": "warn",
"line": 6
},
{
"message": "truncated warnings: we've encountered coordinate precision warning 10 times, no more warnings will be reported",
"level": "warn",
"line": 7
}
]
[]
47 changes: 1 addition & 46 deletions test/data/bad/excessive_precision_truncated.result-object
Original file line number Diff line number Diff line change
@@ -1,46 +1 @@
[
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "precision of coordinates should be reduced",
"level": "warn"
},
{
"message": "truncated warnings: we've encountered coordinate precision warning 10 times, no more warnings will be reported",
"level": "warn"
}
]
[]
47 changes: 45 additions & 2 deletions test/hint.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,54 @@ test('geojsonhint', function(t) {
t.deepEqual(geojsonhint.hint('{"type":"invalid","type":"Feature","properties":{},"geometry":null}', {
noDuplicateMembers: true
}), [{
"line": 1,
"message": "An object contained duplicate members, making parsing ambigous: type"
line: 1,
message: 'An object contained duplicate members, making parsing ambigous: type'
}], 'sketchy object not permitted by default');
t.end();
});
test('noDuplicateMembers option=true', function(t) {
t.deepEqual(geojsonhint.hint('{ "type": "Point", "coordinates": [100.0000000001, 5.0000000001] }', {
precisionWarning: true
}), [{
line: 1,
level: 'warn',
message: 'precision of coordinates should be reduced'
}, {
line: 1,
level: 'warn',
message: 'precision of coordinates should be reduced'
}], 'sketchy object not permitted by default');
t.end();
});
test('noDuplicateMembers option=true', function(t) {
var excessiveFeature = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
100.0000001,
100.0000001
]
},
properties: {}
};
var featureCollection = {
type: 'FeatureCollection',
features: []
};
for (var i = 0; i < 100; i++) featureCollection.features.push(excessiveFeature);
var truncated = geojsonhint.hint(JSON.stringify(featureCollection, null, 2), {
precisionWarning: true
})
t.equal(truncated.length, 11);
t.deepEqual(truncated[10], {
line: 63,
level: 'warn',
message: 'truncated warnings: we\'ve encountered coordinate precision warning 10 times, '
+ 'no more warnings will be reported'
});
t.end();
});
test('invalid roots', function(t) {
t.deepEqual(geojsonhint.hint('null'), [{
message: 'The root of a GeoJSON object must be an object.',
Expand Down

0 comments on commit 571ce34

Please sign in to comment.