From ae9a6c8e99a78abca11bc2b03e1511e95580caad Mon Sep 17 00:00:00 2001 From: Yushan Mu Date: Thu, 10 Oct 2024 15:16:34 -0400 Subject: [PATCH] Fixes issue #992: Allow pasting GeoJSON links 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(/()|()|(