├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── dist ├── maplibre-gl-vector-text-protocol.esm.js ├── maplibre-gl-vector-text-protocol.js ├── maplibre-gl-vector-text-protocol.min.js ├── maplibre-gl-vector-text-protocol.min.js.map └── src │ ├── converter.d.ts │ ├── converter.d.ts.map │ ├── index.d.ts │ ├── index.d.ts.map │ └── worker │ ├── actor.d.ts │ ├── actor.d.ts.map │ ├── worker.d.ts │ └── worker.d.ts.map ├── examples ├── data │ ├── beach_ave.gpx │ ├── cape_may_incorporated_places.geojson │ ├── cape_may_incorporated_places.kml │ └── cape_may_restaurants.csv ├── index.css ├── index.html ├── index.js ├── indexv3.html ├── layerSelector.js └── umd.html ├── package.json ├── rollup.config.mjs ├── src ├── converter.ts ├── custom.d.ts ├── index.ts └── worker │ ├── actor.ts │ └── worker.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .npmrc 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Blacklist everything first 2 | * 3 | 4 | # Whitelist specific files or folders 5 | !dist/ 6 | !README.md 7 | !LICENSE 8 | !package.json 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGE LOG 2 | 3 | ## April 28, 2024 - v0.0.5 4 | * Bump to 5 to keep NPM / Github synchronized 5 | 6 | ## April 28, 2024 - v0.0.4 7 | * Export processData so it can use used without adding data to the map directly 8 | * Update libraries 9 | * maplibre-gl ^4.1.2 → ^4.1.3 10 | * rollup ^4.14.1 → ^4.17.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jim McAndrew 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # maplibre-gl-vector-text-protocol 2 | Supports geospatial text based vector data using [MapLibre GL JS](https://github.com/maplibre/maplibre-gl-js) in v1.15.0 or later. 3 | 4 | It makes use of the [addProtocol](https://github.com/maplibre/maplibre-gl-js/pull/30) functionality that was added in version [1.15.0](https://github.com/maplibre/maplibre-gl-js/releases/tag/v1.15.0). 5 | 6 | It can be used with Mapbox GL JS 1.x.x using the [mapbox-gl-custom-protocol](https://www.github.com/jimmyrocks/mapbox-gl-custom-protocol) library. I haven't tested it with Mapbox GL JS 2+. 7 | 8 | Web workers are used to convert `CSV`, `TSV`, `Topojson`, and `OSM` formats. `KML`, `GPX`, and `TCX` formats are based on XML and use the [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser), which isn't available to web workers, so they are converted to GeoJSON in the main thread. 9 | 10 | ## Supported Formats 🗎 11 | * [`Topojson`](https://en.wikipedia.org/wiki/GeoJSON#TopoJSON) - A more compact JSON based format than [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) that takes advantage of shared **topo**logies. 12 | * [`OSM`](https://wiki.openstreetmap.org/wiki/OSM_JSON) - Open Street Map json/xml. 13 | * [`KML`](https://en.wikipedia.org/wiki/Keyhole_Markup_Language) - **K**eyhole **M**arkup **L**anguage, popularized by [Google Earth](https://en.wikipedia.org/wiki/Google_Earth). 14 | * [`GPX`](https://en.wikipedia.org/wiki/GPS_Exchange_Format) - **GP**S E**x**change Format - A common XML-based format used by may GPS devices. 15 | * [`TCX`](https://en.wikipedia.org/wiki/Training_Center_XML) - **T**raining **C**enter **X**ML - An XML-based format used by various Garmin devices and applications (e.g. [Garmin Connect](https://connect.garmin.com)). 16 | * [`CSV`](https://en.wikipedia.org/wiki/Comma-separated_values) - **C**omma-**S**eparated **V**alues, the old reliable of data formats. No options are exposed, Latitude fields must start with "lat" and Longitude fields must start with "lon" or "lng". Will also work with bar (|) and tab (\t) separated values. 17 | * [`TSV`](https://en.wikipedia.org/wiki/Tab-separated_values) - **T**ab-**S**eparated **V**alue - Same as CSV, but it forces the delimiter to be a tab character (\t). 18 | 19 | ## Objective ✨ 20 | The [`addProtocol`](https://github.com/maplibre/maplibre-gl-js/blob/492bec58c5684609af8fba81ef01e5f5a3ef0711/src/index.js#L177) feature makes it extremely easy to extend the existing functionality of MapLibre sources without creating a new source type using the [addSourceType](https://github.com/maplibre/maplibre-gl-js/blob/d375def728d23b9d443a4dcaab0fd06df912223e/src/ui/map.ts#L1583) feature. This makes it very easy to support all kinds of new things in MapLibre. 21 | 22 | ## Inspiration 💡 23 | I have worked on many projects where users want to add their own data to a map, but their data is rarely in the right format. This library makes it as easy as adding a `csv://` before the file path to bring a csv file in. 24 | 25 | There are a lot of [Geospatial File Formats](https://en.wikipedia.org/wiki/GIS_file_formats#Vector) out there, this library is intended to serve the most common formats (CSV, KML, GPX, Topojson, OSM) without creating a huge library. There are other formats I would like to support, but they will be available in different libraries. 26 | 27 | ## External Libraries 📚 28 | This project would not be possible if it weren't for the core libraries that drive it: 29 | * `@tmcw/togeojson` - Supported by [placemark.io](https://placemark.io) - `KML`, `GPX`, `TCX` support 30 | * `csv2geojson` - Supported by [Mapbox](https://mapbox.com) - `CSV`, `TSV` support 31 | * `topojson-client` - From [Mike Bostock](https://github.com/mbostock) - `Topojson` support 32 | * `osm2geojson-lite` - From [tibetty](https://github.com/tibetty/osm2geojson-lite) - `osm2geojson-lite` support 33 | 34 | I'd also like to thank the Mapbox🚀 and MapLibre teams for creating such a great project that is easily extendable. 35 | 36 | ## Usage 🛠️ 37 | 38 | ```javascript 39 | 40 | 41 | // Add all types 42 | VectorTextProtocol.addProtocols(maplibregl); 43 | 44 | // Individual protocols can be added as well 45 | maplibregl.addProtocol('csv', VectorTextProtocol.VectorTextProtocol); 46 | maplibregl.addProtocol('kml', VectorTextProtocol.VectorTextProtocol); 47 | ``` 48 | 49 | ## Examples ⚙️ 50 | * [KML, CSV, TOPOJSON, GPX (using Modules)](https://loc8.us/maplibre-gl-vector-text-protocol/examples/index.html) 51 | * [TOPOJSON (using UMD)](https://loc8.us/maplibre-gl-vector-text-protocol/examples/umd.html) 52 | ### Codepen 53 | * [TOPOJSON](https://codepen.io/jimmyrocks/pen/ExbPXZP) 54 | -------------------------------------------------------------------------------- /dist/maplibre-gl-vector-text-protocol.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"maplibre-gl-vector-text-protocol.min.js","sources":["../node_modules/d3-dsv/src/dsv.js","../node_modules/d3-dsv/src/csv.js","../node_modules/d3-dsv/src/tsv.js","../node_modules/@mapbox/sexagesimal/index.js","../node_modules/csv2geojson/index.js","../node_modules/topojson-client/src/identity.js","../node_modules/topojson-client/src/feature.js","../node_modules/topojson-client/src/transform.js","../node_modules/topojson-client/src/reverse.js","../node_modules/@tmcw/togeojson/dist/togeojson.es.mjs","../node_modules/@mapbox/polyline/src/polyline.js","../node_modules/osm2geojson-lite/lib/utils.js","../node_modules/osm2geojson-lite/lib/osmobjs.js","../node_modules/osm2geojson-lite/lib/xmlparser.js","../node_modules/osm2geojson-lite/lib/index.js"],"sourcesContent":["function objectConverter(columns) {\n return new Function(\"d\", \"return {\" + columns.map(function(name, i) {\n return JSON.stringify(name) + \": d[\" + i + \"]\";\n }).join(\",\") + \"}\");\n}\n\nfunction customConverter(columns, f) {\n var object = objectConverter(columns);\n return function(row, i) {\n return f(object(row), i, columns);\n };\n}\n\n// Compute unique columns in order of discovery.\nfunction inferColumns(rows) {\n var columnSet = Object.create(null),\n columns = [];\n\n rows.forEach(function(row) {\n for (var column in row) {\n if (!(column in columnSet)) {\n columns.push(columnSet[column] = column);\n }\n }\n });\n\n return columns;\n}\n\nexport default function(delimiter) {\n var reFormat = new RegExp(\"[\\\"\" + delimiter + \"\\n]\"),\n delimiterCode = delimiter.charCodeAt(0);\n\n function parse(text, f) {\n var convert, columns, rows = parseRows(text, function(row, i) {\n if (convert) return convert(row, i - 1);\n columns = row, convert = f ? customConverter(row, f) : objectConverter(row);\n });\n rows.columns = columns;\n return rows;\n }\n\n function parseRows(text, f) {\n var EOL = {}, // sentinel value for end-of-line\n EOF = {}, // sentinel value for end-of-file\n rows = [], // output rows\n N = text.length,\n I = 0, // current character index\n n = 0, // the current line number\n t, // the current token\n eol; // is the current token followed by EOL?\n\n function token() {\n if (I >= N) return EOF; // special case: end of file\n if (eol) return eol = false, EOL; // special case: end of line\n\n // special case: quotes\n var j = I, c;\n if (text.charCodeAt(j) === 34) {\n var i = j;\n while (i++ < N) {\n if (text.charCodeAt(i) === 34) {\n if (text.charCodeAt(i + 1) !== 34) break;\n ++i;\n }\n }\n I = i + 2;\n c = text.charCodeAt(i + 1);\n if (c === 13) {\n eol = true;\n if (text.charCodeAt(i + 2) === 10) ++I;\n } else if (c === 10) {\n eol = true;\n }\n return text.slice(j + 1, i).replace(/\"\"/g, \"\\\"\");\n }\n\n // common case: find next delimiter or newline\n while (I < N) {\n var k = 1;\n c = text.charCodeAt(I++);\n if (c === 10) eol = true; // \\n\n else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \\r|\\r\\n\n else if (c !== delimiterCode) continue;\n return text.slice(j, I - k);\n }\n\n // special case: last token before EOF\n return text.slice(j);\n }\n\n while ((t = token()) !== EOF) {\n var a = [];\n while (t !== EOL && t !== EOF) {\n a.push(t);\n t = token();\n }\n if (f && (a = f(a, n++)) == null) continue;\n rows.push(a);\n }\n\n return rows;\n }\n\n function format(rows, columns) {\n if (columns == null) columns = inferColumns(rows);\n return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {\n return columns.map(function(column) {\n return formatValue(row[column]);\n }).join(delimiter);\n })).join(\"\\n\");\n }\n\n function formatRows(rows) {\n return rows.map(formatRow).join(\"\\n\");\n }\n\n function formatRow(row) {\n return row.map(formatValue).join(delimiter);\n }\n\n function formatValue(text) {\n return text == null ? \"\"\n : reFormat.test(text += \"\") ? \"\\\"\" + text.replace(/\\\"/g, \"\\\"\\\"\") + \"\\\"\"\n : text;\n }\n\n return {\n parse: parse,\n parseRows: parseRows,\n format: format,\n formatRows: formatRows\n };\n}\n","import dsv from \"./dsv\";\n\nvar csv = dsv(\",\");\n\nexport var csvParse = csv.parse;\nexport var csvParseRows = csv.parseRows;\nexport var csvFormat = csv.format;\nexport var csvFormatRows = csv.formatRows;\n","import dsv from \"./dsv\";\n\nvar tsv = dsv(\"\\t\");\n\nexport var tsvParse = tsv.parse;\nexport var tsvParseRows = tsv.parseRows;\nexport var tsvFormat = tsv.format;\nexport var tsvFormatRows = tsv.formatRows;\n","module.exports = element;\nmodule.exports.pair = pair;\nmodule.exports.format = format;\nmodule.exports.formatPair = formatPair;\nmodule.exports.coordToDMS = coordToDMS;\n\n\nfunction element(input, dims) {\n var result = search(input, dims);\n return (result === null) ? null : result.val;\n}\n\n\nfunction formatPair(input) {\n return format(input.lat, 'lat') + ' ' + format(input.lon, 'lon');\n}\n\n\n// Is 0 North or South?\nfunction format(input, dim) {\n var dms = coordToDMS(input, dim);\n return dms.whole + '° ' +\n (dms.minutes ? dms.minutes + '\\' ' : '') +\n (dms.seconds ? dms.seconds + '\" ' : '') + dms.dir;\n}\n\n\nfunction coordToDMS(input, dim) {\n var dirs = { lat: ['N', 'S'], lon: ['E', 'W'] }[dim] || '';\n var dir = dirs[input >= 0 ? 0 : 1];\n var abs = Math.abs(input);\n var whole = Math.floor(abs);\n var fraction = abs - whole;\n var fractionMinutes = fraction * 60;\n var minutes = Math.floor(fractionMinutes);\n var seconds = Math.floor((fractionMinutes - minutes) * 60);\n\n return {\n whole: whole,\n minutes: minutes,\n seconds: seconds,\n dir: dir\n };\n}\n\n\nfunction search(input, dims) {\n if (!dims) dims = 'NSEW';\n if (typeof input !== 'string') return null;\n\n input = input.toUpperCase();\n var regex = /^[\\s\\,]*([NSEW])?\\s*([\\-|\\—|\\―]?[0-9.]+)[°º˚]?\\s*(?:([0-9.]+)['’′‘]\\s*)?(?:([0-9.]+)(?:''|\"|”|″)\\s*)?([NSEW])?/;\n\n var m = input.match(regex);\n if (!m) return null; // no match\n\n var matched = m[0];\n\n // extract dimension.. m[1] = leading, m[5] = trailing\n var dim;\n if (m[1] && m[5]) { // if matched both..\n dim = m[1]; // keep leading\n matched = matched.slice(0, -1); // remove trailing dimension from match\n } else {\n dim = m[1] || m[5];\n }\n\n // if unrecognized dimension\n if (dim && dims.indexOf(dim) === -1) return null;\n\n // extract DMS\n var deg = m[2] ? parseFloat(m[2]) : 0;\n var min = m[3] ? parseFloat(m[3]) / 60 : 0;\n var sec = m[4] ? parseFloat(m[4]) / 3600 : 0;\n var sign = (deg < 0) ? -1 : 1;\n if (dim === 'S' || dim === 'W') sign *= -1;\n\n return {\n val: (Math.abs(deg) + min + sec) * sign,\n dim: dim,\n matched: matched,\n remain: input.slice(matched.length)\n };\n}\n\n\nfunction pair(input, dims) {\n input = input.trim();\n var one = search(input, dims);\n if (!one) return null;\n\n input = one.remain.trim();\n var two = search(input, dims);\n if (!two || two.remain) return null;\n\n if (one.dim) {\n return swapdim(one.val, two.val, one.dim);\n } else {\n return [one.val, two.val];\n }\n}\n\n\nfunction swapdim(a, b, dim) {\n if (dim === 'N' || dim === 'S') return [a, b];\n if (dim === 'W' || dim === 'E') return [b, a];\n}\n","'use strict';\n\nvar dsv = require('d3-dsv'),\n sexagesimal = require('@mapbox/sexagesimal');\n\nvar latRegex = /(Lat)(itude)?/gi,\n lonRegex = /(L)(on|ng)(gitude)?/i;\n\nfunction guessHeader(row, regexp) {\n var name, match, score;\n for (var f in row) {\n match = f.match(regexp);\n if (match && (!name || match[0].length / f.length > score)) {\n score = match[0].length / f.length;\n name = f;\n }\n }\n return name;\n}\n\nfunction guessLatHeader(row) { return guessHeader(row, latRegex); }\nfunction guessLonHeader(row) { return guessHeader(row, lonRegex); }\n\nfunction isLat(f) { return !!f.match(latRegex); }\nfunction isLon(f) { return !!f.match(lonRegex); }\n\nfunction keyCount(o) {\n return (typeof o == 'object') ? Object.keys(o).length : 0;\n}\n\nfunction autoDelimiter(x) {\n var delimiters = [',', ';', '\\t', '|'];\n var results = [];\n\n delimiters.forEach(function (delimiter) {\n var res = dsv.dsvFormat(delimiter).parse(x);\n if (res.length >= 1) {\n var count = keyCount(res[0]);\n for (var i = 0; i < res.length; i++) {\n if (keyCount(res[i]) !== count) return;\n }\n results.push({\n delimiter: delimiter,\n arity: Object.keys(res[0]).length,\n });\n }\n });\n\n if (results.length) {\n return results.sort(function (a, b) {\n return b.arity - a.arity;\n })[0].delimiter;\n } else {\n return null;\n }\n}\n\n/**\n * Silly stopgap for dsv to d3-dsv upgrade\n *\n * @param {Array} x dsv output\n * @returns {Array} array without columns member\n */\nfunction deleteColumns(x) {\n delete x.columns;\n return x;\n}\n\nfunction auto(x) {\n var delimiter = autoDelimiter(x);\n if (!delimiter) return null;\n return deleteColumns(dsv.dsvFormat(delimiter).parse(x));\n}\n\nfunction csv2geojson(x, options, callback) {\n\n if (!callback) {\n callback = options;\n options = {};\n }\n\n options.delimiter = options.delimiter || ',';\n\n var latfield = options.latfield || '',\n lonfield = options.lonfield || '',\n crs = options.crs || '';\n\n var features = [],\n featurecollection = {type: 'FeatureCollection', features: features};\n\n if (crs !== '') {\n featurecollection.crs = {type: 'name', properties: {name: crs}};\n }\n\n if (options.delimiter === 'auto' && typeof x == 'string') {\n options.delimiter = autoDelimiter(x);\n if (!options.delimiter) {\n callback({\n type: 'Error',\n message: 'Could not autodetect delimiter'\n });\n return;\n }\n }\n\n var numericFields = options.numericFields ? options.numericFields.split(',') : null;\n\n var parsed = (typeof x == 'string') ?\n dsv.dsvFormat(options.delimiter).parse(x, function (d) {\n if (numericFields) {\n for (var key in d) {\n if (numericFields.includes(key)) {\n d[key] = +d[key];\n }\n }\n }\n return d;\n }) : x;\n\n if (!parsed.length) {\n callback(null, featurecollection);\n return;\n }\n\n var errors = [];\n var i;\n\n\n if (!latfield) latfield = guessLatHeader(parsed[0]);\n if (!lonfield) lonfield = guessLonHeader(parsed[0]);\n var noGeometry = (!latfield || !lonfield);\n\n if (noGeometry) {\n for (i = 0; i < parsed.length; i++) {\n features.push({\n type: 'Feature',\n properties: parsed[i],\n geometry: null\n });\n }\n callback(errors.length ? errors : null, featurecollection);\n return;\n }\n\n for (i = 0; i < parsed.length; i++) {\n if (parsed[i][lonfield] !== undefined &&\n parsed[i][latfield] !== undefined) {\n\n var lonk = parsed[i][lonfield],\n latk = parsed[i][latfield],\n lonf, latf,\n a;\n\n a = sexagesimal(lonk, 'EW');\n if (a) lonk = a;\n a = sexagesimal(latk, 'NS');\n if (a) latk = a;\n\n lonf = parseFloat(lonk);\n latf = parseFloat(latk);\n\n if (isNaN(lonf) ||\n isNaN(latf)) {\n errors.push({\n message: 'A row contained an invalid value for latitude or longitude',\n row: parsed[i],\n index: i\n });\n } else {\n if (!options.includeLatLon) {\n delete parsed[i][lonfield];\n delete parsed[i][latfield];\n }\n\n features.push({\n type: 'Feature',\n properties: parsed[i],\n geometry: {\n type: 'Point',\n coordinates: [\n parseFloat(lonf),\n parseFloat(latf)\n ]\n }\n });\n }\n }\n }\n\n callback(errors.length ? errors : null, featurecollection);\n}\n\nfunction toLine(gj) {\n var features = gj.features;\n var line = {\n type: 'Feature',\n geometry: {\n type: 'LineString',\n coordinates: []\n }\n };\n for (var i = 0; i < features.length; i++) {\n line.geometry.coordinates.push(features[i].geometry.coordinates);\n }\n line.properties = features.reduce(function (aggregatedProperties, newFeature) {\n for (var key in newFeature.properties) {\n if (!aggregatedProperties[key]) {\n aggregatedProperties[key] = [];\n }\n aggregatedProperties[key].push(newFeature.properties[key]);\n }\n return aggregatedProperties;\n }, {});\n return {\n type: 'FeatureCollection',\n features: [line]\n };\n}\n\nfunction toPolygon(gj) {\n var features = gj.features;\n var poly = {\n type: 'Feature',\n geometry: {\n type: 'Polygon',\n coordinates: [[]]\n }\n };\n for (var i = 0; i < features.length; i++) {\n poly.geometry.coordinates[0].push(features[i].geometry.coordinates);\n }\n poly.properties = features.reduce(function (aggregatedProperties, newFeature) {\n for (var key in newFeature.properties) {\n if (!aggregatedProperties[key]) {\n aggregatedProperties[key] = [];\n }\n aggregatedProperties[key].push(newFeature.properties[key]);\n }\n return aggregatedProperties;\n }, {});\n return {\n type: 'FeatureCollection',\n features: [poly]\n };\n}\n\nmodule.exports = {\n isLon: isLon,\n isLat: isLat,\n guessLatHeader: guessLatHeader,\n guessLonHeader: guessLonHeader,\n csv: dsv.csvParse,\n tsv: dsv.tsvParse,\n dsv: dsv,\n auto: auto,\n csv2geojson: csv2geojson,\n toLine: toLine,\n toPolygon: toPolygon\n};\n","export default function(x) {\n return x;\n}\n","import reverse from \"./reverse.js\";\nimport transform from \"./transform.js\";\n\nexport default function(topology, o) {\n if (typeof o === \"string\") o = topology.objects[o];\n return o.type === \"GeometryCollection\"\n ? {type: \"FeatureCollection\", features: o.geometries.map(function(o) { return feature(topology, o); })}\n : feature(topology, o);\n}\n\nfunction feature(topology, o) {\n var id = o.id,\n bbox = o.bbox,\n properties = o.properties == null ? {} : o.properties,\n geometry = object(topology, o);\n return id == null && bbox == null ? {type: \"Feature\", properties: properties, geometry: geometry}\n : bbox == null ? {type: \"Feature\", id: id, properties: properties, geometry: geometry}\n : {type: \"Feature\", id: id, bbox: bbox, properties: properties, geometry: geometry};\n}\n\nexport function object(topology, o) {\n var transformPoint = transform(topology.transform),\n arcs = topology.arcs;\n\n function arc(i, points) {\n if (points.length) points.pop();\n for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) {\n points.push(transformPoint(a[k], k));\n }\n if (i < 0) reverse(points, n);\n }\n\n function point(p) {\n return transformPoint(p);\n }\n\n function line(arcs) {\n var points = [];\n for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);\n if (points.length < 2) points.push(points[0]); // This should never happen per the specification.\n return points;\n }\n\n function ring(arcs) {\n var points = line(arcs);\n while (points.length < 4) points.push(points[0]); // This may happen if an arc has only two points.\n return points;\n }\n\n function polygon(arcs) {\n return arcs.map(ring);\n }\n\n function geometry(o) {\n var type = o.type, coordinates;\n switch (type) {\n case \"GeometryCollection\": return {type: type, geometries: o.geometries.map(geometry)};\n case \"Point\": coordinates = point(o.coordinates); break;\n case \"MultiPoint\": coordinates = o.coordinates.map(point); break;\n case \"LineString\": coordinates = line(o.arcs); break;\n case \"MultiLineString\": coordinates = o.arcs.map(line); break;\n case \"Polygon\": coordinates = polygon(o.arcs); break;\n case \"MultiPolygon\": coordinates = o.arcs.map(polygon); break;\n default: return null;\n }\n return {type: type, coordinates: coordinates};\n }\n\n return geometry(o);\n}\n","import identity from \"./identity.js\";\n\nexport default function(transform) {\n if (transform == null) return identity;\n var x0,\n y0,\n kx = transform.scale[0],\n ky = transform.scale[1],\n dx = transform.translate[0],\n dy = transform.translate[1];\n return function(input, i) {\n if (!i) x0 = y0 = 0;\n var j = 2, n = input.length, output = new Array(n);\n output[0] = (x0 += input[0]) * kx + dx;\n output[1] = (y0 += input[1]) * ky + dy;\n while (j < n) output[j] = input[j], ++j;\n return output;\n };\n}\n","export default function(array, n) {\n var t, j = array.length, i = j - n;\n while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;\n}\n","function $(element, tagName) {\n return Array.from(element.getElementsByTagName(tagName));\n}\nfunction normalizeId(id) {\n return id[0] === \"#\" ? id : `#${id}`;\n}\nfunction $ns(element, tagName, ns) {\n return Array.from(element.getElementsByTagNameNS(ns, tagName));\n}\n/**\n * get the content of a text node, if any\n */\nfunction nodeVal(node) {\n node?.normalize();\n return (node && node.textContent) || \"\";\n}\n/**\n * Get one Y child of X, if any, otherwise null\n */\nfunction get1(node, tagName, callback) {\n const n = node.getElementsByTagName(tagName);\n const result = n.length ? n[0] : null;\n if (result && callback)\n callback(result);\n return result;\n}\nfunction get(node, tagName, callback) {\n const properties = {};\n if (!node)\n return properties;\n const n = node.getElementsByTagName(tagName);\n const result = n.length ? n[0] : null;\n if (result && callback) {\n return callback(result, properties);\n }\n return properties;\n}\nfunction val1(node, tagName, callback) {\n const val = nodeVal(get1(node, tagName));\n if (val && callback)\n return callback(val) || {};\n return {};\n}\nfunction $num(node, tagName, callback) {\n const val = parseFloat(nodeVal(get1(node, tagName)));\n if (isNaN(val))\n return undefined;\n if (val && callback)\n return callback(val) || {};\n return {};\n}\nfunction num1(node, tagName, callback) {\n const val = parseFloat(nodeVal(get1(node, tagName)));\n if (isNaN(val))\n return undefined;\n if (callback)\n callback(val);\n return val;\n}\nfunction getMulti(node, propertyNames) {\n const properties = {};\n for (const property of propertyNames) {\n val1(node, property, (val) => {\n properties[property] = val;\n });\n }\n return properties;\n}\nfunction isElement(node) {\n return node?.nodeType === 1;\n}\n\nfunction getLineStyle(node) {\n return get(node, \"line\", (lineStyle) => {\n const val = Object.assign({}, val1(lineStyle, \"color\", (color) => {\n return { stroke: `#${color}` };\n }), $num(lineStyle, \"opacity\", (opacity) => {\n return { \"stroke-opacity\": opacity };\n }), $num(lineStyle, \"width\", (width) => {\n // GPX width is in mm, convert to px with 96 px per inch\n return { \"stroke-width\": (width * 96) / 25.4 };\n }));\n return val;\n });\n}\n\nfunction getExtensions(node) {\n let values = [];\n if (node === null)\n return values;\n for (const child of Array.from(node.childNodes)) {\n if (!isElement(child))\n continue;\n const name = abbreviateName(child.nodeName);\n if (name === \"gpxtpx:TrackPointExtension\") {\n // loop again for nested garmin extensions (eg. \"gpxtpx:hr\")\n values = values.concat(getExtensions(child));\n }\n else {\n // push custom extension (eg. \"power\")\n const val = nodeVal(child);\n values.push([name, parseNumeric(val)]);\n }\n }\n return values;\n}\nfunction abbreviateName(name) {\n return [\"heart\", \"gpxtpx:hr\", \"hr\"].includes(name) ? \"heart\" : name;\n}\nfunction parseNumeric(val) {\n const num = parseFloat(val);\n return isNaN(num) ? val : num;\n}\n\nfunction coordPair$1(node) {\n const ll = [\n parseFloat(node.getAttribute(\"lon\") || \"\"),\n parseFloat(node.getAttribute(\"lat\") || \"\"),\n ];\n if (isNaN(ll[0]) || isNaN(ll[1])) {\n return null;\n }\n num1(node, \"ele\", (val) => {\n ll.push(val);\n });\n const time = get1(node, \"time\");\n return {\n coordinates: ll,\n time: time ? nodeVal(time) : null,\n extendedValues: getExtensions(get1(node, \"extensions\")),\n };\n}\n\nfunction extractProperties(node) {\n const properties = getMulti(node, [\n \"name\",\n \"cmt\",\n \"desc\",\n \"type\",\n \"time\",\n \"keywords\",\n ]);\n const extensions = Array.from(node.getElementsByTagNameNS(\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\", \"*\"));\n for (const child of extensions) {\n if (child.parentNode?.parentNode === node) {\n properties[child.tagName.replace(\":\", \"_\")] = nodeVal(child);\n }\n }\n const links = $(node, \"link\");\n if (links.length) {\n properties.links = links.map((link) => Object.assign({ href: link.getAttribute(\"href\") }, getMulti(link, [\"text\", \"type\"])));\n }\n return properties;\n}\n\n/**\n * Extract points from a trkseg or rte element.\n */\nfunction getPoints$1(node, pointname) {\n const pts = $(node, pointname);\n const line = [];\n const times = [];\n const extendedValues = {};\n for (let i = 0; i < pts.length; i++) {\n const c = coordPair$1(pts[i]);\n if (!c) {\n continue;\n }\n line.push(c.coordinates);\n if (c.time)\n times.push(c.time);\n for (const [name, val] of c.extendedValues) {\n const plural = name === \"heart\" ? name : name.replace(\"gpxtpx:\", \"\") + \"s\";\n if (!extendedValues[plural]) {\n extendedValues[plural] = Array(pts.length).fill(null);\n }\n extendedValues[plural][i] = val;\n }\n }\n if (line.length < 2)\n return; // Invalid line in GeoJSON\n return {\n line: line,\n times: times,\n extendedValues: extendedValues,\n };\n}\n/**\n * Extract a LineString geometry from a rte\n * element.\n */\nfunction getRoute(node) {\n const line = getPoints$1(node, \"rtept\");\n if (!line)\n return;\n return {\n type: \"Feature\",\n properties: Object.assign({ _gpxType: \"rte\" }, extractProperties(node), getLineStyle(get1(node, \"extensions\"))),\n geometry: {\n type: \"LineString\",\n coordinates: line.line,\n },\n };\n}\nfunction getTrack(node) {\n const segments = $(node, \"trkseg\");\n const track = [];\n const times = [];\n const extractedLines = [];\n for (const segment of segments) {\n const line = getPoints$1(segment, \"trkpt\");\n if (line) {\n extractedLines.push(line);\n if (line.times && line.times.length)\n times.push(line.times);\n }\n }\n if (extractedLines.length === 0)\n return null;\n const multi = extractedLines.length > 1;\n const properties = Object.assign({ _gpxType: \"trk\" }, extractProperties(node), getLineStyle(get1(node, \"extensions\")), times.length\n ? {\n coordinateProperties: {\n times: multi ? times : times[0],\n },\n }\n : {});\n for (const line of extractedLines) {\n track.push(line.line);\n if (!properties.coordinateProperties) {\n properties.coordinateProperties = {};\n }\n const props = properties.coordinateProperties;\n const entries = Object.entries(line.extendedValues);\n for (let i = 0; i < entries.length; i++) {\n const [name, val] = entries[i];\n if (multi) {\n if (!props[name]) {\n props[name] = extractedLines.map((line) => new Array(line.line.length).fill(null));\n }\n props[name][i] = val;\n }\n else {\n props[name] = val;\n }\n }\n }\n return {\n type: \"Feature\",\n properties: properties,\n geometry: multi\n ? {\n type: \"MultiLineString\",\n coordinates: track,\n }\n : {\n type: \"LineString\",\n coordinates: track[0],\n },\n };\n}\n/**\n * Extract a point, if possible, from a given node,\n * which is usually a wpt or trkpt\n */\nfunction getPoint(node) {\n const properties = Object.assign(extractProperties(node), getMulti(node, [\"sym\"]));\n const pair = coordPair$1(node);\n if (!pair)\n return null;\n return {\n type: \"Feature\",\n properties,\n geometry: {\n type: \"Point\",\n coordinates: pair.coordinates,\n },\n };\n}\n/**\n * Convert GPX to GeoJSON incrementally, returning\n * a [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)\n * that yields output feature by feature.\n */\nfunction* gpxGen(node) {\n for (const track of $(node, \"trk\")) {\n const feature = getTrack(track);\n if (feature)\n yield feature;\n }\n for (const route of $(node, \"rte\")) {\n const feature = getRoute(route);\n if (feature)\n yield feature;\n }\n for (const waypoint of $(node, \"wpt\")) {\n const point = getPoint(waypoint);\n if (point)\n yield point;\n }\n}\n/**\n *\n * Convert a GPX document to GeoJSON. The first argument, `doc`, must be a GPX\n * document as an XML DOM - not as a string. You can get this using jQuery's default\n * `.ajax` function or using a bare XMLHttpRequest with the `.response` property\n * holding an XML DOM.\n *\n * The output is a JavaScript object of GeoJSON data, same as `.kml` outputs, with the\n * addition of a `_gpxType` property on each `LineString` feature that indicates whether\n * the feature was encoded as a route (`rte`) or track (`trk`) in the GPX document.\n */\nfunction gpx(node) {\n return {\n type: \"FeatureCollection\",\n features: Array.from(gpxGen(node)),\n };\n}\n\nconst EXTENSIONS_NS = \"http://www.garmin.com/xmlschemas/ActivityExtension/v2\";\nconst TRACKPOINT_ATTRIBUTES = [\n [\"heartRate\", \"heartRates\"],\n [\"Cadence\", \"cadences\"],\n // Extended Trackpoint attributes\n [\"Speed\", \"speeds\"],\n [\"Watts\", \"watts\"],\n];\nconst LAP_ATTRIBUTES = [\n [\"TotalTimeSeconds\", \"totalTimeSeconds\"],\n [\"DistanceMeters\", \"distanceMeters\"],\n [\"MaximumSpeed\", \"maxSpeed\"],\n [\"AverageHeartRateBpm\", \"avgHeartRate\"],\n [\"MaximumHeartRateBpm\", \"maxHeartRate\"],\n // Extended Lap attributes\n [\"AvgSpeed\", \"avgSpeed\"],\n [\"AvgWatts\", \"avgWatts\"],\n [\"MaxWatts\", \"maxWatts\"],\n];\nfunction getProperties(node, attributeNames) {\n const properties = [];\n for (const [tag, alias] of attributeNames) {\n let elem = get1(node, tag);\n if (!elem) {\n const elements = node.getElementsByTagNameNS(EXTENSIONS_NS, tag);\n if (elements.length) {\n elem = elements[0];\n }\n }\n const val = parseFloat(nodeVal(elem));\n if (!isNaN(val)) {\n properties.push([alias, val]);\n }\n }\n return properties;\n}\nfunction coordPair(node) {\n const ll = [num1(node, \"LongitudeDegrees\"), num1(node, \"LatitudeDegrees\")];\n if (ll[0] === undefined ||\n isNaN(ll[0]) ||\n ll[1] === undefined ||\n isNaN(ll[1])) {\n return null;\n }\n const heartRate = get1(node, \"HeartRateBpm\");\n const time = nodeVal(get1(node, \"Time\"));\n get1(node, \"AltitudeMeters\", (alt) => {\n const a = parseFloat(nodeVal(alt));\n if (!isNaN(a)) {\n ll.push(a);\n }\n });\n return {\n coordinates: ll,\n time: time || null,\n heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null,\n extensions: getProperties(node, TRACKPOINT_ATTRIBUTES),\n };\n}\nfunction getPoints(node) {\n const pts = $(node, \"Trackpoint\");\n const line = [];\n const times = [];\n const heartRates = [];\n if (pts.length < 2)\n return null; // Invalid line in GeoJSON\n const extendedProperties = {};\n const result = { extendedProperties };\n for (let i = 0; i < pts.length; i++) {\n const c = coordPair(pts[i]);\n if (c === null)\n continue;\n line.push(c.coordinates);\n const { time, heartRate, extensions } = c;\n if (time)\n times.push(time);\n if (heartRate)\n heartRates.push(heartRate);\n for (const [alias, value] of extensions) {\n if (!extendedProperties[alias]) {\n extendedProperties[alias] = Array(pts.length).fill(null);\n }\n extendedProperties[alias][i] = value;\n }\n }\n if (line.length < 2)\n return null;\n return Object.assign(result, {\n line: line,\n times: times,\n heartRates: heartRates,\n });\n}\nfunction getLap(node) {\n const segments = $(node, \"Track\");\n const track = [];\n const times = [];\n const heartRates = [];\n const allExtendedProperties = [];\n let line;\n const properties = Object.assign(Object.fromEntries(getProperties(node, LAP_ATTRIBUTES)), get(node, \"Name\", (nameElement) => {\n return { name: nodeVal(nameElement) };\n }));\n for (const segment of segments) {\n line = getPoints(segment);\n if (line) {\n track.push(line.line);\n if (line.times.length)\n times.push(line.times);\n if (line.heartRates.length)\n heartRates.push(line.heartRates);\n allExtendedProperties.push(line.extendedProperties);\n }\n }\n for (let i = 0; i < allExtendedProperties.length; i++) {\n const extendedProperties = allExtendedProperties[i];\n for (const property in extendedProperties) {\n if (segments.length === 1) {\n if (line) {\n properties[property] = line.extendedProperties[property];\n }\n }\n else {\n if (!properties[property]) {\n properties[property] = track.map((track) => Array(track.length).fill(null));\n }\n properties[property][i] = extendedProperties[property];\n }\n }\n }\n if (track.length === 0)\n return null;\n if (times.length || heartRates.length) {\n properties.coordinateProperties = Object.assign(times.length\n ? {\n times: track.length === 1 ? times[0] : times,\n }\n : {}, heartRates.length\n ? {\n heart: track.length === 1 ? heartRates[0] : heartRates,\n }\n : {});\n }\n return {\n type: \"Feature\",\n properties: properties,\n geometry: track.length === 1\n ? {\n type: \"LineString\",\n coordinates: track[0],\n }\n : {\n type: \"MultiLineString\",\n coordinates: track,\n },\n };\n}\n/**\n * Incrementally convert a TCX document to GeoJSON. The\n * first argument, `doc`, must be a TCX\n * document as an XML DOM - not as a string.\n */\nfunction* tcxGen(node) {\n for (const lap of $(node, \"Lap\")) {\n const feature = getLap(lap);\n if (feature)\n yield feature;\n }\n for (const course of $(node, \"Courses\")) {\n const feature = getLap(course);\n if (feature)\n yield feature;\n }\n}\n/**\n * Convert a TCX document to GeoJSON. The first argument, `doc`, must be a TCX\n * document as an XML DOM - not as a string.\n */\nfunction tcx(node) {\n return {\n type: \"FeatureCollection\",\n features: Array.from(tcxGen(node)),\n };\n}\n\nfunction fixColor(v, prefix) {\n const properties = {};\n const colorProp = prefix == \"stroke\" || prefix === \"fill\" ? prefix : prefix + \"-color\";\n if (v[0] === \"#\") {\n v = v.substring(1);\n }\n if (v.length === 6 || v.length === 3) {\n properties[colorProp] = \"#\" + v;\n }\n else if (v.length === 8) {\n properties[prefix + \"-opacity\"] = parseInt(v.substring(0, 2), 16) / 255;\n properties[colorProp] =\n \"#\" + v.substring(6, 8) + v.substring(4, 6) + v.substring(2, 4);\n }\n return properties;\n}\n\nfunction numericProperty(node, source, target) {\n const properties = {};\n num1(node, source, (val) => {\n properties[target] = val;\n });\n return properties;\n}\nfunction getColor(node, output) {\n return get(node, \"color\", (elem) => fixColor(nodeVal(elem), output));\n}\nfunction extractIconHref(node) {\n return get(node, \"Icon\", (icon, properties) => {\n val1(icon, \"href\", (href) => {\n properties.icon = href;\n });\n return properties;\n });\n}\nfunction extractIcon(node) {\n return get(node, \"IconStyle\", (iconStyle) => {\n return Object.assign(getColor(iconStyle, \"icon\"), numericProperty(iconStyle, \"scale\", \"icon-scale\"), numericProperty(iconStyle, \"heading\", \"icon-heading\"), get(iconStyle, \"hotSpot\", (hotspot) => {\n const left = parseFloat(hotspot.getAttribute(\"x\") || \"\");\n const top = parseFloat(hotspot.getAttribute(\"y\") || \"\");\n const xunits = hotspot.getAttribute(\"xunits\") || \"\";\n const yunits = hotspot.getAttribute(\"yunits\") || \"\";\n if (!isNaN(left) && !isNaN(top))\n return {\n \"icon-offset\": [left, top],\n \"icon-offset-units\": [xunits, yunits],\n };\n return {};\n }), extractIconHref(iconStyle));\n });\n}\nfunction extractLabel(node) {\n return get(node, \"LabelStyle\", (labelStyle) => {\n return Object.assign(getColor(labelStyle, \"label\"), numericProperty(labelStyle, \"scale\", \"label-scale\"));\n });\n}\nfunction extractLine(node) {\n return get(node, \"LineStyle\", (lineStyle) => {\n return Object.assign(getColor(lineStyle, \"stroke\"), numericProperty(lineStyle, \"width\", \"stroke-width\"));\n });\n}\nfunction extractPoly(node) {\n return get(node, \"PolyStyle\", (polyStyle, properties) => {\n return Object.assign(properties, get(polyStyle, \"color\", (elem) => fixColor(nodeVal(elem), \"fill\")), val1(polyStyle, \"fill\", (fill) => {\n if (fill === \"0\")\n return { \"fill-opacity\": 0 };\n }), val1(polyStyle, \"outline\", (outline) => {\n if (outline === \"0\")\n return { \"stroke-opacity\": 0 };\n }));\n });\n}\nfunction extractStyle(node) {\n return Object.assign({}, extractPoly(node), extractLine(node), extractLabel(node), extractIcon(node));\n}\n\nconst toNumber = (x) => Number(x);\nconst typeConverters = {\n string: (x) => x,\n int: toNumber,\n uint: toNumber,\n short: toNumber,\n ushort: toNumber,\n float: toNumber,\n double: toNumber,\n bool: (x) => Boolean(x),\n};\nfunction extractExtendedData(node, schema) {\n return get(node, \"ExtendedData\", (extendedData, properties) => {\n for (const data of $(extendedData, \"Data\")) {\n properties[data.getAttribute(\"name\") || \"\"] = nodeVal(get1(data, \"value\"));\n }\n for (const simpleData of $(extendedData, \"SimpleData\")) {\n const name = simpleData.getAttribute(\"name\") || \"\";\n const typeConverter = schema[name] || typeConverters.string;\n properties[name] = typeConverter(nodeVal(simpleData));\n }\n return properties;\n });\n}\nfunction getMaybeHTMLDescription(node) {\n const descriptionNode = get1(node, \"description\");\n for (const c of Array.from(descriptionNode?.childNodes || [])) {\n if (c.nodeType === 4) {\n return {\n description: {\n \"@type\": \"html\",\n value: nodeVal(c),\n },\n };\n }\n }\n return {};\n}\nfunction extractTimeSpan(node) {\n return get(node, \"TimeSpan\", (timeSpan) => {\n return {\n timespan: {\n begin: nodeVal(get1(timeSpan, \"begin\")),\n end: nodeVal(get1(timeSpan, \"end\")),\n },\n };\n });\n}\nfunction extractTimeStamp(node) {\n return get(node, \"TimeStamp\", (timeStamp) => {\n return { timestamp: nodeVal(get1(timeStamp, \"when\")) };\n });\n}\nfunction extractCascadedStyle(node, styleMap) {\n return val1(node, \"styleUrl\", (styleUrl) => {\n styleUrl = normalizeId(styleUrl);\n if (styleMap[styleUrl]) {\n return Object.assign({ styleUrl }, styleMap[styleUrl]);\n }\n // For backward-compatibility. Should we still include\n // styleUrl even if it's not resolved?\n return { styleUrl };\n });\n}\n\nconst removeSpace = /\\s*/g;\nconst trimSpace = /^\\s*|\\s*$/g;\nconst splitSpace = /\\s+/;\n/**\n * Get one coordinate from a coordinate array, if any\n */\nfunction coord1(value) {\n return value\n .replace(removeSpace, \"\")\n .split(\",\")\n .map(parseFloat)\n .filter((num) => !isNaN(num))\n .slice(0, 3);\n}\n/**\n * Get all coordinates from a coordinate array as [[],[]]\n */\nfunction coord(value) {\n return value\n .replace(trimSpace, \"\")\n .split(splitSpace)\n .map(coord1)\n .filter((coord) => {\n return coord.length >= 2;\n });\n}\nfunction gxCoords(node) {\n let elems = $(node, \"coord\");\n if (elems.length === 0) {\n elems = $ns(node, \"coord\", \"*\");\n }\n const coordinates = elems.map((elem) => {\n return nodeVal(elem).split(\" \").map(parseFloat);\n });\n if (coordinates.length === 0) {\n return null;\n }\n return {\n geometry: coordinates.length > 2\n ? {\n type: \"LineString\",\n coordinates,\n }\n : {\n type: \"Point\",\n coordinates: coordinates[0],\n },\n times: $(node, \"when\").map((elem) => nodeVal(elem)),\n };\n}\nfunction fixRing(ring) {\n if (ring.length === 0)\n return ring;\n const first = ring[0];\n const last = ring[ring.length - 1];\n let equal = true;\n for (let i = 0; i < Math.max(first.length, last.length); i++) {\n if (first[i] !== last[i]) {\n equal = false;\n break;\n }\n }\n if (!equal) {\n return ring.concat([ring[0]]);\n }\n return ring;\n}\nfunction getCoordinates(node) {\n return nodeVal(get1(node, \"coordinates\"));\n}\nfunction getGeometry(node) {\n let geometries = [];\n let coordTimes = [];\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes.item(i);\n if (isElement(child)) {\n switch (child.tagName) {\n case \"MultiGeometry\":\n case \"MultiTrack\":\n case \"gx:MultiTrack\": {\n const childGeometries = getGeometry(child);\n geometries = geometries.concat(childGeometries.geometries);\n coordTimes = coordTimes.concat(childGeometries.coordTimes);\n break;\n }\n case \"Point\": {\n const coordinates = coord1(getCoordinates(child));\n if (coordinates.length >= 2) {\n geometries.push({\n type: \"Point\",\n coordinates,\n });\n }\n break;\n }\n case \"LinearRing\":\n case \"LineString\": {\n const coordinates = coord(getCoordinates(child));\n if (coordinates.length >= 2) {\n geometries.push({\n type: \"LineString\",\n coordinates,\n });\n }\n break;\n }\n case \"Polygon\": {\n const coords = [];\n for (const linearRing of $(child, \"LinearRing\")) {\n const ring = fixRing(coord(getCoordinates(linearRing)));\n if (ring.length >= 4) {\n coords.push(ring);\n }\n }\n if (coords.length) {\n geometries.push({\n type: \"Polygon\",\n coordinates: coords,\n });\n }\n break;\n }\n case \"Track\":\n case \"gx:Track\": {\n const gx = gxCoords(child);\n if (!gx)\n break;\n const { times, geometry } = gx;\n geometries.push(geometry);\n if (times.length)\n coordTimes.push(times);\n break;\n }\n }\n }\n }\n return {\n geometries,\n coordTimes,\n };\n}\n\nfunction geometryListToGeometry(geometries) {\n return geometries.length === 0\n ? null\n : geometries.length === 1\n ? geometries[0]\n : {\n type: \"GeometryCollection\",\n geometries,\n };\n}\nfunction getPlacemark(node, styleMap, schema, options) {\n const { coordTimes, geometries } = getGeometry(node);\n const geometry = geometryListToGeometry(geometries);\n if (!geometry && options.skipNullGeometry) {\n return null;\n }\n const feature = {\n type: \"Feature\",\n geometry,\n properties: Object.assign(getMulti(node, [\n \"name\",\n \"address\",\n \"visibility\",\n \"open\",\n \"phoneNumber\",\n \"description\",\n ]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length\n ? {\n coordinateProperties: {\n times: coordTimes.length === 1 ? coordTimes[0] : coordTimes,\n },\n }\n : {}),\n };\n if (feature.properties?.visibility !== undefined) {\n feature.properties.visibility = feature.properties.visibility !== \"0\";\n }\n const id = node.getAttribute(\"id\");\n if (id !== null && id !== \"\")\n feature.id = id;\n return feature;\n}\n\nfunction getGroundOverlayBox(node) {\n const latLonQuad = get1(node, \"gx:LatLonQuad\");\n if (latLonQuad) {\n const ring = fixRing(coord(getCoordinates(node)));\n return {\n geometry: {\n type: \"Polygon\",\n coordinates: [ring],\n },\n };\n }\n return getLatLonBox(node);\n}\nconst DEGREES_TO_RADIANS = Math.PI / 180;\nfunction rotateBox(bbox, coordinates, rotation) {\n const center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];\n return [\n coordinates[0].map((coordinate) => {\n const dy = coordinate[1] - center[1];\n const dx = coordinate[0] - center[0];\n const distance = Math.sqrt(Math.pow(dy, 2) + Math.pow(dx, 2));\n const angle = Math.atan2(dy, dx) + rotation * DEGREES_TO_RADIANS;\n return [\n center[0] + Math.cos(angle) * distance,\n center[1] + Math.sin(angle) * distance,\n ];\n }),\n ];\n}\nfunction getLatLonBox(node) {\n const latLonBox = get1(node, \"LatLonBox\");\n if (latLonBox) {\n const north = num1(latLonBox, \"north\");\n const west = num1(latLonBox, \"west\");\n const east = num1(latLonBox, \"east\");\n const south = num1(latLonBox, \"south\");\n const rotation = num1(latLonBox, \"rotation\");\n if (typeof north === \"number\" &&\n typeof south === \"number\" &&\n typeof west === \"number\" &&\n typeof east === \"number\") {\n const bbox = [west, south, east, north];\n let coordinates = [\n [\n [west, north],\n [east, north],\n [east, south],\n [west, south],\n [west, north], // top left (again)\n ],\n ];\n if (typeof rotation === \"number\") {\n coordinates = rotateBox(bbox, coordinates, rotation);\n }\n return {\n bbox,\n geometry: {\n type: \"Polygon\",\n coordinates,\n },\n };\n }\n }\n return null;\n}\nfunction getGroundOverlay(node, styleMap, schema, options) {\n const box = getGroundOverlayBox(node);\n const geometry = box?.geometry || null;\n if (!geometry && options.skipNullGeometry) {\n return null;\n }\n const feature = {\n type: \"Feature\",\n geometry,\n properties: Object.assign(\n /**\n * Related to\n * https://gist.github.com/tmcw/037a1cb6660d74a392e9da7446540f46\n */\n { \"@geometry-type\": \"groundoverlay\" }, getMulti(node, [\n \"name\",\n \"address\",\n \"visibility\",\n \"open\",\n \"phoneNumber\",\n \"description\",\n ]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractIconHref(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node)),\n };\n if (box?.bbox) {\n feature.bbox = box.bbox;\n }\n if (feature.properties?.visibility !== undefined) {\n feature.properties.visibility = feature.properties.visibility !== \"0\";\n }\n const id = node.getAttribute(\"id\");\n if (id !== null && id !== \"\")\n feature.id = id;\n return feature;\n}\n\nfunction getStyleId(style) {\n let id = style.getAttribute(\"id\");\n const parentNode = style.parentNode;\n if (!id &&\n isElement(parentNode) &&\n parentNode.localName === \"CascadingStyle\") {\n id = parentNode.getAttribute(\"kml:id\") || parentNode.getAttribute(\"id\");\n }\n return normalizeId(id || \"\");\n}\nfunction buildStyleMap(node) {\n const styleMap = {};\n for (const style of $(node, \"Style\")) {\n styleMap[getStyleId(style)] = extractStyle(style);\n }\n for (const map of $(node, \"StyleMap\")) {\n const id = normalizeId(map.getAttribute(\"id\") || \"\");\n val1(map, \"styleUrl\", (styleUrl) => {\n styleUrl = normalizeId(styleUrl);\n if (styleMap[styleUrl]) {\n styleMap[id] = styleMap[styleUrl];\n }\n });\n }\n return styleMap;\n}\nfunction buildSchema(node) {\n const schema = {};\n for (const field of $(node, \"SimpleField\")) {\n schema[field.getAttribute(\"name\") || \"\"] =\n typeConverters[field.getAttribute(\"type\") || \"\"] ||\n typeConverters[\"string\"];\n }\n return schema;\n}\nconst FOLDER_PROPS = [\n \"name\",\n \"visibility\",\n \"open\",\n \"address\",\n \"description\",\n \"phoneNumber\",\n \"visibility\",\n];\nfunction getFolder(node) {\n const meta = {};\n for (const child of Array.from(node.childNodes)) {\n if (isElement(child) && FOLDER_PROPS.includes(child.tagName)) {\n meta[child.tagName] = nodeVal(child);\n }\n }\n return {\n type: \"folder\",\n meta,\n children: [],\n };\n}\n/**\n * Yield a nested tree with KML folder structure\n *\n * This generates a tree with the given structure:\n *\n * ```js\n * {\n * \"type\": \"root\",\n * \"children\": [\n * {\n * \"type\": \"folder\",\n * \"meta\": {\n * \"name\": \"Test\"\n * },\n * \"children\": [\n * // ...features and folders\n * ]\n * }\n * // ...features\n * ]\n * }\n * ```\n *\n * ### GroundOverlay\n *\n * GroundOverlay elements are converted into\n * `Feature` objects with `Polygon` geometries,\n * a property like:\n *\n * ```json\n * {\n * \"@geometry-type\": \"groundoverlay\"\n * }\n * ```\n *\n * And the ground overlay's image URL in the `href`\n * property. Ground overlays will need to be displayed\n * with a separate method to other features, depending\n * on which map framework you're using.\n */\nfunction kmlWithFolders(node, options = {\n skipNullGeometry: false,\n}) {\n const styleMap = buildStyleMap(node);\n const schema = buildSchema(node);\n const tree = { type: \"root\", children: [] };\n function traverse(node, pointer, options) {\n if (isElement(node)) {\n switch (node.tagName) {\n case \"GroundOverlay\": {\n const placemark = getGroundOverlay(node, styleMap, schema, options);\n if (placemark) {\n pointer.children.push(placemark);\n }\n break;\n }\n case \"Placemark\": {\n const placemark = getPlacemark(node, styleMap, schema, options);\n if (placemark) {\n pointer.children.push(placemark);\n }\n break;\n }\n case \"Folder\": {\n const folder = getFolder(node);\n pointer.children.push(folder);\n pointer = folder;\n break;\n }\n }\n }\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n traverse(node.childNodes[i], pointer, options);\n }\n }\n }\n traverse(node, tree, options);\n return tree;\n}\n/**\n * Convert KML to GeoJSON incrementally, returning\n * a [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators)\n * that yields output feature by feature.\n */\nfunction* kmlGen(node, options = {\n skipNullGeometry: false,\n}) {\n const styleMap = buildStyleMap(node);\n const schema = buildSchema(node);\n for (const placemark of $(node, \"Placemark\")) {\n const feature = getPlacemark(placemark, styleMap, schema, options);\n if (feature)\n yield feature;\n }\n for (const groundOverlay of $(node, \"GroundOverlay\")) {\n const feature = getGroundOverlay(groundOverlay, styleMap, schema, options);\n if (feature)\n yield feature;\n }\n}\n/**\n * Convert a KML document to GeoJSON. The first argument, `doc`, must be a KML\n * document as an XML DOM - not as a string. You can get this using jQuery's default\n * `.ajax` function or using a bare XMLHttpRequest with the `.response` property\n * holding an XML DOM.\n *\n * The output is a JavaScript object of GeoJSON data. You can convert it to a string\n * with [JSON.stringify](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)\n * or use it directly in libraries.\n */\nfunction kml(node, options = {\n skipNullGeometry: false,\n}) {\n return {\n type: \"FeatureCollection\",\n features: Array.from(kmlGen(node, options)),\n };\n}\n\nexport { gpx, gpxGen, kml, kmlGen, kmlWithFolders, tcx, tcxGen };\n//# sourceMappingURL=togeojson.es.mjs.map\n","'use strict';\n\n/**\n * Based off of [the offical Google document](https://developers.google.com/maps/documentation/utilities/polylinealgorithm)\n *\n * Some parts from [this implementation](http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEncoder.js)\n * by [Mark McClure](http://facstaff.unca.edu/mcmcclur/)\n *\n * @module polyline\n */\n\nvar polyline = {};\n\nfunction py2_round(value) {\n // Google's polyline algorithm uses the same rounding strategy as Python 2, which is different from JS for negative values\n return Math.floor(Math.abs(value) + 0.5) * (value >= 0 ? 1 : -1);\n}\n\nfunction encode(current, previous, factor) {\n current = py2_round(current * factor);\n previous = py2_round(previous * factor);\n var coordinate = (current - previous) * 2;\n if (coordinate < 0) {\n coordinate = -coordinate - 1\n }\n var output = '';\n while (coordinate >= 0x20) {\n output += String.fromCharCode((0x20 | (coordinate & 0x1f)) + 63);\n coordinate /= 32;\n }\n output += String.fromCharCode((coordinate | 0) + 63);\n return output;\n}\n\n/**\n * Decodes to a [latitude, longitude] coordinates array.\n *\n * This is adapted from the implementation in Project-OSRM.\n *\n * @param {String} str\n * @param {Number} precision\n * @returns {Array}\n *\n * @see https://github.com/Project-OSRM/osrm-frontend/blob/master/WebContent/routing/OSRM.RoutingGeometry.js\n */\npolyline.decode = function(str, precision) {\n var index = 0,\n lat = 0,\n lng = 0,\n coordinates = [],\n shift = 0,\n result = 0,\n byte = null,\n latitude_change,\n longitude_change,\n factor = Math.pow(10, Number.isInteger(precision) ? precision : 5);\n\n // Coordinates have variable length when encoded, so just keep\n // track of whether we've hit the end of the string. In each\n // loop iteration, a single coordinate is decoded.\n while (index < str.length) {\n\n // Reset shift, result, and byte\n byte = null;\n shift = 1;\n result = 0;\n\n do {\n byte = str.charCodeAt(index++) - 63;\n result += (byte & 0x1f) * shift;\n shift *= 32;\n } while (byte >= 0x20);\n\n latitude_change = (result & 1) ? ((-result - 1) / 2) : (result / 2);\n\n shift = 1;\n result = 0;\n\n do {\n byte = str.charCodeAt(index++) - 63;\n result += (byte & 0x1f) * shift;\n shift *= 32;\n } while (byte >= 0x20);\n\n longitude_change = (result & 1) ? ((-result - 1) / 2) : (result / 2);\n\n lat += latitude_change;\n lng += longitude_change;\n\n coordinates.push([lat / factor, lng / factor]);\n }\n\n return coordinates;\n};\n\n/**\n * Encodes the given [latitude, longitude] coordinates array.\n *\n * @param {Array.>} coordinates\n * @param {Number} precision\n * @returns {String}\n */\npolyline.encode = function(coordinates, precision) {\n if (!coordinates.length) { return ''; }\n\n var factor = Math.pow(10, Number.isInteger(precision) ? precision : 5),\n output = encode(coordinates[0][0], 0, factor) + encode(coordinates[0][1], 0, factor);\n\n for (var i = 1; i < coordinates.length; i++) {\n var a = coordinates[i], b = coordinates[i - 1];\n output += encode(a[0], b[0], factor);\n output += encode(a[1], b[1], factor);\n }\n\n return output;\n};\n\nfunction flipped(coords) {\n var flipped = [];\n for (var i = 0; i < coords.length; i++) {\n var coord = coords[i].slice();\n flipped.push([coord[1], coord[0]]);\n }\n return flipped;\n}\n\n/**\n * Encodes a GeoJSON LineString feature/geometry.\n *\n * @param {Object} geojson\n * @param {Number} precision\n * @returns {String}\n */\npolyline.fromGeoJSON = function(geojson, precision) {\n if (geojson && geojson.type === 'Feature') {\n geojson = geojson.geometry;\n }\n if (!geojson || geojson.type !== 'LineString') {\n throw new Error('Input must be a GeoJSON LineString');\n }\n return polyline.encode(flipped(geojson.coordinates), precision);\n};\n\n/**\n * Decodes to a GeoJSON LineString geometry.\n *\n * @param {String} str\n * @param {Number} precision\n * @returns {Object}\n */\npolyline.toGeoJSON = function(str, precision) {\n var coords = polyline.decode(str, precision);\n return {\n type: 'LineString',\n coordinates: flipped(coords)\n };\n};\n\nif (typeof module === 'object' && module.exports) {\n module.exports = polyline;\n}\n","module.exports = (() => {\n 'use strict';\n\n const purgeProps = (obj, blacklist) => {\n if (obj) {\n let rs = Object.assign({}, obj);\n if (blacklist) {\n for (let prop of blacklist) {\n delete rs[prop];\n }\n }\n return rs;\n }\n return {};\n }\n\n const mergeProps = (obj1, obj2) => {\n obj1 = obj1 ? obj1 : {};\n obj2 = obj2 ? obj2 : {};\n return Object.assign(obj1, obj2);\n }\n\n const addPropToFeature = (f, k, v) => {\n if (f.properties && k && v) {\n f.properties[k] = v;\n }\n }\n\n const addPropToFeatures = (fs, k, v) => {\n for (let f of fs) {\n addPropToFeature(f, k, v);\n }\n }\n\n const first = a => a[0];\n const last = a => a[a.length - 1];\n const coordsToKey = a => a.join(',');\n\n const addToMap = (m, k, v) => {\n let a = m[k];\n if (a) {\n a.push(v);\n } else {\n m[k] = [v];\n }\n }\n\n const removeFromMap = (m, k, v) => {\n let a = m[k];\n let idx = null;\n if (a && (idx = a.indexOf(v)) >= 0) {\n a.splice(idx, 1);\n }\n }\n\n const getFirstFromMap = (m, k) => {\n let a = m[k];\n if (a && a.length > 0) {\n return a[0];\n }\n return null;\n }\n\n // need 3+ different points to form a ring, here using > 3 is 'coz a the first and the last points are actually the same\n const isRing = a => a.length > 3 && coordsToKey(first(a)) === coordsToKey(last(a));\n\n const ringDirection = (a, xIdx, yIdx) => {\n xIdx = xIdx || 0, yIdx = yIdx || 1;\n // get the index of the point which has the maximum x value\n let m = a.reduce((maxxIdx, v, idx) => a[maxxIdx][xIdx] > v[xIdx] ? maxxIdx : idx, 0);\n // 'coz the first point is virtually the same one as the last point, \n // we need to skip a.length - 1 for left when m = 0,\n // and skip 0 for right when m = a.length - 1;\n let l = m <= 0 ? a.length - 2 : m - 1, r = m >= a.length - 1 ? 1 : m + 1;\n let xa = a[l][xIdx], xb = a[m][xIdx], xc = a[r][xIdx];\n let ya = a[l][yIdx], yb = a[m][yIdx], yc = a[r][yIdx];\n let det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);\n return det < 0 ? 'clockwise' : 'counterclockwise';\n }\n\n const ptInsidePolygon = (pt, polygon, xIdx, yIdx) => {\n xIdx = xIdx || 0, yIdx = yIdx || 1;\n let result = false;\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n if ((polygon[i][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[j][xIdx] ||\n polygon[j][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[i][xIdx]) &&\n pt[yIdx] < (polygon[j][yIdx] - polygon[i][yIdx]) * (pt[xIdx] - polygon[i][xIdx]) / (polygon[j][xIdx] - polygon[i][xIdx]) + polygon[i][yIdx]) {\n result = !result;\n }\n\n }\n return result;\n }\n\n const strToFloat = el => el instanceof Array ? el.map(strToFloat) : parseFloat(el);\n\n class RefElements extends Map {\n constructor() {\n super();\n this.binders = [];\n }\n\n add(k, v) {\n if (!this.has(k)) {\n this.set(k, v);\n }\n // suppress duplcated key error\n // else\n // throw `Error: adding duplicated key '${k}' to RefElements`;\n }\n\n addBinder(binder) {\n this.binders.push(binder);\n }\n\n bindAll() {\n this.binders.forEach(binder => binder.bind());\n }\n }\n\n class LateBinder {\n constructor(container, valueFunc, ctx, args) {\n this.container = container;\n this.valueFunc = valueFunc;\n this.ctx = ctx;\n this.args = args;\n }\n\n bind() {\n let v = this.valueFunc.apply(this.ctx, this.args);\n if (this.container instanceof Array) {\n let idx = this.container.indexOf(this);\n if (idx >= 0) {\n let args = [idx, 1];\n if (v) {\n args.push(v);\n }\n [].splice.apply(this.container, args);\n }\n } else if (typeof this.container === 'object') {\n let k = Object.keys(this.container).find(v => this.container[v] === this);\n if (k) {\n if (v) {\n this.container[k] = v;\n } else {\n delete this.container[k];\n }\n }\n }\n }\n }\n\n class WayCollection extends Array {\n constructor() {\n super();\n this.firstMap = {};\n this.lastMap = {};\n }\n\n addWay(way) {\n way = way.toCoordsArray();\n if (way.length > 0) {\n this.push(way);\n addToMap(this.firstMap, coordsToKey(first(way)), way);\n addToMap(this.lastMap, coordsToKey(last(way)), way);\n }\n }\n\n toStrings() {\n let strings = [], way = null;\n while (way = this.shift()) {\n removeFromMap(this.firstMap, coordsToKey(first(way)), way);\n removeFromMap(this.lastMap, coordsToKey(last(way)), way);\n let current = way, next = null;\n do {\n let key = coordsToKey(last(current)), shouldReverse = false;\n\n next = getFirstFromMap(this.firstMap, key);\n if (!next) {\n next = getFirstFromMap(this.lastMap, key);\n shouldReverse = true;\n }\n\n if (next) {\n this.splice(this.indexOf(next), 1);\n removeFromMap(this.firstMap, coordsToKey(first(next)), next);\n removeFromMap(this.lastMap, coordsToKey(last(next)), next);\n if (shouldReverse) {\n // always reverse shorter one to save time\n if (next.length > current.length) {\n [current, next] = [next, current];\n }\n next.reverse();\n }\n\n current = current.concat(next.slice(1));\n }\n } while (next);\n strings.push(strToFloat(current));\n }\n\n return strings;\n }\n\n toRings(direction) {\n let strings = this.toStrings();\n let rings = [], string = null;\n while (string = strings.shift()) {\n if (isRing(string)) {\n if (ringDirection(string) !== direction) {\n string.reverse();\n }\n rings.push(string);\n }\n }\n return rings;\n }\n }\n\n return {\n purgeProps, mergeProps,\n first, last, coordsToKey,\n addToMap, removeFromMap, getFirstFromMap,\n isRing, ringDirection, ptInsidePolygon, strToFloat,\n RefElements, LateBinder, WayCollection\n };\n})();\n","module.exports = (() => {\n 'use strict';\n\n const { first, last, coordsToKey,\n addToMap, removeFromMap, getFirstFromMap,\n isRing, ringDirection, ptInsidePolygon, strToFloat,\n LateBinder, WayCollection } = require('./utils.js'),\n polygonTags = require('./polytags.json');\n\n class OsmObject {\n constructor(type, id, refElems) {\n this.type = type;\n this.id = id;\n this.refElems = refElems;\n this.tags = {};\n this.props = { id: this.getCompositeId() };\n this.refCount = 0;\n this.hasTag = false;\n if (refElems) {\n refElems.add(this.getCompositeId(), this);\n }\n }\n\n addTags(tags) {\n this.tags = Object.assign(this.tags, tags);\n this.hasTag = tags ? true : false;\n }\n\n addTag(k, v) {\n this.tags[k] = v;\n this.hasTag = k ? true : false;\n }\n\n addProp(k, v) {\n this.props[k] = v;\n }\n\n addProps(props) {\n this.props = Object.assign(this.props, props);\n }\n\n getCompositeId() {\n return `${this.type}/${this.id}`;\n }\n\n getProps() {\n return Object.assign(this.props, this.tags);\n }\n\n toFeatureArray() {\n return [];\n }\n }\n\n class Node extends OsmObject {\n constructor(id, refElems) {\n super('node', id, refElems);\n this.latLng = null;\n }\n\n setLatLng(latLng) {\n this.latLng = latLng;\n }\n\n toFeatureArray() {\n if (this.latLng) {\n return [{\n type: 'Feature',\n id: this.getCompositeId(),\n properties: this.getProps(),\n geometry: {\n type: 'Point',\n coordinates: strToFloat([this.latLng.lon, this.latLng.lat])\n }\n }];\n }\n\n return [];\n }\n\n getLatLng() {\n return this.latLng;\n }\n }\n\n class Way extends OsmObject {\n constructor(id, refElems) {\n super('way', id, refElems);\n this.latLngArray = [];\n this.isPolygon = false;\n }\n\n addLatLng(latLng) {\n this.latLngArray.push(latLng);\n }\n\n setLatLngArray(latLngArray) {\n this.latLngArray = latLngArray;\n }\n\n addNodeRef(ref) {\n let binder = new LateBinder(this.latLngArray, function (id) {\n let node = this.refElems.get(`node/${id}`);\n if (node) {\n node.refCount++;\n return node.getLatLng();\n }\n }, this, [ref]);\n\n this.latLngArray.push(binder);\n this.refElems.addBinder(binder);\n }\n\n analyzeGeometryType(k, v) {\n let o = polygonTags[k];\n if (o) {\n this.isPolygon = true;\n if (o.whitelist) {\n this.isPolygon = o.whitelist.indexOf(v) >= 0 ? true : false;\n } else if (o.blacklist) {\n this.isPolygon = o.blacklist.indexOf(v) >= 0 ? false : true;\n }\n }\n }\n\n addTags(tags) {\n super.addTags(tags);\n for (let [k, v] of Object.entries(tags)) {\n this.analyzeGeometryType(k, v);\n }\n }\n\n addTag(k, v) {\n super.addTag(k, v);\n this.analyzeGeometryType(k, v);\n }\n\n toCoordsArray() {\n return this.latLngArray.map(latLng => [latLng.lon, latLng.lat]);\n }\n\n toFeatureArray() {\n let coordsArray = this.toCoordsArray();\n if (coordsArray.length > 1) {\n coordsArray = strToFloat(coordsArray);\n let feature = {\n type: 'Feature',\n id: this.getCompositeId(),\n properties: this.getProps(),\n geometry: {\n type: 'LineString',\n coordinates: coordsArray\n }\n };\n\n if (this.isPolygon && isRing(coordsArray)) {\n if (ringDirection(coordsArray) !== 'counterclockwise') {\n coordsArray.reverse();\n }\n\n feature.geometry = {\n type: 'Polygon',\n coordinates: [coordsArray]\n };\n\n return [feature];\n }\n\n return [feature];\n }\n\n return [];\n }\n }\n\n class Relation extends OsmObject {\n constructor(id, refElems) {\n super('relation', id, refElems);\n this.relations = [];\n this.nodes = [];\n this.bounds = null;\n }\n\n setBounds(bounds) {\n this.bounds = bounds;\n }\n\n addMember(member) {\n switch (member.type) {\n // super relation, need to do combination\n case 'relation':\n let binder = new LateBinder(this.relations, function (id) {\n let relation = this.refElems.get(`relation/${id}`);\n if (relation) {\n relation.refCount++;\n return relation;\n }\n }, this, [member.ref]);\n this.relations.push(binder);\n this.refElems.addBinder(binder);\n break;\n\n case 'way':\n if (!member.role) {\n member.role = '';\n }\n let ways = this[member.role];\n if (!ways) {\n ways = this[member.role] = [];\n }\n if (member.geometry) {\n let way = new Way(member.ref, this.refElems);\n way.setLatLngArray(member.geometry);\n way.refCount++;\n ways.push(way);\n } else if (member.nodes) {\n let way = new Way(member.ref, this.refElems);\n for (let nid of member.nodes) {\n way.addNodeRef(nid);\n }\n way.refCount++;\n ways.push(way);\n } else {\n let binder = new LateBinder(ways, function (id) {\n let way = this.refElems.get(`way/${id}`);\n if (way) {\n way.refCount++;\n return way;\n }\n }, this, [member.ref]);\n ways.push(binder);\n this.refElems.addBinder(binder);\n }\n break;\n\n case 'node':\n let node = null;\n if (member.lat && member.lon) {\n node = new Node(member.ref, this.refElems);\n node.setLatLng({ lon: member.lon, lat: member.lat });\n if (member.tags) {\n node.addTags(member.tags);\n }\n for (let [k, v] of Object.entries(member)) {\n if (['id', 'type', 'lat', 'lon'].indexOf(k) < 0) {\n node.addProp(k, v);\n }\n }\n\n node.refCount++;\n this.nodes.push(node);\n } else {\n let binder = new LateBinder(this.nodes, function (id) {\n let node = this.refElems.get(`node/${id}`);\n if (node) {\n node.refCount++;\n return node;\n }\n }, this, [member.ref]);\n this.nodes.push(binder);\n this.refElems.addBinder(binder);\n }\n break;\n\n default:\n break;\n }\n }\n\n toFeatureArray() {\n const constructStringGeometry = (ws) => {\n let strings = ws ? ws.toStrings() : [];\n if (strings.length > 0) {\n if (strings.length === 1) return {\n type: 'LineString',\n coordinates: strings[0]\n }\n\n return {\n type: 'MultiLineString',\n coordinates: strings\n }\n }\n return null;\n }\n\n const constructPolygonGeometry = (ows, iws) => {\n let outerRings = ows ? ows.toRings('counterclockwise') : [],\n innerRings = iws ? iws.toRings('clockwise') : [];\n\n if (outerRings.length > 0) {\n let compositPolyons = [];\n\n let ring = null;\n for (ring of outerRings)\n compositPolyons.push([ring]);\n\n // link inner polygons to outer containers\n while (ring = innerRings.shift()) {\n for (let idx in outerRings) {\n if (ptInsidePolygon(first(ring), outerRings[idx])) {\n compositPolyons[idx].push(ring);\n break;\n }\n }\n }\n\n // construct the Polygon/MultiPolygon geometry\n if (compositPolyons.length === 1) {\n return {\n type: 'Polygon',\n coordinates: compositPolyons[0]\n };\n }\n\n return {\n type: 'MultiPolygon',\n coordinates: compositPolyons\n }\n }\n\n return null;\n }\n\n let polygonFeatures = [], stringFeatures = [], pointFeatures = [];\n const waysFieldNames = ['outer', 'inner', ''];\n // need to do combination when there're nested relations\n for (let relation of this.relations) {\n if (relation) {\n for (let fieldName of waysFieldNames) {\n let ways = relation[fieldName];\n if (ways) {\n let thisWays = this[fieldName];\n if (thisWays) {\n [].splice.apply(thisWays, [thisWays.length, 0].concat(ways));\n } else {\n this[fieldName] = ways;\n }\n }\n }\n }\n }\n\n for (let fieldName of waysFieldNames) {\n let ways = this[fieldName];\n if (ways) {\n this[fieldName] = new WayCollection();\n for (let way of ways) {\n this[fieldName].addWay(way);\n }\n }\n }\n\n let geometry = null;\n\n let feature = {\n type: 'Feature',\n id: this.getCompositeId(),\n bbox: this.bounds,\n properties: this.getProps()\n };\n\n if (!this.bounds) {\n delete feature.bbox;\n }\n\n if (this.outer) {\n geometry = constructPolygonGeometry(this.outer, this.inner);\n if (geometry) {\n feature.geometry = geometry;\n polygonFeatures.push(feature);\n }\n }\n else if (this['']) {\n geometry = constructStringGeometry(this['']);\n if (geometry) {\n feature.geometry = geometry;\n stringFeatures.push(feature);\n }\n }\n\n for (let node of this.nodes) {\n pointFeatures = pointFeatures.concat(node.toFeatureArray());\n }\n\n return polygonFeatures.concat(stringFeatures).concat(pointFeatures);\n }\n }\n\n return { Node, Way, Relation };\n})();","module.exports = (() => {\n 'use strict';\n\n function conditioned(evt) {\n return evt.match(/^(.+?)\\[(.+?)\\]>$/g) != null;\n }\n\n function parseEvent(evt) {\n let match = /^(.+?)\\[(.+?)\\]>$/g.exec(evt);\n if (match) {\n return { evt: match[1] + '>', exp: match[2] };\n }\n return { evt: evt };\n }\n\n function genConditionFunc(cond) {\n let body = 'return ' + cond.replace(/(\\$.+?)(?=[=!.])/g, 'node.$&') + ';';\n return new Function('node', body);\n }\n\n return class {\n constructor(opts) {\n if (opts) {\n this.queryParent = opts.queryParent ? true : false;\n this.progressive = opts.progressive;\n if (this.queryParent) {\n this.parentMap = new WeakMap();\n }\n }\n this.evtListeners = {};\n }\n\n parse(xml, parent, dir) {\n dir = dir ? dir + '.' : '';\n let nodeRegEx = /<([^ >\\/]+)(.*?)>/mg, nodeMatch = null, nodes = [];\n while (nodeMatch = nodeRegEx.exec(xml)) {\n let tag = nodeMatch[1], node = { $tag: tag }, fullTag = dir + tag;\n\n let attrText = nodeMatch[2].trim(), closed = false;\n if (attrText.endsWith('/') || tag.startsWith('?') || tag.startsWith('!')) {\n closed = true;\n }\n\n let attRegEx1 = /([^ ]+?)=\"(.+?)\"/g, attRegEx2 = /([^ ]+?)='(.+?)'/g;\n let attMatch = null, hasAttrs = false;\n while (attMatch = attRegEx1.exec(attrText)) {\n hasAttrs = true;\n node[attMatch[1]] = attMatch[2];\n }\n if (!hasAttrs)\n while (attMatch = attRegEx2.exec(attrText)) {\n hasAttrs = true;\n node[attMatch[1]] = attMatch[2];\n }\n\n if (!hasAttrs && attrText !== '') {\n node.text = attrText;\n }\n if (this.progressive) {\n this.emit(`<${fullTag}>`, node, parent);\n }\n\n if (!closed) {\n let innerRegEx = new RegExp(`([^]+?)<\\/${tag}>`, 'g');\n innerRegEx.lastIndex = nodeRegEx.lastIndex;\n let innerMatch = innerRegEx.exec(xml);\n if (innerMatch && innerMatch[1]) {\n nodeRegEx.lastIndex = innerRegEx.lastIndex;\n let innerNodes = this.parse(innerMatch[1], node, fullTag);\n if (innerNodes.length > 0) {\n node.$innerNodes = innerNodes;\n } else {\n node.$innerText = innerMatch[1];\n }\n }\n }\n if (this.queryParent && parent) {\n this.parentMap.set(node, parent);\n }\n\n if (this.progressive) {\n this.emit(``, node, parent);\n }\n\n nodes.push(node);\n }\n\n return nodes;\n }\n\n getParent(node) {\n if (this.queryParent) {\n return this.parentMap.get(node);\n }\n return null;\n }\n\n #addListener(evt, func) {\n let funcs = this.evtListeners[evt];\n if (funcs) {\n funcs.push(func);\n } else {\n this.evtListeners[evt] = [func];\n }\n }\n\n // support javascript condition for the last tag\n addListener(evt, func) {\n if (conditioned(evt)) {\n // func.prototype = evt;\n evt = parseEvent(evt);\n func.condition = genConditionFunc(evt.exp);\n evt = evt.evt;\n }\n this.#addListener(evt, func);\n }\n\n #removeListener(evt, func) {\n let funcs = this.evtListeners[evt];\n let idx = null;\n if (funcs && (idx = funcs.indexOf(func)) >= 0) {\n funcs.splice(idx, 1);\n }\n }\n\n removeListener(evt, func) {\n if (conditioned(evt)) {\n evt = parseEvent(evt);\n evt = evt.evt;\n }\n this.#removeListener(evt, func);\n }\n\n emit(evt, ...args) {\n let funcs = this.evtListeners[evt];\n if (funcs) {\n for (let func of funcs) {\n if (func.condition) {\n if (func.condition.apply(null, args) === true) {\n func.apply(null, args);\n }\n } else {\n func.apply(null, args);\n }\n }\n }\n }\n\n on(evt, func) {\n this.addListener(evt, func);\n }\n\n off(evt, func) {\n this.removeListener(evt, func);\n }\n };\n})();","const { Node, Way, Relation } = require('./osmobjs.js'),\n { purgeProps, RefElements } = require('./utils.js'),\n XmlParser = require('./xmlparser.js');\n\nmodule.exports = (osm, opts) => {\n let completeFeature = false, renderTagged = false, excludeWay = true;\n\n const parseOpts = opts => {\n if (opts) {\n completeFeature = opts.completeFeature || opts.allFeatures ? true : false;\n renderTagged = opts.renderTagged ? true : false;\n let wayOpt = opts.suppressWay || opts.excludeWay;\n if (wayOpt !== undefined && !wayOpt) {\n excludeWay = false;\n }\n }\n }\n\n parseOpts(opts);\n\n const detectFormat = osm => {\n if (osm.elements) {\n return 'json';\n }\n if (osm.indexOf('= 0) {\n return 'xml';\n }\n if (osm.trim().startsWith('{')) {\n return 'json-raw';\n }\n return 'invalid';\n }\n\n let format = detectFormat(osm);\n\n let refElements = new RefElements(), featureArray = [];\n\n const analyzeFeaturesFromJson = osm => {\n for (let elem of osm.elements) {\n switch (elem.type) {\n case 'node':\n let node = new Node(elem.id, refElements);\n if (elem.tags) {\n node.addTags(elem.tags);\n }\n node.addProps(purgeProps(elem, ['id', 'type', 'tags', 'lat', 'lon']));\n node.setLatLng(elem);\n break;\n\n case 'way':\n let way = new Way(elem.id, refElements);\n if (elem.tags) {\n way.addTags(elem.tags);\n }\n way.addProps(purgeProps(elem, ['id', 'type', 'tags', 'nodes', 'geometry']));\n if (elem.nodes) {\n for (let n of elem.nodes) {\n way.addNodeRef(n);\n }\n } else if (elem.geometry) {\n way.setLatLngArray(elem.geometry);\n }\n break;\n\n case 'relation':\n let relation = new Relation(elem.id, refElements);\n if (elem.bounds) {\n relation.setBounds([parseFloat(elem.bounds.minlon), parseFloat(elem.bounds.minlat), parseFloat(elem.bounds.maxlon), parseFloat(elem.bounds.maxlat)]);\n }\n if (elem.tags) {\n relation.addTags(elem.tags);\n }\n relation.addProps(purgeProps(elem, ['id', 'type', 'tags', 'bounds', 'members']));\n if (elem.members) {\n for (let member of elem.members) {\n relation.addMember(member);\n }\n }\n break;\n\n default:\n break;\n }\n }\n }\n\n const analyzeFeaturesFromXml = osm => {\n const xmlParser = new XmlParser({ progressive: true });\n\n xmlParser.on('', node => {\n let nd = new Node(node.id, refElements);\n for (let [k, v] of Object.entries(node))\n if (!k.startsWith('$') && ['id', 'lon', 'lat'].indexOf(k) < 0) {\n nd.addProp(k, v);\n }\n nd.setLatLng(node);\n if (node.$innerNodes) {\n for (let ind of node.$innerNodes) {\n if (ind.$tag === 'tag') {\n nd.addTag(ind.k, ind.v);\n }\n }\n }\n });\n\n xmlParser.on('', node => {\n let way = new Way(node.id, refElements);\n for (let [k, v] of Object.entries(node)) {\n if (!k.startsWith('$') && ['id'].indexOf(k) < 0) {\n way.addProp(k, v);\n }\n }\n if (node.$innerNodes) {\n for (let ind of node.$innerNodes) {\n if (ind.$tag === 'nd') {\n if (ind.lon && ind.lat) {\n way.addLatLng(ind);\n } else if (ind.ref) {\n way.addNodeRef(ind.ref);\n }\n } else if (ind.$tag === 'tag')\n way.addTag(ind.k, ind.v);\n }\n }\n });\n\n xmlParser.on('', node => {\n new Relation(node.id, refElements);\n });\n\n xmlParser.on('', (node, parent) => {\n let relation = refElements.get(`relation/${parent.id}`);\n let member = {\n type: node.type,\n role: node.role ? node.role : '',\n ref: node.ref\n };\n if (node.lat && node.lon) {\n member.lat = node.lat, member.lon = node.lon, member.tags = {};\n for (let [k, v] of Object.entries(node)) {\n if (!k.startsWith('$') && ['type', 'lat', 'lon'].indexOf(k) < 0) {\n member[k] = v;\n }\n }\n }\n if (node.$innerNodes) {\n let geometry = [];\n let nodes = [];\n for (let ind of node.$innerNodes) {\n if (ind.lat && ind.lon) {\n geometry.push(ind);\n } else {\n nodes.push(ind.ref);\n }\n }\n if (geometry.length > 0) {\n member.geometry = geometry;\n } else if (nodes.length > 0) {\n member.nodes = nodes;\n }\n }\n relation.addMember(member);\n });\n\n xmlParser.on('', (node, parent) => {\n refElements.get(`relation/${parent.id}`).setBounds([parseFloat(node.minlon), parseFloat(node.minlat), parseFloat(node.maxlon), parseFloat(node.maxlat)]);\n });\n\n xmlParser.on('', (node, parent) => {\n refElements.get(`relation/${parent.id}`).addTag(node.k, node.v);\n });\n\n xmlParser.parse(osm);\n }\n\n if (format === 'json-raw') {\n osm = JSON.parse(osm);\n if (osm.elements) {\n format = 'json';\n } else {\n format = 'invalid';\n }\n }\n\n if (format === 'json') {\n analyzeFeaturesFromJson(osm);\n } else if (format === 'xml') {\n analyzeFeaturesFromXml(osm);\n }\n\n refElements.bindAll();\n\n for (let v of refElements.values()) {\n if (v.refCount <= 0 || (v.hasTag && renderTagged && !(v instanceof Way && excludeWay))) {\n let features = v.toFeatureArray();\n // return the first geometry of the first relation element\n if (v instanceof Relation && !completeFeature && features.length > 0) {\n return features[0].geometry;\n }\n featureArray = featureArray.concat(features);\n }\n }\n\n return { type: 'FeatureCollection', features: featureArray };\n}\n"],"names":["objectConverter","columns","Function","map","name","i","JSON","stringify","join","dsv$1","delimiter","reFormat","RegExp","delimiterCode","charCodeAt","parseRows","text","f","t","eol","EOL","EOF","rows","N","length","I","n","token","c","j","slice","replace","k","a","push","formatRow","row","formatValue","test","parse","convert","object","customConverter","format","columnSet","Object","create","forEach","column","inferColumns","concat","formatRows","csv","dsv","csvParse","csvParseRows","csvFormat","csvFormatRows","tsv","tsvParse","tsvParseRows","tsvFormat","tsvFormatRows","input","dim","dms","coordToDMS","whole","minutes","seconds","dir","lat","lon","abs","Math","floor","fractionMinutes","search","dims","m","toUpperCase","match","matched","indexOf","deg","parseFloat","min","sec","sign","val","remain","sexagesimalModule","exports","result","pair","one","trim","two","b","swapdim","formatPair","require$$0","sexagesimal","require$$1","latRegex","lonRegex","guessHeader","regexp","score","guessLatHeader","guessLonHeader","keyCount","o","keys","autoDelimiter","x","results","res","dsvFormat","count","arity","sort","csv2geojson_1","isLon","isLat","auto","deleteColumns","csv2geojson","options","callback","latfield","lonfield","crs","features","featurecollection","type","properties","numericFields","split","parsed","d","key","includes","errors","geometry","undefined","lonf","latf","lonk","latk","isNaN","message","index","includeLatLon","coordinates","toLine","gj","line","reduce","aggregatedProperties","newFeature","toPolygon","poly","identity","feature","topology","id","bbox","transformPoint","transform","x0","y0","kx","scale","ky","dx","translate","dy","output","Array","arcs","arc","points","pop","array","reverse","point","p","ring","polygon","geometries","$","element","tagName","from","getElementsByTagName","normalizeId","nodeVal","node","normalize","textContent","get1","get","val1","$num","num1","getMulti","propertyNames","property","isElement","nodeType","getLineStyle","lineStyle","assign","color","stroke","opacity","width","getExtensions","values","child","childNodes","abbreviateName","nodeName","parseNumeric","num","coordPair$1","ll","getAttribute","time","extendedValues","extractProperties","extensions","getElementsByTagNameNS","parentNode","links","link","href","getPoints$1","pointname","pts","times","plural","fill","getRoute","_gpxType","getTrack","segments","track","extractedLines","segment","multi","coordinateProperties","props","entries","getPoint","gpxGen","route","waypoint","EXTENSIONS_NS","TRACKPOINT_ATTRIBUTES","LAP_ATTRIBUTES","getProperties","attributeNames","tag","alias","elem","elements","coordPair","heartRate","alt","getPoints","heartRates","extendedProperties","value","getLap","allExtendedProperties","fromEntries","nameElement","heart","tcxGen","lap","course","fixColor","v","prefix","colorProp","substring","parseInt","numericProperty","source","target","getColor","extractIconHref","icon","extractStyle","polyStyle","outline","extractPoly","extractLine","labelStyle","extractLabel","iconStyle","hotspot","left","top","xunits","yunits","extractIcon","toNumber","Number","typeConverters","string","int","uint","short","ushort","float","double","bool","Boolean","extractExtendedData","schema","extendedData","data","simpleData","typeConverter","getMaybeHTMLDescription","descriptionNode","description","extractTimeSpan","timeSpan","timespan","begin","end","extractTimeStamp","timeStamp","timestamp","extractCascadedStyle","styleMap","styleUrl","removeSpace","trimSpace","splitSpace","coord1","filter","coord","gxCoords","elems","ns","$ns","fixRing","first","last","equal","max","getCoordinates","getGeometry","coordTimes","item","childGeometries","coords","linearRing","gx","getPlacemark","geometryListToGeometry","skipNullGeometry","visibility","getGroundOverlayBox","latLonBox","north","west","east","south","rotation","center","coordinate","distance","sqrt","pow","angle","atan2","DEGREES_TO_RADIANS","cos","sin","rotateBox","getLatLonBox","PI","getGroundOverlay","box","getStyleId","style","localName","buildStyleMap","buildSchema","field","FOLDER_PROPS","kmlGen","placemark","groundOverlay","tree","children","traverse","pointer","folder","meta","getFolder","polyline","py2_round","encode","current","previous","factor","String","fromCharCode","flipped","decode","str","precision","latitude_change","lng","shift","byte","isInteger","fromGeoJSON","geojson","Error","toGeoJSON","module","utils","coordsToKey","addToMap","removeFromMap","idx","splice","getFirstFromMap","isRing","ringDirection","xIdx","yIdx","maxxIdx","l","r","xa","xb","xc","ya","yb","strToFloat","el","RefElements","Map","constructor","super","this","binders","add","has","set","addBinder","binder","bindAll","bind","purgeProps","obj","blacklist","rs","prop","mergeProps","obj1","obj2","ptInsidePolygon","pt","LateBinder","container","valueFunc","ctx","args","apply","find","WayCollection","firstMap","lastMap","addWay","way","toCoordsArray","toStrings","strings","next","shouldReverse","toRings","direction","rings","osmobjs","polygonTags","OsmObject","refElems","tags","getCompositeId","refCount","hasTag","addTags","addTag","addProp","addProps","getProps","toFeatureArray","Node","latLng","setLatLng","getLatLng","Way","latLngArray","isPolygon","addLatLng","setLatLngArray","addNodeRef","ref","analyzeGeometryType","whitelist","coordsArray","Relation","relations","nodes","bounds","setBounds","addMember","member","relation","role","ways","nid","polygonFeatures","stringFeatures","pointFeatures","waysFieldNames","fieldName","thisWays","outer","ows","iws","outerRings","innerRings","compositPolyons","constructPolygonGeometry","inner","ws","constructStringGeometry","xmlparser","conditioned","evt","parseEvent","exec","exp","opts","queryParent","progressive","parentMap","WeakMap","evtListeners","xml","parent","nodeRegEx","nodeMatch","$tag","fullTag","attrText","closed","endsWith","startsWith","attRegEx1","attRegEx2","attMatch","hasAttrs","emit","innerRegEx","lastIndex","innerMatch","innerNodes","$innerNodes","$innerText","getParent","addListener","func","funcs","condition","cond","body","genConditionFunc","removeListener","on","off","XmlParser","require$$2","lib","osm","completeFeature","renderTagged","excludeWay","allFeatures","wayOpt","suppressWay","parseOpts","detectFormat","refElements","featureArray","minlon","minlat","maxlon","maxlat","members","analyzeFeaturesFromJson","xmlParser","nd","ind","analyzeFeaturesFromXml","objects"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]} -------------------------------------------------------------------------------- /dist/src/converter.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { FeatureCollection, GeoJsonProperties } from 'geojson'; 3 | import * as csv2geojson from 'csv2geojson'; 4 | export declare const supportedFormats: readonly ["topojson", "osm", "kml", "gpx", "tcx", "csv", "tsv", "polyline"]; 5 | export type supportedFormatsType = typeof supportedFormats[number]; 6 | export type supportedOptions = { 7 | csvOptions?: csv2geojson.csvOptions; 8 | polylineOptions?: { 9 | precision?: number; 10 | properties?: GeoJsonProperties; 11 | type?: 'point' | 'line' | 'polygon'; 12 | }; 13 | }; 14 | export declare class Converter { 15 | _conversionFn: () => Promise; 16 | _rawData: string; 17 | _format: supportedFormatsType; 18 | _options: supportedOptions; 19 | constructor(format: supportedFormatsType, data: string, options?: supportedOptions); 20 | /** 21 | * Creates a blank GeoJSON feature collection. 22 | * @returns A new GeoJSON feature collection with no features. 23 | */ 24 | blankGeoJSON: () => FeatureCollection; 25 | convert(): Promise; 26 | /** 27 | * Load the XML data as GeoJSON 28 | * @returns A promise resolving to a GeoJSON FeatureCollection 29 | */ 30 | loadXml(): Promise; 31 | /** 32 | * Loads and parses CSV data into a GeoJSON FeatureCollection. 33 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 34 | */ 35 | loadCsv(): Promise; 36 | /** 37 | * Loads TopoJSON data and converts it into a GeoJSON FeatureCollection 38 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 39 | */ 40 | loadTopoJson(): Promise; 41 | /** 42 | * Loads OSM data and converts it into a GeoJSON FeatureCollection 43 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 44 | */ 45 | loadOsm(): Promise; 46 | /** 47 | * Loads and parses Polyline data into a GeoJSON FeatureCollection. 48 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 49 | */ 50 | loadPolyline(): Promise; 51 | } 52 | //# sourceMappingURL=converter.d.ts.map -------------------------------------------------------------------------------- /dist/src/converter.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/converter.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAwB,MAAM,SAAS,CAAC;AAErF,OAAO,KAAK,WAAW,MAAM,aAAa,CAAC;AAM3C,eAAO,MAAM,gBAAgB,6EAA8E,CAAC;AAC5G,MAAM,MAAM,oBAAoB,GAAG,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC3B,UAAU,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC;IACpC,eAAe,CAAC,EAAE;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,iBAAiB,CAAC;QAC/B,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;KACtC,CAAA;CACJ,CAAC;AAEF,qBAAa,SAAS;IAClB,aAAa,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,EAAE,gBAAgB,CAAC;gBAEf,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAmBtF;;;OAGG;IACH,YAAY,EAAE,MAAM,iBAAiB,CAGlC;IAEG,OAAO;IAQb;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAS3C;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA0B3C;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA4BhD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAI3C;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,iBAAiB,CAAC;CA+CnD"} -------------------------------------------------------------------------------- /dist/src/index.d.ts: -------------------------------------------------------------------------------- 1 | import { RequestParameters, default as MapLibrary, GetResourceResponse } from 'maplibre-gl'; 2 | import { FeatureCollection } from 'geojson'; 3 | import { supportedFormatsType, supportedOptions } from './converter'; 4 | /** 5 | * The processData function accepts a URL, prefix, and an optional controller 6 | * and tries to read and convert the data 7 | * @param url - The URL of the resource. 8 | * @param prefix - The prefix used to process the data 9 | * @param controller - optional controller that can be used to cancel a request 10 | * @returns A geojson FeatureCollection (or undefined) 11 | */ 12 | export declare function processData(url: string, prefix: supportedFormatsType, controller?: AbortController): Promise; 13 | /** 14 | * Selects the appropriate Vector Text Protocol version based on the type of controller provided. 15 | * 16 | * @param requestParameters - The parameters for the request including the URL. 17 | * @param controller - Either an AbortController or a callback function. 18 | * @returns Either a Promise for V4 or an object with a cancel method for V3. 19 | */ 20 | export declare const VectorTextProtocol: (requestParameters: RequestParameters, controller: AbortController | ((e: string | null, d?: FeatureCollection) => void)) => Promise> | { 21 | cancel: () => void; 22 | }; 23 | /** 24 | * Add options to a URL for the Vector Text Protocol. 25 | * 26 | * @param url - The URL to add options to. 27 | * @param options - The options to add to the URL. 28 | * @returns A string with the updated URL. 29 | */ 30 | export declare const addOptions: (url: string | URL, options: supportedOptions) => string | URL; 31 | /** 32 | * Add the vector text protocol to a map library for each supported format. 33 | * @param mapLibrary - The MapLibrary object to add the protocols to. 34 | */ 35 | export declare const addProtocols: (mapLibrary: typeof MapLibrary) => void; 36 | export declare const vectorFormats: readonly ["topojson", "osm", "kml", "gpx", "tcx", "csv", "tsv", "polyline"]; 37 | export { supportedFormatsType } from './converter'; 38 | //# sourceMappingURL=index.d.ts.map -------------------------------------------------------------------------------- /dist/src/index.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,EACjB,OAAO,IAAI,UAAU,EACrB,mBAAmB,EACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAa,oBAAoB,EAAoB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAuBlG;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAuCjJ;AAsED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,sBACR,iBAAiB,cACxB,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC,KAClF,QAAQ,oBAAoB,iBAAiB,GAAG,SAAS,CAAC,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,IAAI,CAAA;CAMpF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAS,MAAM,GAAG,GAAG,WAAW,gBAAgB,iBActE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,eAAgB,iBAAiB,SAIzD,CAAC;AAEF,eAAO,MAAM,aAAa,6EAAmB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"} -------------------------------------------------------------------------------- /dist/src/worker/actor.d.ts: -------------------------------------------------------------------------------- 1 | import type { SubClasses } from './worker'; 2 | export declare class Actor { 3 | subClass: any; 4 | worker: Worker; 5 | handlers: Map void; 7 | 'reject': (value: Error) => void; 8 | }>; 9 | initId: string; 10 | _: Record | undefined; 11 | /** 12 | * Creates a new instance of the `Actor` class. 13 | * @param subClass - The name of the subclass. 14 | * @param args - The arguments to pass to the subclass constructor. 15 | */ 16 | constructor(subClass: SubClasses, args: Array); 17 | /** 18 | * Waits for the initialization of the object to complete and returns the resulting object. 19 | * @returns A promise that resolves with the initialized object. 20 | */ 21 | onLoad(): Promise; 22 | /** 23 | * returns a Promise for a given command that will be executed in a worker. 24 | * @param command - The command to execute. 25 | * @returns A Promise that resolves with the result of the command execution or rejects with an error. 26 | */ 27 | exec(command: string): (...args: any[]) => Promise; 28 | /** 29 | * Returns a Promise that resolves with the result of a command sent to a Web Worker. 30 | * @param command - The command to send to the Web Worker. 31 | * @returns A Promise that resolves with the result of the command. 32 | */ 33 | get(command: string): Promise; 34 | } 35 | //# sourceMappingURL=actor.d.ts.map -------------------------------------------------------------------------------- /dist/src/worker/actor.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"actor.d.ts","sourceRoot":"","sources":["../../../src/worker/actor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,UAAU,CAAC;AAExD,qBAAa,KAAK;IACd,QAAQ,EAAE,GAAG,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE;QAClB,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;QAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;KACnC,CAAC,CAAC;IACH,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;IAExC;;;;OAIG;gBACS,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IAiDlD;;;OAGG;IACH,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC;IAatB;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;IAuBvD;;;;OAIG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAiBrC"} -------------------------------------------------------------------------------- /dist/src/worker/worker.d.ts: -------------------------------------------------------------------------------- 1 | export interface MessageData { 2 | 'type': 'response' | 'error' | 'init' | 'exec' | 'get' | 'init_response'; 3 | 'id': string; 4 | 'message': Array; 5 | 'error'?: Error; 6 | 'command': string; 7 | } 8 | declare const subClasses: readonly ["Converter"]; 9 | export type SubClasses = typeof subClasses[number]; 10 | export {}; 11 | //# sourceMappingURL=worker.d.ts.map -------------------------------------------------------------------------------- /dist/src/worker/worker.d.ts.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/worker/worker.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,eAAe,CAAC;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,QAAA,MAAM,UAAU,wBAAyB,CAAC;AAC1C,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC"} -------------------------------------------------------------------------------- /examples/data/beach_ave.gpx: -------------------------------------------------------------------------------- 1 | 2 | Filtered OSM data converted to GPX by overpass turboBeach Avenuealt_name=County Highway 604 3 | highway=tertiary 4 | lanes=2 5 | lit=yes 6 | name=Beach Avenue 7 | oneway=no 8 | ref=CR 604 9 | source:name=survey 10 | surface=asphalt 11 | tiger:cfcc=A41 12 | tiger:county=Cape May, NJ 13 | tiger:name_base=Beach 14 | tiger:name_base_1=County Highway 604 15 | tiger:name_type=Dr 16 | tiger:zip_left=08204 17 | tiger:zip_right=08204Beach Avenuealt_name=County Highway 604 18 | highway=tertiary 19 | lanes=2 20 | maxspeed=25 mph 21 | name=Beach Avenue 22 | ref=CR 604 23 | surface=asphalt 24 | survey:date=2015-10-17 25 | tiger:cfcc=A41 26 | tiger:county=Cape May, NJ 27 | tiger:name_base=Beach 28 | tiger:name_base_1=County Highway 604 29 | tiger:name_type=Dr 30 | tiger:zip_left=08204 31 | tiger:zip_right=08204Beach Avenuealt_name=County Highway 604 32 | highway=tertiary 33 | lanes=2 34 | maxspeed=25 mph 35 | name=Beach Avenue 36 | ref=CR 604 37 | surface=asphalt 38 | tiger:cfcc=A41 39 | tiger:county=Cape May, NJ 40 | tiger:name_base=Beach 41 | tiger:name_base_1=County Highway 604 42 | tiger:name_type=Dr 43 | tiger:reviewed=no 44 | tiger:zip_left=08204 45 | tiger:zip_right=08204Beach Avenuealt_name=County Highway 604 46 | highway=tertiary 47 | lanes=3 48 | lanes:backward=2 49 | lanes:forward=1 50 | lit=yes 51 | name=Beach Avenue 52 | oneway=no 53 | ref=CR 604 54 | source:name=survey 55 | surface=asphalt 56 | tiger:cfcc=A41 57 | tiger:county=Cape May, NJ 58 | tiger:name_base=Beach 59 | tiger:name_base_1=County Highway 604 60 | tiger:name_type=Dr 61 | tiger:zip_left=08204 62 | tiger:zip_right=08204 63 | turn:lanes:backward=|rightBeach Avenuealt_name=County Highway 604 64 | highway=tertiary 65 | lanes=3 66 | lanes:backward=1 67 | lanes:forward=2 68 | lit=yes 69 | name=Beach Avenue 70 | oneway=no 71 | ref=CR 604 72 | source:name=survey 73 | surface=asphalt 74 | tiger:cfcc=A41 75 | tiger:county=Cape May, NJ 76 | tiger:name_base=Beach 77 | tiger:name_base_1=County Highway 604 78 | tiger:name_type=Dr 79 | tiger:zip_left=08204 80 | tiger:zip_right=08204 81 | turn:lanes:forward=left|Beach Avenuealt_name=County Highway 604 82 | highway=tertiary 83 | lanes=3 84 | lanes:backward=1 85 | lanes:forward=2 86 | name=Beach Avenue 87 | oneway=no 88 | ref=CR 604 89 | surface=asphalt 90 | survey:date=2015-10-17 91 | tiger:cfcc=A41 92 | tiger:county=Cape May, NJ 93 | tiger:name_base=Beach 94 | tiger:name_base_1=County Highway 604 95 | tiger:name_type=Dr 96 | tiger:zip_left=08204 97 | tiger:zip_right=08204 98 | turn:lanes:forward=left|Beach Avenuealt_name=County Highway 604 99 | highway=tertiary 100 | lanes=2 101 | lit=yes 102 | name=Beach Avenue 103 | oneway=no 104 | ref=CR 604 105 | source:name=survey 106 | surface=asphalt 107 | tiger:cfcc=A41 108 | tiger:county=Cape May, NJ 109 | tiger:name_base=Beach 110 | tiger:name_base_1=County Highway 604 111 | tiger:name_type=Dr 112 | tiger:zip_left=08204 113 | tiger:zip_right=08204Beach Avenuealt_name=County Highway 604 114 | highway=tertiary 115 | lanes=2 116 | lit=yes 117 | name=Beach Avenue 118 | oneway=no 119 | ref=CR 604 120 | source:name=survey 121 | surface=asphalt 122 | tiger:cfcc=A41 123 | tiger:county=Cape May, NJ 124 | tiger:name_base=Beach 125 | tiger:name_base_1=County Highway 604 126 | tiger:name_type=Dr 127 | tiger:zip_left=08204 128 | tiger:zip_right=08204Beach Avenuealt_name=County Highway 604 129 | highway=tertiary 130 | lanes=2 131 | name=Beach Avenue 132 | oneway=no 133 | ref=CR 604 134 | source:name=survey 135 | surface=asphalt 136 | tiger:cfcc=A41 137 | tiger:county=Cape May, NJ 138 | tiger:name_base=Beach 139 | tiger:name_base_1=County Highway 604 140 | tiger:name_type=Dr 141 | tiger:zip_left=08204 142 | tiger:zip_right=08204 -------------------------------------------------------------------------------- /examples/data/cape_may_restaurants.csv: -------------------------------------------------------------------------------- 1 | Lon,Lat,node_id,amenity,name,cuisine 2 | -74.9240905,38.9314775,node/2668042329,restaurant,The Blue Pig Tavern, 3 | -74.9235904,38.9321656,node/4269020158,restaurant,Tisha's Fine Dining, 4 | -74.9229949,38.9304472,node/4269020175,restaurant,George's Place, 5 | -74.9222267,38.9304928,node/4269020176,restaurant,Y B, 6 | -74.921045,38.9305072,node/4269020185,restaurant,Cabanas Beach Bar & Grill, 7 | -74.9212548,38.9305288,node/4269020210,restaurant,Blue Moon Pizza, 8 | -74.9286053,38.9303859,node/4269040153,restaurant,Rusty Nail, 9 | -74.9242976,38.9321708,node/4269043553,restaurant,That's Amore, 10 | -74.9235954,38.9325113,node/4269043554,restaurant,Louisa's Cafe, 11 | -74.9241207,38.9319708,node/4269043556,restaurant,Cape May Pizza, 12 | -74.9224554,38.9333619,node/4269043577,restaurant,Jojo Pizza, 13 | -74.9194566,38.9308589,node/4269119887,restaurant,Aleathea's, 14 | -74.9212412,38.9341178,node/4269120225,restaurant,Asian Legends, 15 | -74.9211607,38.9340302,node/4269120226,restaurant,Mario's Pizza & Italian, 16 | -74.9168336,38.9309033,node/4269120596,restaurant,Union Park Dining Room, 17 | -74.9102599,38.9320212,node/4269169574,restaurant,Sea Salt, 18 | -74.908346,38.9328039,node/4269169583,restaurant,Hemingway's, 19 | -74.9098421,38.9466451,node/4269173977,restaurant,Big Wave Burritos, 20 | -74.9087764,38.9466129,node/4269173982,restaurant,Cappy's Seaside Pizza & Steaks, 21 | -74.9112036,38.9316934,node/4269812060,restaurant,Harry's Ocean Bar & Grille, 22 | -74.9168154,38.930357,node/4269812061,restaurant,Manga Beachfront Pizza,pizza 23 | -74.9165975,38.9304109,node/4269812062,restaurant,Surfside Delites, 24 | -74.9170268,38.9301732,node/4987008532,restaurant,McGlades On The Pier, 25 | -74.9182861,38.9310235,node/4987008533,restaurant,Louie's Pizza,pizza 26 | -74.9180225,38.9302381,node/5598722999,restaurant,Mermaids restaurant, -------------------------------------------------------------------------------- /examples/index.css: -------------------------------------------------------------------------------- 1 | /* From here https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/ */ 2 | 3 | body { margin: 0; padding: 0; } 4 | 5 | #map { position: absolute; top: 0; bottom: 0; width: 100%; } 6 | 7 | #menu { 8 | background: #fff; 9 | position: absolute; 10 | z-index: 1; 11 | top: 10px; 12 | right: 10px; 13 | border-radius: 3px; 14 | width: 180px; 15 | border: 1px solid rgba(0, 0, 0, 0.4); 16 | font-family: 'Open Sans', sans-serif; 17 | } 18 | 19 | #menu a { 20 | font-size: 13px; 21 | color: #404040; 22 | display: block; 23 | margin: 0; 24 | padding: 0; 25 | padding: 10px; 26 | text-decoration: none; 27 | border-bottom: 1px solid rgba(0, 0, 0, 0.25); 28 | text-align: center; 29 | } 30 | 31 | #menu a:last-child { 32 | border: none; 33 | } 34 | 35 | #menu a:hover { 36 | background-color: #f8f8f8; 37 | color: #404040; 38 | } 39 | 40 | #menu a.active { 41 | background-color: #3887be; 42 | color: #ffffff; 43 | } 44 | 45 | #menu a.active:hover { 46 | background: #3074a4; 47 | } -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Display a map with an XML, CSV, or TopoJSON Overlay 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | import { addProtocols } from "../dist/maplibre-gl-vector-text-protocol.esm.js"; 2 | import { default as layerSelector } from "./layerSelector.js"; 3 | 4 | const map = new maplibregl.Map({ 5 | container: 'map', // container id 6 | style: 'https://demotiles.maplibre.org/style.json', // style URL 7 | center: [-74.8306, 39.06], // starting position [lng, lat] 8 | zoom: 9 // starting zoom 9 | }); 10 | 11 | // Add the sources for all the types 12 | addProtocols(maplibregl); 13 | 14 | // Use a prefix so the layer selector can find our layers 15 | const layerIdPrefix = 'example-'; 16 | 17 | map.on('load', () => { 18 | 19 | // Add few sources and layers to show how each converter works 20 | 21 | // KML 22 | const kmlSourceName = 'cape-may-incorporated-place (kml)'; 23 | const kmlLink = 'kml://./data/cape_may_incorporated_places.kml'; 24 | map.addSource(kmlSourceName, { 25 | 'type': 'geojson', 26 | 'data': kmlLink, 27 | }); 28 | map.addLayer({ 29 | 'id': layerIdPrefix + kmlSourceName, 30 | 'type': 'fill', 31 | 'source': kmlSourceName, 32 | 'minzoom': 0, 33 | 'maxzoom': 20, 34 | 'paint': { 35 | 'fill-opacity': 0.5, 36 | 'fill-color': 'green', 37 | 'fill-outline-color': 'gray' 38 | } 39 | }); 40 | 41 | // TOPOJSON 42 | const topojsonSourceName = 'us-congress-113 (topojson)'; 43 | const topojsonLink = 'topojson://https://gist.githubusercontent.com/mbostock/4090846/raw/07e73f3c2d21558489604a0bc434b3a5cf41a867/us-congress-113.json' 44 | map.addSource(topojsonSourceName, { 45 | 'type': 'geojson', 46 | 'data': topojsonLink, 47 | }); 48 | map.addLayer({ 49 | 'id': layerIdPrefix + topojsonSourceName, 50 | 'type': 'fill', 51 | 'source': topojsonSourceName, 52 | 'minzoom': 0, 53 | 'maxzoom': 20, 54 | 'paint': { 55 | 'fill-opacity': 0.25, 56 | 'fill-color': 'yellow', 57 | 'fill-outline-color': 'gray' 58 | } 59 | }); 60 | 61 | // OSM polygon (json) 62 | const osmSourceName = 'marsh (osm polygon json)'; 63 | const osmLink = 'osm://https://www.openstreetmap.org/api/0.6/relation/5544086/full.json' 64 | map.addSource(osmSourceName, { 65 | 'type': 'geojson', 66 | 'data': osmLink, 67 | }); 68 | map.addLayer({ 69 | 'id': layerIdPrefix + osmSourceName, 70 | 'type': 'fill', 71 | 'source': osmSourceName, 72 | 'minzoom': 0, 73 | 'maxzoom': 20, 74 | 'paint': { 75 | 'fill-opacity': 0.25, 76 | 'fill-color': 'blue', 77 | 'fill-outline-color': 'gray' 78 | } 79 | }); 80 | 81 | // OSM line (xml) 82 | const osmLineSourceName = 'madison ave (osm line xml)'; 83 | const osmLineLink = 'osm://https://www.openstreetmap.org/api/0.6/relation/968291/full' 84 | map.addSource(osmLineSourceName, { 85 | 'type': 'geojson', 86 | 'data': osmLineLink, 87 | }); 88 | map.addLayer({ 89 | 'id': layerIdPrefix + osmLineSourceName, 90 | 'type': 'line', 91 | 'source': osmLineSourceName, 92 | 'minzoom': 0, 93 | 'maxzoom': 20, 94 | 'paint': { 95 | 'line-opacity': 0.4, 96 | 'line-color': 'blue', 97 | } 98 | }); 99 | 100 | // CSV 101 | const csvSourceName = 'restaurants (csv)'; 102 | const csvLink = 'csv://./data/cape_may_restaurants.csv'; 103 | map.addSource(csvSourceName, { 104 | 'type': 'geojson', 105 | 'data': csvLink, 106 | }); 107 | map.addLayer({ 108 | 'id': layerIdPrefix + csvSourceName, 109 | 'type': 'circle', 110 | 'source': csvSourceName, 111 | 'minzoom': 0, 112 | 'maxzoom': 20, 113 | 'paint': { 114 | 'circle-color': 'orange', 115 | 'circle-radius': 5, 116 | 'circle-stroke-color': 'black' 117 | } 118 | }); 119 | 120 | // GPX 121 | const gpxSourceName = 'beach ave (gpx)'; 122 | const gpxLink = 'gpx://./data/beach_ave.gpx'; 123 | map.addSource(gpxSourceName, { 124 | 'type': 'geojson', 125 | 'data': gpxLink, 126 | }); 127 | map.addLayer({ 128 | 'id': layerIdPrefix + gpxSourceName, 129 | 'type': 'line', 130 | 'source': gpxSourceName, 131 | 'minzoom': 0, 132 | 'maxzoom': 20, 133 | 'paint': { 134 | 'line-color': 'red', 135 | 'line-width': 5 136 | } 137 | }); 138 | 139 | 140 | // Polyline 141 | const polylineSourceName = 'pittsburg ave (polyline)'; 142 | const polylineProperties = { 143 | "@id": "way/11605426", 144 | "alt_name": "County Highway 622", 145 | "cycleway": "lane", 146 | "highway": "tertiary", 147 | "name": "Pittsburg Avenue", 148 | }; 149 | const polylinePath = 'ymslF`cdhMSJcBv@}@`@QHcDzA{CpA}CvA{CtAcAd@KDo@ZyAp@GByCtAOFgCjAGBaBt@u@ZOHyCrAKFqCnAGB{CvAOFkClAgAd@OHKJKPIN'; 150 | // Convert the string into a Blob 151 | const polylineBlob = new Blob([polylinePath], { type: 'text/plain' }); 152 | 153 | // Create a data URL from the Blob 154 | const polylineURL = 'polyline://' + URL.createObjectURL(polylineBlob); 155 | console.log('s1', polylineBlob, polylineURL); 156 | /*addOptions(polylineURL, { 157 | polylineOptions: { 158 | properties: polylineProperties 159 | } 160 | });*/ 161 | 162 | map.addSource(polylineSourceName, { 163 | 'type': 'geojson', 164 | 'data': polylineURL, 165 | }); 166 | map.addLayer({ 167 | 'id': layerIdPrefix + polylineSourceName, 168 | 'type': 'line', 169 | 'source': polylineSourceName, 170 | 'minzoom': 0, 171 | 'maxzoom': 20, 172 | 'paint': { 173 | 'line-color': 'purple', 174 | 'line-width': 5 175 | } 176 | }); 177 | }); 178 | 179 | // After the last frame rendered before the map enters an "idle" state, 180 | // add the toggle fields / layer selector 181 | map.on('idle', () => { 182 | // Add the layer selector 183 | layerSelector(map, layerIdPrefix); 184 | }); 185 | -------------------------------------------------------------------------------- /examples/indexv3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Display a map with an XML, CSV, or TopoJSON Overlay 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/layerSelector.js: -------------------------------------------------------------------------------- 1 | // Adapted from: https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/ 2 | 3 | export default function layerSelector (map, prefix) { 4 | // Enumerate ids of the layers 5 | const prefixRegexp = new RegExp(`^${prefix}`); 6 | const toggleableLayerIds = Object.keys(map.style._layers) 7 | .filter(name => name.match(prefixRegexp)); 8 | 9 | toggleableLayerIds.forEach(layerId => { 10 | // Make the name nicer 11 | const layerName = layerId.replace(prefixRegexp, ''); 12 | 13 | if (!document.getElementById(layerId)) { 14 | 15 | // Create a link. 16 | const link = document.createElement('a'); 17 | link.id = layerId; 18 | link.href = '#'; 19 | link.textContent = layerName, 20 | link.className = 'active'; 21 | 22 | // Show or hide layer when the toggle is clicked. 23 | link.onclick = function (e) { 24 | const clickedLayer = this.id; 25 | e.preventDefault(); 26 | e.stopPropagation(); 27 | 28 | const visibility = map.getLayoutProperty( 29 | clickedLayer, 30 | 'visibility' 31 | ); 32 | 33 | // Toggle layer visibility by changing the layout object's visibility property. 34 | if (visibility !== 'none') { 35 | map.setLayoutProperty(clickedLayer, 'visibility', 'none'); 36 | this.className = ''; 37 | } else { 38 | this.className = 'active'; 39 | map.setLayoutProperty( 40 | clickedLayer, 41 | 'visibility', 42 | 'visible' 43 | ); 44 | } 45 | }; 46 | 47 | const layers = document.getElementById('menu'); 48 | layers.appendChild(link); 49 | } 50 | }); 51 | }; -------------------------------------------------------------------------------- /examples/umd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Display a map with an XML, CSV, or TopoJSON Overlay 7 | 8 | 9 | 10 | 11 | 12 | ß 13 | 14 |
15 | 16 | 48 | 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maplibre-gl-vector-text-protocol", 3 | "version": "0.0.5", 4 | "description": "Allows various text based vector formats to be used with maplibre gl js", 5 | "keywords": [ 6 | "maplibre", 7 | "topojson", 8 | "osm", 9 | "kml", 10 | "gpx", 11 | "tcx", 12 | "csv", 13 | "tsv", 14 | "convert" 15 | ], 16 | "author": "James McAndrew ", 17 | "license": "MIT", 18 | "main": "dist/maplibre-gl-vector-text-protocol.js", 19 | "module": "dist/maplibre-gl-vector-text-protocol.esm.js", 20 | "browser": "dist/maplibre-gl-vector-text-protocol.min.js", 21 | "types": "dist/src/index.d.ts", 22 | "files": [ 23 | "dist" 24 | ], 25 | "scripts": { 26 | "clean": "rm -rf ./dist", 27 | "build-dev": "NODE_ENV=development npm run build", 28 | "watch-dev": "NODE_ENV=development npm run watch", 29 | "build-prod": "NODE_ENV=production npm run build", 30 | "build": "npm run clean && rollup -c rollup.config.mjs", 31 | "watch": "npm run clean && rollup -c rollup.config.mjs --watch", 32 | "test": "echo 'no tests available'" 33 | }, 34 | "devDependencies": { 35 | "@rollup/plugin-commonjs": "^25.0.7", 36 | "@rollup/plugin-json": "^6.1.0", 37 | "@rollup/plugin-node-resolve": "^15.2.3", 38 | "@rollup/plugin-terser": "^0.4.4", 39 | "@types/geojson": "^7946.0.14", 40 | "@types/mapbox__polyline": "^1.0.5", 41 | "@types/topojson": "^3.2.6", 42 | "maplibre-gl": "^4.1.3", 43 | "rollup": "^4.17.0", 44 | "rollup-plugin-sourcemaps": "^0.6.3", 45 | "rollup-plugin-typescript2": "^0.36.0", 46 | "rollup-plugin-web-worker-loader": "^1.6.1", 47 | "typescript": "^5.4.5" 48 | }, 49 | "overrides": { 50 | "rollup-plugin-web-worker-loader": { 51 | "rollup": "^4.0.2" 52 | } 53 | }, 54 | "dependencies": { 55 | "@mapbox/polyline": "^1.2.1", 56 | "@tmcw/togeojson": "5.8.1", 57 | "csv2geojson": "^5.1.2", 58 | "osm2geojson-lite": "^0.9.4", 59 | "topojson-client": "^3.1.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import merge from 'deepmerge'; 4 | import terser from "@rollup/plugin-terser"; 5 | import typescript from 'rollup-plugin-typescript2'; 6 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 7 | import commonjs from '@rollup/plugin-commonjs'; 8 | import json from '@rollup/plugin-json'; 9 | import webWorkerLoader from 'rollup-plugin-web-worker-loader'; 10 | 11 | import { readFileSync, readdirSync, writeFileSync } from 'fs'; 12 | 13 | const { main, module, browser, devDependencies } = JSON.parse(readFileSync('package.json')); 14 | const env = process.env.NODE_ENV || 'development'; 15 | 16 | const updateMaplibreVersion = () => { 17 | const updateVersion = (fileContent) => { 18 | const maplibreVersion = devDependencies['maplibre-gl'].replace(/[\^~]/g, ''); 19 | const regex = /https:\/\/unpkg\.com\/maplibre-gl@[^]?\d+\.\d+\.\d+\/dist\/maplibre-gl/g; 20 | const newVersionString = `https://unpkg.com/maplibre-gl@${maplibreVersion}/dist/maplibre-gl`; 21 | return fileContent.replace(regex, newVersionString); 22 | }; 23 | readdirSync('./examples').map(item => { 24 | if (item.match(/.+?\.html/) && item !== 'indexv3.html') { 25 | const fileContent = readFileSync('./examples/' + item, { encoding: 'utf8', flag: 'r' }); 26 | const newFileContent = updateVersion(fileContent); 27 | writeFileSync('./examples/' + item, newFileContent); 28 | } 29 | }); 30 | }; 31 | updateMaplibreVersion(); 32 | 33 | const baseConfig = { 34 | input: './src/index.ts', 35 | output: { 36 | name: 'VectorTextProtocol' 37 | }, 38 | treeshake: env === 'production', 39 | plugins: [webWorkerLoader({ 40 | 'extensions': ['.ts'] 41 | }), typescript(), nodeResolve(), commonjs(), json()] 42 | }; 43 | 44 | const configs = [{ 45 | environments: ['development', 'production'], 46 | output: { 47 | format: 'umd', 48 | file: main 49 | } 50 | }, { 51 | environments: ['production'], 52 | output: { 53 | format: 'umd', 54 | file: browser, 55 | sourcemap: true 56 | }, 57 | plugins: [terser()] 58 | }, { 59 | environments: ['production'], 60 | output: { 61 | format: 'esm', 62 | file: module 63 | } 64 | }] 65 | .filter(config => config.environments === undefined || config.environments.indexOf(env) > -1) 66 | .map(config => { delete config.environments; return config; }) 67 | .map(config => merge(baseConfig, config)); 68 | 69 | console.log(configs); 70 | 71 | export default configs; 72 | -------------------------------------------------------------------------------- /src/converter.ts: -------------------------------------------------------------------------------- 1 | import { FeatureCollection, GeoJsonProperties, Geometry, LineString } from 'geojson'; 2 | import { Topology } from 'topojson-specification' 3 | import * as csv2geojson from 'csv2geojson'; 4 | import { feature as topojsonFeature } from 'topojson-client'; 5 | import * as toGeoJson from '@tmcw/togeojson'; 6 | import { toGeoJSON as polylineToGeoJSON } from '@mapbox/polyline'; 7 | import osm2geojson from 'osm2geojson-lite'; 8 | 9 | export const supportedFormats = ['topojson', 'osm', 'kml', 'gpx', 'tcx', 'csv', 'tsv', 'polyline'] as const; 10 | export type supportedFormatsType = typeof supportedFormats[number]; 11 | 12 | export type supportedOptions = { 13 | csvOptions?: csv2geojson.csvOptions, 14 | polylineOptions?: { 15 | precision?: number, 16 | properties?: GeoJsonProperties, 17 | type?: 'point' | 'line' | 'polygon' 18 | } 19 | }; 20 | 21 | export class Converter { 22 | _conversionFn: () => Promise; 23 | _rawData: string; 24 | _format: supportedFormatsType; 25 | _options: supportedOptions; 26 | 27 | constructor(format: supportedFormatsType, data: string, options: supportedOptions = {}) { 28 | this._rawData = data; 29 | this._format = format; 30 | this._options = options; 31 | 32 | const converters: { [key: string]: () => Promise } = { 33 | 'topojson': this.loadTopoJson, 34 | 'osm': this.loadOsm, 35 | 'kml': this.loadXml, 36 | 'gpx': this.loadXml, 37 | 'tcx': this.loadXml, 38 | 'csv': this.loadCsv, 39 | 'tsv': this.loadCsv, 40 | 'polyline': this.loadPolyline 41 | }; 42 | this._conversionFn = converters[format]; 43 | 44 | } 45 | 46 | /** 47 | * Creates a blank GeoJSON feature collection. 48 | * @returns A new GeoJSON feature collection with no features. 49 | */ 50 | blankGeoJSON: () => FeatureCollection = () => ({ 51 | type: 'FeatureCollection', 52 | features: [], 53 | }); 54 | 55 | async convert() { 56 | if (!this._conversionFn) { 57 | return new Promise((_, rej) => rej(`No converter exists for ${this._format}`)); 58 | } else { 59 | return this._conversionFn(); 60 | } 61 | } 62 | 63 | /** 64 | * Load the XML data as GeoJSON 65 | * @returns A promise resolving to a GeoJSON FeatureCollection 66 | */ 67 | async loadXml(): Promise { 68 | // Use the appropriate parser based on the format 69 | const geojson = (toGeoJson as any)[this._format]( 70 | new DOMParser().parseFromString(this._rawData, "text/xml") 71 | ); 72 | 73 | return geojson; 74 | } 75 | 76 | /** 77 | * Loads and parses CSV data into a GeoJSON FeatureCollection. 78 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 79 | */ 80 | async loadCsv(): Promise { 81 | // Define options for the csv2geojson library 82 | let options: csv2geojson.csvOptions = this._options.csvOptions || {}; // TODO allow CSV options 83 | 84 | if (this._format === 'tsv') { 85 | options.delimiter = '\t'; 86 | } 87 | 88 | // Use the csv2geojson library to convert the CSV to GeoJSON 89 | const geojson = await new Promise((resolve, reject) => { 90 | csv2geojson.csv2geojson( 91 | this._rawData, 92 | options, 93 | (err: string, data: FeatureCollection) => { 94 | if (err) { 95 | reject(err); 96 | } else { 97 | resolve(data); 98 | } 99 | } 100 | ); 101 | }); 102 | 103 | return geojson; 104 | } 105 | 106 | /** 107 | * Loads TopoJSON data and converts it into a GeoJSON FeatureCollection 108 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 109 | */ 110 | async loadTopoJson(): Promise { 111 | 112 | type TopoJson = { 113 | type?: 'Topology'; 114 | objects?: { [key: string]: Topology }; 115 | arcs?: any; 116 | }; 117 | let topoJsonData: TopoJson = {}; 118 | 119 | try { 120 | topoJsonData = JSON.parse(this._rawData); 121 | } catch (e) { 122 | throw "Invalid TopoJson"; 123 | } 124 | 125 | // Convert the data 126 | let result: FeatureCollection = this.blankGeoJSON(); 127 | if (topoJsonData.type === "Topology" && topoJsonData.objects !== undefined) { 128 | result = { 129 | type: "FeatureCollection", 130 | features: result.features = Object.keys(topoJsonData.objects).map(key => 131 | topojsonFeature(topoJsonData as any, key) 132 | ).reduce((a: any[], v) => [...a, ...(v as any).features], []) 133 | }; 134 | } 135 | return result; 136 | }; 137 | 138 | /** 139 | * Loads OSM data and converts it into a GeoJSON FeatureCollection 140 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 141 | */ 142 | async loadOsm(): Promise { 143 | return osm2geojson(this._rawData) as FeatureCollection; 144 | } 145 | 146 | /** 147 | * Loads and parses Polyline data into a GeoJSON FeatureCollection. 148 | * @returns A Promise that resolves with the GeoJSON FeatureCollection. 149 | */ 150 | async loadPolyline(): Promise { 151 | let options = this._options.polylineOptions || {}; 152 | 153 | // Use the @mapbox/polyline library to convert the polyline to GeoJSON 154 | const geojson = await new Promise((resolve, reject) => { 155 | try { 156 | const lineString = polylineToGeoJSON(this._rawData, options.precision); 157 | let geometry: Geometry = lineString; 158 | 159 | if (options.type === 'point') { 160 | if (lineString.coordinates.length === 1) { 161 | // Make it a point 162 | geometry = { 163 | 'type': 'Point', 164 | 'coordinates': lineString.coordinates[0] 165 | } 166 | } else { 167 | console.warn('Cannot convert polyline to ' + options.type) 168 | } 169 | } else if (options.type === 'polygon') { 170 | if ( 171 | lineString.coordinates[0][0] === lineString.coordinates[lineString.coordinates.length - 1][0] && 172 | lineString.coordinates[0][1] === lineString.coordinates[lineString.coordinates.length - 1][1]) { 173 | // Make it a polygon 174 | geometry = { 175 | 'type': 'Polygon', 176 | 'coordinates': [lineString.coordinates] 177 | } 178 | } else { 179 | console.warn('Cannot convert polyline to ' + options.type) 180 | } 181 | } 182 | resolve({ 183 | type: "FeatureCollection", 184 | features: [{ 185 | "type": "Feature", 186 | "geometry": geometry, 187 | "properties": options.properties || {} 188 | }] 189 | }); 190 | } catch (err) { 191 | reject(err) 192 | } 193 | }); 194 | 195 | return geojson; 196 | } 197 | } -------------------------------------------------------------------------------- /src/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@tmcw/togeojson' { 2 | export function kml(doc: Document): FeatureCollection; 3 | export function gpx(doc: Document): FeatureCollection; 4 | export function tcx(doc: Document): FeatureCollection; 5 | } 6 | 7 | declare module 'csv2geojson' { 8 | export interface csvOptions { 9 | 'latfield'?: string, 10 | 'lonfield'?: string, 11 | 'delimiter'?: string 12 | } 13 | 14 | export function csv2geojson( 15 | csvString: string, 16 | options: csvOptions, 17 | callback: (err: string, data: FeatureCollection) => void 18 | ): void 19 | } 20 | 21 | declare module 'web-worker:*' { 22 | const WorkerFactory: new () => Worker; 23 | export default WorkerFactory; 24 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | RequestParameters, 3 | default as MapLibrary, 4 | GetResourceResponse 5 | } from 'maplibre-gl'; 6 | 7 | import { FeatureCollection } from 'geojson'; 8 | import { Converter, supportedFormatsType, supportedFormats, supportedOptions } from './converter'; 9 | import { Actor } from './worker/actor'; 10 | 11 | // Make sure we can support workers in the current browser / runtime 12 | const supportsWorkers = () => { 13 | let supported = false; 14 | try { 15 | supported = typeof (window.Worker) === 'function'; 16 | } catch (e) { 17 | supported = false; 18 | } 19 | return supported; 20 | }; 21 | 22 | // Safari changes https:// to http// for some reason, so this is broken in Safari and iPhone 23 | // So to fix this we add it back 24 | const needsUrlCheck = (new URL('test://http://example.com')).href !== 'test://http://example.com'; 25 | const checkUrl = (url: string): string | undefined => { 26 | const safariFixRegex = new RegExp('^(https?)(\/\/)') 27 | const cleanUrl = url.replace(safariFixRegex, '$1:$2'); 28 | return cleanUrl; 29 | } 30 | 31 | /** 32 | * The processData function accepts a URL, prefix, and an optional controller 33 | * and tries to read and convert the data 34 | * @param url - The URL of the resource. 35 | * @param prefix - The prefix used to process the data 36 | * @param controller - optional controller that can be used to cancel a request 37 | * @returns A geojson FeatureCollection (or undefined) 38 | */ 39 | export async function processData(url: string, prefix: supportedFormatsType, controller?: AbortController): Promise { 40 | const response = await fetch(url, controller ? { signal: controller.signal } : undefined); 41 | 42 | let options = {}; 43 | 44 | // Parse the URL 45 | const urlObject = new URL(url, window.location.href); 46 | 47 | if (urlObject.hash.length) { 48 | // Extract the hash (including the "#" symbol) 49 | const hash = urlObject.hash; 50 | 51 | // Remove the "#" symbol from the hash and decode it 52 | const decodedHash = decodeURIComponent(hash.slice(1)); // Remove the "#" symbol 53 | 54 | try { 55 | options = JSON.parse(decodedHash); 56 | } catch (e) { 57 | console.warn('Error parsing or reading URL:', e); 58 | } 59 | } 60 | 61 | if (response.status == 200) { 62 | const rawData = await response.text(); 63 | let convertPromise; 64 | const usesDOM = (['kml', 'tcx', 'gpx'].includes(prefix)); 65 | if (usesDOM || !supportsWorkers()) { 66 | // XML uses the DOM, which isn't available to web workers 67 | // It is possible to use xmldom to do this, but that increases the bundle size by 3x 68 | const converter = new Converter(prefix, rawData, options); 69 | convertPromise = converter.convert(); 70 | } else { 71 | const converter = new Actor('Converter', [prefix, rawData, options]); 72 | convertPromise = converter.exec('convert')(); 73 | } 74 | return await convertPromise; 75 | } else { 76 | throw (new Error(`Data fetch error: ${response.statusText}`)); 77 | } 78 | }; 79 | 80 | /** 81 | * Processes the URL and returns the prefix and cleaned URL. 82 | * 83 | * @param url - The URL to process. 84 | * @returns An object with the prefix and cleaned URL. 85 | */ 86 | const processUrl = (url: string) => { 87 | const prefix = url.split('://')[0] as supportedFormatsType; 88 | const replacedUrl = url.replace(new RegExp(`^${prefix}://`), ''); 89 | 90 | // Apply the Safari fix (if needed) to the URL 91 | const cleanUrl = needsUrlCheck ? checkUrl(replacedUrl) : replacedUrl; 92 | return { prefix, url: cleanUrl }; 93 | } 94 | /** 95 | * Handles the Vector Text Protocol for version 4. 96 | * 97 | * @param requestParameters - The parameters for the request including the URL. 98 | * @param controller - An AbortController instance to manage the request lifecycle. 99 | * @returns A promise resolving to a GetResourceResponse containing a FeatureCollection or undefined. 100 | * @throws Will throw an error if the URL is invalid or if any other error occurs during data processing. 101 | */ 102 | const VectorTextProtocolV4 = async ( 103 | requestParameters: RequestParameters, 104 | controller: AbortController 105 | ): Promise> => { 106 | const { prefix, url } = processUrl(requestParameters.url); 107 | 108 | if (url) { 109 | try { 110 | // Process the data and return the response 111 | const data = await processData(url, prefix, controller); 112 | return { data }; 113 | } catch (e) { 114 | // Catch and rethrow errors with additional context 115 | throw new Error((e as any) || 'Unknown Error'); 116 | } 117 | } else { 118 | // Handle invalid URL case 119 | throw new Error('Invalid URL: ' + requestParameters.url); 120 | } 121 | }; 122 | 123 | /** 124 | * Handles the Vector Text Protocol for version 3. 125 | * 126 | * @param requestParameters - The parameters for the request including the URL. 127 | * @param callback - A callback function to handle the response or error. 128 | * @returns An object with a cancel function to abort the request. 129 | */ 130 | const VectorTextProtocolV3 = ( 131 | requestParameters: RequestParameters, 132 | callback: (e: string | null, d?: FeatureCollection) => void 133 | ) => { 134 | const controller = new AbortController(); 135 | const { prefix, url } = processUrl(requestParameters.url); 136 | 137 | 138 | if (url) { 139 | processData(url, prefix, controller) 140 | .then(data => callback(null, data)) 141 | .catch(e => callback(e)) 142 | } 143 | 144 | // Return an object with a cancel method to abort the request 145 | return { cancel: () => { controller.abort() } }; 146 | }; 147 | 148 | /** 149 | * Selects the appropriate Vector Text Protocol version based on the type of controller provided. 150 | * 151 | * @param requestParameters - The parameters for the request including the URL. 152 | * @param controller - Either an AbortController or a callback function. 153 | * @returns Either a Promise for V4 or an object with a cancel method for V3. 154 | */ 155 | export const VectorTextProtocol = ( 156 | requestParameters: RequestParameters, 157 | controller: AbortController | ((e: string | null, d?: FeatureCollection) => void) 158 | ): Promise> | { cancel: () => void } => { 159 | if (controller instanceof AbortController) { 160 | return VectorTextProtocolV4(requestParameters, controller); 161 | } else { 162 | return VectorTextProtocolV3(requestParameters, controller) 163 | } 164 | } 165 | 166 | /** 167 | * Add options to a URL for the Vector Text Protocol. 168 | * 169 | * @param url - The URL to add options to. 170 | * @param options - The options to add to the URL. 171 | * @returns A string with the updated URL. 172 | */ 173 | export const addOptions = (url: string | URL, options: supportedOptions) => { 174 | try { 175 | // Parse the original URL 176 | const urlObject = new URL(url); 177 | 178 | // Set the hash property with the GeoJSON data 179 | urlObject.hash = `#${encodeURIComponent(JSON.stringify(options))}`; 180 | 181 | // Convert the updated URL object back to a string 182 | return urlObject.toString(); 183 | } catch (error) { 184 | console.error('Error parsing or updating URL:', error); 185 | return url; // Return the original URL if there's an error 186 | } 187 | } 188 | 189 | /** 190 | * Add the vector text protocol to a map library for each supported format. 191 | * @param mapLibrary - The MapLibrary object to add the protocols to. 192 | */ 193 | export const addProtocols = (mapLibrary: typeof MapLibrary) => { 194 | supportedFormats.forEach(type => { 195 | mapLibrary.addProtocol(type, VectorTextProtocol as (requestParameters: RequestParameters, controller: AbortController) => Promise>); 196 | }) 197 | }; 198 | 199 | export const vectorFormats = supportedFormats; 200 | export { supportedFormatsType } from './converter'; -------------------------------------------------------------------------------- /src/worker/actor.ts: -------------------------------------------------------------------------------- 1 | import WebWorker from 'web-worker:./worker'; 2 | 3 | const randomString = () => Math.random().toString(36).substring(2); 4 | 5 | import type { MessageData, SubClasses } from './worker'; 6 | 7 | export class Actor { 8 | subClass: any; 9 | worker: Worker; 10 | handlers: Map void, 12 | 'reject': (value: Error) => void 13 | }>; 14 | initId: string; 15 | _: Record | undefined; 16 | 17 | /** 18 | * Creates a new instance of the `Actor` class. 19 | * @param subClass - The name of the subclass. 20 | * @param args - The arguments to pass to the subclass constructor. 21 | */ 22 | constructor(subClass: SubClasses, args: Array) { 23 | // Generate a random initialization ID 24 | this.initId = randomString() + '-' + subClass; 25 | 26 | // Create a new Web Worker and a new Map for handlers 27 | this.worker = new WebWorker(); 28 | this.handlers = new Map(); 29 | 30 | // Listen for messages from the worker 31 | this.worker.onmessage = (event: any) => { 32 | const data = event.data as MessageData; 33 | const handler = this.handlers.get(data.id); 34 | const that = this; 35 | 36 | if (handler) { 37 | // Handle responses from the worker 38 | if (data.type === 'response') { 39 | handler.resolve(data.message); 40 | } 41 | // Handle errors from the worker 42 | if (data.type === 'error') { 43 | const error = data.error || new Error(`Unknown error with ${subClass}`); 44 | handler.reject(error); 45 | } 46 | // Handle initialization responses from the worker 47 | if (data.type === 'init_response') { 48 | this._ = Object.keys(data.message) 49 | .map(key => { 50 | const isFn = typeof data.message[key as any] === 'function'; 51 | const subFunction = function () { 52 | return isFn ? (that.exec(key))(...arguments) : that.get(key); 53 | }; 54 | return [key, subFunction]; 55 | }) 56 | .reduce((a, c) => ({ ...a, ...{ [c[0] as string]: c[1] } }), {}); 57 | handler.resolve(this._); 58 | } 59 | } 60 | }; 61 | 62 | // Tell the worker to initialize the subclass 63 | this.worker.postMessage({ 64 | type: 'init', 65 | id: this.initId, 66 | command: subClass, 67 | message: args 68 | } as MessageData); 69 | } 70 | 71 | /** 72 | * Waits for the initialization of the object to complete and returns the resulting object. 73 | * @returns A promise that resolves with the initialized object. 74 | */ 75 | onLoad(): Promise { 76 | return new Promise((resolve) => { 77 | // If initialization is still in progress, add a new handler for the initialization result 78 | if (this._ === undefined) { 79 | this.handlers.set(this.initId, { resolve, 'reject': resolve }); 80 | } else { 81 | // Otherwise, immediately resolve the promise with the initialized object 82 | resolve(this._); 83 | } 84 | }); 85 | } 86 | 87 | 88 | /** 89 | * returns a Promise for a given command that will be executed in a worker. 90 | * @param command - The command to execute. 91 | * @returns A Promise that resolves with the result of the command execution or rejects with an error. 92 | */ 93 | exec(command: string): (...args: any[]) => Promise { 94 | // Keep track of this class 95 | const that = this; 96 | 97 | // Return a function that returns a Promise 98 | return function (...args: any[]): Promise { 99 | return new Promise((resolve, reject) => { 100 | const id = randomString() + '-' + command; 101 | 102 | // Set up the resolve and reject handlers for the Promise 103 | that.handlers.set(id, { resolve, reject }); 104 | 105 | // Tell the worker to run the command with the provided arguments 106 | that.worker.postMessage({ 107 | type: 'exec', 108 | id: id, 109 | command: command, 110 | message: [...args] 111 | } as MessageData); 112 | }); 113 | }; 114 | } 115 | 116 | /** 117 | * Returns a Promise that resolves with the result of a command sent to a Web Worker. 118 | * @param command - The command to send to the Web Worker. 119 | * @returns A Promise that resolves with the result of the command. 120 | */ 121 | get(command: string): Promise { 122 | return new Promise((resolve, reject) => { 123 | // Generate a unique ID for this request 124 | const id = randomString() + '-' + command; 125 | 126 | // Store the resolve and reject functions for later use 127 | this.handlers.set(id, { resolve, reject }); 128 | 129 | // Send the command to the worker 130 | this.worker.postMessage({ 131 | type: 'get', 132 | id, 133 | command, 134 | message: [], 135 | } as MessageData); 136 | }); 137 | } 138 | }; -------------------------------------------------------------------------------- /src/worker/worker.ts: -------------------------------------------------------------------------------- 1 | import { Converter } from '../converter'; 2 | 3 | export interface MessageData { 4 | 'type': 'response' | 'error' | 'init' | 'exec' | 'get' | 'init_response', 5 | 'id': string, 6 | 'message': Array, 7 | 'error'?: Error, 8 | 'command': string 9 | } 10 | 11 | const subClasses = ['Converter'] as const; 12 | export type SubClasses = typeof subClasses[number]; 13 | const libraries: { [_: string]: any } = { 14 | 'Converter': Converter 15 | }; 16 | 17 | let subClass: any; 18 | 19 | self.addEventListener('message', e => { 20 | const data = (e.data || e) as MessageData; 21 | 22 | const post = (id: string, err: Error | undefined, res?: any, type?: string) => { 23 | postMessage({ 24 | type: type ? type : (err ? 'error' : 'response'), 25 | id: id, 26 | message: res, 27 | error: err 28 | } as MessageData) 29 | } 30 | 31 | const commands = { 32 | 'init': (msg: MessageData) => { 33 | const { id, command, message } = msg; 34 | subClass = new libraries[command](message[0], message[1]); 35 | 36 | // return the class' methods 37 | const fns = [ 38 | ...Object.getOwnPropertyNames(libraries[command].prototype), 39 | ...Object.keys(subClass) 40 | ].map(key => [key, typeof libraries[command].prototype[key]]) 41 | .reduce((a, c) => ({ ...a, ...{ [c[0]]: c[1] } }), {}); 42 | post(id, undefined, fns, 'init_response') 43 | }, 44 | 'get': function (msg: MessageData) { 45 | const { id, command } = msg; 46 | if (subClass && subClass[command]) { 47 | post(id, undefined, subClass[command]); 48 | } else { 49 | post(id, undefined, undefined); 50 | } 51 | }, 52 | 'exec': function (msg: MessageData) { 53 | const { id, command, message } = msg; 54 | 55 | if (subClass && subClass[command] && typeof subClass[command] === 'function') { 56 | const cmd = (subClass[command] as () => Promise) 57 | .apply(subClass, message as []); 58 | 59 | if (!!cmd && typeof cmd.then === 'function') { 60 | // It's a promise, so wait for it 61 | cmd 62 | .then(res => post(id, undefined, res)) 63 | .catch(e => post(id, e)); 64 | } else { 65 | // Not a promise, just return it 66 | post(id, undefined, cmd); 67 | } 68 | } else { 69 | // Error 70 | post(id, new Error(`command "${command}" not found`)); 71 | } 72 | } 73 | }; 74 | 75 | if (commands[data.type as 'init' | 'exec' | 'get']) { 76 | commands[data.type as 'init' | 'exec' | 'get'](data) 77 | } 78 | }); 79 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2018", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "esnext", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | "declarationDir": "./dist", /* Specify the output directory for generated declaration files. */ 67 | 68 | /* Interop Constraints */ 69 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 70 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 71 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 72 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 73 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 74 | 75 | /* Type Checking */ 76 | "strict": true, /* Enable all strict type-checking options. */ 77 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 78 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 79 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 80 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 81 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 82 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 83 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 84 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 85 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 86 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 87 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 88 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 89 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 90 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 91 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 92 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 93 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 94 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 95 | 96 | /* Completeness */ 97 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 98 | "skipLibCheck": true, /* Skip type checking all .d.ts files. */ 99 | "outDir": "./out-tsc", 100 | "rootDir": "./" 101 | }, 102 | "include": ["./src/**/*.ts"] 103 | } 104 | --------------------------------------------------------------------------------