From 3bc9087fff3653dc1fde50d04d8e0c2941791129 Mon Sep 17 00:00:00 2001 From: Kristofor Carle Date: Sat, 10 Jun 2017 15:50:29 -0400 Subject: [PATCH 1/4] upgrade strxml to fix warnings related to old version of tap --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7cab23f..55aec3d 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "minimist": "0.1.0", - "strxml": "0.0.0", + "strxml": "1.0.0", "rw": "0.0.4" } } From 05bb2a39361c2f9c9dc8ea61ddd9a16f50771d06 Mon Sep 17 00:00:00 2001 From: Kristofor Carle Date: Tue, 27 Jun 2017 12:41:51 -0400 Subject: [PATCH 2/4] fix breaking changes from latest strxml --- index.js | 68 ++++++++++++++++------------- package.json | 3 +- tokml.js | 121 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 113 insertions(+), 79 deletions(-) diff --git a/index.js b/index.js index f08f16e..904d6bf 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ +var esc = require('xml-escape'); var strxml = require('strxml'), - tag = strxml.tag, - encode = strxml.encode; + tag = strxml.tag; module.exports = function tokml(geojson, options) { @@ -14,12 +14,12 @@ module.exports = function tokml(geojson, options) { }; return '' + - tag('kml', + tag('kml', {'xmlns': 'http://www.opengis.net/kml/2.2'}, tag('Document', documentName(options) + documentDescription(options) + root(geojson, options) - ), [['xmlns', 'http://www.opengis.net/kml/2.2']]); + )); }; function feature(options, styleHashesArray) { @@ -89,15 +89,15 @@ function documentDescription(options) { } function name(_, options) { - return _[options.name] ? tag('name', encode(_[options.name])) : ''; + return _[options.name] ? tag('name', _[options.name]) : ''; } function description(_, options) { - return _[options.description] ? tag('description', encode(_[options.description])) : ''; + return _[options.description] ? tag('description', _[options.description]) : ''; } function timestamp(_, options) { - return _[options.timestamp] ? tag('TimeStamp', tag('when', encode(_[options.timestamp]))) : ''; + return _[options.timestamp] ? tag('TimeStamp', tag('when', _[options.timestamp])) : ''; } // ## Geometry Types @@ -114,10 +114,10 @@ var geometry = { if (!_.coordinates.length) return ''; var outer = _.coordinates[0], inner = _.coordinates.slice(1), - outerRing = tag('outerBoundaryIs', + outerRing = tag('outerBoundaryIs', tag('LinearRing', tag('coordinates', linearring(outer)))), innerRings = inner.map(function(i) { - return tag('innerBoundaryIs', + return tag('innerBoundaryIs', tag('LinearRing', tag('coordinates', linearring(i)))); }).join(''); return tag('Polygon', outerRing + innerRings); @@ -175,11 +175,11 @@ function linearring(_) { // ## Data function extendeddata(_) { - return tag('ExtendedData', pairs(_).map(data).join('')); + return tag('ExtendedData', {}, pairs(_).map(data).join('')); } function data(_) { - return tag('Data', tag('value', encode(_[1])), [['name', encode(_[0])]]); + return tag('Data', {'name': _[0]}, tag('value', {}, esc(_[1] ? _[1].toString() : ''))); } // ## Marker style @@ -188,11 +188,12 @@ function hasMarkerStyle(_) { } function markerStyle(_, styleHash) { - return tag('Style', - tag('IconStyle', - tag('Icon', - tag('href', iconUrl(_)))) + - iconSize(_), [['id', styleHash]]); + return tag('Style', {'id': styleHash}, + tag('IconStyle', + tag('Icon', + tag('href', iconUrl(_))) + ) + iconSize(_) + ); } function iconUrl(_) { @@ -205,12 +206,12 @@ function iconUrl(_) { } 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' + }, ''); } // ## Polygon and Line style @@ -227,20 +228,19 @@ function hasPolygonAndLineStyle(_) { } function polygonAndLineStyle(_, styleHash) { - var lineStyle = tag('LineStyle', [ - tag('color', hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555') + - tag('width', _['stroke-width'] === undefined ? 2 : _['stroke-width']) - ]); + 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') - ]); + polyStyle = tag('PolyStyle', + tag('color', {}, hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555') + ); } - return tag('Style', lineStyle + polyStyle, [['id', styleHash]]); + return tag('Style', {'id': styleHash}, lineStyle + polyStyle); } // ## Style helpers @@ -289,6 +289,12 @@ function hexToKmlColor(hexColor, opacity) { // ## General helpers function pairs(_) { var o = []; - for (var i in _) o.push([i, _[i]]); + for (var i in _){ + if(_[i]){ + o.push([i, _[i]]); + }else{ + o.push([i, '']); + } + } return o; } \ No newline at end of file diff --git a/package.json b/package.json index 55aec3d..7b81865 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ }, "dependencies": { "minimist": "0.1.0", + "rw": "0.0.4", "strxml": "1.0.0", - "rw": "0.0.4" + "xml-escape": "^1.1.0" } } diff --git a/tokml.js b/tokml.js index 2377b7e..262f7dc 100644 --- a/tokml.js +++ b/tokml.js @@ -1,7 +1,7 @@ (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 e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o' + - tag('kml', + tag('kml', {'xmlns': 'http://www.opengis.net/kml/2.2'}, tag('Document', documentName(options) + documentDescription(options) + root(geojson, options) - ), [['xmlns', 'http://www.opengis.net/kml/2.2']]); + )); }; function feature(options, styleHashesArray) { @@ -90,15 +90,15 @@ function documentDescription(options) { } function name(_, options) { - return _[options.name] ? tag('name', encode(_[options.name])) : ''; + return _[options.name] ? tag('name', _[options.name]) : ''; } function description(_, options) { - return _[options.description] ? tag('description', encode(_[options.description])) : ''; + return _[options.description] ? tag('description', _[options.description]) : ''; } function timestamp(_, options) { - return _[options.timestamp] ? tag('TimeStamp', tag('when', encode(_[options.timestamp]))) : ''; + return _[options.timestamp] ? tag('TimeStamp', tag('when', _[options.timestamp])) : ''; } // ## Geometry Types @@ -115,10 +115,10 @@ var geometry = { if (!_.coordinates.length) return ''; var outer = _.coordinates[0], inner = _.coordinates.slice(1), - outerRing = tag('outerBoundaryIs', + outerRing = tag('outerBoundaryIs', tag('LinearRing', tag('coordinates', linearring(outer)))), innerRings = inner.map(function(i) { - return tag('innerBoundaryIs', + return tag('innerBoundaryIs', tag('LinearRing', tag('coordinates', linearring(i)))); }).join(''); return tag('Polygon', outerRing + innerRings); @@ -176,11 +176,11 @@ function linearring(_) { // ## Data function extendeddata(_) { - return tag('ExtendedData', pairs(_).map(data).join('')); + return tag('ExtendedData', {}, pairs(_).map(data).join('')); } function data(_) { - return tag('Data', tag('value', encode(_[1])), [['name', encode(_[0])]]); + return tag('Data', {'name': _[0]}, tag('value', {}, esc(_[1] ? _[1].toString() : ''))); } // ## Marker style @@ -189,11 +189,12 @@ function hasMarkerStyle(_) { } function markerStyle(_, styleHash) { - return tag('Style', - tag('IconStyle', - tag('Icon', - tag('href', iconUrl(_)))) + - iconSize(_), [['id', styleHash]]); + return tag('Style', {'id': styleHash}, + tag('IconStyle', + tag('Icon', + tag('href', iconUrl(_))) + ) + iconSize(_) + ); } function iconUrl(_) { @@ -206,12 +207,12 @@ function iconUrl(_) { } 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' + }, ''); } // ## Polygon and Line style @@ -228,20 +229,19 @@ function hasPolygonAndLineStyle(_) { } function polygonAndLineStyle(_, styleHash) { - var lineStyle = tag('LineStyle', [ - tag('color', hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555') + - tag('width', _['stroke-width'] === undefined ? 2 : _['stroke-width']) - ]); + 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') - ]); + polyStyle = tag('PolyStyle', + tag('color', {}, hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555') + ); } - return tag('Style', lineStyle + polyStyle, [['id', styleHash]]); + return tag('Style', {'id': styleHash}, lineStyle + polyStyle); } // ## Style helpers @@ -290,23 +290,31 @@ function hexToKmlColor(hexColor, opacity) { // ## General helpers function pairs(_) { var o = []; - for (var i in _) o.push([i, _[i]]); + for (var i in _){ + if(_[i]){ + o.push([i, _[i]]); + }else{ + o.push([i, '']); + } + } return o; } -},{"strxml":2}],2:[function(require,module,exports){ +},{"strxml":2,"xml-escape":3}],2:[function(require,module,exports){ +var esc = require('xml-escape'); + module.exports.attr = attr; module.exports.tagClose = tagClose; module.exports.tag = tag; -module.exports.encode = encode; /** * @param {array} _ an array of attributes * @returns {string} */ -function attr(_) { - return (_ && _.length) ? (' ' + _.map(function(a) { - return a[0] + '="' + a[1] + '"'; - }).join(' ')) : ''; +function attr(attributes) { + if (!Object.keys(attributes).length) return ''; + return ' ' + Object.keys(attributes).map(function(key) { + return key + '="' + esc(attributes[key]) + '"'; + }).join(' '); } /** @@ -324,20 +332,39 @@ function tagClose(el, attributes) { * @param {array} attributes array of pairs * @returns {string} */ -function tag(el, contents, attributes) { +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 + ''; } -/** - * @param {string} _ a string of attribute - * @returns {string} - */ -function encode(_) { - return (_ === null ? '' : _.toString()).replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"'); +},{"xml-escape":3}],3:[function(require,module,exports){ + + +var escape = module.exports = function escape(string, ignore) { + var pattern; + + if (string === null || string === undefined) return; + + ignore = (ignore || '').replace(/[^&"<>\']/g, ''); + pattern = '([&"<>\'])'.replace(new RegExp('[' + ignore + ']', 'g'), ''); + + return string.replace(new RegExp(pattern, 'g'), function(str, item) { + return escape.map[item]; + }) } +var map = escape.map = { + '>': '>' + , '<': '<' + , "'": ''' + , '"': '"' + , '&': '&' +} },{}]},{},[1])(1) }); \ No newline at end of file From b1bb13f2b4bd4e5effc200466aa8930cbf80b47e Mon Sep 17 00:00:00 2001 From: Kristofor Carle Date: Tue, 27 Jun 2017 13:37:57 -0400 Subject: [PATCH 3/4] use strxml repo directly until tap patch is published --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b81865..9f0e7e1 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "dependencies": { "minimist": "0.1.0", "rw": "0.0.4", - "strxml": "1.0.0", + "strxml": "mapbox/strxml", "xml-escape": "^1.1.0" } } From a02e05e04f57d354e6b6018b19dee2c92903fc32 Mon Sep 17 00:00:00 2001 From: Kristofor Carle Date: Sat, 5 May 2018 22:00:27 -0400 Subject: [PATCH 4/4] escape name, description and timestamp fields --- index.js | 6 +++--- tokml.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 904d6bf..4866de9 100644 --- a/index.js +++ b/index.js @@ -89,15 +89,15 @@ function documentDescription(options) { } function name(_, options) { - return _[options.name] ? tag('name', _[options.name]) : ''; + return _[options.name] ? tag('name', esc(_[options.name])) : ''; } function description(_, options) { - return _[options.description] ? tag('description', _[options.description]) : ''; + return _[options.description] ? tag('description', esc(_[options.description])) : ''; } function timestamp(_, options) { - return _[options.timestamp] ? tag('TimeStamp', tag('when', _[options.timestamp])) : ''; + return _[options.timestamp] ? tag('TimeStamp', tag('when', esc(_[options.timestamp]))) : ''; } // ## Geometry Types diff --git a/tokml.js b/tokml.js index 262f7dc..18cebc1 100644 --- a/tokml.js +++ b/tokml.js @@ -1,4 +1,4 @@ -(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 e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o