From ccf7b1f38886431a9e3282a63fcf43a6b7605ba0 Mon Sep 17 00:00:00 2001 From: Yushan Mu <93682606+yushan-mu@users.noreply.github.com> Date: Fri, 6 Dec 2024 14:32:48 -0500 Subject: [PATCH] Fixes issue #992: Allow pasting GeoJSON links (#996) Edited description, strict equality, and test timeouts allow pasting of links ending in json or geojson which may have different content type Added tests for files with (geo)json extensions Cleaned up and synched tests --- src/mapml/utils/Util.js | 61 ++-- test/e2e/data/geojson/geojsonFeature.geojson | 276 +++++++++++++++++++ test/e2e/data/geojson/geojsonPoint.json | 54 ++++ test/e2e/mapml-viewer/mapml-viewer.html | 4 + test/e2e/mapml-viewer/mapml-viewer.test.js | 61 ++++ test/e2e/web-map/map.html | 4 + test/e2e/web-map/map.test.js | 61 ++++ test/server.js | 44 +++ 8 files changed, 547 insertions(+), 18 deletions(-) create mode 100644 test/e2e/data/geojson/geojsonFeature.geojson create mode 100644 test/e2e/data/geojson/geojsonPoint.json diff --git a/src/mapml/utils/Util.js b/src/mapml/utils/Util.js index 34ac1352a..9e18790a9 100644 --- a/src/mapml/utils/Util.js +++ b/src/mapml/utils/Util.js @@ -646,29 +646,54 @@ export const Util = { return [column, row]; }, - // Pastes text to a mapml-viewer/map element(mapEl), text can be a mapml link, geojson, or a map-layer - // used for pasting layers through ctrl+v, drag/drop, and pasting through the contextmenu + // Pastes text to a mapml-viewer/map element(mapEl), text can be a mapml link, GeoJSON link, GeoJSON, + // or a map-layer used for pasting layers through ctrl+v, drag/drop, and pasting through the contextmenu // _pasteLayer: HTMLElement Str -> None // Effects: append a map-layer element to mapEl, if it is valid - _pasteLayer: function (mapEl, text) { + _pasteLayer: async function (mapEl, text) { try { + // try to process text as a link new URL(text); - // create a new child of the element - let l = - ''; - mapEl.insertAdjacentHTML('beforeend', l); - mapEl.lastElementChild.whenReady().catch(() => { - if (mapEl) { - // should invoke lifecyle callbacks automatically by removing it from DOM - mapEl.removeChild(mapEl.lastChild); + // get the content type of the link + const response = await fetch(text); + const contentType = response.headers.get('Content-Type'); + // get the file extension by removing any query strings that may exist + let ext = response.url + .split('?')[0] + .split('#')[0] + .split('.') + .pop() + .toLowerCase(); + if ( + contentType === 'application/json' || + contentType === 'application/geo+json' || + ext === 'geojson' || + ext === 'json' + ) { + // try to process as GeoJSON + const textContent = await response.text(); + try { + mapEl.geojson2mapml(JSON.parse(textContent)); + } catch { + console.log('Error parsing GeoJSON from: ' + text); } - // garbage collect it - l = null; - }); + } else { + // try to process as a mapml file + // create a new child of the element + let l = + ''; + mapEl.insertAdjacentHTML('beforeend', l); + mapEl.lastElementChild.whenReady().catch(() => { + if (mapEl) { + // should invoke lifecyle callbacks automatically by removing it from DOM + mapEl.removeChild(mapEl.lastChild); + } + }); + } } catch (err) { text = text .replace(/()|()|(