From: Marwin Hochfelsner <50826859+hlfan@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:30:57 +0000 (+0200) Subject: Add parseGeoURI function and tests X-Git-Tag: live~14^2~2 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/aa89366ded46bae404475afc9cfeeba3d027c5d5?hp=-c Add parseGeoURI function and tests --- aa89366ded46bae404475afc9cfeeba3d027c5d5 diff --git a/app/assets/javascripts/osm.js.erb b/app/assets/javascripts/osm.js.erb index 31f92da84..31997e303 100644 --- a/app/assets/javascripts/osm.js.erb +++ b/app/assets/javascripts/osm.js.erb @@ -121,6 +121,29 @@ OSM = { return mapParams; }, + parseGeoURI: function (geoURI) { + let url; + try { + url = new URL(geoURI); + } catch (e) { return; } + if (!url?.pathname || url.protocol !== "geo:") return; + const [path, ...params] = url.pathname.split(";"); + let coords; + try { + coords = L.latLng(path.split(",")); + } catch (e) { return; } + if (!coords) return; + const searchParams = new URLSearchParams(params.join("&").toLowerCase()); + const crs = searchParams.get("crs"); + if (crs && crs !== "wgs84") return; + const uncertainty = parseFloat(searchParams.get("u")); + const zoom = parseFloat(url.searchParams.get("z")); + const out = { coords }; + if (uncertainty >= 0) out.uncertainty = uncertainty; + if (zoom >= 0) out.zoom = zoom; + return out; + }, + parseHash: function (hash = location.hash) { const args = {}; diff --git a/test/javascripts/osm_test.js b/test/javascripts/osm_test.js index 10d562959..cac209c0f 100644 --- a/test/javascripts/osm_test.js +++ b/test/javascripts/osm_test.js @@ -130,6 +130,99 @@ describe("OSM", function () { }); }); + describe(".parseGeoURI", function () { + it("parses basic geoURIs", function () { + let params = OSM.parseGeoURI("geo:57.6247,-3.6845"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845)); + expect(params.zoom).to.be.undefined; + expect(params.uncertainty).to.be.undefined; + params = OSM.parseGeoURI("GEO:57.6247,-3.6845"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845)); + }); + it("parses only geoURIs", function () { + let params = OSM.parseGeoURI("latlng:57.6247,-3.6845"); + expect(params).to.be.undefined; + params = OSM.parseGeoURI("geo57.6247,-3.6845"); + expect(params).to.be.undefined; + }); + it("rejects geoURIs with less than 2 coordinates", function () { + const params = OSM.parseGeoURI("geo:57.6247"); + expect(params).to.be.undefined; + }); + it("parses geoURIs with altitude", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845,100"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845, 100)); + }); + it("rejects geoURIs with more than 3 coordinates", function () { + const params = OSM.parseGeoURI("geo:123,57.6247,-3.6845,100"); + expect(params).to.be.undefined; + }); + it("ignores non-numeric coordinates", function () { + let params = OSM.parseGeoURI("geo:57.6247,-3.6845,abc"); + expect(params.coords.lat).to.equal(57.6247); + expect(params.coords.lng).to.equal(-3.6845); + expect(isNaN(params.coords.alt)).to.be.true; + params = OSM.parseGeoURI("geo:57.6247,abc"); + expect(params).to.be.undefined; + }); + it("parses geoURIs with crs", function () { + let params = OSM.parseGeoURI("geo:57.6247,-3.6845;crs=wgs84"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845)); + params = OSM.parseGeoURI("geo:57.6247,-3.6845;CRS=wgs84"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845)); + params = OSM.parseGeoURI("geo:57.6247,-3.6845;CRS=WGS84"); + expect(params.coords).to.deep.equal(L.latLng(57.6247, -3.6845)); + }); + it("rejects geoURIs with different crs", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845;crs=utm"); + expect(params).to.be.undefined; + }); + it("parses geoURIs with uncertainty", function () { + let params = OSM.parseGeoURI("geo:57.6247,-3.6845;u=100"); + expect(params.uncertainty).to.equal(100); + params = OSM.parseGeoURI("geo:57.6247,-3.6845;U=100"); + expect(params.uncertainty).to.equal(100); + }); + it("ignores negative uncertainty", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845;u=-100"); + expect(params.uncertainty).to.be.undefined; + }); + it("ignores non-numeric uncertainty", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845;u=abc"); + expect(params.uncertainty).to.be.undefined; + }); + it("parses uncertainty 0", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845;u=0"); + expect(params.uncertainty).to.equal(0); + }); + it("ignores uncertainty in the query parameters", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845?u=100"); + expect(params.uncertainty).to.be.undefined; + }); + it("parses geoURIs with zoom", function () { + let params = OSM.parseGeoURI("geo:57.6247,-3.6845?z=16"); + expect(params.zoom).to.equal(16); + params = OSM.parseGeoURI("geo:57.6247,-3.6845?Z=16"); + expect(params.zoom).to.be.undefined; + }); + it("ignores non-numeric zoom", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845?z=abc"); + expect(params.zoom).to.be.undefined; + }); + it("ignores negative zoom", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845?z=-100"); + expect(params.zoom).to.be.undefined; + }); + it("parses geoURIs with zoom level 0", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845?z=0"); + expect(params.zoom).to.equal(0); + }); + it("ignores zoom in the geouri parameters", function () { + const params = OSM.parseGeoURI("geo:57.6247,-3.6845;z=16"); + expect(params.zoom).to.be.undefined; + }); + }); + describe(".parseHash", function () { it("parses lat/lon/zoom params", function () { const args = OSM.parseHash("#map=5/57.6247/-3.6845&layers=M");