@maphubs/tokml
Advanced tools
Comparing version 0.5.2 to 0.6.0
@@ -0,16 +1,22 @@ | ||
## 0.6.0 | ||
- Fix #2 setting the `simplestyle` option will now exclude the options from the `<ExtendedData>` of the KML | ||
- Upgrade dependencies | ||
- Simplify dependencies by removing unused website and moving helper functions into this repo | ||
## 0.5.2 | ||
* Add support for placemark ID attributes https://github.com/mapbox/tokml/issues/39 | ||
- Add support for placemark ID attributes https://github.com/mapbox/tokml/issues/39 | ||
## 0.5.0 | ||
* Upgrade dependencies to resolve security audit warnings | ||
- Upgrade dependencies to resolve security audit warnings | ||
## 0.4.0 | ||
* Adds support for simplestyle-spec. Thanks [Vincent Sels!](https://github.com/vincentsels) | ||
- Adds support for simplestyle-spec. Thanks [Vincent Sels!](https://github.com/vincentsels) | ||
## 0.3.0 | ||
* Add support for encoding the KML TimeStamp tag from a field in a GeoJSON | ||
- Add support for encoding the KML TimeStamp tag from a field in a GeoJSON | ||
properties object | ||
@@ -20,29 +26,29 @@ | ||
* Fixes order of Geometry and ExtendedData tags in Placemarks | ||
- Fixes order of Geometry and ExtendedData tags in Placemarks | ||
## 0.2.3 | ||
* Tolerates empty Polygon coordinates | ||
* Tolerates empty geometry collections | ||
- Tolerates empty Polygon coordinates | ||
- Tolerates empty geometry collections | ||
## 0.2.2 | ||
* Fix formatting of `ExtendedData` sections | ||
* Improved CLI help | ||
- Fix formatting of `ExtendedData` sections | ||
- Improved CLI help | ||
## 0.2.1 | ||
* Fix encoded output of non-string data values | ||
- Fix encoded output of non-string data values | ||
## 0.2.0 | ||
* [simplestyle-spec](https://github.com/mapbox/simplestyle-spec) support | ||
* better help for the `tokml` binary | ||
- [simplestyle-spec](https://github.com/mapbox/simplestyle-spec) support | ||
- better help for the `tokml` binary | ||
## 0.1.0 | ||
* Support document name and description properties. | ||
- Support document name and description properties. | ||
## 0.0.3 | ||
* Support bare features and geometries. | ||
- Support bare features and geometries. |
559
index.js
@@ -1,104 +0,129 @@ | ||
var esc = require('xml-escape'); | ||
var strxml = require('strxml'), | ||
tag = strxml.tag; | ||
var esc = require('./lib/xml-escape') | ||
var strxml = require('./lib/strxml'), | ||
tag = strxml.tag | ||
module.exports = function tokml(geojson, options) { | ||
options = options || { | ||
documentName: undefined, | ||
documentDescription: undefined, | ||
name: 'name', | ||
description: 'description', | ||
simplestyle: false, | ||
timestamp: 'timestamp' | ||
} | ||
options = options || { | ||
documentName: undefined, | ||
documentDescription: undefined, | ||
name: 'name', | ||
description: 'description', | ||
simplestyle: false, | ||
timestamp: 'timestamp' | ||
}; | ||
return ( | ||
'<?xml version="1.0" encoding="UTF-8"?>' + | ||
tag( | ||
'kml', | ||
{ xmlns: 'http://www.opengis.net/kml/2.2' }, | ||
tag( | ||
'Document', | ||
documentName(options) + | ||
documentDescription(options) + | ||
root(geojson, options) | ||
) | ||
) | ||
) | ||
} | ||
return '<?xml version="1.0" encoding="UTF-8"?>' + | ||
tag('kml', {'xmlns': 'http://www.opengis.net/kml/2.2'}, | ||
tag('Document', | ||
documentName(options) + | ||
documentDescription(options) + | ||
root(geojson, options) | ||
)); | ||
}; | ||
function feature(options, styleHashesArray) { | ||
return function (_) { | ||
if (!_.properties || !geometry.valid(_.geometry)) return '' | ||
var geometryString = geometry.any(_.geometry) | ||
if (!geometryString) return '' | ||
function feature(options, styleHashesArray) { | ||
return function(_) { | ||
if (!_.properties || !geometry.valid(_.geometry)) return ''; | ||
var geometryString = geometry.any(_.geometry); | ||
if (!geometryString) return ''; | ||
var styleDefinition = '', | ||
styleReference = ''; | ||
if (options.simplestyle) { | ||
var styleHash = hashStyle(_.properties); | ||
if (styleHash) { | ||
if (geometry.isPoint(_.geometry) && hasMarkerStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = markerStyle(_.properties, styleHash); | ||
styleHashesArray.push(styleHash); | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash); | ||
} else if ((geometry.isPolygon(_.geometry) || geometry.isLine(_.geometry)) && | ||
hasPolygonAndLineStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = polygonAndLineStyle(_.properties, styleHash); | ||
styleHashesArray.push(styleHash); | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash); | ||
} | ||
// Note that style of GeometryCollection / MultiGeometry is not supported | ||
} | ||
var styleDefinition = '', | ||
styleReference = '' | ||
if (options.simplestyle) { | ||
var styleHash = hashStyle(_.properties) | ||
if (styleHash) { | ||
if (geometry.isPoint(_.geometry) && hasMarkerStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = markerStyle(_.properties, styleHash) | ||
styleHashesArray.push(styleHash) | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash) | ||
removeMarkerStyle(_.properties) | ||
} else if ( | ||
(geometry.isPolygon(_.geometry) || geometry.isLine(_.geometry)) && | ||
hasPolygonAndLineStyle(_.properties) | ||
) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = polygonAndLineStyle(_.properties, styleHash) | ||
styleHashesArray.push(styleHash) | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash) | ||
removePolygonAndLineStyle(_.properties) | ||
} | ||
var attributes = {} | ||
if (_.id) attributes.id = _.id | ||
return styleDefinition + tag('Placemark', | ||
attributes, | ||
name(_.properties, options) + | ||
description(_.properties, options) + | ||
extendeddata(_.properties) + | ||
timestamp(_.properties, options) + | ||
geometryString + | ||
styleReference); | ||
}; | ||
// Note that style of GeometryCollection / MultiGeometry is not supported | ||
} | ||
} | ||
var attributes = {} | ||
if (_.id) attributes.id = _.id | ||
return ( | ||
styleDefinition + | ||
tag( | ||
'Placemark', | ||
attributes, | ||
name(_.properties, options) + | ||
description(_.properties, options) + | ||
extendeddata(_.properties) + | ||
timestamp(_.properties, options) + | ||
geometryString + | ||
styleReference | ||
) | ||
) | ||
} | ||
} | ||
function root(_, options) { | ||
if (!_.type) return ''; | ||
var styleHashesArray = []; | ||
switch (_.type) { | ||
case 'FeatureCollection': | ||
if (!_.features) return ''; | ||
return _.features.map(feature(options, styleHashesArray)).join(''); | ||
case 'Feature': | ||
return feature(options, styleHashesArray)(_); | ||
default: | ||
return feature(options, styleHashesArray)({ | ||
type: 'Feature', | ||
geometry: _, | ||
properties: {} | ||
}); | ||
} | ||
if (!_.type) return '' | ||
var styleHashesArray = [] | ||
switch (_.type) { | ||
case 'FeatureCollection': | ||
if (!_.features) return '' | ||
return _.features.map(feature(options, styleHashesArray)).join('') | ||
case 'Feature': | ||
return feature(options, styleHashesArray)(_) | ||
default: | ||
return feature( | ||
options, | ||
styleHashesArray | ||
)({ | ||
type: 'Feature', | ||
geometry: _, | ||
properties: {} | ||
}) | ||
} | ||
} | ||
function documentName(options) { | ||
return (options.documentName !== undefined) ? tag('name', options.documentName) : ''; | ||
return options.documentName !== undefined | ||
? tag('name', options.documentName) | ||
: '' | ||
} | ||
function documentDescription(options) { | ||
return (options.documentDescription !== undefined) ? tag('description', options.documentDescription) : ''; | ||
return options.documentDescription !== undefined | ||
? tag('description', options.documentDescription) | ||
: '' | ||
} | ||
function name(_, options) { | ||
return _[options.name] ? tag('name', esc(_[options.name])) : ''; | ||
return _[options.name] ? tag('name', esc(_[options.name])) : '' | ||
} | ||
function description(_, options) { | ||
return _[options.description] ? tag('description', esc(_[options.description])) : ''; | ||
return _[options.description] | ||
? tag('description', esc(_[options.description])) | ||
: '' | ||
} | ||
function timestamp(_, options) { | ||
return _[options.timestamp] ? tag('TimeStamp', tag('when', esc(_[options.timestamp]))) : ''; | ||
return _[options.timestamp] | ||
? tag('TimeStamp', tag('when', esc(_[options.timestamp]))) | ||
: '' | ||
} | ||
@@ -110,69 +135,94 @@ | ||
var geometry = { | ||
Point: function(_) { | ||
return tag('Point', tag('coordinates', _.coordinates.join(','))); | ||
}, | ||
LineString: function(_) { | ||
return tag('LineString', tag('coordinates', linearring(_.coordinates))); | ||
}, | ||
Polygon: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
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(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.Point({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
MultiPolygon: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.Polygon({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
MultiLineString: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.LineString({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
GeometryCollection: function(_) { | ||
return tag('MultiGeometry', | ||
_.geometries.map(geometry.any).join('')); | ||
}, | ||
valid: function(_) { | ||
return _ && _.type && (_.coordinates || | ||
_.type === 'GeometryCollection' && _.geometries && _.geometries.every(geometry.valid)); | ||
}, | ||
any: function(_) { | ||
if (geometry[_.type]) { | ||
return geometry[_.type](_); | ||
} else { | ||
return ''; | ||
} | ||
}, | ||
isPoint: function(_) { | ||
return _.type === 'Point' || | ||
_.type === 'MultiPoint'; | ||
}, | ||
isPolygon: function(_) { | ||
return _.type === 'Polygon' || | ||
_.type === 'MultiPolygon'; | ||
}, | ||
isLine: function(_) { | ||
return _.type === 'LineString' || | ||
_.type === 'MultiLineString'; | ||
Point: function (_) { | ||
return tag('Point', tag('coordinates', _.coordinates.join(','))) | ||
}, | ||
LineString: function (_) { | ||
return tag('LineString', tag('coordinates', linearring(_.coordinates))) | ||
}, | ||
Polygon: function (_) { | ||
if (!_.coordinates.length) return '' | ||
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 (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.Point({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
MultiPolygon: function (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.Polygon({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
MultiLineString: function (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.LineString({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
GeometryCollection: function (_) { | ||
return tag('MultiGeometry', _.geometries.map(geometry.any).join('')) | ||
}, | ||
valid: function (_) { | ||
return ( | ||
_ && | ||
_.type && | ||
(_.coordinates || | ||
(_.type === 'GeometryCollection' && | ||
_.geometries && | ||
_.geometries.every(geometry.valid))) | ||
) | ||
}, | ||
any: function (_) { | ||
if (geometry[_.type]) { | ||
return geometry[_.type](_) | ||
} else { | ||
return '' | ||
} | ||
}; | ||
}, | ||
isPoint: function (_) { | ||
return _.type === 'Point' || _.type === 'MultiPoint' | ||
}, | ||
isPolygon: function (_) { | ||
return _.type === 'Polygon' || _.type === 'MultiPolygon' | ||
}, | ||
isLine: function (_) { | ||
return _.type === 'LineString' || _.type === 'MultiLineString' | ||
} | ||
} | ||
function linearring(_) { | ||
return _.map(function(cds) { return cds.join(','); }).join(' '); | ||
return _.map(function (cds) { | ||
return cds.join(',') | ||
}).join(' ') | ||
} | ||
@@ -182,7 +232,11 @@ | ||
function extendeddata(_) { | ||
return tag('ExtendedData', {}, pairs(_).map(data).join('')); | ||
return tag('ExtendedData', {}, pairs(_).map(data).join('')) | ||
} | ||
function data(_) { | ||
return tag('Data', {'name': _[0]}, tag('value', {}, esc(_[1] ? _[1].toString() : ''))); | ||
return tag( | ||
'Data', | ||
{ name: _[0] }, | ||
tag('value', {}, esc(_[1] ? _[1].toString() : '')) | ||
) | ||
} | ||
@@ -192,30 +246,47 @@ | ||
function hasMarkerStyle(_) { | ||
return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']); | ||
return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']) | ||
} | ||
function removeMarkerStyle(_) { | ||
delete _['marker-size'] | ||
delete _['marker-symbol'] | ||
delete _['marker-color'] | ||
delete _['marker-shape'] | ||
} | ||
function markerStyle(_, styleHash) { | ||
return tag('Style', {'id': styleHash}, | ||
tag('IconStyle', | ||
tag('Icon', | ||
tag('href', iconUrl(_))) | ||
) + iconSize(_) | ||
); | ||
return tag( | ||
'Style', | ||
{ id: styleHash }, | ||
tag('IconStyle', tag('Icon', tag('href', iconUrl(_)))) + iconSize(_) | ||
) | ||
} | ||
function iconUrl(_) { | ||
var size = _['marker-size'] || 'medium', | ||
symbol = _['marker-symbol'] ? '-' + _['marker-symbol'] : '', | ||
color = (_['marker-color'] || '7e7e7e').replace('#', ''); | ||
var size = _['marker-size'] || 'medium', | ||
symbol = _['marker-symbol'] ? '-' + _['marker-symbol'] : '', | ||
color = (_['marker-color'] || '7e7e7e').replace('#', '') | ||
return 'https://api.tiles.mapbox.com/v3/marker/' + 'pin-' + size.charAt(0) + | ||
symbol + '+' + color + '.png'; | ||
return ( | ||
'https://api.tiles.mapbox.com/v3/marker/' + | ||
'pin-' + | ||
size.charAt(0) + | ||
symbol + | ||
'+' + | ||
color + | ||
'.png' | ||
) | ||
} | ||
function iconSize(_) { | ||
return tag('hotSpot', { | ||
'xunits': 'fraction', | ||
'yunits': 'fraction', | ||
'x': '0.5', | ||
'y': '0.5' | ||
}, ''); | ||
return tag( | ||
'hotSpot', | ||
{ | ||
xunits: 'fraction', | ||
yunits: 'fraction', | ||
x: '0.5', | ||
y: '0.5' | ||
}, | ||
'' | ||
) | ||
} | ||
@@ -225,27 +296,48 @@ | ||
function hasPolygonAndLineStyle(_) { | ||
for (var key in _) { | ||
if ({ | ||
"stroke": true, | ||
"stroke-opacity": true, | ||
"stroke-width": true, | ||
"fill": true, | ||
"fill-opacity": true | ||
}[key]) return true; | ||
} | ||
for (var key in _) { | ||
if ( | ||
{ | ||
stroke: true, | ||
'stroke-opacity': true, | ||
'stroke-width': true, | ||
fill: true, | ||
'fill-opacity': true | ||
}[key] | ||
) | ||
return true | ||
} | ||
} | ||
function removePolygonAndLineStyle(_) { | ||
delete _['stroke'] | ||
delete _['stroke-opacity'] | ||
delete _['stroke-width'] | ||
delete _['fill'] | ||
delete _['fill-opacity'] | ||
} | ||
function polygonAndLineStyle(_, styleHash) { | ||
var lineStyle = tag('LineStyle', tag('color', hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555') + | ||
tag('width', {}, _['stroke-width'] === undefined ? 2 : _['stroke-width']) | ||
); | ||
var polyStyle = ''; | ||
if (_['fill'] || _['fill-opacity']) { | ||
polyStyle = tag('PolyStyle', | ||
tag('color', {}, hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555') | ||
); | ||
} | ||
return tag('Style', {'id': styleHash}, lineStyle + polyStyle); | ||
var lineStyle = tag( | ||
'LineStyle', | ||
tag( | ||
'color', | ||
hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555' | ||
) + | ||
tag('width', {}, _['stroke-width'] === undefined ? 2 : _['stroke-width']) | ||
) | ||
var polyStyle = '' | ||
if (_['fill'] || _['fill-opacity']) { | ||
polyStyle = tag( | ||
'PolyStyle', | ||
tag( | ||
'color', | ||
{}, | ||
hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555' | ||
) | ||
) | ||
} | ||
return tag('Style', { id: styleHash }, lineStyle + polyStyle) | ||
} | ||
@@ -255,41 +347,48 @@ | ||
function hashStyle(_) { | ||
var hash = ''; | ||
if (_['marker-symbol']) hash = hash + 'ms' + _['marker-symbol']; | ||
if (_['marker-color']) hash = hash + 'mc' + _['marker-color'].replace('#', ''); | ||
if (_['marker-size']) hash = hash + 'ms' + _['marker-size']; | ||
if (_['stroke']) hash = hash + 's' + _['stroke'].replace('#', ''); | ||
if (_['stroke-width']) hash = hash + 'sw' + _['stroke-width'].toString().replace('.', ''); | ||
if (_['stroke-opacity']) hash = hash + 'mo' + _['stroke-opacity'].toString().replace('.', ''); | ||
if (_['fill']) hash = hash + 'f' + _['fill'].replace('#', ''); | ||
if (_['fill-opacity']) hash = hash + 'fo' + _['fill-opacity'].toString().replace('.', ''); | ||
return hash; | ||
var hash = '' | ||
if (_['marker-symbol']) hash = hash + 'ms' + _['marker-symbol'] | ||
if (_['marker-color']) hash = hash + 'mc' + _['marker-color'].replace('#', '') | ||
if (_['marker-size']) hash = hash + 'ms' + _['marker-size'] | ||
if (_['stroke']) hash = hash + 's' + _['stroke'].replace('#', '') | ||
if (_['stroke-width']) | ||
hash = hash + 'sw' + _['stroke-width'].toString().replace('.', '') | ||
if (_['stroke-opacity']) | ||
hash = hash + 'mo' + _['stroke-opacity'].toString().replace('.', '') | ||
if (_['fill']) hash = hash + 'f' + _['fill'].replace('#', '') | ||
if (_['fill-opacity']) | ||
hash = hash + 'fo' + _['fill-opacity'].toString().replace('.', '') | ||
return hash | ||
} | ||
function hexToKmlColor(hexColor, opacity) { | ||
if (typeof hexColor !== 'string') return ''; | ||
hexColor = hexColor.replace('#', '').toLowerCase(); | ||
if (hexColor.length === 3) { | ||
hexColor = hexColor[0] + hexColor[0] + | ||
hexColor[1] + hexColor[1] + | ||
hexColor[2] + hexColor[2]; | ||
} else if (hexColor.length !== 6) { | ||
return ''; | ||
} | ||
var r = hexColor[0] + hexColor[1]; | ||
var g = hexColor[2] + hexColor[3]; | ||
var b = hexColor[4] + hexColor[5]; | ||
var o = 'ff'; | ||
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { | ||
o = (opacity * 255).toString(16); | ||
if (o.indexOf('.') > -1) o = o.substr(0, o.indexOf('.')); | ||
if (o.length < 2) o = '0' + o; | ||
} | ||
return o + b + g + r; | ||
if (typeof hexColor !== 'string') return '' | ||
hexColor = hexColor.replace('#', '').toLowerCase() | ||
if (hexColor.length === 3) { | ||
hexColor = | ||
hexColor[0] + | ||
hexColor[0] + | ||
hexColor[1] + | ||
hexColor[1] + | ||
hexColor[2] + | ||
hexColor[2] | ||
} else if (hexColor.length !== 6) { | ||
return '' | ||
} | ||
var r = hexColor[0] + hexColor[1] | ||
var g = hexColor[2] + hexColor[3] | ||
var b = hexColor[4] + hexColor[5] | ||
var o = 'ff' | ||
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { | ||
o = (opacity * 255).toString(16) | ||
if (o.indexOf('.') > -1) o = o.substr(0, o.indexOf('.')) | ||
if (o.length < 2) o = '0' + o | ||
} | ||
return o + b + g + r | ||
} | ||
@@ -299,11 +398,11 @@ | ||
function pairs(_) { | ||
var o = []; | ||
for (var i in _){ | ||
if(_[i]){ | ||
o.push([i, _[i]]); | ||
}else{ | ||
o.push([i, '']); | ||
} | ||
var o = [] | ||
for (var i in _) { | ||
if (_[i]) { | ||
o.push([i, _[i]]) | ||
} else { | ||
o.push([i, '']) | ||
} | ||
return o; | ||
} | ||
} | ||
return o | ||
} |
{ | ||
"name": "@maphubs/tokml", | ||
"version": "0.5.2", | ||
"version": "0.6.0", | ||
"description": "convert geojson to kml", | ||
@@ -9,3 +9,3 @@ "main": "index.js", | ||
"build": "browserify -s tokml index.js > tokml.js", | ||
"cov": "istanbul cover test/kml.test.js && coveralls < ./coverage/lcov.info" | ||
"cov": "nyc npm test && nyc report --reporter=text-lcov | coveralls" | ||
}, | ||
@@ -28,16 +28,13 @@ "repository": { | ||
"devDependencies": { | ||
"browserify": "^16.2.3", | ||
"corslite": "0.0.7", | ||
"coveralls": "^3.0.2", | ||
"browserify": "^16.5.2", | ||
"coveralls": "^3.1.0", | ||
"fuzzer": "^0.2.1", | ||
"glob": "^7.1.3", | ||
"istanbul": "^0.4.5", | ||
"tap": "^12.1.1" | ||
"nyc": "^15.1.0", | ||
"tap": "^14.10.8" | ||
}, | ||
"dependencies": { | ||
"minimist": "^1.2.0", | ||
"rw": "^1.3.3", | ||
"strxml": "mapbox/strxml", | ||
"xml-escape": "^1.1.0" | ||
"minimist": "^1.2.5", | ||
"rw": "^1.3.3" | ||
} | ||
} |
@@ -33,4 +33,4 @@ Forked from https://github.com/mapbox/tokml | ||
var kmlNameDescription = tokml(geojsonObject, { | ||
name: 'name', | ||
description: 'description' | ||
name: "name", | ||
description: "description", | ||
}); | ||
@@ -40,4 +40,4 @@ | ||
var kmlDocumentName = tokml(geojsonObject, { | ||
documentName: 'My List Of Markers', | ||
documentDescription: "One of the many places you are not I am" | ||
documentName: "My List Of Markers", | ||
documentDescription: "One of the many places you are not I am", | ||
}); | ||
@@ -60,12 +60,12 @@ ``` | ||
* `name`: the name of the property in each GeoJSON Feature that contains | ||
- `name`: the name of the property in each GeoJSON Feature that contains | ||
the feature's name | ||
* `description`: the name of the property in each GeoJSON Feature that contains | ||
- `description`: the name of the property in each GeoJSON Feature that contains | ||
the feature's description | ||
**Timestamp:** KML can associate features with a moment in time via the `TimeStamp` tag. GeoJSON doesn't | ||
**Timestamp:** KML can associate features with a moment in time via the `TimeStamp` tag. GeoJSON doesn't | ||
have a comparable field, but a custom property can be mapped | ||
* `timestamp`: the name of the property in each GeoJSON Feature that contains | ||
a timestamp in XML Schema Time (yyyy-mm-ddThh:mm:sszzzzzz) | ||
- `timestamp`: the name of the property in each GeoJSON Feature that contains | ||
a timestamp in XML Schema Time (yyyy-mm-ddThh:mm:sszzzzzz) | ||
@@ -75,8 +75,8 @@ **Document name and description**: KML supports `name` and `description` properties | ||
* `documentName`: the name of the full document | ||
* `documentDescription`: the description of the full document | ||
- `documentName`: the name of the full document | ||
- `documentDescription`: the description of the full document | ||
**[simplestyle-spec](https://github.com/mapbox/simplestyle-spec)** support: | ||
* `simplestyle`: set to `true` to convert simplestyle-spec styles into KML styles | ||
- `simplestyle`: set to `true` to convert simplestyle-spec styles into KML styles | ||
@@ -93,3 +93,3 @@ ## Development | ||
npm install | ||
npm test | ||
yarn install | ||
yarn run test |
632
tokml.js
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tokml = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
var esc = require('xml-escape'); | ||
var strxml = require('strxml'), | ||
tag = strxml.tag; | ||
var esc = require('./lib/xml-escape') | ||
var strxml = require('./lib/strxml'), | ||
tag = strxml.tag | ||
module.exports = function tokml(geojson, options) { | ||
options = options || { | ||
documentName: undefined, | ||
documentDescription: undefined, | ||
name: 'name', | ||
description: 'description', | ||
simplestyle: false, | ||
timestamp: 'timestamp' | ||
} | ||
options = options || { | ||
documentName: undefined, | ||
documentDescription: undefined, | ||
name: 'name', | ||
description: 'description', | ||
simplestyle: false, | ||
timestamp: 'timestamp' | ||
}; | ||
return ( | ||
'<?xml version="1.0" encoding="UTF-8"?>' + | ||
tag( | ||
'kml', | ||
{ xmlns: 'http://www.opengis.net/kml/2.2' }, | ||
tag( | ||
'Document', | ||
documentName(options) + | ||
documentDescription(options) + | ||
root(geojson, options) | ||
) | ||
) | ||
) | ||
} | ||
return '<?xml version="1.0" encoding="UTF-8"?>' + | ||
tag('kml', {'xmlns': 'http://www.opengis.net/kml/2.2'}, | ||
tag('Document', | ||
documentName(options) + | ||
documentDescription(options) + | ||
root(geojson, options) | ||
)); | ||
}; | ||
function feature(options, styleHashesArray) { | ||
return function (_) { | ||
if (!_.properties || !geometry.valid(_.geometry)) return '' | ||
var geometryString = geometry.any(_.geometry) | ||
if (!geometryString) return '' | ||
function feature(options, styleHashesArray) { | ||
return function(_) { | ||
if (!_.properties || !geometry.valid(_.geometry)) return ''; | ||
var geometryString = geometry.any(_.geometry); | ||
if (!geometryString) return ''; | ||
var styleDefinition = '', | ||
styleReference = ''; | ||
if (options.simplestyle) { | ||
var styleHash = hashStyle(_.properties); | ||
if (styleHash) { | ||
if (geometry.isPoint(_.geometry) && hasMarkerStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = markerStyle(_.properties, styleHash); | ||
styleHashesArray.push(styleHash); | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash); | ||
} else if ((geometry.isPolygon(_.geometry) || geometry.isLine(_.geometry)) && | ||
hasPolygonAndLineStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = polygonAndLineStyle(_.properties, styleHash); | ||
styleHashesArray.push(styleHash); | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash); | ||
} | ||
// Note that style of GeometryCollection / MultiGeometry is not supported | ||
} | ||
var styleDefinition = '', | ||
styleReference = '' | ||
if (options.simplestyle) { | ||
var styleHash = hashStyle(_.properties) | ||
if (styleHash) { | ||
if (geometry.isPoint(_.geometry) && hasMarkerStyle(_.properties)) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = markerStyle(_.properties, styleHash) | ||
styleHashesArray.push(styleHash) | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash) | ||
removeMarkerStyle(_.properties) | ||
} else if ( | ||
(geometry.isPolygon(_.geometry) || geometry.isLine(_.geometry)) && | ||
hasPolygonAndLineStyle(_.properties) | ||
) { | ||
if (styleHashesArray.indexOf(styleHash) === -1) { | ||
styleDefinition = polygonAndLineStyle(_.properties, styleHash) | ||
styleHashesArray.push(styleHash) | ||
} | ||
styleReference = tag('styleUrl', '#' + styleHash) | ||
removePolygonAndLineStyle(_.properties) | ||
} | ||
var attributes = {} | ||
if (_.id) attributes.id = _.id | ||
return styleDefinition + tag('Placemark', | ||
attributes, | ||
name(_.properties, options) + | ||
description(_.properties, options) + | ||
extendeddata(_.properties) + | ||
timestamp(_.properties, options) + | ||
geometryString + | ||
styleReference); | ||
}; | ||
// Note that style of GeometryCollection / MultiGeometry is not supported | ||
} | ||
} | ||
var attributes = {} | ||
if (_.id) attributes.id = _.id | ||
return ( | ||
styleDefinition + | ||
tag( | ||
'Placemark', | ||
attributes, | ||
name(_.properties, options) + | ||
description(_.properties, options) + | ||
extendeddata(_.properties) + | ||
timestamp(_.properties, options) + | ||
geometryString + | ||
styleReference | ||
) | ||
) | ||
} | ||
} | ||
function root(_, options) { | ||
if (!_.type) return ''; | ||
var styleHashesArray = []; | ||
switch (_.type) { | ||
case 'FeatureCollection': | ||
if (!_.features) return ''; | ||
return _.features.map(feature(options, styleHashesArray)).join(''); | ||
case 'Feature': | ||
return feature(options, styleHashesArray)(_); | ||
default: | ||
return feature(options, styleHashesArray)({ | ||
type: 'Feature', | ||
geometry: _, | ||
properties: {} | ||
}); | ||
} | ||
if (!_.type) return '' | ||
var styleHashesArray = [] | ||
switch (_.type) { | ||
case 'FeatureCollection': | ||
if (!_.features) return '' | ||
return _.features.map(feature(options, styleHashesArray)).join('') | ||
case 'Feature': | ||
return feature(options, styleHashesArray)(_) | ||
default: | ||
return feature( | ||
options, | ||
styleHashesArray | ||
)({ | ||
type: 'Feature', | ||
geometry: _, | ||
properties: {} | ||
}) | ||
} | ||
} | ||
function documentName(options) { | ||
return (options.documentName !== undefined) ? tag('name', options.documentName) : ''; | ||
return options.documentName !== undefined | ||
? tag('name', options.documentName) | ||
: '' | ||
} | ||
function documentDescription(options) { | ||
return (options.documentDescription !== undefined) ? tag('description', options.documentDescription) : ''; | ||
return options.documentDescription !== undefined | ||
? tag('description', options.documentDescription) | ||
: '' | ||
} | ||
function name(_, options) { | ||
return _[options.name] ? tag('name', esc(_[options.name])) : ''; | ||
return _[options.name] ? tag('name', esc(_[options.name])) : '' | ||
} | ||
function description(_, options) { | ||
return _[options.description] ? tag('description', esc(_[options.description])) : ''; | ||
return _[options.description] | ||
? tag('description', esc(_[options.description])) | ||
: '' | ||
} | ||
function timestamp(_, options) { | ||
return _[options.timestamp] ? tag('TimeStamp', tag('when', esc(_[options.timestamp]))) : ''; | ||
return _[options.timestamp] | ||
? tag('TimeStamp', tag('when', esc(_[options.timestamp]))) | ||
: '' | ||
} | ||
@@ -111,69 +136,94 @@ | ||
var geometry = { | ||
Point: function(_) { | ||
return tag('Point', tag('coordinates', _.coordinates.join(','))); | ||
}, | ||
LineString: function(_) { | ||
return tag('LineString', tag('coordinates', linearring(_.coordinates))); | ||
}, | ||
Polygon: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
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(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.Point({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
MultiPolygon: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.Polygon({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
MultiLineString: function(_) { | ||
if (!_.coordinates.length) return ''; | ||
return tag('MultiGeometry', _.coordinates.map(function(c) { | ||
return geometry.LineString({ coordinates: c }); | ||
}).join('')); | ||
}, | ||
GeometryCollection: function(_) { | ||
return tag('MultiGeometry', | ||
_.geometries.map(geometry.any).join('')); | ||
}, | ||
valid: function(_) { | ||
return _ && _.type && (_.coordinates || | ||
_.type === 'GeometryCollection' && _.geometries && _.geometries.every(geometry.valid)); | ||
}, | ||
any: function(_) { | ||
if (geometry[_.type]) { | ||
return geometry[_.type](_); | ||
} else { | ||
return ''; | ||
} | ||
}, | ||
isPoint: function(_) { | ||
return _.type === 'Point' || | ||
_.type === 'MultiPoint'; | ||
}, | ||
isPolygon: function(_) { | ||
return _.type === 'Polygon' || | ||
_.type === 'MultiPolygon'; | ||
}, | ||
isLine: function(_) { | ||
return _.type === 'LineString' || | ||
_.type === 'MultiLineString'; | ||
Point: function (_) { | ||
return tag('Point', tag('coordinates', _.coordinates.join(','))) | ||
}, | ||
LineString: function (_) { | ||
return tag('LineString', tag('coordinates', linearring(_.coordinates))) | ||
}, | ||
Polygon: function (_) { | ||
if (!_.coordinates.length) return '' | ||
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 (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.Point({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
MultiPolygon: function (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.Polygon({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
MultiLineString: function (_) { | ||
if (!_.coordinates.length) return '' | ||
return tag( | ||
'MultiGeometry', | ||
_.coordinates | ||
.map(function (c) { | ||
return geometry.LineString({ coordinates: c }) | ||
}) | ||
.join('') | ||
) | ||
}, | ||
GeometryCollection: function (_) { | ||
return tag('MultiGeometry', _.geometries.map(geometry.any).join('')) | ||
}, | ||
valid: function (_) { | ||
return ( | ||
_ && | ||
_.type && | ||
(_.coordinates || | ||
(_.type === 'GeometryCollection' && | ||
_.geometries && | ||
_.geometries.every(geometry.valid))) | ||
) | ||
}, | ||
any: function (_) { | ||
if (geometry[_.type]) { | ||
return geometry[_.type](_) | ||
} else { | ||
return '' | ||
} | ||
}; | ||
}, | ||
isPoint: function (_) { | ||
return _.type === 'Point' || _.type === 'MultiPoint' | ||
}, | ||
isPolygon: function (_) { | ||
return _.type === 'Polygon' || _.type === 'MultiPolygon' | ||
}, | ||
isLine: function (_) { | ||
return _.type === 'LineString' || _.type === 'MultiLineString' | ||
} | ||
} | ||
function linearring(_) { | ||
return _.map(function(cds) { return cds.join(','); }).join(' '); | ||
return _.map(function (cds) { | ||
return cds.join(',') | ||
}).join(' ') | ||
} | ||
@@ -183,7 +233,11 @@ | ||
function extendeddata(_) { | ||
return tag('ExtendedData', {}, pairs(_).map(data).join('')); | ||
return tag('ExtendedData', {}, pairs(_).map(data).join('')) | ||
} | ||
function data(_) { | ||
return tag('Data', {'name': _[0]}, tag('value', {}, esc(_[1] ? _[1].toString() : ''))); | ||
return tag( | ||
'Data', | ||
{ name: _[0] }, | ||
tag('value', {}, esc(_[1] ? _[1].toString() : '')) | ||
) | ||
} | ||
@@ -193,30 +247,47 @@ | ||
function hasMarkerStyle(_) { | ||
return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']); | ||
return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']) | ||
} | ||
function removeMarkerStyle(_) { | ||
delete _['marker-size'] | ||
delete _['marker-symbol'] | ||
delete _['marker-color'] | ||
delete _['marker-shape'] | ||
} | ||
function markerStyle(_, styleHash) { | ||
return tag('Style', {'id': styleHash}, | ||
tag('IconStyle', | ||
tag('Icon', | ||
tag('href', iconUrl(_))) | ||
) + iconSize(_) | ||
); | ||
return tag( | ||
'Style', | ||
{ id: styleHash }, | ||
tag('IconStyle', tag('Icon', tag('href', iconUrl(_)))) + iconSize(_) | ||
) | ||
} | ||
function iconUrl(_) { | ||
var size = _['marker-size'] || 'medium', | ||
symbol = _['marker-symbol'] ? '-' + _['marker-symbol'] : '', | ||
color = (_['marker-color'] || '7e7e7e').replace('#', ''); | ||
var size = _['marker-size'] || 'medium', | ||
symbol = _['marker-symbol'] ? '-' + _['marker-symbol'] : '', | ||
color = (_['marker-color'] || '7e7e7e').replace('#', '') | ||
return 'https://api.tiles.mapbox.com/v3/marker/' + 'pin-' + size.charAt(0) + | ||
symbol + '+' + color + '.png'; | ||
return ( | ||
'https://api.tiles.mapbox.com/v3/marker/' + | ||
'pin-' + | ||
size.charAt(0) + | ||
symbol + | ||
'+' + | ||
color + | ||
'.png' | ||
) | ||
} | ||
function iconSize(_) { | ||
return tag('hotSpot', { | ||
'xunits': 'fraction', | ||
'yunits': 'fraction', | ||
'x': '0.5', | ||
'y': '0.5' | ||
}, ''); | ||
return tag( | ||
'hotSpot', | ||
{ | ||
xunits: 'fraction', | ||
yunits: 'fraction', | ||
x: '0.5', | ||
y: '0.5' | ||
}, | ||
'' | ||
) | ||
} | ||
@@ -226,27 +297,48 @@ | ||
function hasPolygonAndLineStyle(_) { | ||
for (var key in _) { | ||
if ({ | ||
"stroke": true, | ||
"stroke-opacity": true, | ||
"stroke-width": true, | ||
"fill": true, | ||
"fill-opacity": true | ||
}[key]) return true; | ||
} | ||
for (var key in _) { | ||
if ( | ||
{ | ||
stroke: true, | ||
'stroke-opacity': true, | ||
'stroke-width': true, | ||
fill: true, | ||
'fill-opacity': true | ||
}[key] | ||
) | ||
return true | ||
} | ||
} | ||
function removePolygonAndLineStyle(_) { | ||
delete _['stroke'] | ||
delete _['stroke-opacity'] | ||
delete _['stroke-width'] | ||
delete _['fill'] | ||
delete _['fill-opacity'] | ||
} | ||
function polygonAndLineStyle(_, styleHash) { | ||
var lineStyle = tag('LineStyle', tag('color', hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555') + | ||
tag('width', {}, _['stroke-width'] === undefined ? 2 : _['stroke-width']) | ||
); | ||
var polyStyle = ''; | ||
if (_['fill'] || _['fill-opacity']) { | ||
polyStyle = tag('PolyStyle', | ||
tag('color', {}, hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555') | ||
); | ||
} | ||
return tag('Style', {'id': styleHash}, lineStyle + polyStyle); | ||
var lineStyle = tag( | ||
'LineStyle', | ||
tag( | ||
'color', | ||
hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555' | ||
) + | ||
tag('width', {}, _['stroke-width'] === undefined ? 2 : _['stroke-width']) | ||
) | ||
var polyStyle = '' | ||
if (_['fill'] || _['fill-opacity']) { | ||
polyStyle = tag( | ||
'PolyStyle', | ||
tag( | ||
'color', | ||
{}, | ||
hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555' | ||
) | ||
) | ||
} | ||
return tag('Style', { id: styleHash }, lineStyle + polyStyle) | ||
} | ||
@@ -256,41 +348,48 @@ | ||
function hashStyle(_) { | ||
var hash = ''; | ||
if (_['marker-symbol']) hash = hash + 'ms' + _['marker-symbol']; | ||
if (_['marker-color']) hash = hash + 'mc' + _['marker-color'].replace('#', ''); | ||
if (_['marker-size']) hash = hash + 'ms' + _['marker-size']; | ||
if (_['stroke']) hash = hash + 's' + _['stroke'].replace('#', ''); | ||
if (_['stroke-width']) hash = hash + 'sw' + _['stroke-width'].toString().replace('.', ''); | ||
if (_['stroke-opacity']) hash = hash + 'mo' + _['stroke-opacity'].toString().replace('.', ''); | ||
if (_['fill']) hash = hash + 'f' + _['fill'].replace('#', ''); | ||
if (_['fill-opacity']) hash = hash + 'fo' + _['fill-opacity'].toString().replace('.', ''); | ||
return hash; | ||
var hash = '' | ||
if (_['marker-symbol']) hash = hash + 'ms' + _['marker-symbol'] | ||
if (_['marker-color']) hash = hash + 'mc' + _['marker-color'].replace('#', '') | ||
if (_['marker-size']) hash = hash + 'ms' + _['marker-size'] | ||
if (_['stroke']) hash = hash + 's' + _['stroke'].replace('#', '') | ||
if (_['stroke-width']) | ||
hash = hash + 'sw' + _['stroke-width'].toString().replace('.', '') | ||
if (_['stroke-opacity']) | ||
hash = hash + 'mo' + _['stroke-opacity'].toString().replace('.', '') | ||
if (_['fill']) hash = hash + 'f' + _['fill'].replace('#', '') | ||
if (_['fill-opacity']) | ||
hash = hash + 'fo' + _['fill-opacity'].toString().replace('.', '') | ||
return hash | ||
} | ||
function hexToKmlColor(hexColor, opacity) { | ||
if (typeof hexColor !== 'string') return ''; | ||
hexColor = hexColor.replace('#', '').toLowerCase(); | ||
if (hexColor.length === 3) { | ||
hexColor = hexColor[0] + hexColor[0] + | ||
hexColor[1] + hexColor[1] + | ||
hexColor[2] + hexColor[2]; | ||
} else if (hexColor.length !== 6) { | ||
return ''; | ||
} | ||
var r = hexColor[0] + hexColor[1]; | ||
var g = hexColor[2] + hexColor[3]; | ||
var b = hexColor[4] + hexColor[5]; | ||
var o = 'ff'; | ||
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { | ||
o = (opacity * 255).toString(16); | ||
if (o.indexOf('.') > -1) o = o.substr(0, o.indexOf('.')); | ||
if (o.length < 2) o = '0' + o; | ||
} | ||
return o + b + g + r; | ||
if (typeof hexColor !== 'string') return '' | ||
hexColor = hexColor.replace('#', '').toLowerCase() | ||
if (hexColor.length === 3) { | ||
hexColor = | ||
hexColor[0] + | ||
hexColor[0] + | ||
hexColor[1] + | ||
hexColor[1] + | ||
hexColor[2] + | ||
hexColor[2] | ||
} else if (hexColor.length !== 6) { | ||
return '' | ||
} | ||
var r = hexColor[0] + hexColor[1] | ||
var g = hexColor[2] + hexColor[3] | ||
var b = hexColor[4] + hexColor[5] | ||
var o = 'ff' | ||
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { | ||
o = (opacity * 255).toString(16) | ||
if (o.indexOf('.') > -1) o = o.substr(0, o.indexOf('.')) | ||
if (o.length < 2) o = '0' + o | ||
} | ||
return o + b + g + r | ||
} | ||
@@ -300,15 +399,18 @@ | ||
function pairs(_) { | ||
var o = []; | ||
for (var i in _){ | ||
if(_[i]){ | ||
o.push([i, _[i]]); | ||
}else{ | ||
o.push([i, '']); | ||
} | ||
var o = [] | ||
for (var i in _) { | ||
if (_[i]) { | ||
o.push([i, _[i]]) | ||
} else { | ||
o.push([i, '']) | ||
} | ||
return o; | ||
} | ||
return o | ||
} | ||
},{"strxml":2,"xml-escape":3}],2:[function(require,module,exports){ | ||
var esc = require('xml-escape'); | ||
},{"./lib/strxml":2,"./lib/xml-escape":3}],2:[function(require,module,exports){ | ||
// strxml from https://github.com/mapbox/strxml | ||
var esc = require("./xml-escape"); | ||
module.exports.attr = attr; | ||
@@ -323,6 +425,11 @@ module.exports.tagClose = tagClose; | ||
function attr(attributes) { | ||
if (!Object.keys(attributes).length) return ''; | ||
return ' ' + Object.keys(attributes).map(function(key) { | ||
if (!Object.keys(attributes).length) return ""; | ||
return ( | ||
" " + | ||
Object.keys(attributes) | ||
.map(function (key) { | ||
return key + '="' + esc(attributes[key]) + '"'; | ||
}).join(' '); | ||
}) | ||
.join(" ") | ||
); | ||
} | ||
@@ -336,3 +443,3 @@ | ||
function tagClose(el, attributes) { | ||
return '<' + el + attr(attributes) + '/>'; | ||
return "<" + el + attr(attributes) + "/>"; | ||
} | ||
@@ -347,16 +454,22 @@ | ||
function tag(el, attributes, contents) { | ||
if (Array.isArray(attributes) || typeof attributes === 'string') { | ||
contents = attributes; | ||
attributes = {}; | ||
} | ||
if (Array.isArray(contents)) contents = '\n' + contents.map(function(content) { | ||
return ' ' + content; | ||
}).join('\n') + '\n'; | ||
return '<' + el + attr(attributes) + '>' + contents + '</' + el + '>'; | ||
if (Array.isArray(attributes) || typeof attributes === "string") { | ||
contents = attributes; | ||
attributes = {}; | ||
} | ||
if (Array.isArray(contents)) | ||
contents = | ||
"\n" + | ||
contents | ||
.map(function (content) { | ||
return " " + content; | ||
}) | ||
.join("\n") + | ||
"\n"; | ||
return "<" + el + attr(attributes) + ">" + contents + "</" + el + ">"; | ||
} | ||
},{"xml-escape":3}],3:[function(require,module,exports){ | ||
},{"./xml-escape":3}],3:[function(require,module,exports){ | ||
// originally from https://github.com/miketheprogrammer/xml-escape | ||
var escape = module.exports = function escape(string, ignore) { | ||
var escape = (module.exports = function escape(string, ignore) { | ||
var pattern; | ||
@@ -366,18 +479,19 @@ | ||
ignore = (ignore || '').replace(/[^&"<>\']/g, ''); | ||
pattern = '([&"<>\'])'.replace(new RegExp('[' + ignore + ']', 'g'), ''); | ||
ignore = (ignore || "").replace(/[^&"<>\']/g, ""); | ||
pattern = "([&\"<>'])".replace(new RegExp("[" + ignore + "]", "g"), ""); | ||
return string.replace(new RegExp(pattern, 'g'), function(str, item) { | ||
return escape.map[item]; | ||
}) | ||
} | ||
return string.replace(new RegExp(pattern, "g"), function (str, item) { | ||
return escape.map[item]; | ||
}); | ||
}); | ||
var map = escape.map = { | ||
'>': '>' | ||
, '<': '<' | ||
, "'": ''' | ||
, '"': '"' | ||
, '&': '&' | ||
} | ||
var map = (escape.map = { | ||
">": ">", | ||
"<": "<", | ||
"'": "'", | ||
'"': """, | ||
"&": "&", | ||
}); | ||
},{}]},{},[1])(1) | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
2
6
0
5
66843
1022
- Removedstrxml@mapbox/strxml
- Removedxml-escape@^1.1.0
- Removedxml-escape@1.1.0(transitive)
Updatedminimist@^1.2.5