[gnome-maps/wip/mlundblad/improve-osm-url-parsing: 5/7] WIP: Add module with URL parsing util functions




commit 4d0670acc7894b4ff5309bee37b2612339dd0728
Author: Marcus Lundblad <ml update uu se>
Date:   Mon Nov 30 22:54:53 2020 +0100

    WIP: Add module with URL parsing util functions

 src/org.gnome.Maps.src.gresource.xml |   1 +
 src/urls.js                          | 104 +++++++++++++++++++++++++++++++++++
 tests/meson.build                    |   2 +-
 tests/urlsTest.js                    |  68 +++++++++++++++++++++++
 4 files changed, 174 insertions(+), 1 deletion(-)
---
diff --git a/src/org.gnome.Maps.src.gresource.xml b/src/org.gnome.Maps.src.gresource.xml
index 8a6dede5..d9eea458 100644
--- a/src/org.gnome.Maps.src.gresource.xml
+++ b/src/org.gnome.Maps.src.gresource.xml
@@ -104,6 +104,7 @@
     <file>userLocationBubble.js</file>
     <file>userLocationMarker.js</file>
     <file>utils.js</file>
+    <file>urls.js</file>
     <file>wikipedia.js</file>
     <file>xmldom/dom.js</file>
     <file>xmldom/domparser.js</file>
diff --git a/src/urls.js b/src/urls.js
new file mode 100644
index 00000000..96b698f2
--- /dev/null
+++ b/src/urls.js
@@ -0,0 +1,104 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2020 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+const _ = imports.gettext.gettext;
+
+const GLib = imports.gi.GLib;
+
+// Matches URLs for OpenStreetMap (for addressing objects or coordinates)
+const OSM_URL_REGEX = new RegExp(/https?:\/\/(www\.)?openstreetmap\.org./);
+
+/**
+ * For URLs identifiable as pointing to a coordinate
+ * e.g. an openstreetmap.org URL with lat and lon query parameters,
+ * returns [lat, lon, optional zoom], otherwise [].
+ */
+function parseAsCoordinateURL(url) {
+    if (url.match(OSM_URL_REGEX)) {
+        /* it seems #map= is not handle well by parse_params(), so just remove
+         * the # as a work-around
+         */
+        let uri = GLib.Uri.parse(url.replace('#map=', 'map='), GLib.UriFlags.NONE);
+        let params = GLib.Uri.parse_params(uri.get_query(), -1, '&',
+                                           GLib.UriParamsFlags.NONE);
+
+        let lat = params.lat;
+        let lon = params.lon;
+        let mlat = params.mlat;
+        let mlon = params.mlon;
+        let zoom;
+        let map = params.map;
+
+        if (map) {
+            let parts = map.split('/');
+
+            if (parts.length !== 3) {
+                return [];
+            } else {
+                zoom = parseInt(parts[0]);
+                lat = parseFloat(parts[1]);
+                lon = parseFloat(parts[2]);
+            }
+        } else if (mlat && mlon) {
+            lat = parseFloat(mlat);
+            lon = parseFloat(mlon);
+
+            if (params.zoom)
+                zoom = parseInt(params.zoom);
+        } else if (lat && lon) {
+            lat = parseFloat(lat);
+            lon = parseFloat(lon);
+
+            if (params.zoom)
+                zoom = parseInt(params.zoom);
+        } else {
+            return [];
+        }
+
+        return [lat, lon, zoom];
+    } else {
+        return [];
+    }
+}
+
+/**
+ * For URLs addressing a specific OSM object (node, way, or relation),
+ * returns [type,id], otherwise [].
+ */
+function parseAsObjectURL(url) {
+    if (url.match(OSM_URL_REGEX)) {
+        let uri = GLib.Uri.parse(url, GLib.UriFlags.NONE);
+        let path = uri.get_path();
+        let parts = path.split('/');
+
+        if (parts.length === 3 && parts[0] === '' &&
+            (parts[1] === 'node' ||
+             parts[1] === 'way' ||
+             parts[1] === 'relation')) {
+            let id = parseInt(parts[2]);
+
+            if (id > 0)
+                return [parts[1], id];
+        }
+    }
+
+    return [];
+}
diff --git a/tests/meson.build b/tests/meson.build
index 86475d09..551ade73 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -1,4 +1,4 @@
-tests = ['addressTest', 'colorTest', 'osmNamesTest', 'utilsTest']
+tests = ['addressTest', 'colorTest', 'osmNamesTest', 'utilsTest', 'urlsTest']
 
 foreach test : tests
   script_conf = configuration_data()
diff --git a/tests/urlsTest.js b/tests/urlsTest.js
new file mode 100644
index 00000000..b276df98
--- /dev/null
+++ b/tests/urlsTest.js
@@ -0,0 +1,68 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2020 Marcus Lundblad
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+const JsUnit = imports.jsUnit;
+
+const URLS = imports.urls;
+
+const OSM_COORD_URL1 =
+    'https://www.openstreetmap.org/?lat=39.9882&lon=-78.2409&zoom=14&layers=B000FTF';
+
+function main() {
+    parseAsObjectURLTest();
+    parseAsCoordinateURLTest();
+}
+
+function parseAsObjectURLTest() {
+    _assertArrayEquals([], URLS.parseAsObjectURL('https://www.example.com'));
+    _assertArrayEquals([], URLS.parseAsObjectURL('https://www.openstreet.org/'));
+    _assertArrayEquals(['node', 1],
+                       URLS.parseAsObjectURL('https://www.openstreetmap.org/node/1'));
+    _assertArrayEquals(['way', 2],
+                       URLS.parseAsObjectURL('https://www.openstreetmap.org/way/2'));
+    _assertArrayEquals(['relation', 3],
+                       URLS.parseAsObjectURL('https://www.openstreetmap.org/relation/3'));
+    _assertArrayEquals([],
+                       URLS.parseAsObjectURL('https://www.openstreetmap.org/foo/1'));
+    _assertArrayEquals(['node', 4],
+                       URLS.parseAsObjectURL('https://openstreetmap.org/node/4'));
+    _assertArrayEquals(['node', 5],
+                       URLS.parseAsObjectURL('http://www.openstreetmap.org/node/5'));
+}
+
+function parseAsCoordinateURLTest() {
+    _assertArrayEquals([],
+                       URLS.parseAsCoordinateURL('https://www.example.com'));
+    _assertArrayEquals([],
+                       URLS.parseAsCoordinateURL('https://www.openstreet.org/'));
+    _assertArrayEquals([39.9882, -78.2409, 14],
+                       
URLS.parseAsCoordinateURL('https://www.openstreetmap.org/?lat=39.9882&lon=-78.2409&zoom=14&layers=B000FTF'));
+    _assertArrayEquals([59.40538, 17.34894, 12],
+                       
URLS.parseAsCoordinateURL('https://www.openstreetmap.org/?#map=12/59.40538/17.34894'));
+}
+
+function _assertArrayEquals(arr1, arr2) {
+    JsUnit.assertEquals(arr1.length, arr2.length);
+    for (let i = 0; i < arr1.length; i++) {
+        JsUnit.assertEquals(arr1[i], arr2[i]);
+    }
+}
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]