From df76ffd80e4553869b08b67d091130dd96b25029 Mon Sep 17 00:00:00 2001 From: David Larlet Date: Thu, 11 Jan 2024 14:50:02 -0500 Subject: [PATCH 01/15] feat: Create an oEmbed endpoint for maps Fix #162 --- umap/templates/umap/map_detail.html | 3 ++ umap/tests/test_map_views.py | 70 ++++++++++++++++++++++++++--- umap/tests/test_views.py | 2 +- umap/urls.py | 1 + umap/views.py | 62 ++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 8 deletions(-) diff --git a/umap/templates/umap/map_detail.html b/umap/templates/umap/map_detail.html index 25f927e7..8efc7c96 100644 --- a/umap/templates/umap/map_detail.html +++ b/umap/templates/umap/map_detail.html @@ -12,6 +12,9 @@ {% endcompress %} {% umap_js locale=locale %} {% if object.share_status != object.PUBLIC %}{% endif %} + {% endblock extra_head %} {% block content %} {% block map_init %} diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index 6ef798e2..b8595900 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -275,7 +275,7 @@ def test_owner_cannot_access_map_with_share_status_blocked(client, map): assert response.status_code == 403 -def test_non_editor_cannot_access_map_if_share_status_private(client, map, user): # noqa +def test_non_editor_cannot_access_map_if_share_status_private(client, map, user): url = reverse("map", args=(map.slug, map.pk)) map.share_status = map.PRIVATE map.save() @@ -346,14 +346,14 @@ def test_anonymous_create(cookieclient, post_data): @pytest.mark.usefixtures("allow_anonymous") -def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): # noqa +def test_anonymous_update_without_cookie_fails(client, anonymap, post_data): url = reverse("map_update", kwargs={"map_id": anonymap.pk}) response = client.post(url, post_data) assert response.status_code == 403 @pytest.mark.usefixtures("allow_anonymous") -def test_anonymous_update_with_cookie_should_work(cookieclient, anonymap, post_data): # noqa +def test_anonymous_update_with_cookie_should_work(cookieclient, anonymap, post_data): url = reverse("map_update", kwargs={"map_id": anonymap.pk}) # POST only mendatory fields name = "new map name" @@ -420,7 +420,7 @@ def test_bad_anonymous_edit_url_should_return_403(cookieclient, anonymap): @pytest.mark.usefixtures("allow_anonymous") def test_clone_anonymous_map_should_not_be_possible_if_user_is_not_allowed( client, anonymap, user -): # noqa +): assert Map.objects.count() == 1 url = reverse("map_clone", kwargs={"map_id": anonymap.pk}) anonymap.edit_status = anonymap.OWNER @@ -434,7 +434,7 @@ def test_clone_anonymous_map_should_not_be_possible_if_user_is_not_allowed( @pytest.mark.usefixtures("allow_anonymous") -def test_clone_map_should_be_possible_if_edit_status_is_anonymous(client, anonymap): # noqa +def test_clone_map_should_be_possible_if_edit_status_is_anonymous(client, anonymap): assert Map.objects.count() == 1 url = reverse("map_clone", kwargs={"map_id": anonymap.pk}) anonymap.edit_status = anonymap.ANONYMOUS @@ -675,3 +675,63 @@ def test_download_my_map(client, map, datalayer): # Test response is a json j = json.loads(response.content.decode()) assert j["type"] == "umap" + + +@pytest.mark.parametrize("share_status", [Map.PRIVATE, Map.BLOCKED, Map.OPEN]) +def test_oembed_shared_status_map(client, map, datalayer, share_status): + map.share_status = share_status + map.save() + url = f"{reverse('map_oembed')}?url=http://testserver{map.get_absolute_url()}" + response = client.get(url) + assert response.status_code == 403 + + +def test_oembed_no_url_map(client, map, datalayer): + url = reverse("map_oembed") + response = client.get(url) + assert response.status_code == 404 + + +def test_oembed_wrong_format_map(client, map, datalayer): + url = ( + f"{reverse('map_oembed')}" + f"?url=http://testserver{map.get_absolute_url()}&format=xml" + ) + response = client.get(url) + assert response.status_code == 501 + + +def test_oembed_wrong_domain_map(client, map, datalayer): + url = f"{reverse('map_oembed')}?url=http://BADserver{map.get_absolute_url()}" + response = client.get(url) + assert response.status_code == 404 + + +def test_oembed_map(client, map, datalayer): + url = f"{reverse('map_oembed')}?url=http://testserver{map.get_absolute_url()}" + response = client.get(url) + assert response.status_code == 200 + j = json.loads(response.content.decode()) + assert j["type"] == "rich" + assert j["version"] == "1.0" + assert j["width"] == 800 + assert j["height"] == 300 + assert j["html"] == ( + '' + f'

See full screen

' + ) + + +def test_oembed_link(client, map, datalayer): + response = client.get(map.get_absolute_url()) + assert response.status_code == 200 + assert ( + '' in response.content.decode() diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index 1c865357..5686500c 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -1,6 +1,6 @@ import json import socket -from datetime import date, datetime, timedelta +from datetime import datetime, timedelta import pytest from django.conf import settings diff --git a/umap/urls.py b/umap/urls.py index f2905025..53893748 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -41,6 +41,7 @@ urlpatterns = [ ), re_path(r"^i18n/", include("django.conf.urls.i18n")), re_path(r"^agnocomplete/", include("agnocomplete.urls")), + re_path(r"^map/oembed/", views.MapOEmbed.as_view(), name="map_oembed"), re_path( r"^map/(?P\d+)/download/", can_view_map(views.MapDownload.as_view()), diff --git a/umap/views.py b/umap/views.py index 1032bdf0..d661dcfe 100644 --- a/umap/views.py +++ b/umap/views.py @@ -18,21 +18,23 @@ from django.contrib.auth import logout as do_logout from django.contrib.gis.measure import D from django.contrib.postgres.search import SearchQuery, SearchVector from django.contrib.staticfiles.storage import staticfiles_storage +from django.core.exceptions import PermissionDenied from django.core.mail import send_mail from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.core.signing import BadSignature, Signer from django.core.validators import URLValidator, ValidationError -from django.db.models import Q from django.http import ( + Http404, HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, HttpResponsePermanentRedirect, HttpResponseRedirect, + HttpResponseServerError, ) from django.middleware.gzip import re_accepts_gzip from django.shortcuts import get_object_or_404 -from django.urls import reverse, reverse_lazy +from django.urls import resolve, reverse, reverse_lazy from django.utils.encoding import smart_bytes from django.utils.http import http_date from django.utils.timezone import make_aware @@ -526,6 +528,16 @@ class PermissionsMixin: class MapView(MapDetailMixin, PermissionsMixin, DetailView): + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["oembed_absolute_uri"] = self.request.build_absolute_uri( + reverse("map_oembed") + ) + context["absolute_uri"] = self.request.build_absolute_uri( + self.object.get_absolute_url() + ) + return context + def get(self, request, *args, **kwargs): self.object = self.get_object() canonical = self.get_canonical_url() @@ -607,6 +619,52 @@ class MapDownload(DetailView): return response +class MapOEmbed(View): + def get(self, request, *args, **kwargs): + data = {"type": "rich", "version": "1.0"} + format_ = request.GET.get("format", "json") + if format_ != "json": + response = HttpResponseServerError("Only `json` format is implemented.") + response.status_code = 501 + return response + + url = request.GET.get("url") + if not url: + raise Http404("Missing `url` parameter.") + + parsed_url = urlparse(url) + netloc = parsed_url.netloc + allowed_hosts = settings.ALLOWED_HOSTS + if parsed_url.hostname not in allowed_hosts and allowed_hosts != ["*"]: + raise Http404("Host not allowed.") + + url_path = parsed_url.path + view, args, kwargs = resolve(url_path) + if "slug" not in kwargs or "map_id" not in kwargs: + raise Http404("Invalid URL path.") + + map_ = Map.objects.get(id=kwargs["map_id"], slug=kwargs["slug"]) + + if map_.share_status != Map.PUBLIC: + raise PermissionDenied("This map is not public.") + + map_url = map_.get_absolute_url() + label = _("See full screen") + height = 300 + data["height"] = height + width = 800 + data["width"] = width + # TODISCUSS: do we keep width=100% by default for the iframe? + html = ( + f'' + f'

{label}

' + ) + data["html"] = html + return simple_json_response(**data) + + class MapViewGeoJSON(MapView): def get_canonical_url(self): return reverse("map_geojson", args=(self.object.pk,)) From 87b7c5627e7ba4a70f044a6d1854d516331c407e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:47:35 +0000 Subject: [PATCH 02/15] chore: bump vermin from 1.5.2 to 1.6.0 Bumps [vermin](https://github.com/netromdk/vermin) from 1.5.2 to 1.6.0. - [Release notes](https://github.com/netromdk/vermin/releases) - [Commits](https://github.com/netromdk/vermin/compare/v1.5.2...v1.6.0) --- updated-dependencies: - dependency-name: vermin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c8c80e93..ff3c3e48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ dev = [ "djlint==1.34.1", "mkdocs==1.5.3", "mkdocs-material==9.4.14", - "vermin==1.5.2", + "vermin==1.6.0", "pymdown-extensions==10.4", "isort==5.12", ] From 4227e171f3cb20f9386ee1503fabd76d1b70efdb Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 16 Jan 2024 12:28:59 +0100 Subject: [PATCH 03/15] fix: empty file input when closing the importer panel Otherwise, we cannot import anything else than a file, even when closing and reopening the panel. User needs to refresh the page. --- umap/static/umap/js/umap.importer.js | 1 + umap/tests/integration/test_import.py | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/umap/static/umap/js/umap.importer.js b/umap/static/umap/js/umap.importer.js index 83b37699..c9f4db9e 100644 --- a/umap/static/umap/js/umap.importer.js +++ b/umap/static/umap/js/umap.importer.js @@ -16,6 +16,7 @@ L.U.Importer = L.Class.extend({ { type: 'file', multiple: 'multiple', autofocus: true }, this.fileBox ) + this.map.ui.once('panel:closed', () => (this.fileInput.value = null)) this.urlInput = L.DomUtil.element( 'input', { type: 'text', placeholder: L._('Provide an URL here') }, diff --git a/umap/tests/integration/test_import.py b/umap/tests/integration/test_import.py index 14f914b1..ac5a3cdc 100644 --- a/umap/tests/integration/test_import.py +++ b/umap/tests/integration/test_import.py @@ -11,8 +11,9 @@ def test_umap_import_from_file(live_server, datalayer, page): button = page.get_by_title("Import data") expect(button).to_be_visible() button.click() + file_input = page.locator("input[type='file']") with page.expect_file_chooser() as fc_info: - page.locator("input[type='file']").click() + file_input.click() file_chooser = fc_info.value path = Path(__file__).parent.parent / "fixtures/display_on_load.umap" file_chooser.set_files(path) @@ -23,6 +24,10 @@ def test_umap_import_from_file(live_server, datalayer, page): expect(layers).to_have_count(3) nonloaded = page.locator(".umap-browse-datalayers li.off") expect(nonloaded).to_have_count(1) + assert file_input.input_value() + # Close the import panel + page.keyboard.press("Escape") + assert not file_input.input_value() def test_umap_import_geojson_from_textarea(live_server, datalayer, page): From 9f377da1b224ee63b6e810b2907ead0a8677c0df Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 15 Jan 2024 15:50:28 +0100 Subject: [PATCH 04/15] Introduce UMAP_HOME_FEED to control which maps are shown on the home page For now we have only three modes: - latest, which is the default and shows the last updated maps - highlighted, which shows only the map that have been starred by a least one staff member - None, which does not show any map --- docs/config/settings.md | 7 +++++ umap/settings/base.py | 1 + umap/templates/umap/home.html | 6 +++-- umap/tests/test_views.py | 49 +++++++++++++++++++++++++++++++++++ umap/views.py | 17 +++++++++--- 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/docs/config/settings.md b/docs/config/settings.md index f9995078..9c8c0666 100644 --- a/docs/config/settings.md +++ b/docs/config/settings.md @@ -218,6 +218,13 @@ ready for production use (no backup, etc.) Link to show on the header under the "Feedback and help" label. +#### UMAP_HOME_FEED + +Which feed to display on the home page. Three valid values: +- `"latest"`, which shows the latest maps (default) +- `"highlighted"`, which shows the maps that have been starred by a staff member +- `None`, which does not show any map on the home page + #### UMAP_MAPS_PER_PAGE How many maps to show in maps list, like search or home page. diff --git a/umap/settings/base.py b/umap/settings/base.py index 7437f416..76b1ad15 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -249,6 +249,7 @@ DATABASES = {"default": env.db(default="postgis://localhost:5432/umap")} UMAP_DEFAULT_SHARE_STATUS = None UMAP_DEFAULT_EDIT_STATUS = None UMAP_DEFAULT_FEATURES_HAVE_OWNERS = False +UMAP_HOME_FEED = "latest" UMAP_READONLY = env("UMAP_READONLY", default=False) UMAP_GZIP = True diff --git a/umap/templates/umap/home.html b/umap/templates/umap/home.html index cfd9fce0..47b2b880 100644 --- a/umap/templates/umap/home.html +++ b/umap/templates/umap/home.html @@ -10,7 +10,9 @@ {% endif %}
-

{% blocktrans %}Get inspired, browse maps{% endblocktrans %}

-
{% include "umap/map_list.html" %}
+ {% if maps %} +

{% blocktrans %}Get inspired, browse maps{% endblocktrans %}

+
{% include "umap/map_list.html" %}
+ {% endif %}
{% endblock maincontent %} diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index 1c865357..7055cd5d 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -10,6 +10,7 @@ from django.urls import reverse from django.utils.timezone import make_aware from umap import VERSION +from umap.models import Map, Star from umap.views import validate_url from .base import MapFactory, UserFactory @@ -391,3 +392,51 @@ def test_webmanifest(client): }, ] } + + +@pytest.mark.django_db +def test_home_feed(client, settings, user, tilelayer): + settings.UMAP_HOME_FEED = "latest" + staff = UserFactory(username="Staff", is_staff=True) + starred = MapFactory( + owner=user, name="A public map starred by staff", share_status=Map.PUBLIC + ) + MapFactory( + owner=user, name="A public map not starred by staff", share_status=Map.PUBLIC + ) + non_staff = MapFactory( + owner=user, name="A public map starred by non staff", share_status=Map.PUBLIC + ) + private = MapFactory( + owner=user, name="A private map starred by staff", share_status=Map.PRIVATE + ) + reserved = MapFactory( + owner=user, name="A reserved map starred by staff", share_status=Map.OPEN + ) + Star.objects.create(by=staff, map=starred) + Star.objects.create(by=staff, map=private) + Star.objects.create(by=staff, map=reserved) + Star.objects.create(by=user, map=non_staff) + response = client.get(reverse("home")) + content = response.content.decode() + assert "A public map starred by staff" in content + assert "A public map not starred by staff" in content + assert "A public map starred by non staff" in content + assert "A private map starred by staff" not in content + assert "A reserved map starred by staff" not in content + settings.UMAP_HOME_FEED = "highlighted" + response = client.get(reverse("home")) + content = response.content.decode() + assert "A public map starred by staff" in content + assert "A public map not starred by staff" not in content + assert "A public map starred by non staff" not in content + assert "A private map starred by staff" not in content + assert "A reserved map starred by staff" not in content + settings.UMAP_HOME_FEED = None + response = client.get(reverse("home")) + content = response.content.decode() + assert "A public map starred by staff" not in content + assert "A public map not starred by staff" not in content + assert "A public map starred by non staff" not in content + assert "A private map starred by staff" not in content + assert "A reserved map starred by staff" not in content diff --git a/umap/views.py b/umap/views.py index 1032bdf0..4f4aff50 100644 --- a/umap/views.py +++ b/umap/views.py @@ -119,13 +119,26 @@ class PublicMapsMixin(object): maps = qs.order_by("-modified_at") return maps + def get_highlighted_maps(self): + staff = User.objects.filter(is_staff=True) + stars = Star.objects.filter(by__in=staff).values("map") + qs = Map.public.filter(pk__in=stars) + maps = qs.order_by("-modified_at") + return maps + class Home(PaginatorMixin, TemplateView, PublicMapsMixin): template_name = "umap/home.html" list_template_name = "umap/map_list.html" def get_context_data(self, **kwargs): - maps = self.get_public_maps() + if settings.UMAP_HOME_FEED is None: + maps = [] + elif settings.UMAP_HOME_FEED == "highlighted": + maps = self.get_highlighted_maps() + else: + maps = self.get_public_maps() + maps = self.paginate(maps, settings.UMAP_MAPS_PER_PAGE) demo_map = None if hasattr(settings, "UMAP_DEMO_PK"): @@ -141,8 +154,6 @@ class Home(PaginatorMixin, TemplateView, PublicMapsMixin): except Map.DoesNotExist: pass - maps = self.paginate(maps, settings.UMAP_MAPS_PER_PAGE) - return { "maps": maps, "demo_map": demo_map, From cf13d1575354d669a6837a00b93202613d9547fc Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Tue, 16 Jan 2024 19:58:10 +0100 Subject: [PATCH 05/15] fix: honour datalayersControl=expanded in querystring fix #1525 --- umap/static/umap/js/umap.js | 5 +++ umap/tests/integration/test_querystring.py | 39 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 umap/tests/integration/test_querystring.py diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 88d328e7..bf0f5f91 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -122,6 +122,11 @@ L.U.Map.include({ `${this.HIDDABLE_CONTROLS[i]}Control` ) } + // Specific case for datalayersControl + // which accept "expanded" value, on top of true/false/null + if (L.Util.queryString('datalayersControl') === 'expanded') { + L.Util.setFromQueryString(this.options, 'datalayersControl') + } this.datalayersOnLoad = L.Util.queryString('datalayers') this.options.onLoadPanel = L.Util.queryString( 'onLoadPanel', diff --git a/umap/tests/integration/test_querystring.py b/umap/tests/integration/test_querystring.py new file mode 100644 index 00000000..faab701e --- /dev/null +++ b/umap/tests/integration/test_querystring.py @@ -0,0 +1,39 @@ +import pytest +from playwright.sync_api import expect + +pytestmark = pytest.mark.django_db + + +def test_scale_control(map, live_server, datalayer, page): + control = page.locator(".leaflet-control-scale") + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(control).to_be_visible() + page.goto(f"{live_server.url}{map.get_absolute_url()}?scaleControl=false") + expect(control).to_be_hidden() + + +def test_datalayers_control(map, live_server, datalayer, page): + control = page.locator(".umap-browse-toggle") + box = page.locator(".umap-browse-datalayers") + more = page.get_by_title("More controls") + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(control).to_be_visible() + expect(box).to_be_hidden() + page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=true") + expect(control).to_be_visible() + expect(box).to_be_hidden() + page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=null") + expect(control).to_be_hidden() + expect(more).to_be_visible() + more.click() + expect(control).to_be_visible() + expect(box).to_be_hidden() + page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=false") + expect(control).to_be_hidden() + expect(more).to_be_visible() + more.click() + expect(control).to_be_hidden() + expect(box).to_be_hidden() + page.goto(f"{live_server.url}{map.get_absolute_url()}?datalayersControl=expanded") + expect(control).to_be_hidden() + expect(box).to_be_visible() From fb63588ac550d250737cb484a74eab0ab648d451 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 17 Jan 2024 11:25:47 +0100 Subject: [PATCH 06/15] chore: use https://umap-project.org link in map footer --- umap/static/umap/js/umap.controls.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index f4bdead3..0b0817b2 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -1192,7 +1192,7 @@ L.U.AttributionControl = L.Control.Attribution.extend({ '', container, ` — ${L._('Powered by uMap')}`, - 'https://github.com/umap-project/umap/' + 'https://umap-project.org/' ) } L.DomUtil.createLink('attribution-toggle', this._container, '') From 502cd4cdedb5ed2ccce2ad1ca37ad91ff81c3ac3 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 17 Jan 2024 11:39:06 +0100 Subject: [PATCH 07/15] chore: remove support for settings starting with LEAFLET_STORAGE_ They are deprecated since 1.0 --- umap/settings/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/umap/settings/__init__.py b/umap/settings/__init__.py index 97943a35..914e8dc6 100644 --- a/umap/settings/__init__.py +++ b/umap/settings/__init__.py @@ -34,10 +34,7 @@ if path: for key in dir(d): if key.isupper(): value = getattr(d, key) - if key.startswith("LEAFLET_STORAGE"): - # Retrocompat pre 1.0, remove me in 1.1. - globals()["UMAP" + key[15:]] = value - elif key == "UMAP_CUSTOM_TEMPLATES": + if key == "UMAP_CUSTOM_TEMPLATES": if "DIRS" in globals()["TEMPLATES"][0]: globals()["TEMPLATES"][0]["DIRS"].insert(0, value) else: From 7e5c15b5b0b51776b0e9c5b7a631d1e5e060165b Mon Sep 17 00:00:00 2001 From: David Larlet Date: Fri, 19 Jan 2024 11:12:49 -0500 Subject: [PATCH 08/15] fix(1545): fix icons for mailto and tel Fix #1545 --- umap/static/umap/map.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index e34e1751..8ced20f0 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -1317,10 +1317,10 @@ a.add-datalayer:hover, margin: 5px; } a[href^='mailto']::before { - content: '🖃 '; + content: '✉︎ '; } a[href^='tel']::before { - content: '🕿 '; + content: '☎︎ '; } address span { padding-right: 5px; From d696fe885f14719d718e7c379151da0fa5caf423 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 22 Jan 2024 11:09:30 +0100 Subject: [PATCH 09/15] fix: do not ask more classes than available values in choropleth It actually does not make sense, and it's a sanity check: some computation algorithms fail in this situation. --- umap/static/umap/js/umap.layer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index 49edb3c4..ddb467e0 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -194,6 +194,7 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({ let mode = this.datalayer.options.choropleth.mode, classes = +this.datalayer.options.choropleth.classes || 5, breaks + classes = Math.min(classes, values.length) if (mode === 'manual') { const manualBreaks = this.datalayer.options.choropleth.breaks if (manualBreaks) { From ae4c1a9454f849fe3b8d7a8e53667e8be3a19c9d Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 22 Jan 2024 12:13:15 +0100 Subject: [PATCH 10/15] fix: build browser once features are on the map, not before MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Features title may contain variables, which include geographical ones (center, lat, lon…), and in this case the feature must be on the map to be able to compute them (eg. the polygon center). fix #1519 --- umap/static/umap/js/umap.browser.js | 14 ++++---- umap/tests/integration/test_browser.py | 48 ++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/umap/static/umap/js/umap.browser.js b/umap/static/umap/js/umap.browser.js index 77c3049d..177ccb8f 100644 --- a/umap/static/umap/js/umap.browser.js +++ b/umap/static/umap/js/umap.browser.js @@ -110,13 +110,13 @@ L.U.Browser = L.Class.extend({ const formContainer = L.DomUtil.create('div', '', container) const dataContainer = L.DomUtil.create('div', 'umap-browse-features', container) - const appendAll = () => { + const rebuildHTML = () => { dataContainer.innerHTML = '' this.map.eachBrowsableDataLayer((datalayer) => { this.addDatalayer(datalayer, dataContainer) }) } - const resetLayers = () => { + const redrawDataLayers = () => { this.map.eachBrowsableDataLayer((datalayer) => { datalayer.resetLayer(true) }) @@ -129,16 +129,16 @@ L.U.Browser = L.Class.extend({ makeDirty: false, callback: (e) => { if (e.helper.field === 'options.inBbox') { - if (this.options.inBbox) this.map.on('moveend', appendAll) - else this.map.off('moveend', appendAll) + if (this.options.inBbox) this.map.on('moveend', rebuildHTML) + else this.map.off('moveend', rebuildHTML) } - appendAll() - resetLayers() + redrawDataLayers() + rebuildHTML() }, }) formContainer.appendChild(builder.build()) - appendAll() + rebuildHTML() this.map.ui.openPanel({ data: { html: container }, diff --git a/umap/tests/integration/test_browser.py b/umap/tests/integration/test_browser.py index bde3acd7..f0a8c727 100644 --- a/umap/tests/integration/test_browser.py +++ b/umap/tests/integration/test_browser.py @@ -13,12 +13,12 @@ DATALAYER_DATA = { "features": [ { "type": "Feature", - "properties": {"name": "one point in france"}, + "properties": {"name": "one point in france", "foo": "point"}, "geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]}, }, { "type": "Feature", - "properties": {"name": "one polygon in greenland"}, + "properties": {"name": "one polygon in greenland", "foo": "polygon"}, "geometry": { "type": "Polygon", "coordinates": [ @@ -34,7 +34,7 @@ DATALAYER_DATA = { }, { "type": "Feature", - "properties": {"name": "one line in new zeland"}, + "properties": {"name": "one line in new zeland", "foo": "line"}, "geometry": { "type": "LineString", "coordinates": [ @@ -72,14 +72,28 @@ def test_data_browser_should_be_open(live_server, page, bootstrap, map): def test_data_browser_should_be_filterable(live_server, page, bootstrap, map): page.goto(f"{live_server.url}{map.get_absolute_url()}") markers = page.locator(".leaflet-marker-icon") + paths = page.locator(".leaflet-overlay-pane path") expect(markers).to_have_count(1) - el = page.locator("input[name='filter']") - expect(el).to_be_visible() - el.type("poly") + expect(paths).to_have_count(2) + filter_ = page.locator("input[name='filter']") + expect(filter_).to_be_visible() + filter_.type("poly") expect(page.get_by_text("one point in france")).to_be_hidden() expect(page.get_by_text("one line in new zeland")).to_be_hidden() expect(page.get_by_text("one polygon in greenland")).to_be_visible() expect(markers).to_have_count(0) # Hidden by filter + expect(paths).to_have_count(1) # Only polygon + # Empty the filter + filter_.fill("") + filter_.blur() + expect(markers).to_have_count(1) + expect(paths).to_have_count(2) + filter_.type("point") + expect(page.get_by_text("one point in france")).to_be_visible() + expect(page.get_by_text("one line in new zeland")).to_be_hidden() + expect(page.get_by_text("one polygon in greenland")).to_be_hidden() + expect(markers).to_have_count(1) + expect(paths).to_have_count(0) def test_data_browser_can_show_only_visible_features(live_server, page, bootstrap, map): @@ -131,3 +145,25 @@ def test_data_browser_bbox_limit_should_be_dynamic(live_server, page, bootstrap, expect(page.get_by_text("one point in france")).to_be_visible() expect(page.get_by_text("one polygon in greenland")).to_be_visible() expect(page.get_by_text("one line in new zeland")).to_be_hidden() + + +def test_data_browser_with_variable_in_name(live_server, page, bootstrap, map): + # Include a variable + map.settings["properties"]["labelKey"] = "{name} ({foo})" + map.save() + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(page.get_by_text("one point in france (point)")).to_be_visible() + expect(page.get_by_text("one line in new zeland (line)")).to_be_visible() + expect(page.get_by_text("one polygon in greenland (polygon)")).to_be_visible() + filter_ = page.locator("input[name='filter']") + expect(filter_).to_be_visible() + filter_.type("foobar") # Hide all + expect(page.get_by_text("one point in france (point)")).to_be_hidden() + expect(page.get_by_text("one line in new zeland (line)")).to_be_hidden() + expect(page.get_by_text("one polygon in greenland (polygon)")).to_be_hidden() + # Empty back the filter + filter_.fill("") + filter_.blur() + expect(page.get_by_text("one point in france (point)")).to_be_visible() + expect(page.get_by_text("one line in new zeland (line)")).to_be_visible() + expect(page.get_by_text("one polygon in greenland (polygon)")).to_be_visible() From d4e253190f1c0296e66299c2db55b9f6a38a087b Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 22 Jan 2024 17:26:06 +0100 Subject: [PATCH 11/15] feat: set preconnect link for tilelayer --- umap/templates/umap/map_detail.html | 5 ++++ umap/tests/base.py | 2 +- umap/tests/integration/test_export_map.py | 2 +- umap/tests/integration/test_map.py | 29 +++++++++++++++++++++++ umap/tests/test_map_views.py | 4 ++-- umap/views.py | 16 +++++++++++++ 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/umap/templates/umap/map_detail.html b/umap/templates/umap/map_detail.html index 42000f4a..88eb5d4e 100644 --- a/umap/templates/umap/map_detail.html +++ b/umap/templates/umap/map_detail.html @@ -7,6 +7,11 @@ map_detail {% endblock body_class %} {% block extra_head %} + {% if preconnect_domains %} + {% for domain in preconnect_domains %} + + {% endfor %} + {% endif %} {% umap_css %} {% umap_js locale=locale %} {% if object.share_status != object.PUBLIC %}{% endif %} diff --git a/umap/tests/base.py b/umap/tests/base.py index 687793e6..62f948eb 100644 --- a/umap/tests/base.py +++ b/umap/tests/base.py @@ -81,7 +81,7 @@ class MapFactory(factory.django.DjangoModelFactory): "attribution": "\xa9 OSM Contributors", "maxZoom": 18, "minZoom": 0, - "url_template": "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", + "url_template": "https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", }, "tilelayersControl": True, "zoom": 7, diff --git a/umap/tests/integration/test_export_map.py b/umap/tests/integration/test_export_map.py index e1735e9b..69599dde 100644 --- a/umap/tests/integration/test_export_map.py +++ b/umap/tests/integration/test_export_map.py @@ -61,7 +61,7 @@ def test_umap_export(map, live_server, datalayer, page): "attribution": "© OSM Contributors", "maxZoom": 18, "minZoom": 0, - "url_template": "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", + "url_template": "https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", }, "tilelayersControl": True, "zoom": 7, diff --git a/umap/tests/integration/test_map.py b/umap/tests/integration/test_map.py index 3bcbb2f8..7f77ad5f 100644 --- a/umap/tests/integration/test_map.py +++ b/umap/tests/integration/test_map.py @@ -12,6 +12,35 @@ from ..base import DataLayerFactory pytestmark = pytest.mark.django_db +def test_preconnect_for_tilelayer(map, page, live_server, tilelayer): + page.goto(f"{live_server.url}{map.get_absolute_url()}") + meta = page.locator('link[rel="preconnect"]') + expect(meta).to_have_count(1) + expect(meta).to_have_attribute("href", "//a.tile.openstreetmap.fr") + # Add custom tilelayer + map.settings["properties"]["tilelayer"] = { + "name": "OSM Piano FR", + "maxZoom": 20, + "minZoom": 0, + "attribution": "test", + "url_template": "https://a.piano.tiles.quaidorsay.fr/fr{r}/{z}/{x}/{y}.png", + } + map.save() + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(meta).to_have_attribute("href", "//a.piano.tiles.quaidorsay.fr") + # Add custom tilelayer with variable in domain, should create a preconnect + map.settings["properties"]["tilelayer"] = { + "name": "OSM Piano FR", + "maxZoom": 20, + "minZoom": 0, + "attribution": "test", + "url_template": "https://{s}.piano.tiles.quaidorsay.fr/fr{r}/{z}/{x}/{y}.png", + } + map.save() + page.goto(f"{live_server.url}{map.get_absolute_url()}") + expect(meta).to_have_count(0) + + def test_default_view_latest_without_datalayer_should_use_default_center( map, live_server, datalayer, page ): diff --git a/umap/tests/test_map_views.py b/umap/tests/test_map_views.py index 6ef798e2..f31350e3 100644 --- a/umap/tests/test_map_views.py +++ b/umap/tests/test_map_views.py @@ -19,7 +19,7 @@ def post_data(): return { "name": "name", "center": '{"type":"Point","coordinates":[13.447265624999998,48.94415123418794]}', # noqa - "settings": '{"type":"Feature","geometry":{"type":"Point","coordinates":[5.0592041015625,52.05924589011585]},"properties":{"tilelayer":{"maxZoom":20,"url_template":"http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png","minZoom":0,"attribution":"HOT and friends"},"licence":"","description":"","name":"test enrhûmé","tilelayersControl":true,"displayDataBrowserOnLoad":false,"displayPopupFooter":true,"displayCaptionOnLoad":false,"miniMap":true,"moreControl":true,"scaleControl":true,"zoomControl":true,"datalayersControl":true,"zoom":8}}', # noqa + "settings": '{"type":"Feature","geometry":{"type":"Point","coordinates":[5.0592041015625,52.05924589011585]},"properties":{"tilelayer":{"maxZoom":20,"url_template":"http://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png","minZoom":0,"attribution":"HOT and friends"},"licence":"","description":"","name":"test enrhûmé","tilelayersControl":true,"displayDataBrowserOnLoad":false,"displayPopupFooter":true,"displayCaptionOnLoad":false,"miniMap":true,"moreControl":true,"scaleControl":true,"zoomControl":true,"datalayersControl":true,"zoom":8}}', # noqa } @@ -624,7 +624,7 @@ def test_download(client, map, datalayer): "attribution": "© OSM Contributors", "maxZoom": 18, "minZoom": 0, - "url_template": "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", + "url_template": "https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png", }, "tilelayersControl": True, "zoom": 7, diff --git a/umap/views.py b/umap/views.py index 4561fadf..b152afea 100644 --- a/umap/views.py +++ b/umap/views.py @@ -421,6 +421,21 @@ class MapDetailMixin: model = Map pk_url_kwarg = "map_id" + def set_preconnect(self, properties, context): + # Try to extract the tilelayer domain, in order to but a preconnect meta. + url_template = properties.get("tilelayer", {}).get("url_template") + # Not explicit tilelayer set, take the first of the list, which will be + # used by frontend too. + if not url_template: + tilelayers = properties.get("tilelayers") + if tilelayers: + url_template = tilelayers[0].get("url_template") + if url_template: + domain = urlparse(url_template).netloc + # Do not try to preconnect on domains with variables + if domain and "{" not in domain: + context["preconnect_domains"] = [f"//{domain}"] + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) user = self.request.user @@ -473,6 +488,7 @@ class MapDetailMixin: map_settings["properties"].update(properties) map_settings["properties"]["datalayers"] = self.get_datalayers() context["map_settings"] = json.dumps(map_settings, indent=settings.DEBUG) + self.set_preconnect(map_settings["properties"], context) return context def get_datalayers(self): From 256d6c631c048fba356f5814bf8d1d0032cde6e9 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 29 Jan 2024 12:24:16 +0100 Subject: [PATCH 12/15] feat: use svg for default icon (circle) fix #1560 --- umap/models.py | 2 +- umap/static/umap/img/marker.svg | 4 ++++ umap/static/umap/test/_pre.js | 2 +- umap/tests/integration/test_picto.py | 6 +++--- umap/views.py | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 umap/static/umap/img/marker.svg diff --git a/umap/models.py b/umap/models.py index c74e7c0e..d63f00fd 100644 --- a/umap/models.py +++ b/umap/models.py @@ -216,7 +216,7 @@ class Map(NamedModel): "umap_id": self.pk, "onLoadPanel": "none", "captionBar": False, - "default_iconUrl": "%sumap/img/marker.png" % settings.STATIC_URL, + "default_iconUrl": "%sumap/img/marker.svg" % settings.STATIC_URL, "slideshow": {}, } ) diff --git a/umap/static/umap/img/marker.svg b/umap/static/umap/img/marker.svg new file mode 100644 index 00000000..9b579a76 --- /dev/null +++ b/umap/static/umap/img/marker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/umap/static/umap/test/_pre.js b/umap/static/umap/test/_pre.js index 22e519c2..30d407d3 100644 --- a/umap/static/umap/test/_pre.js +++ b/umap/static/umap/test/_pre.js @@ -132,7 +132,7 @@ function initMap(options) { map_update_permissions: '/map/{map_id}/update/permissions/', map_download: '/map/{map_id}/download/', }, - default_iconUrl: '../src/img/marker.png', + default_iconUrl: '../src/img/marker.svg', zoom: 6, share_statuses: [ [1, 'Tout le monde (public)'], diff --git a/umap/tests/integration/test_picto.py b/umap/tests/integration/test_picto.py index 673c0c9c..96048b08 100644 --- a/umap/tests/integration/test_picto.py +++ b/umap/tests/integration/test_picto.py @@ -46,7 +46,7 @@ def test_can_change_picto_at_map_level(map, live_server, page, pictos): marker = page.locator(".umap-div-icon img") expect(marker).to_have_count(1) # Should have default img - expect(marker).to_have_attribute("src", "/static/umap/img/marker.png") + expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg") edit_settings = page.get_by_title("Edit map properties") expect(edit_settings).to_be_visible() edit_settings.click() @@ -66,7 +66,7 @@ def test_can_change_picto_at_map_level(map, live_server, page, pictos): symbols.click() expect(marker).to_have_attribute("src", "/uploads/pictogram/star.svg") undefine.click() - expect(marker).to_have_attribute("src", "/static/umap/img/marker.png") + expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg") def test_can_change_picto_at_datalayer_level(map, live_server, page, pictos): @@ -147,7 +147,7 @@ def test_can_use_remote_url_as_picto(map, live_server, page, pictos): marker = page.locator(".umap-div-icon img") expect(marker).to_have_count(1) # Should have default img - expect(marker).to_have_attribute("src", "/static/umap/img/marker.png") + expect(marker).to_have_attribute("src", "/static/umap/img/marker.svg") edit_settings = page.get_by_title("Edit map properties") expect(edit_settings).to_be_visible() edit_settings.click() diff --git a/umap/views.py b/umap/views.py index 4561fadf..30e57a27 100644 --- a/umap/views.py +++ b/umap/views.py @@ -428,7 +428,7 @@ class MapDetailMixin: "urls": _urls_for_js(), "tilelayers": TileLayer.get_list(), "editMode": self.edit_mode, - "default_iconUrl": "%sumap/img/marker.png" % settings.STATIC_URL, # noqa + "default_iconUrl": "%sumap/img/marker.svg" % settings.STATIC_URL, # noqa "umap_id": self.get_umap_id(), "starred": self.is_starred(), "licences": dict((l.name, l.json) for l in Licence.objects.all()), From 902240fe341794f1d9048d16ef12572cd1689048 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 29 Jan 2024 13:54:46 +0100 Subject: [PATCH 13/15] tests: fix test_collaborative_editing_draw_markers We needed to: - make playwright to wait for ajax requests - add a sleep to prevent saving two datalayer's version in the same second --- .../integration/test_collaborative_editing.py | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/umap/tests/integration/test_collaborative_editing.py b/umap/tests/integration/test_collaborative_editing.py index 1772e123..29cd9b58 100644 --- a/umap/tests/integration/test_collaborative_editing.py +++ b/umap/tests/integration/test_collaborative_editing.py @@ -1,9 +1,14 @@ +import re +from time import sleep + from playwright.sync_api import expect from umap.models import DataLayer from ..base import DataLayerFactory, MapFactory +DATALAYER_UPDATE = re.compile(r".*/datalayer/update/.*") + def test_collaborative_editing_create_markers(context, live_server, tilelayer): # Let's create a new map with an empty datalayer @@ -31,11 +36,17 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer): map_el_p1.click(position={"x": 200, "y": 200}) expect(marker_pane_p1).to_have_count(1) - save_p1.click() + with page_one.expect_response(DATALAYER_UPDATE): + save_p1.click() + # Prefent two layers to be saved on the same second, as we compare them based + # on time in case of conflict. FIXME do not use time for comparison. + sleep(1) assert DataLayer.objects.get(pk=datalayer.pk).settings == { "browsable": True, "displayOnLoad": True, "name": "test datalayer", + "editMode": "advanced", + "inCaption": True, } # Now navigate to this map from another tab @@ -60,7 +71,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer): map_el_p2.click(position={"x": 220, "y": 220}) expect(marker_pane_p2).to_have_count(2) - save_p2.click() + with page_two.expect_response(DATALAYER_UPDATE): + save_p2.click() + sleep(1) # No change after the save expect(marker_pane_p2).to_have_count(2) assert DataLayer.objects.get(pk=datalayer.pk).settings == { @@ -75,7 +88,8 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer): create_marker_p1.click() map_el_p1.click(position={"x": 150, "y": 150}) expect(marker_pane_p1).to_have_count(2) - save_p1.click() + with page_one.expect_response(DATALAYER_UPDATE): + save_p1.click() # Should now get the other marker too expect(marker_pane_p1).to_have_count(3) assert DataLayer.objects.get(pk=datalayer.pk).settings == { @@ -92,7 +106,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer): create_marker_p1.click() map_el_p1.click(position={"x": 180, "y": 150}) expect(marker_pane_p1).to_have_count(4) - save_p1.click() + with page_one.expect_response(DATALAYER_UPDATE): + save_p1.click() + sleep(1) # Should now get the other marker too assert DataLayer.objects.get(pk=datalayer.pk).settings == { "browsable": True, @@ -110,7 +126,9 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer): create_marker_p2.click() map_el_p2.click(position={"x": 250, "y": 150}) expect(marker_pane_p2).to_have_count(3) - save_p2.click() + with page_two.expect_response(DATALAYER_UPDATE): + save_p2.click() + sleep(1) # Should now get the other markers too assert DataLayer.objects.get(pk=datalayer.pk).settings == { "browsable": True, From c3691b235e6413880c615cc1785eedc8a4fd569b Mon Sep 17 00:00:00 2001 From: David Larlet Date: Mon, 29 Jan 2024 13:30:13 -0500 Subject: [PATCH 14/15] docs: define an explicit release stragegy --- docs/changelog.md | 2 +- docs/release.md | 33 +++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 7c28d262..dd7a6e3c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -42,7 +42,7 @@ - `umap/templates/umap/map_table.html` - `umap/templates/umap/user_dashboard.html` -[See the diff](https://github.com/umap-project/umap/compare/1.12.2...1.13.0#diff-1311890945256dbddf0e59928c2e9d4f59fd6bcc6b1fd33719ef35f03e5168b4). +[See the diff](https://github.com/umap-project/umap/compare/1.12.2...1.13.0#files_bucket). ## 1.12.2 - 2023-12-29 diff --git a/docs/release.md b/docs/release.md index fbb3e696..947f77ee 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,4 +1,6 @@ -# How to make a release +# Releases + +## How to make a release 1. Run tests: - `make test` @@ -20,12 +22,35 @@ 9. `make publish` 10. `make docker` -## Deploying instances +### Deploying instances -### OSMfr +#### OSMfr The process is manual for now, Yohan has one Makefile on his computer. -### ANCT +#### ANCT Update the [Dockerfile](https://gitlab.com/incubateur-territoires/startups/donnees-et-territoires/umap-dsfr-moncomptepro/-/blob/main/Dockerfile?ref_type=heads) with correct version and put a tag `YYYY.MM.DD` in order to deploy it to production. + + +## When to make a release + +We aim to support [Baseline](https://developer.mozilla.org/en-US/blog/baseline-evolution-on-mdn/) “Widely available” (implemented in major browsers within the last 30 months). + +### Major (2.Y.Z) + +* when we bump Django to a major version +* when we change how we store data (both in database and filesystem) + +### Minor (X.3.Z) + +* when we add new features +* when we improve an existing feature +* when we improve the usability +* when we change templates + +If it's not a major nor a patch, it's a minor. + +### Patch (X.Y.12) + +* when there are bugfixes From 65f1cdd6b4569657ef5e219d9b377fec85c41958 Mon Sep 17 00:00:00 2001 From: David Larlet Date: Mon, 29 Jan 2024 14:13:03 -0500 Subject: [PATCH 15/15] lint: use eslint with a browserslist configuration --- .eslintrc.json | 11 + .github/workflows/test-docs.yml | 89 +- Makefile | 3 +- package-lock.json | 1715 +++++++++++++++++++++++++++++- package.json | 7 +- umap/static/umap/js/umap.core.js | 1 + umap/static/umap/test/.eslintrc | 1 - 7 files changed, 1759 insertions(+), 68 deletions(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..6aef9e75 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "plugins": ["compat"], + "extends": ["plugin:compat/recommended"], + "env": { + "es6": true + }, + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + } +} diff --git a/.github/workflows/test-docs.yml b/.github/workflows/test-docs.yml index 08011612..52c275dc 100644 --- a/.github/workflows/test-docs.yml +++ b/.github/workflows/test-docs.yml @@ -2,9 +2,9 @@ name: Test & Docs on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] jobs: tests: @@ -24,57 +24,58 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.12"] + python-version: ['3.8', '3.12'] database: [postgresql] steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: '**/pyproject.toml' - - name: Install dependencies - run: | - sudo apt update - sudo apt install libgdal-dev - python -m pip install --upgrade pip - make develop installjs vendors - - name: run tests - run: make test - env: - DJANGO_SETTINGS_MODULE: 'umap.tests.settings' - UMAP_SETTINGS: 'umap/tests/settings.py' + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: '**/pyproject.toml' + - name: Install dependencies + run: | + sudo apt update + sudo apt install libgdal-dev + python -m pip install --upgrade pip + make develop installjs vendors + - name: run tests + run: make test + env: + DJANGO_SETTINGS_MODULE: 'umap.tests.settings' + UMAP_SETTINGS: 'umap/tests/settings.py' lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install dependencies - run: | - python3 -m pip install -e .[test,dev] + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + python3 -m pip install -e .[test,dev] + make installjs - - name: Run Lint - run: make lint - - - name: Run Docs - run: make docs + - name: Run Lint + run: make lint + + - name: Run Docs + run: make docs docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install dependencies - run: | - python3 -m pip install -r docs/requirements.txt + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + python3 -m pip install -r docs/requirements.txt - - name: Run Docs - run: mkdocs build + - name: Run Docs + run: mkdocs build diff --git a/Makefile b/Makefile index 6939e99a..c09c21f0 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,10 @@ format: ## Format the code and templates files .PHONY: lint lint: ## Lint the code and template files + npx eslint umap/static/umap/ &&\ djlint umap/templates --lint &&\ isort --check --profile black umap/ &&\ - ruff format --check --target-version=py38 umap/ &&\ + ruff format --check --target-version=py38 umap/ &&\ vermin --no-tips --violations -t=3.8- umap/ docs: ## Compile the docs diff --git a/package-lock.json b/package-lock.json index aca9d953..9d0e0cf6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,8 @@ }, "devDependencies": { "chai": "^3.3.0", + "eslint": "^8.56.0", + "eslint-plugin-compat": "^4.2.0", "happen": "~0.1.3", "lebab": "^3.2.1", "mocha": "^10.2.0", @@ -48,6 +50,148 @@ "uglify-js": "~3.17.4" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, "node_modules/@mapbox/sexagesimal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mapbox/sexagesimal/-/sexagesimal-1.1.0.tgz", @@ -59,6 +203,47 @@ "node": ">=4.0.0" } }, + "node_modules/@mdn/browser-compat-data": { + "version": "5.5.8", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.8.tgz", + "integrity": "sha512-E4gRHp5Kko37r6z1dO2qQ7xUUWig6GltUteuzi5WUKqHEayGN9DdGJWlgrYGnvwFc2Omh33MTJ8IXsD3t7+Okw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -137,15 +322,21 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -163,6 +354,22 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -236,6 +443,15 @@ "node": "*" } }, + "node_modules/ast-metadata-inferer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz", + "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==", + "dev": true, + "dependencies": { + "@mdn/browser-compat-data": "^5.2.34" + } + }, "node_modules/ast-types": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", @@ -319,6 +535,38 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer-equal": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", @@ -382,6 +630,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -394,6 +651,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, "node_modules/chai": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", @@ -526,6 +803,20 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/csv2geojson": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/csv2geojson/-/csv2geojson-5.1.1.tgz", @@ -673,6 +964,18 @@ "node": ">=0.4.0" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", @@ -700,6 +1003,12 @@ "domelementtype": "1" } }, + "node_modules/electron-to-chromium": { + "version": "1.4.648", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", + "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", + "dev": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -755,10 +1064,102 @@ "node": ">=4.0" } }, + "node_modules/eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-compat": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz", + "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==", + "dev": true, + "dependencies": { + "@mdn/browser-compat-data": "^5.3.13", + "ast-metadata-inferer": "^0.8.0", + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001524", + "find-up": "^5.0.0", + "lodash.memoize": "^4.1.2", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=14.x" + }, + "peerDependencies": { + "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -767,13 +1168,47 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -797,6 +1232,18 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -818,6 +1265,15 @@ "node": ">=4.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/f-matches": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/f-matches/-/f-matches-1.1.0.tgz", @@ -830,6 +1286,45 @@ "node": ">=4" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -867,6 +1362,26 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -1029,6 +1544,21 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -1041,6 +1571,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/happen": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/happen/-/happen-0.1.3.tgz", @@ -1148,6 +1684,40 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==" }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1273,6 +1843,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1318,6 +1897,12 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -1330,6 +1915,24 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/jsonparse": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", @@ -1364,6 +1967,15 @@ "xmldom": "^0.1.21" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", @@ -1533,6 +2145,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1560,6 +2185,18 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -1737,6 +2374,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/nise": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", @@ -1768,6 +2411,12 @@ "node": ">=4" } }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, "node_modules/nopt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", @@ -1831,6 +2480,23 @@ "wordwrap": "~0.0.2" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/osm-polygon-features": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/osm-polygon-features/-/osm-polygon-features-0.9.2.tgz", @@ -1910,6 +2576,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1928,6 +2606,15 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-scurry": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.8.0.tgz", @@ -1989,6 +2676,12 @@ "pbf": "bin/pbf" } }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2001,6 +2694,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -2026,6 +2728,35 @@ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-2.2.0.tgz", "integrity": "sha1-0pxs1z+2VZePtpiWkRgNuEQRn2E=" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2085,6 +2816,15 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/resolve-protobuf-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", @@ -2093,6 +2833,96 @@ "protocol-buffers-schema": "^2.0.2" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/runforcover": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", @@ -2129,6 +2959,33 @@ } ] }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -2138,6 +2995,27 @@ "randombytes": "^2.1.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -2296,6 +3174,12 @@ "node": ">=0.8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/through": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", @@ -2399,6 +3283,18 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", @@ -2408,6 +3304,18 @@ "node": "*" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -2425,6 +3333,45 @@ "node": ">=0.8.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -2448,6 +3395,21 @@ "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -2523,6 +3485,12 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yamlish": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", @@ -2584,11 +3552,152 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, "@mapbox/sexagesimal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mapbox/sexagesimal/-/sexagesimal-1.1.0.tgz", "integrity": "sha1-Y877k6RUlI0xpV6vRAx6rbOeM5o=" }, + "@mdn/browser-compat-data": { + "version": "5.5.8", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.8.tgz", + "integrity": "sha512-E4gRHp5Kko37r6z1dO2qQ7xUUWig6GltUteuzi5WUKqHEayGN9DdGJWlgrYGnvwFc2Omh33MTJ8IXsD3t7+Okw==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -2660,15 +3769,21 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, "acorn-jsx": { @@ -2678,6 +3793,18 @@ "dev": true, "requires": {} }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -2733,6 +3860,15 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "ast-metadata-inferer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz", + "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==", + "dev": true, + "requires": { + "@mdn/browser-compat-data": "^5.2.34" + } + }, "ast-types": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", @@ -2798,6 +3934,18 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.22.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, "buffer-equal": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.2.tgz", @@ -2842,12 +3990,24 @@ "get-intrinsic": "^1.0.2" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001581", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", + "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "dev": true + }, "chai": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", @@ -2953,6 +4113,17 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "csv2geojson": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/csv2geojson/-/csv2geojson-5.1.1.tgz", @@ -3059,6 +4230,15 @@ "traverse": "0.6.x" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", @@ -3085,6 +4265,12 @@ "domelementtype": "1" } }, + "electron-to-chromium": { + "version": "1.4.648", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", + "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3127,19 +4313,120 @@ } } }, + "eslint": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "eslint-plugin-compat": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz", + "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==", + "dev": true, + "requires": { + "@mdn/browser-compat-data": "^5.3.13", + "ast-metadata-inferer": "^0.8.0", + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001524", + "find-up": "^5.0.0", + "lodash.memoize": "^4.1.2", + "semver": "^7.5.4" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } @@ -3150,6 +4437,15 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -3165,6 +4461,12 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "f-matches": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/f-matches/-/f-matches-1.1.0.tgz", @@ -3174,6 +4476,42 @@ "lodash": "^4.17.5" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3199,6 +4537,23 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3330,6 +4685,15 @@ "is-glob": "^4.0.1" } }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3339,6 +4703,12 @@ "get-intrinsic": "^1.1.3" } }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "happen": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/happen/-/happen-0.1.3.tgz", @@ -3424,6 +4794,28 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==" }, + "ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3510,6 +4902,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -3540,6 +4938,12 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3549,6 +4953,24 @@ "argparse": "^2.0.1" } }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "jsonparse": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", @@ -3577,6 +4999,15 @@ "xmldom": "^0.1.21" } }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", @@ -3723,6 +5154,16 @@ } } }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3744,6 +5185,18 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3881,6 +5334,12 @@ "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "nise": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", @@ -3911,6 +5370,12 @@ } } }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, "nopt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-2.2.1.tgz", @@ -3959,6 +5424,20 @@ "wordwrap": "~0.0.2" } }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, "osm-polygon-features": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/osm-polygon-features/-/osm-polygon-features-0.9.2.tgz", @@ -4017,6 +5496,15 @@ "p-limit": "^3.0.2" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4029,6 +5517,12 @@ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-scurry": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.8.0.tgz", @@ -4079,12 +5573,24 @@ "resolve-protobuf-schema": "^2.0.0" } }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -4101,6 +5607,18 @@ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-2.2.0.tgz", "integrity": "sha1-0pxs1z+2VZePtpiWkRgNuEQRn2E=" }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4151,6 +5669,12 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "resolve-protobuf-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.0.0.tgz", @@ -4159,6 +5683,65 @@ "protocol-buffers-schema": "^2.0.2" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "runforcover": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/runforcover/-/runforcover-0.0.2.tgz", @@ -4178,6 +5761,26 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -4187,6 +5790,21 @@ "randombytes": "^2.1.0" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -4304,6 +5922,12 @@ "yamlish": "*" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "through": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", @@ -4399,12 +6023,27 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", "dev": true }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4416,6 +6055,25 @@ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -4439,6 +6097,15 @@ "resolved": "https://registry.npmjs.org/wgs84/-/wgs84-0.0.0.tgz", "integrity": "sha1-NP3FVZF7blfPKigu0ENxDASc3HY=" }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -4492,6 +6159,12 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yamlish": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/yamlish/-/yamlish-0.0.7.tgz", diff --git a/package.json b/package.json index 7d9b551e..8827b8cf 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ }, "devDependencies": { "chai": "^3.3.0", + "eslint": "^8.56.0", + "eslint-plugin-compat": "^4.2.0", "happen": "~0.1.3", "lebab": "^3.2.1", "mocha": "^10.2.0", @@ -60,5 +62,8 @@ "simple-statistics": "^7.8.3", "togpx": "^0.5.4", "tokml": "0.4.0" - } + }, + "browserslist": [ + "> 0.5%, last 2 versions, Firefox ESR, not dead, not op_mini all" + ] } diff --git a/umap/static/umap/js/umap.core.js b/umap/static/umap/js/umap.core.js index 99a123ea..2f5a845f 100644 --- a/umap/static/umap/js/umap.core.js +++ b/umap/static/umap/js/umap.core.js @@ -548,6 +548,7 @@ L.U.Help = L.Class.extend({ label.title = label.textContent = L._('Close') this.content = L.DomUtil.create('div', 'umap-help-content', this.box) this.isMacOS = /mac/i.test( + // eslint-disable-next-line compat/compat -- Fallback available. navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform ) }, diff --git a/umap/static/umap/test/.eslintrc b/umap/static/umap/test/.eslintrc index 08d92416..cdc6bb73 100644 --- a/umap/static/umap/test/.eslintrc +++ b/umap/static/umap/test/.eslintrc @@ -7,7 +7,6 @@ "after": true, "it": true, "sinon": true, - "qs": true, "enableEdit": true, "disableEdit": true, "changeInputValue": true,