diff --git a/src/maps/export.js b/src/maps/export.js
index 5ac535183..aa7746712 100644
--- a/src/maps/export.js
+++ b/src/maps/export.js
@@ -3,29 +3,53 @@ import { saveAs } from 'file-saver'
export function exportAsGPX (markers, filename) {
saveAs(new Blob(
- [toXML({
- _name: 'gpx',
- _attrs: {
- version: '1.1',
- 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
- 'xsi:schemaLocation': 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd',
- },
- _content: markers.map(marker => {
- const { lat, lng: lon } = marker.latLng
- return {
- _name: 'wpt',
- _attrs: {
- lat,
- lon,
- },
- _content: marker.gpx,
- }
- }),
- }, {
- header: true,
- })],
+ [markersAsGPX(markers)],
{
type: 'application/gpx+xml',
},
), filename)
}
+
+export function markersAsGPX (markers) {
+ return toXML({
+ _name: 'gpx',
+ _attrs: {
+ version: '1.1',
+ 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation': 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd',
+ },
+ _content: markers.map(marker => {
+ const { lat, lng: lon } = marker.latLng
+ return {
+ _name: 'wpt',
+ _attrs: {
+ lat,
+ lon,
+ },
+ // Remove this handling if https://github.com/davidcalhoun/jstoxml/issues/41 gets fixed!
+ _content: escapeObject(marker.gpx),
+ }
+ }),
+ }, {
+ header: true,
+ })
+}
+
+// Only escapes top level values and assumes they are strings
+function escapeObject (obj) {
+ const newObj = {}
+ for (const key of Object.keys(obj)) {
+ newObj[key] = escapeValue(obj[key])
+ }
+ return newObj
+}
+
+function escapeValue (content) {
+ return content.replace(/[<>&"']/g, c => ({
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '"': '"',
+ "'": ''',
+ }[c]))
+}
diff --git a/src/maps/export.spec.js b/src/maps/export.spec.js
new file mode 100644
index 000000000..419442271
--- /dev/null
+++ b/src/maps/export.spec.js
@@ -0,0 +1,34 @@
+import { groupMarker } from './components/markers'
+import { makeGroup } from '>/enrichedFactories'
+
+import { markersAsGPX } from './export'
+
+describe('map export', () => {
+ it('creates GPX', async () => {
+ const marker = groupMarker(makeGroup({ name: 'foobar' }))
+ expect(markersAsGPX([marker])).toBe(`
+
+
+
+ foobar
+ groups
+
+
+ `.trim().replace(/\s*\n\s*/g, ''),
+ )
+ })
+
+ it('escapes content correctly', () => {
+ const marker = groupMarker(makeGroup({ name: 'foo & bar' }))
+ expect(markersAsGPX([marker])).toBe(`
+
+
+
+ foo & bar
+ groups
+
+
+ `.trim().replace(/\s*\n\s*/g, ''),
+ )
+ })
+})