Skip to content

Commit

Permalink
Support everything, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tmcw committed Oct 9, 2013
1 parent 5c54581 commit ba6927c
Show file tree
Hide file tree
Showing 20 changed files with 283 additions and 44 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tokml.js:
browserify -s tokml index.js > tokml.js
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,38 @@

Convert [GeoJSON](http://geojson.org/) to [KML](https://developers.google.com/kml/documentation/).

## usage
## Usage

npm install --save tokml

## api
as a binary:

npm install -g tokml
tokml file.geojson > file.kml
tokml < file.geojson > file.kml

## Example

```js
var kml = tokml(geojsonObject);
```

## API

### `tokml(geojsonObject)`

Given [GeoJSON](http://geojson.org/) data as an object, return KML data as a
string of XML.

## Development

Requires [node.js](http://nodejs.org/) and [browserify](https://github.com/substack/node-browserify):

To build `tokml.js`:

make

To run tests:

npm install
npm test
85 changes: 51 additions & 34 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
module.exports = tokml;

var header = '<?xml version="1.0" encoding="UTF-8"?>' +
'<kml xmlns="http://www.opengis.net/kml/2.2">',
footer = '</kml>';

module.exports = function tokml(geojson) {
return '<?xml version="1.0" encoding="UTF-8"?>' +
tag('kml',
tag('Document',
geojson.features.map(feature).join('')
), [['xmlns', 'http://www.opengis.net/kml/2.2']]);
};

// ## Geometry Types
//
// https://developers.google.com/kml/documentation/kmlreference#geometry
function point(_) {
return tag('Point', tag('coordinates', _.coordinates.join(',')));
}

function linestring(_) {
return tag('LineString', tag('coordinates', linearring(_.coordinates)));
}
var geometry = {
Point: function(_) {
return tag('Point', tag('coordinates', _.coordinates.join(',')));
},
LineString: function(_) {
return tag('LineString', tag('coordinates', linearring(_.coordinates)));
},
Polygon: function(_) {
var outer = _.coordinates[0],
inner = _.coordinates.slice(1),
outerRing = tag('outerBoundaryIs',
tag('LinearRing', tag('coordinates', linearring(outer)))),
innerRings = inner.map(function(i) {
return tag('innerBoundaryIs',
tag('LinearRing', tag('coordinates', linearring(i))));
}).join('');
return tag('Polygon', outerRing + innerRings);
},
MultiPoint: function(_) {
return tag('MultiGeometry', _.coordinates.map(function(c) {
return geometry.Point({ coordinates: c });
}).join(''));
},
MultiPolygon: function(_) {
return tag('MultiGeometry', _.coordinates.map(function(c) {
return geometry.Polygon({ coordinates: c });
}).join(''));
},
MultiLineString: function(_) {
return tag('MultiGeometry', _.coordinates.map(function(c) {
return geometry.LineString({ coordinates: c });
}).join(''));
},
GeometryCollection: function(_) {
return tag('MultiGeometry',
_.geometries.map(geometry.any).join(''));
},
any: function(_) {
if (geometry[_.type]) {
return geometry[_.type](_);
} else { }
}
};

function linearring(_) {
return _.map(function(cds) { return cds.join(','); }).join(' ');
}

function polygon(_) {
return tag('Polygon',
tag('outerBoundaryIs',
tag('LinearRing',
tag('coordinates', linearring(_.coordinates[0])))));
}

// ## Data
function extendeddata(_) {
return tag('ExtendedData', pairs(_).map(data).join(''));
Expand All @@ -36,25 +66,12 @@ function data(_) {
return tag('Data', _[1], [['name', _[0]]]);
}

var geometry = {
Point: point,
LineString: linestring,
Polygon: polygon
};

function feature(_) {
return tag('Placemark',
geometry[_.geometry.type](_.geometry) +
geometry.any(_.geometry) +
extendeddata(_.properties));
}

// # tokml
function tokml(geojson) {
return header +
geojson.features.map(feature).join('') +
footer;
}

// ## Helpers
function pairs(_) {
var o = [];
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@
"license": "BSD-2-Clause",
"devDependencies": {
"expect.js": "~0.2.0",
"mocha": "~1.13.0"
"mocha": "~1.13.0",
"glob": "~3.2.6"
},
"dependencies": {
"minimist": "0.0.5"
"minimist": "0.0.5",
"concat-stream": "~1.0.1",
"sharkdown": "0.0.1"
}
}
7 changes: 7 additions & 0 deletions scripts/regenerate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var tokml = require('../'),
fs = require('fs'),
glob = require('glob');

glob.sync('test/data/*.geojson').forEach(function(g) {
fs.writeFileSync(g.replace('.geojson', '.kml'), tokml(JSON.parse(fs.readFileSync(g))));
});
1 change: 1 addition & 0 deletions test/data/featurecollection.kml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><Point><coordinates>102,0.5</coordinates></Point><ExtendedData><Data name="prop0">value0</Data></ExtendedData></Placemark><Placemark><LineString><coordinates>102,0 103,1 104,0 105,1</coordinates></LineString><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">0</Data></ExtendedData></Placemark><Placemark><Polygon><outerBoundaryIs><LinearRing><coordinates>100,0 101,0 101,1 100,1 100,0</coordinates></LinearRing></outerBoundaryIs></Polygon><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
20 changes: 20 additions & 0 deletions test/data/geometrycollection.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{ "type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": { "type": "GeometryCollection",
"geometries": [
{ "type": "Point",
"coordinates": [100.0, 0.0]
},
{ "type": "LineString",
"coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
}
]
},
"properties": {
"prop0": "value0",
"prop1": "val2"
}
}
]
}
1 change: 1 addition & 0 deletions test/data/geometrycollection.kml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><MultiGeometry><Point><coordinates>100,0</coordinates></Point><LineString><coordinates>101,0 102,1</coordinates></LineString></MultiGeometry><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
2 changes: 1 addition & 1 deletion test/data/linestring.kml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Placemark><LineString><coordinates>100,0 101,1</coordinates></LineString><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></kml>
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><LineString><coordinates>100,0 101,1</coordinates></LineString><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
16 changes: 16 additions & 0 deletions test/data/multilinestring.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{ "type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": { "type": "MultiLineString",
"coordinates": [
[ [100.0, 0.0], [101.0, 1.0] ],
[ [102.0, 2.0], [103.0, 3.0] ]
]
},
"properties": {
"prop0": "value0",
"prop1": "val2"
}
}
]
}
1 change: 1 addition & 0 deletions test/data/multilinestring.kml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><MultiGeometry><LineString><coordinates>100,0 101,1</coordinates></LineString><LineString><coordinates>102,2 103,3</coordinates></LineString></MultiGeometry><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
13 changes: 13 additions & 0 deletions test/data/multipoint.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{ "type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": { "type": "MultiPoint",
"coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
},
"properties": {
"prop0": "value0",
"prop1": "val2"
}
}
]
}
1 change: 1 addition & 0 deletions test/data/multipoint.kml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><MultiGeometry><Point><coordinates>100,0</coordinates></Point><Point><coordinates>101,1</coordinates></Point></MultiGeometry><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
17 changes: 17 additions & 0 deletions test/data/multipolygon.geojson
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{ "type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": { "type": "MultiPolygon",
"coordinates": [
[[[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]]]
]
},
"properties": {
"prop0": "value0",
"prop1": "val2"
}
}
]
}
1 change: 1 addition & 0 deletions test/data/multipolygon.kml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><MultiGeometry><Polygon><outerBoundaryIs><LinearRing><coordinates>102,2 103,2 103,3 102,3 102,2</coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LinearRing><coordinates>100,0 101,0 101,1 100,1 100,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><coordinates>100.2,0.2 100.8,0.2 100.8,0.8 100.2,0.8 100.2,0.2</coordinates></LinearRing></innerBoundaryIs></Polygon></MultiGeometry><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
2 changes: 1 addition & 1 deletion test/data/point.kml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Placemark><Point><coordinates>100,0</coordinates></Point><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></kml>
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><Point><coordinates>100,0</coordinates></Point><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
2 changes: 1 addition & 1 deletion test/data/polygon.kml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Placemark><Polygon><outerBoundaryIs><LinearRing><coordinates>100,0 101,0 101,1 100,1 100,0</coordinates></LinearRing></outerBoundaryIs></Polygon><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></kml>
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><Polygon><outerBoundaryIs><LinearRing><coordinates>100,0 101,0 101,1 100,1 100,0</coordinates></LinearRing></outerBoundaryIs></Polygon><ExtendedData><Data name="prop0">value0</Data><Data name="prop1">val2</Data></ExtendedData></Placemark></Document></kml>
9 changes: 9 additions & 0 deletions test/kml.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ describe('tokml', function() {
it('linestring', function() {
expect(tokml(file('linestring.geojson'))).to.eql(output('linestring.kml'));
});
it('multilinestring', function() {
expect(tokml(file('multilinestring.geojson'))).to.eql(output('multilinestring.kml'));
});
it('multipoint', function() {
expect(tokml(file('multipoint.geojson'))).to.eql(output('multipoint.kml'));
});
it('multipolygon', function() {
expect(tokml(file('multipolygon.geojson'))).to.eql(output('multipolygon.kml'));
});
});

function file(f) {
Expand Down
13 changes: 10 additions & 3 deletions tokml
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#!/usr/bin/env node

var tokml = require('./'),
sharkdown = require('sharkdown'),
concat = require('concat-stream'),
fs = require('fs'),
argv = require('minimist')(process.argv.slice(2));

process.stdout.write(
tokml(JSON.parse(fs.readFileSync(argv._[0])))
);
if (process.stdin.isTTY && !argv._[0]) {
process.stdout.write(sharkdown(fs.readFileSync(__dirname + '/README.md')));
process.exit(1);
}

(argv._.length ? fs.createReadStream(argv._[0]) : process.stdin).pipe(concat(convert));

function convert(data) { process.stdout.write(tokml(JSON.parse(data))); }
Loading

0 comments on commit ba6927c

Please sign in to comment.