diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ad6b6642..8ee4f359 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: env: - DATABASE_URL: postgres://user:password@localhost:5432/readux + DATABASE_URL: postgres://user:password@localhost:5432/readux_test DJANGO_ENV: test jobs: @@ -16,9 +16,9 @@ jobs: services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:7.17.5 + image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4 env: - STACK_VERSION: 7.17.5 + STACK_VERSION: 8.13.4 xpack.security.enabled: false cluster.name: readux-elasticsearch http.port: 9200 @@ -32,7 +32,7 @@ jobs: - 9200:9200 postgres: - image: postgres:12 + image: postgres:16 env: POSTGRES_PASSWORD: password POSTGRES_USER: user @@ -62,7 +62,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v4 with: - node-version: "20" + node-version: "24" - name: Install system requirements run: | @@ -86,16 +86,16 @@ jobs: # - name: Test Export # run: pytest apps/export/ - # - name: Test IIIF - # run: pytest apps/iiif/ + - name: Test IIIF + run: pytest apps/iiif/ - # - name: Test Readux - # run: pytest apps/readux/ + - name: Test Readux + run: pytest apps/readux/ - # - name: Test Users - # run: pytest apps/users/ + - name: Test Users + run: pytest apps/users/ - # - name: Test Webpack build - # run: | - # npm install - # npx webpack + - name: Test Vite build + run: | + npm install + npm run build diff --git a/apps/cms/models.py b/apps/cms/models.py index 9056f0ce..e4f332e5 100644 --- a/apps/cms/models.py +++ b/apps/cms/models.py @@ -3,7 +3,6 @@ from wagtail.models import Page from wagtail.fields import RichTextField, StreamField from wagtail.admin.panels import FieldPanel, MultiFieldPanel -from wagtailautocomplete.edit_handlers import AutocompletePanel from django.db import models from apps.cms.blocks import BaseStreamBlock from apps.readux.forms import AllCollectionsForm, AllVolumesForm @@ -237,7 +236,12 @@ def get_context(self, request): class HomePage(Page): - """Home page""" + """ + Home page + + NOTE: If the HomePage admin panel becomes unwieldy (collections or manifests lists grow large), the proper Wagtail 6 replacement is to register Collection and Manifest as snippets and use a SnippetChooserPanel or implement a custom ChooserWidget. But that's a separate improvement — for now this unblocks manage.py check. Give it another run. + """ + tagline = RichTextField(blank=True) content_display = models.CharField( max_length=20, @@ -313,9 +317,9 @@ class HomePage(Page): FieldPanel('tagline', classname="full"), FieldPanel('background_image', classname="full"), FieldPanel('content_display', classname="full"), - AutocompletePanel('featured_collections', target_model="kollections.Collection"), + FieldPanel('featured_collections'), FieldPanel('featured_collections_sort_order', classname="full"), - AutocompletePanel('featured_volumes', target_model="manifests.Manifest"), + FieldPanel('featured_volumes'), FieldPanel('featured_volumes_sort_order', classname="full"), MultiFieldPanel(children=[ FieldPanel('featured_story_title'), diff --git a/apps/iiif/kollections/admin.py b/apps/iiif/kollections/admin.py index 571c8aed..4cf632f8 100644 --- a/apps/iiif/kollections/admin.py +++ b/apps/iiif/kollections/admin.py @@ -5,7 +5,7 @@ from import_export import resources from import_export.admin import ImportExportModelAdmin -from apps.iiif.manifests.admin import SummernoteMixin +from apps.iiif.manifests.admin import RichTextMixin from .models import Collection from ..manifests.models import Manifest @@ -38,7 +38,7 @@ def manifest_pid(self, instance): manifest_pid.short_description = 'Manifest Local ID' -class CollectionAdmin(ImportExportModelAdmin, SummernoteMixin, admin.ModelAdmin): +class CollectionAdmin(ImportExportModelAdmin, RichTextMixin, admin.ModelAdmin): """Django admin configuration for a collection.""" inlines = [ ManifestInline, @@ -46,6 +46,6 @@ class CollectionAdmin(ImportExportModelAdmin, SummernoteMixin, admin.ModelAdmin) resource_class = CollectionResource list_display = ('id', 'pid', 'metadata', 'summary', 'label') search_fields = ('label', 'summary', 'pid') - summernote_fields = ('summary', 'summary_en',) + rich_text_fields = ('summary', 'summary_en',) admin.site.register(Collection, CollectionAdmin) diff --git a/apps/iiif/manifests/admin.py b/apps/iiif/manifests/admin.py index 126cc0fd..7b4d953d 100644 --- a/apps/iiif/manifests/admin.py +++ b/apps/iiif/manifests/admin.py @@ -6,7 +6,7 @@ from import_export import resources, fields from import_export.admin import ImportExportModelAdmin from import_export.widgets import ManyToManyWidget, ForeignKeyWidget -from django_summernote.admin import SummernoteModelAdmin +from tinymce.widgets import TinyMCE from .models import Manifest, Note, ImageServer, RelatedLink, Language from .forms import ManifestAdminForm from .views import AddToCollectionsView, MetadataImportView @@ -64,21 +64,18 @@ class RelatedLinksInline(admin.TabularInline): min_num = 0 -class SummernoteMixin(SummernoteModelAdmin): - class Media: - # NOTE: have to include these js and css dependencies for summernote when not using iframe - js = ( - "//code.jquery.com/jquery-3.7.1.min.js", - "//cdn.jsdelivr.net/npm/jquery.ui.widget@1.10.3/jquery.ui.widget.min.js", - ) - css = { - "all": [ - "//cdn.jsdelivr.net/npm/summernote@0.8.20/dist/summernote-lite.min.css" - ], - } +class RichTextMixin: + """Mixin that applies a TinyMCE widget to fields listed in rich_text_fields.""" + + rich_text_fields = () + + def formfield_for_dbfield(self, db_field, request, **kwargs): + if db_field.name in self.rich_text_fields: + kwargs["widget"] = TinyMCE() + return super().formfield_for_dbfield(db_field, request, **kwargs) -class ManifestAdmin(ImportExportModelAdmin, SummernoteMixin, admin.ModelAdmin): +class ManifestAdmin(ImportExportModelAdmin, RichTextMixin, admin.ModelAdmin): """Django admin configuration for manifests""" resource_class = ManifestResource @@ -95,7 +92,7 @@ class ManifestAdmin(ImportExportModelAdmin, SummernoteMixin, admin.ModelAdmin): "publisher", ) search_fields = ("id", "pid", "label", "author", "published_date") - summernote_fields = ("summary",) + rich_text_fields = ("summary",) form = ManifestAdminForm actions = ["add_to_collections_action"] inlines = [RelatedLinksInline] diff --git a/apps/iiif/manifests/documents.py b/apps/iiif/manifests/documents.py index e5c07e36..b261a8b4 100644 --- a/apps/iiif/manifests/documents.py +++ b/apps/iiif/manifests/documents.py @@ -57,12 +57,26 @@ class Index: """Settings for Elasticsearch""" name = f"{settings.INDEX_PREFIX}_manifests" if settings.INDEX_PREFIX else "manifests" + settings = { + "analysis": { + "analyzer": { + "en": { + "type": "custom", + "tokenizer": "standard", + "filter": ["lowercase", "stop", "porter_stem"], + } + } + } + } class Django: """Settings for automatically pulling data from Django""" model = Manifest ignore_signals = True + # Django 4.2+ requires chunk_size when calling iterator() on a queryset + # that uses prefetch_related(). This value is passed through as chunk_size. + queryset_pagination = 2000 # fields to map dynamically in Elasticsearch fields = [ diff --git a/apps/iiif/manifests/models.py b/apps/iiif/manifests/models.py index 10016e5b..9da60ac1 100644 --- a/apps/iiif/manifests/models.py +++ b/apps/iiif/manifests/models.py @@ -12,8 +12,10 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.conf import settings +from datetime import date as _date from edtf.fields import EDTFField from apps.iiif.manifests.validators import validate_edtf +from apps.utils.dates import date_to_jd, jd_to_date from ..choices import Choices from ..kollections.models import Collection from ..models import IiifBase @@ -424,6 +426,32 @@ def save(self, *args, **kwargs): # pylint: disable = arguments-differ super().save(*args, **kwargs) + # EDTFField.pre_save() runs inside super().save() and can write extreme JD + # values for imprecise strings like "186X" — upper bounds reaching year 9999, + # lower bounds falling before year 1 AD. Clamp after the fact using a direct + # queryset update() to avoid triggering another recursive save(). + today_jd = date_to_jd(_date.today()) + min_jd = date_to_jd(_date(1, 1, 1)) + # Read the raw float values EDTFField wrote during super().save() without + # going through EDTFField.from_db_value (which can recurse). .values() returns + # plain Python values, bypassing field descriptors entirely. + date_fields = ("date_earliest", "date_latest", "date_sort_ascending", "date_sort_descending") + db_dates = type(self).objects.filter(pk=self.pk).values(*date_fields).first() or {} + + update_fields = {} + for field in ("date_earliest", "date_sort_ascending"): + val = db_dates.get(field) + if val is not None and (jd_to_date(val) is None or val < min_jd): + update_fields[field] = None + for field in ("date_latest", "date_sort_descending"): + val = db_dates.get(field) + if val is not None and val > today_jd: + update_fields[field] = today_jd + if update_fields: + type(self).objects.filter(pk=self.pk).update(**update_fields) + for field, val in update_fields.items(): + setattr(self, field, val) + for collection in self.collections.all(): # pylint: disable = no-member collection.modified_at = self.modified_at collection.save() diff --git a/apps/iiif/models.py b/apps/iiif/models.py index cdc4a231..9e7d35b1 100644 --- a/apps/iiif/models.py +++ b/apps/iiif/models.py @@ -3,6 +3,7 @@ from dirtyfields import DirtyFieldsMixin from django.db import models from django.utils import timezone +from datetime import timezone as dt_timezone import config.settings.local as settings from modelcluster.models import ClusterableModel from apps.utils.noid import encode_noid @@ -63,7 +64,7 @@ def save(self, *args, **kwargs): # pylint: disable = arguments-differ @staticmethod def __js_isoformat(date): return date.astimezone( - timezone.utc).isoformat( + dt_timezone.utc).isoformat( timespec="milliseconds").replace("+00:00", "Z") def clean_pid(self): diff --git a/apps/readux/annotations.py b/apps/readux/annotations.py index 12237f79..c83dbbe0 100644 --- a/apps/readux/annotations.py +++ b/apps/readux/annotations.py @@ -22,7 +22,11 @@ class Annotations(View): """ def get_queryset(self): - return Canvas.objects.filter(pid=self.kwargs["canvas"], manifest__pid=self.kwargs["vol"]) + # Two URL patterns point to this view: + # user_annotations → annotations///list/ (kwarg: "volume") + # user_comments → iiif///annotations//... (kwarg: "vol") + manifest_pid = self.kwargs.get("volume") or self.kwargs.get("vol") + return Canvas.objects.filter(pid=self.kwargs["canvas"], manifest__pid=manifest_pid) def get(self, request, *args, **kwargs): username = kwargs["username"] diff --git a/apps/readux/context_processors.py b/apps/readux/context_processors.py index 2b2a3ef5..9daecb19 100644 --- a/apps/readux/context_processors.py +++ b/apps/readux/context_processors.py @@ -27,18 +27,35 @@ def current_version(_=None): """ repo = Repo(settings.ROOT_DIR.path()) - version_info = {"DJANGO_ENV": environ["DJANGO_ENV"], "APP_VERSION": __version__} + # Prefer the Django setting (which has a default) over os.environ directly, + # to avoid KeyError when DJANGO_ENV is not exported to the shell environment. + django_env = getattr(settings, "DJANGO_ENV", environ.get("DJANGO_ENV", "develop")) - if environ["DJANGO_ENV"] == "production": + version_info = {"DJANGO_ENV": django_env, "APP_VERSION": __version__} + + if django_env == "production": return version_info - return { - **version_info, - "BRANCH": repo.active_branch.name, - "COMMIT": repo.active_branch.commit.hexsha, - "COMMIT_DATE": repo.active_branch.commit.committed_datetime.strftime( - "%m/%d/%Y, %H:%M:%S" - ), - } + + try: + branch = repo.active_branch + return { + **version_info, + "BRANCH": branch.name, + "COMMIT": branch.commit.hexsha, + "COMMIT_DATE": branch.commit.committed_datetime.strftime( + "%m/%d/%Y, %H:%M:%S" + ), + } + except TypeError: + # HEAD is detached — e.g. during a git rebase or a CI checkout of a + # specific commit. Fall back to commit-level info without a branch name. + commit = repo.head.commit + return { + **version_info, + "BRANCH": commit.hexsha[:12], + "COMMIT": commit.hexsha, + "COMMIT_DATE": commit.committed_datetime.strftime("%m/%d/%Y, %H:%M:%S"), + } def footer_template(_): diff --git a/apps/readux/documents.py b/apps/readux/documents.py index 1bd139e5..9cf163eb 100644 --- a/apps/readux/documents.py +++ b/apps/readux/documents.py @@ -27,6 +27,17 @@ class Index: """Settings for Elasticsearch""" name = f"{settings.INDEX_PREFIX}_annotations" if settings.INDEX_PREFIX else "annotations" + settings = { + "analysis": { + "analyzer": { + "en": { + "type": "custom", + "tokenizer": "standard", + "filter": ["lowercase", "stop", "porter_stem"], + } + } + } + } class Django: """Settings for automatically pulling data from Django""" diff --git a/apps/readux/forms.py b/apps/readux/forms.py index 9bd56787..f7c71540 100644 --- a/apps/readux/forms.py +++ b/apps/readux/forms.py @@ -1,6 +1,5 @@ """Forms for Readux search""" -from dateutil import parser from django import forms from django.forms import widgets from django.conf import settings @@ -212,11 +211,14 @@ def set_facets(self, facets): ) def set_date(self, min_date, max_date): - """Use min and max aggregations from Elasticsearch to populate date range fields""" - min_date_object = parser.isoparse(min_date) - self.fields["start_date"].set_initial(min_date_object.strftime("%Y-%m-%d")) - max_date_object = parser.isoparse(max_date) - self.fields["end_date"].set_initial(max_date_object.strftime("%Y-%m-%d")) + """Use min and max aggregations from Elasticsearch to populate date range fields. + + Expects pre-formatted YYYY-MM-DD strings with zero-padded 4-digit years. + Avoid re-formatting via strftime here — strftime does not zero-pad years < 1000 + on all platforms, which breaks the JS date slider. + """ + self.fields["start_date"].set_initial(min_date) + self.fields["end_date"].set_initial(max_date) class CustomDropdownSelect(widgets.ChoiceWidget): diff --git a/apps/readux/search.py b/apps/readux/search.py index 871c836d..7621c0a4 100644 --- a/apps/readux/search.py +++ b/apps/readux/search.py @@ -45,6 +45,8 @@ def get_queryresults(self): volumes = ManifestDocument.search() # filter to only volume matching pid volumes = volumes.filter("term", pid=volume_pid) + # inner_hits carry the per-page match context; canvas_set _source is not needed + volumes = volumes.source(excludes=["canvas_set"]) # build query for nested fields (i.e. canvas position and text) nested_kwargs = { diff --git a/apps/readux/tests/test_forms.py b/apps/readux/tests/test_forms.py index a80b23de..b79b4204 100644 --- a/apps/readux/tests/test_forms.py +++ b/apps/readux/tests/test_forms.py @@ -52,8 +52,8 @@ def test_set_facets(self): @patch("apps.readux.forms.MinMaxDateField.set_initial") def test_set_date(self, mock_set_initial): """Should call set_initial on start_date and end_date form fields with formatted dates""" - min_date = "2022-01-01T00:00:00.000Z" - max_date = "2022-12-31T00:00:00.000Z" + min_date = "2022-01-01" + max_date = "2022-12-31" form = forms.ManifestSearchForm() form.set_date(min_date, max_date) mock_set_initial.assert_has_calls([call("2022-01-01"), call("2022-12-31")], any_order=True) diff --git a/apps/readux/tests/test_views.py b/apps/readux/tests/test_views.py index ec9c8df2..557524b9 100644 --- a/apps/readux/tests/test_views.py +++ b/apps/readux/tests/test_views.py @@ -309,25 +309,24 @@ def test_get_context_data(self, mock_set_date, mock_set_facets): with patch("apps.readux.views.VolumeSearchView.get_queryset") as mock_queryset: volume_search_view.queryset = mock_queryset volume_search_view.object_list = mock_queryset - mock_queryset.return_value.execute.return_value = Mock() - response = mock_queryset.return_value.execute.return_value + # The view calls get_queryset()[:0].execute() for aggregations, so the + # response comes through __getitem__, not directly from .execute(). + response = Mock() + mock_queryset.return_value.__getitem__.return_value.execute.return_value = response # these are not nested facets, so delete "inner" attributes del response.aggregations.language.inner del response.aggregations.author.inner - volume_search_view.get_context_data() - mock_set_facets.assert_called_with( - { - "language": response.aggregations.language.buckets, - "author": response.aggregations.author.buckets, - # collections IS nested, so it should have "inner" attribute - "collections": response.aggregations.collections.inner.buckets, - } - ) - - # should call set_date with the aggregated min and max dates (as strings) - mock_set_date.assert_called_with( - response.aggregations.min_date.value_as_string, - response.aggregations.max_date.value_as_string, - ) + from datetime import date + with patch("apps.readux.views.jd_to_date", side_effect=[date(1800, 1, 1), date(2022, 12, 31)]): + volume_search_view.get_context_data() + mock_set_facets.assert_called_with( + { + "language": response.aggregations.language.buckets, + "author": response.aggregations.author.buckets, + # collections IS nested, so it should have "inner" attribute + "collections": response.aggregations.collections.inner.buckets, + } + ) + mock_set_date.assert_called_with("1800-01-01", "2022-12-31") diff --git a/apps/readux/views.py b/apps/readux/views.py index bc5ad82d..adace0b7 100644 --- a/apps/readux/views.py +++ b/apps/readux/views.py @@ -13,7 +13,7 @@ from django.urls import reverse from elasticsearch_dsl import Q, NestedFacet, TermsFacet from elasticsearch_dsl.query import MultiMatch -from apps.utils.dates import date_to_jd +from apps.utils.dates import date_to_jd, jd_to_date from datetime import date import config.settings.local as settings from apps.iiif.manifests.documents import ManifestDocument @@ -250,7 +250,9 @@ def get_context_data(self, **kwargs): custom_metadata = {} for key, metadata in settings.CUSTOM_METADATA.items(): # Extract multi flag - multi = metadata.get("multi", False) # Default to False if not specified + multi = metadata.get( + "multi", False + ) # Default to False if not specified # Attempt to get this manifest's value for each key value = self.get_metadatum(manifest, key) @@ -430,7 +432,9 @@ def get_context_data(self, **kwargs): else [] ) - volumes_response = self.get_queryset().execute() + # size=0: return aggregations only — no hits, no highlighting, much faster. + # The actual paginated hits come from the ListView machinery above. + volumes_response = self.get_queryset()[:0].execute() # populate a dict with "buckets" of extant categories for each facet facets = {} for facet, _ in self.facets: @@ -447,18 +451,32 @@ def get_context_data(self, **kwargs): ) context_data["form"].set_facets(facets) - # get min and max date aggregations and set on form - if hasattr(volumes_response.aggregations, "min_date"): - min_date = getattr(volumes_response.aggregations, "min_date") - if hasattr(volumes_response.aggregations, "max_date"): - max_date = getattr(volumes_response.aggregations, "max_date") - if hasattr(min_date, "value_as_string") and hasattr( - max_date, "value_as_string" - ): - context_data["form"].set_date( - getattr(min_date, "value_as_string"), - getattr(max_date, "value_as_string"), - ) + # get min and max date aggregations and set on form. + # these are nested under filter buckets (dated_earliest / dated_latest) so that + # undated volumes are excluded from the aggregation range. + aggs = volumes_response.aggregations + dated_earliest = getattr(aggs, "dated_earliest", None) + dated_latest = getattr(aggs, "dated_latest", None) + if dated_earliest and dated_latest: + min_date = getattr(dated_earliest, "min_date", None) + max_date = getattr(dated_latest, "max_date", None) + # value_as_string on a FloatField metric is the raw JD float as a string, + # not an ISO date — convert via jd_to_date instead. + min_jd = getattr(min_date, "value", None) if min_date else None + max_jd = getattr(max_date, "value", None) if max_date else None + if min_jd is not None and max_jd is not None: + # jd_to_date returns None for pre-CE dates (year 0 / 1 BC) because + # Python's date.MINYEAR = 1. Clamp to date(1, 1, 1) so the slider + # has a valid lower bound; BCE volumes remain indexed and searchable. + from datetime import date as _date + min_d = jd_to_date(min_jd) or _date(1, 1, 1) + max_d = jd_to_date(max_jd) + if max_d: + # strftime("%Y") does not zero-pad years < 1000 on all platforms, + # so format manually to guarantee isoparse-compatible 4-digit years. + def _fmt(d): + return f"{d.year:04d}-{d.month:02d}-{d.day:02d}" + context_data["form"].set_date(_fmt(min_d), _fmt(max_d)) # Attach start_canvas to each volume in the current page. # Handle both: paginator page and raw list-like. @@ -472,26 +490,34 @@ def get_context_data(self, **kwargs): pids = [getattr(v, "pid", None) for v in items if getattr(v, "pid", None)] if pids: - # Use the default reverse name: canvas_set - manifests = { - m.pid: m - for m in Manifest.objects - .filter(pid__in=pids) - .prefetch_related("canvas_set") - } + # Two targeted queries instead of prefetch_related("canvas_set"), which + # would load every canvas for every result just to find one per manifest. + canvas_map = {} + + # Query 1: manifests with an explicitly marked starting page. + # DISTINCT ON (manifest_id) returns exactly one row per manifest at the + # DB level — no Python-side deduplication, no dirtyfields deep-copy storm. + for c in ( + Canvas.objects.filter(manifest__pid__in=pids, is_starting_page=True) + .order_by("manifest_id", "position") + .distinct("manifest_id") + .select_related("manifest") + ): + canvas_map[c.manifest.pid] = c + + # Query 2: first canvas by position for the remainder + remaining = [p for p in pids if p not in canvas_map] + if remaining: + for c in ( + Canvas.objects.filter(manifest__pid__in=remaining) + .order_by("manifest_id", "position") + .distinct("manifest_id") + .select_related("manifest") + ): + canvas_map[c.manifest.pid] = c for v in items: - pid = getattr(v, "pid", None) - m = manifests.get(pid) - if not m: - v.start_canvas = None - continue - - # Prefer an explicitly marked starting page, else first by position - start = m.canvas_set.filter(is_starting_page=True).order_by("position").first() - if start is None: - start = m.canvas_set.order_by("position").first() - v.start_canvas = start + v.start_canvas = canvas_map.get(getattr(v, "pid", None)) return context_data @@ -499,6 +525,11 @@ def get_queryset(self): form = self.get_form() volumes = ManifestDocument.search() + # canvas_set contains full OCR text for every page — potentially megabytes per volume. + # Exclude it from _source so ES doesn't serialize and return it for every hit. + # inner_hits (per-page match context) are fetched separately and are unaffected. + volumes = volumes.source(excludes=["canvas_set"]) + if not form.is_valid(): # empty result on invalid form return volumes.filter("match_none") @@ -609,14 +640,22 @@ def get_queryset(self): ) # filter on date published + # Date range overlap logic: include a document if its date window overlaps the + # filter window. A document [earliest, latest] overlaps [start, end] when: + # latest >= start AND earliest <= end + # Using the opposite bound for each filter handles null bounds gracefully — + # if date_earliest is null we can't exclude the document from an end_date filter, + # and if date_latest is null we can't confirm it falls after a start_date. min_date_filter = form_data.get("start_date") if min_date_filter: min_jd = date_to_jd(date(min_date_filter.year, 1, 1)) - volumes = volumes.filter("range", date_earliest={"gte": min_jd}) + volumes = volumes.filter("exists", field="date_latest") + volumes = volumes.filter("range", date_latest={"gte": min_jd}) max_date_filter = form_data.get("end_date") or "" if max_date_filter: max_jd = date_to_jd(date(max_date_filter.year, 12, 31)) - volumes = volumes.filter("range", date_latest={"lte": max_jd}) + volumes = volumes.filter("exists", field="date_earliest") + volumes = volumes.filter("range", date_earliest={"lte": max_jd}) # filter on custom metadata fields if hasattr(settings, "CUSTOM_METADATA") and isinstance( @@ -640,9 +679,16 @@ def get_queryset(self): for facet_name, facet in self.facets: volumes.aggs.bucket(facet_name, facet.get_aggregation()) - # get min and max date published values - volumes.aggs.metric("min_date", "min", field="date_earliest") - volumes.aggs.metric("max_date", "max", field="date_latest") + # get min and max date published values, excluding volumes with no dates. + # Some undated volumes store 0 rather than null, so an exists filter is not + # enough — use a range filter requiring a positive JD value (JD > 0 means + # after 4713 BC; any plausible publication date will satisfy this). + volumes.aggs.bucket( + "dated_earliest", "filter", filter={"exists": {"field": "date_earliest"}} + ).metric("min_date", "min", field="date_earliest") + volumes.aggs.bucket( + "dated_latest", "filter", filter={"exists": {"field": "date_latest"}} + ).metric("max_date", "max", field="date_latest") # sort volumes = volumes.sort(form_data["sort"]) diff --git a/apps/static/css/readux.scss b/apps/static/css/readux.scss index d3571bd0..2bfb597e 100644 --- a/apps/static/css/readux.scss +++ b/apps/static/css/readux.scss @@ -320,7 +320,7 @@ em { color: inherit !important; } .video-thumbnail, iframe, .transparent-overlay { position: absolute; inset: 0; width: 100%; height: 100%; } .video-thumbnail { object-fit: cover; } .transparent-overlay { background-color: rgba($color-black, 0.5); z-index: 1; } -iframe { display: none; } +// iframe { display: none; } /* -------------------------------------------------------------------------- */ /* 10) SECTIONS / HIGHLIGHTS */ @@ -537,3 +537,7 @@ ul.listing-thumbs > li > img.thumbnail-image { height: 150px; } .rx-line-height-sm { line-height: 0.85em; } + +.theme-toggle { + display: none; +} \ No newline at end of file diff --git a/apps/static/js/components/InfoExport.vue b/apps/static/js/components/InfoExport.vue index 35dadc59..176d1ccb 100644 --- a/apps/static/js/components/InfoExport.vue +++ b/apps/static/js/components/InfoExport.vue @@ -150,7 +150,7 @@ export default { window.addEventListener("popstate", this._onHistoryChange); this._updateVisibility(this.canvas); }, - beforeDestroy() { + beforeUnmount() { window.removeEventListener("canvasUpdate", this._onCanvasUpdate); if (this._onHistoryChange) { window.removeEventListener("popstate", this._onHistoryChange); diff --git a/apps/static/js/components/OcrInspector.vue b/apps/static/js/components/OcrInspector.vue index 9cef69fe..d3300563 100644 --- a/apps/static/js/components/OcrInspector.vue +++ b/apps/static/js/components/OcrInspector.vue @@ -249,7 +249,7 @@ export default { }; window.addEventListener("ocrLoaded", this._onOcrLoaded); }, - beforeDestroy() { + beforeUnmount() { window.removeEventListener("ocrLoaded", this._onOcrLoaded); const nodes = this.getOcrNodes(); for (let i = 0; i < nodes.length; i++) this.removeBlockHandlers(nodes[i]); diff --git a/apps/static/js/index.css b/apps/static/js/index.css new file mode 100644 index 00000000..cb3915b6 --- /dev/null +++ b/apps/static/js/index.css @@ -0,0 +1 @@ +.scrollable-container[data-v-352dd644]{max-height:200px;overflow-y:auto} diff --git a/apps/static/js/index.js b/apps/static/js/index.js index f29d81bb..a30fac8d 100644 --- a/apps/static/js/index.js +++ b/apps/static/js/index.js @@ -1,11 +1,18 @@ -window.$ = require('jquery'); -window.axios = require('axios'); -window.noUiSlider = require('nouislider'); -require('@selectize/selectize'); -require('/apps/static/js/vue-readux.js'); +import $ from 'jquery' +import axios from 'axios' +import noUiSlider from 'nouislider' +import '@selectize/selectize' +import UIkit from 'uikit' +import UIkitIcons from 'uikit/dist/js/uikit-icons' +import ECDSAnnotator from 'ecds-annotator/dist/ecds-annotator.min.js' +import './vue-readux.js' -// UIkit -window.UIkit = require('uikit'); -window.UIkitIcons = require('uikit/dist/js/uikit-icons'); -// require('/apps/static/js/project.js'); -window.ECDSAnnotator = require('../../../node_modules/ecds-annotator/dist/ecds-annotator.min.js'); \ No newline at end of file +// Expose globals for non-module scripts (search.js, project.js, etc.) +window.$ = $ +window.jQuery = $ +window.axios = axios +window.noUiSlider = noUiSlider +UIkit.use(UIkitIcons) +window.UIkit = UIkit +window.UIkitIcons = UIkitIcons +window.ECDSAnnotator = ECDSAnnotator diff --git a/apps/static/js/vue-readux.js b/apps/static/js/vue-readux.js index 91e0ff12..44546fe4 100644 --- a/apps/static/js/vue-readux.js +++ b/apps/static/js/vue-readux.js @@ -1,4 +1,4 @@ -import Vue from 'vue' +import { createApp } from 'vue' import VolumeSearch from './components/VolumeSearch.vue' import VolumeAnnotations from './components/VolumeAnnotations.vue' import OcrInspector from './components/OcrInspector.vue' @@ -9,42 +9,51 @@ import InfoExport from './components/InfoExport.vue' import InfoUrlExternal from './components/InfoUrlExternal.vue' import VolumeExportAnnotationBtn from './components/VolumeExportAnnotationBtn.vue' -var readux = new Vue({ - el: "#v-readux", - delimiters: ["[[", "]]"], - components: { - VolumeSearch, VolumeAnnotations, OcrInspector, InfoUrlUnit, InfoUrlSingle, InfoUrlMultiple, InfoExport, InfoUrlExternal, VolumeExportAnnotationBtn +const app = createApp({ + components: { + VolumeSearch, + VolumeAnnotations, + OcrInspector, + InfoUrlUnit, + InfoUrlSingle, + InfoUrlMultiple, + InfoExport, + InfoUrlExternal, + VolumeExportAnnotationBtn, }, - data: { - options: ["title", "author", "date published", "date added"], - searchPrefix: "?sort=", - currentSelection: null, - itemNotFound: false, - showMoreInfo: false, - manifestCount: 0, + data() { + return { + options: ["title", "author", "date published", "date added"], + searchPrefix: "?sort=", + currentSelection: null, + itemNotFound: false, + showMoreInfo: false, + manifestCount: 0, + } }, methods: { - sortBy: function (selection) { - var value = this.searchPrefix + selection; + sortBy(selection) { + const value = this.searchPrefix + selection if (window.location !== value) { - window.location = value; + window.location = value } }, - - toggleMoreInfo: function () { + toggleMoreInfo() { this.showMoreInfo = !this.showMoreInfo - } + }, }, - - mounted: function () { + mounted() { if (this.$refs["v-attr-sort"]) { - this.currentSelection = this.$refs["v-attr-sort"].getAttribute( - "data-sort" - ); + this.currentSelection = this.$refs["v-attr-sort"].getAttribute("data-sort") } - if (window.location.href.includes("?q=")) { - this.showMoreInfo = true; + this.showMoreInfo = true } - } -}); \ No newline at end of file + }, +}) + +// Custom delimiters so Vue expressions don't clash with Django template tags. +// Must be set before mount(). +app.config.compilerOptions.delimiters = ['[[', ']]'] + +app.mount('#v-readux') diff --git a/apps/templates/search_results.html b/apps/templates/search_results.html index 8c24332c..d1473e15 100644 --- a/apps/templates/search_results.html +++ b/apps/templates/search_results.html @@ -22,7 +22,7 @@ {% endblock %} {% block extra_css %} - + - {% endblock %} {% block content %}
-
+
{% avatar user %}

{% block branding_welcome %}{% blocktrans %}Welcome to the {{ site_name }} Wagtail CMS{% endblocktrans %}{% endblock %}  

diff --git a/apps/users/tests/test_adapter.py b/apps/users/tests/test_adapter.py index 5b623f95..ebc95f7c 100644 --- a/apps/users/tests/test_adapter.py +++ b/apps/users/tests/test_adapter.py @@ -1,4 +1,6 @@ +from django.contrib.sessions.middleware import SessionMiddleware from django.test import RequestFactory, TestCase +from allauth.socialaccount.models import SocialLogin from apps.users.adapters import AccountAdapter, SocialAccountAdapter from apps.users.tests.factories import UserFactory, SocialAccountFactory from apps.users.forms import ReaduxSocialSignupForm @@ -8,6 +10,10 @@ class AdapterTest(TestCase): def setUp(self): self.factory = RequestFactory() self.request = self.factory.get('/') + # RequestFactory skips middleware; allauth needs request.session + # (used by setup_user_email inside SocialLogin.save). + SessionMiddleware(get_response=lambda r: None).process_request(self.request) + self.request.session.save() def test_account_adapter_signup(self): aa = AccountAdapter() @@ -19,21 +25,24 @@ def test_social_account_adapter_signup(self): def test_account_adapter_user_save(self): proto_user = UserFactory.build() - proto_sa = SocialAccountFactory.build(user = proto_user) + proto_sa = SocialAccountFactory.build(user=proto_user) + # SocialLogin is the data-wrapper allauth expects; SocialAccount is just + # the model. Passing a raw SocialAccount to save_user causes Django 5's + # Model.save() to receive `request` as `force_insert`. + proto_sl = SocialLogin(user=proto_user, account=proto_sa) saa = SocialAccountAdapter(self.request) form = ReaduxSocialSignupForm( { "name": proto_user.name, "agree": True, - "sociallogin": proto_sa, "email": proto_user.email, "username": proto_user.username }, - sociallogin=proto_sa + sociallogin=proto_sl ) assert form.is_valid() proto_user.save() - proto_sa.user = proto_user - saa.save_user(self.request, proto_sa, form) + saa.save_user(self.request, proto_sl, form) + # SocialLogin.save() updates proto_sl.account (== proto_sa) in place assert proto_sa.user == proto_user assert not proto_sa._state.adding diff --git a/apps/utils/dates.py b/apps/utils/dates.py index 68a75d84..dfe0eae0 100644 --- a/apps/utils/dates.py +++ b/apps/utils/dates.py @@ -1,7 +1,25 @@ -from edtf.convert import struct_time_to_jd -from datetime import date +from edtf.convert import struct_time_to_jd, jd_to_struct_time +from datetime import date, MINYEAR import time def date_to_jd(d: date) -> float: - return struct_time_to_jd(time.strptime(d.strftime("%Y-%m-%d"), "%Y-%m-%d")) + # Use explicit zero-padded formatting — strftime("%Y") does not zero-pad years + # below 1000 on all platforms, causing strptime to reject the result. + date_str = f"{d.year:04d}-{d.month:02d}-{d.day:02d}" + return struct_time_to_jd(time.strptime(date_str, "%Y-%m-%d")) + + +def jd_to_date(jd: float) -> date | None: + """Convert a Julian Day Number (float) back to a Python date. + + Returns None if the JD maps to a year outside Python's date range (e.g. year 0 + from EDTF astronomical year numbering, or any year before MINYEAR=1). + """ + st = jd_to_struct_time(jd) + if st.tm_year < MINYEAR: + return None + try: + return date(st.tm_year, st.tm_mon, st.tm_mday) + except ValueError: + return None diff --git a/config/settings/base.py b/config/settings/base.py index f062553b..2c5270f1 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -31,8 +31,6 @@ SITE_ID = 1 # https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n USE_I18N = True -# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n -USE_L10N = True # https://docs.djangoproject.com/en/dev/ref/settings/#use-tz USE_TZ = True @@ -71,7 +69,7 @@ "modeltranslation", "django.contrib.admin", "import_export", - "django_summernote", + "tinymce", ] THIRD_PARTY_APPS = [ "allauth", @@ -100,9 +98,10 @@ "wagtail.search", "wagtail.admin", "wagtail", - "wagtailautocomplete", - "wagtail_modeladmin", + "wagtail_modeladmin", # replaces wagtail.contrib.modeladmin (removed in Wagtail 6) "wagtailmenus", + "wagtail.contrib.settings", + "crispy_bootstrap4", ] LOCAL_APPS = [ "apps.users.apps.UsersAppConfig", @@ -337,19 +336,38 @@ CORS_ORIGIN_ALLOW_ALL = True # Elasticsearch - +# ES 8.x has security (HTTPS + auth) enabled by default in official packages. +# For servers with security disabled, only ELASTICSEARCH_URL is needed. +# For servers with security enabled, also set ELASTICSEARCH_USER + ELASTICSEARCH_PASSWORD +# (basic auth) or ELASTICSEARCH_API_KEY (base64-encoded id:api_key string). ELASTICSEARCH_DSL = { - "default": {"hosts": env("ELASTICSEARCH_URL", default="http://localhost:9200")}, + "default": { + "hosts": env("ELASTICSEARCH_URL", default="http://localhost:9200"), + } } +INDEX_PREFIX = "readux" + +_es_user = env("ELASTICSEARCH_USER", default="") +_es_password = env("ELASTICSEARCH_PASSWORD", default="") +_es_api_key = env("ELASTICSEARCH_API_KEY", default="") +if _es_api_key: + ELASTICSEARCH_DSL["default"]["api_key"] = _es_api_key +elif _es_user and _es_password: + ELASTICSEARCH_DSL["default"]["basic_auth"] = (_es_user, _es_password) SOCIALACCOUNT_STORE_TOKENS = True -# django-summernote rich text editor settings. see https://github.com/hackerwins/django-summernote -# NOTE: consider replacing after django 4 upgrade -SUMMERNOTE_CONFIG = { - "iframe": False, +# TinyMCE rich text editor — minimal toolbar focused on link creation +TINYMCE_DEFAULT_CONFIG = { + "theme": "silver", + "height": 300, + "menubar": False, + "plugins": "link lists", + "toolbar": "bold italic | link | bullist numlist | removeformat", + "link_assume_external_targets": True, + "relative_urls": False, + "remove_script_host": False, } -SUMMERNOTE_THEME = "lite" # Background image URL configuration BACKGROUND_IMAGE_URL = "/static/images/bg.jpg" # Background image for the homepage; when it doesn't exist, it will fall back to a default solid color diff --git a/config/settings/local.dst b/config/settings/local.dst index a229c2ce..d21e6845 100644 --- a/config/settings/local.dst +++ b/config/settings/local.dst @@ -166,12 +166,6 @@ LOGGING = { }, } -# Elasticsearch -# ------------------------------------------------------------------------------ - -# Must be configured to the host and port running Elasticsearch -ELASTICSEARCH_DSL['default']['hosts'] = 'user:pass@localhost:9200' -INDEX_PREFIX = "readux_test" # Custom metadata fields configuration. Metadata in this list will appear under # "Advanced" in each volume's metadata. Must be a dict with key names diff --git a/config/settings/production.py b/config/settings/production.py index a3d4c8ae..75b7523f 100644 --- a/config/settings/production.py +++ b/config/settings/production.py @@ -1,42 +1,65 @@ import logging +import sentry_sdk +from sentry_sdk.integrations.django import DjangoIntegration +from sentry_sdk.integrations.logging import LoggingIntegration + from .base import * # noqa from .base import env # GENERAL # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env('DJANGO_SECRET_KEY') +SECRET_KEY = env("DJANGO_SECRET_KEY") # https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['readux.ecds.emory.edu']) +ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["readux.ecds.emory.edu"]) # DATABASES # ------------------------------------------------------------------------------ -DATABASES['default'] = env.db('DATABASE_URL') # noqa F405 -DATABASES['default']['ATOMIC_REQUESTS'] = True # noqa F405 -DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default=60) # noqa F405 - +DATABASES = { + "default": { + "NAME": "readuxdev", + "USER": "readuxdev", + "PASSWORD": "xNxCRPYBUm1NFS80ycvC", + "HOST": "ecds-postgres-db-server.cwmnkgmwpxsa.us-east-1.rds.amazonaws.com", + "PORT": 5432, + "ENGINE": "django.db.backends.postgresql", + "ATOMIC_REQUESTS": True, + "AUTOCOMMIT": True, + "CONN_MAX_AGE": 0, + "CONN_HEALTH_CHECKS": False, + "OPTIONS": {"fallback_application_name": "django_shell"}, + "TIME_ZONE": None, + "TEST": { + "CHARSET": None, + "COLLATION": None, + "MIGRATE": True, + "MIRROR": None, + "NAME": None, + }, + } +} # CACHES # ------------------------------------------------------------------------------ CACHES = { - 'default': { - 'BACKEND': 'django_redis.cache.RedisCache', - 'LOCATION': env('REDIS_URL'), - 'OPTIONS': { - 'CLIENT_CLASS': 'django_redis.client.DefaultClient', + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": env("REDIS_URL"), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", # Mimicing memcache behavior. # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior - 'IGNORE_EXCEPTIONS': True, - } + "IGNORE_EXCEPTIONS": True, + }, } } # SECURITY # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") # https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect -SECURE_SSL_REDIRECT = env.bool('DJANGO_SECURE_SSL_REDIRECT', default=True) +SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) # https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure SESSION_COOKIE_SECURE = True # https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly @@ -50,40 +73,44 @@ # TODO: set this to 60 seconds first and then to 518400 once you prove the former works SECURE_HSTS_SECONDS = 60 # https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains -SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool('DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS', default=True) +SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( + "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True +) # https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload -SECURE_HSTS_PRELOAD = env.bool('DJANGO_SECURE_HSTS_PRELOAD', default=True) +SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True) # https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff -SECURE_CONTENT_TYPE_NOSNIFF = env.bool('DJANGO_SECURE_CONTENT_TYPE_NOSNIFF', default=True) +SECURE_CONTENT_TYPE_NOSNIFF = env.bool( + "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True +) # https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter SECURE_BROWSER_XSS_FILTER = True # https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options -X_FRAME_OPTIONS = 'DENY' +X_FRAME_OPTIONS = "DENY" # STORAGES # ------------------------------------------------------------------------------ # https://django-storages.readthedocs.io/en/latest/#installation -INSTALLED_APPS += ['storages'] # noqa F405 +INSTALLED_APPS += ["storages"] # noqa F405 # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_ACCESS_KEY_ID = env('DJANGO_AWS_ACCESS_KEY_ID') +AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_SECRET_ACCESS_KEY = env('DJANGO_AWS_SECRET_ACCESS_KEY') +AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY") # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_STORAGE_BUCKET_NAME = env('DJANGO_AWS_STORAGE_BUCKET_NAME') +AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings AWS_QUERYSTRING_AUTH = False # DO NOT change these unless you know what you're doing. _AWS_EXPIRY = 60 * 60 * 24 * 7 # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings AWS_S3_OBJECT_PARAMETERS = { - 'CacheControl': f'max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate', + "CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate", } # STATIC # ------------------------ -STATICFILES_STORAGE = 'config.settings.production.StaticRootS3Boto3Storage' -STATIC_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/' +STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage" +STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/" # MEDIA # ------------------------------------------------------------------------------ @@ -94,28 +121,28 @@ class StaticRootS3Boto3Storage(S3Boto3Storage): - location = 'static' + location = "static" class MediaRootS3Boto3Storage(S3Boto3Storage): - location = 'media' + location = "media" file_overwrite = False # endregion -DEFAULT_FILE_STORAGE = 'config.settings.production.MediaRootS3Boto3Storage' -MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/' +DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage" +MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" # TEMPLATES # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#templates -TEMPLATES[0]['OPTIONS']['loaders'] = [ # noqa F405 +TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405 ( - 'django.template.loaders.cached.Loader', + "django.template.loaders.cached.Loader", [ - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - ] + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", + ], ), ] @@ -123,101 +150,85 @@ class MediaRootS3Boto3Storage(S3Boto3Storage): # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email DEFAULT_FROM_EMAIL = env( - 'DJANGO_DEFAULT_FROM_EMAIL', - default='Readux ' + "DJANGO_DEFAULT_FROM_EMAIL", default="Readux " ) # https://docs.djangoproject.com/en/dev/ref/settings/#server-email -SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL) +SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) # https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix -EMAIL_SUBJECT_PREFIX = env('DJANGO_EMAIL_SUBJECT_PREFIX', default='[Readux]') +EMAIL_SUBJECT_PREFIX = env("DJANGO_EMAIL_SUBJECT_PREFIX", default="[Readux]") # ADMIN # ------------------------------------------------------------------------------ # Django Admin URL regex. -ADMIN_URL = env('DJANGO_ADMIN_URL') +ADMIN_URL = env("DJANGO_ADMIN_URL") # Anymail (Mailgun) # ------------------------------------------------------------------------------ # https://anymail.readthedocs.io/en/stable/installation/#installing-anymail -INSTALLED_APPS += ['anymail'] # noqa F405 -EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend' +INSTALLED_APPS += ["anymail"] # noqa F405 +EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" # https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference ANYMAIL = { - 'MAILGUN_API_KEY': env('MAILGUN_API_KEY'), - 'MAILGUN_SENDER_DOMAIN': env('MAILGUN_DOMAIN') + "MAILGUN_API_KEY": env("MAILGUN_API_KEY"), + "MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"), } # Gunicorn # ------------------------------------------------------------------------------ -INSTALLED_APPS += ['gunicorn'] # noqa F405 +INSTALLED_APPS += ["gunicorn"] # noqa F405 # Collectfast # ------------------------------------------------------------------------------ # https://github.com/antonagestam/collectfast#installation -INSTALLED_APPS = ['collectfast'] + INSTALLED_APPS # noqa F405 +INSTALLED_APPS = ["collectfast"] + INSTALLED_APPS # noqa F405 AWS_PRELOAD_METADATA = True -# raven -# ------------------------------------------------------------------------------ -# https://docs.sentry.io/clients/python/integrations/django/ -INSTALLED_APPS += ['raven.contrib.django.raven_compat'] # noqa F405 -MIDDLEWARE = ['raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware'] + MIDDLEWARE - # Sentry # ------------------------------------------------------------------------------ -SENTRY_DSN = env('SENTRY_DSN') -SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient') +# https://docs.sentry.io/platforms/python/integrations/django/ +SENTRY_DSN = env("SENTRY_DSN") + +sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[ + DjangoIntegration(), + LoggingIntegration( + level=logging.INFO, # capture INFO and above as breadcrumbs + event_level=logging.ERROR, # send ERRORs as Sentry events + ), + ], + traces_sample_rate=0.1, + send_default_pii=False, +) + LOGGING = { - 'version': 1, - 'disable_existing_loggers': True, - 'root': { - 'level': 'WARNING', - 'handlers': ['sentry'], - }, - 'formatters': { - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(module)s ' - '%(process)d %(thread)d %(message)s' + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "verbose": { + "format": "%(levelname)s %(asctime)s %(module)s " + "%(process)d %(thread)d %(message)s" }, }, - 'handlers': { - 'sentry': { - 'level': 'ERROR', - 'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler', - }, - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'formatter': 'verbose' + "handlers": { + "console": { + "level": "DEBUG", + "class": "logging.StreamHandler", + "formatter": "verbose", } }, - 'loggers': { - 'django.db.backends': { - 'level': 'ERROR', - 'handlers': ['console'], - 'propagate': False, + "loggers": { + "django.db.backends": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, }, - 'raven': { - 'level': 'DEBUG', - 'handlers': ['console'], - 'propagate': False, - }, - 'sentry.errors': { - 'level': 'DEBUG', - 'handlers': ['console'], - 'propagate': False, - }, - 'django.security.DisallowedHost': { - 'level': 'ERROR', - 'handlers': ['console', 'sentry'], - 'propagate': False, + "django.security.DisallowedHost": { + "level": "ERROR", + "handlers": ["console"], + "propagate": False, }, }, } - -SENTRY_CELERY_LOGLEVEL = env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO) -RAVEN_CONFIG = { - 'dsn': SENTRY_DSN -} # Your stuff... # ------------------------------------------------------------------------------ diff --git a/config/urls.py b/config/urls.py index 320c0d8e..656151b5 100644 --- a/config/urls.py +++ b/config/urls.py @@ -11,8 +11,6 @@ from wagtail.admin import urls as wagtailadmin_urls from wagtail.documents import urls as wagtaildocs_urls from wagtail import urls as wagtail_urls -from wagtailautocomplete.urls.admin import urlpatterns as autocomplete_admin_urls - from apps.readux.views import ManifestsSitemap, CollectionsSitemap sitemaps = { @@ -29,7 +27,6 @@ {"sitemaps": sitemaps}, name="django.contrib.sitemaps.views.sitemap", ), - re_path(r"^cms/autocomplete/", include(autocomplete_admin_urls)), re_path(r"^cms/", include(wagtailadmin_urls)), re_path(r"^documents/", include(wagtaildocs_urls)), re_path(r"^pages/", include(wagtail_urls)), @@ -60,7 +57,7 @@ re_path(r"^", include("apps.ocr.urls")), re_path(r"^", include("apps.readux.urls")), re_path(r"", include(wagtail_urls)), - re_path(r"^summernote/", include("django_summernote.urls")), + path("tinymce/", include("tinymce.urls")), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) if settings.DEBUG: diff --git a/package-lock.json b/package-lock.json index c6cb7916..bdb4a5b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,28 +10,17 @@ "license": "ISC", "dependencies": { "@selectize/selectize": "^0.15.2", - "axios": "^0.23.0", + "axios": "^1.7.0", "ecds-annotator": "github:ecds/ecds-annotator#develop", "jquery": "^3.6.0", "nouislider": "^15.8.1", - "vue": "^2.6.14" + "vue": "^3.4.0" }, "devDependencies": { - "@vue/component-compiler-utils": "^3.3.0", - "css-loader": "^7.1.2", - "fontawesome": "^5.6.3", - "jquery": "^3.6.0", - "source-map-loader": "^4.0.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.4.4", + "@vitejs/plugin-vue": "^5.0.0", "uikit": "^3.23.13", "uikit-icons": "^0.5.0", - "vue-loader": "^15.11.1", - "vue-style-loader": "^4.1.3", - "vue-template-compiler": "^2.6.14", - "webpack": "^5.88.2", - "webpack-bundle-tracker": "^1.5.0", - "webpack-cli": "^4.9.2" + "vite": "^5.0.0" } }, "node_modules/@babel/code-frame": { @@ -87,30 +76,30 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -161,26 +150,18 @@ } }, "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", @@ -304,6 +285,397 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -321,15 +693,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -406,9 +769,9 @@ } }, "node_modules/@recogito/annotorious-openseadragon": { - "version": "2.7.18", - "resolved": "https://registry.npmjs.org/@recogito/annotorious-openseadragon/-/annotorious-openseadragon-2.7.18.tgz", - "integrity": "sha512-3A7vDvhHUwh/qilY7eZXZ6AGdT4Lc1K7sT9yftXn12b5sVprkuavP5wTUwMweJI51gyaDh7YOUc/9yZGr/CtLg==", + "version": "2.7.19", + "resolved": "https://registry.npmjs.org/@recogito/annotorious-openseadragon/-/annotorious-openseadragon-2.7.19.tgz", + "integrity": "sha512-r4kK7OwmVjKU26naz474HCx9a5rLK3CiNNxIezindQVTHbEnyCHzaKyuOx35kJOoBJJ6vwrQ55oaeURny1NdMA==", "license": "BSD-3-Clause", "dependencies": { "@recogito/annotorious": "2.7.13", @@ -549,14 +912,364 @@ "object-assign": "^4.1.1" } }, - "node_modules/@selectize/selectize": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@selectize/selectize/-/selectize-0.15.2.tgz", - "integrity": "sha512-gY+yzYfrVTc+1ekCAaEtDvN59+upbibFzhkePyyk6PwOXT6kEb05azGA91/w3C/71lUOHPyd3nzLnfyfuRi+pA==", - "license": "Apache-2.0", - "engines": { - "node": "*" - }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@selectize/selectize": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@selectize/selectize/-/selectize-0.15.2.tgz", + "integrity": "sha512-gY+yzYfrVTc+1ekCAaEtDvN59+upbibFzhkePyyk6PwOXT6kEb05azGA91/w3C/71lUOHPyd3nzLnfyfuRi+pA==", + "license": "Apache-2.0", + "engines": { + "node": "*" + }, "optionalDependencies": { "jquery-ui": "^1.13.2" }, @@ -564,36 +1277,10 @@ "jquery": "^1.7.0 || ^2 || ^3" } }, - "node_modules/@types/eslint": { - "version": "8.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "18.0.0", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -623,288 +1310,130 @@ "dev": true, "license": "MIT" }, - "node_modules/@vue/component-compiler-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", - "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "dev": true, "license": "MIT", - "dependencies": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.36", - "postcss-selector-parser": "^6.0.2", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.0" - }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true, - "license": "ISC" - }, - "node_modules/@vue/component-compiler-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, "engines": { - "node": ">=6.0.0" + "node": "^18.0.0 || >=20.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/@vue/component-compiler-utils/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true, - "license": "ISC" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/compiler-core": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.35.tgz", + "integrity": "sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@babel/parser": "^7.29.3", + "@vue/shared": "3.5.35", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/compiler-dom": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.35.tgz", + "integrity": "sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==", "license": "MIT", "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@vue/compiler-core": "3.5.35", + "@vue/shared": "3.5.35" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.35.tgz", + "integrity": "sha512-G5VPMcXTSywXBgtFOZOnHKBxKSrwXUcvY1iaF5/hRcy7t0J6CH/d8ha9F4nzi00Fax1eLV0QHM7v4mQu68jydw==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@babel/parser": "^7.29.3", + "@vue/compiler-core": "3.5.35", + "@vue/compiler-dom": "3.5.35", + "@vue/compiler-ssr": "3.5.35", + "@vue/shared": "3.5.35", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.15", + "source-map-js": "^1.2.1" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.35.tgz", + "integrity": "sha512-rGhAeXgdM7/ffTJGXT69rCCdTmjDewnFuUZfBQQHTdcEBeWdT5HCGY60y2ytLJr9/Dsu7IntUi5z/w0h6Rjnzw==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@vue/compiler-dom": "3.5.35", + "@vue/shared": "3.5.35" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/reactivity": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.35.tgz", + "integrity": "sha512-tVc+SsHConvh/Lz64qq1pP3rYArBmK42xonovEcxY74SQtvctZodG/zhq54P5dr38cVuw25d27cPNRdlMidpGQ==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@vue/shared": "3.5.35" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/runtime-core": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.35.tgz", + "integrity": "sha512-A/xFNX9loIcWDygeQuNCfKuh0CoYBzxhqEMNah5TSFg9Z53DrFYEN2qi5CU9necjM1OWYegYREUTHmXTmhfXtg==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@vue/reactivity": "3.5.35", + "@vue/shared": "3.5.35" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "dev": true, + "node_modules/@vue/runtime-dom": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.35.tgz", + "integrity": "sha512-odrJ1C391dbGnyDRh8U+rnP7J2amIEzfmRk5vXy7xi3aZhEXofTvpi0T4HJb6jlNqQZTNPR5MPHSB3RHNkIORA==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "@vue/reactivity": "3.5.35", + "@vue/runtime-core": "3.5.35", + "@vue/shared": "3.5.35", + "csstype": "^3.2.3" } }, - "node_modules/@webpack-cli/configtest": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.5.0", - "dev": true, + "node_modules/@vue/server-renderer": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.35.tgz", + "integrity": "sha512-NkebSOYdB97wi8OQcO3HqzZSlymJi/aWsN/7h74OSVhRTm6qGs3Jp3e0rCXynmWwSlKeRrnlIug+ilYoHBmQDA==", "license": "MIT", "dependencies": { - "envinfo": "^7.7.3" + "@vue/compiler-ssr": "3.5.35", + "@vue/shared": "3.5.35" }, "peerDependencies": { - "webpack-cli": "4.x.x" + "vue": "3.5.35" } }, - "node_modules/@webpack-cli/serve": { - "version": "1.7.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/abab": { - "version": "2.0.6", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/acorn": { - "version": "8.7.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } + "node_modules/@vue/shared": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.35.tgz", + "integrity": "sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==", + "license": "MIT" }, - "node_modules/ajv": { - "version": "6.12.6", - "dev": true, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "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" + "debug": "4" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "engines": { + "node": ">= 6.0.0" } }, "node_modules/ansi-regex": { @@ -952,6 +1481,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autobind-decorator": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/autobind-decorator/-/autobind-decorator-2.4.0.tgz", @@ -969,10 +1504,15 @@ "license": "MIT" }, "node_modules/axios": { - "version": "0.23.0", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" } }, "node_modules/babel-plugin-macros": { @@ -990,16 +1530,6 @@ "npm": ">=6" } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1012,13 +1542,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1031,38 +1554,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.21.0", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001358", - "electron-to-chromium": "^1.4.164", - "node-releases": "^2.0.5", - "update-browserslist-db": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -1119,47 +1610,6 @@ "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001358", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1184,14 +1634,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1206,19 +1648,6 @@ "node": ">=12" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -1242,35 +1671,23 @@ "version": "1.1.4", "license": "MIT" }, - "node_modules/colorette": { - "version": "2.0.19", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "dev": true, - "license": "MIT" - }, - "node_modules/computed-style": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/computed-style/-/computed-style-0.1.4.tgz", - "integrity": "sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==" - }, - "node_modules/consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog", - "dev": true, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { - "bluebird": "^3.1.1" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.8" } }, + "node_modules/computed-style": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/computed-style/-/computed-style-0.1.4.tgz", + "integrity": "sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==" + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -1304,77 +1721,10 @@ "node": ">=10" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", - "dev": true, - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/csstype": { - "version": "3.1.0", - "license": "MIT" - }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true, + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/debug": { @@ -1428,6 +1778,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dependency-graph": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", @@ -1490,48 +1849,22 @@ "react-dom": "^18.1.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.167", - "dev": true, - "license": "ISC" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "license": "MIT", + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 4" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "node": ">=0.12" }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/envinfo": { - "version": "7.8.1", - "dev": true, - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/error-ex": { @@ -1561,11 +1894,6 @@ "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "dev": true, - "license": "MIT" - }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -1578,72 +1906,85 @@ "node": ">= 0.4" } }, - "node_modules/escalade": { - "version": "3.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "estraverse": "^5.2.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, - "license": "BSD-2-Clause", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=4.0" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/events": { - "version": "3.3.0", - "dev": true, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", "engines": { - "node": ">=0.8.x" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "license": "MIT" @@ -1664,16 +2005,6 @@ "node": ">=8.6.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "dev": true, - "license": "MIT" - }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -1701,20 +2032,10 @@ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT" }, - "node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/follow-redirects": { - "version": "1.15.1", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -1731,10 +2052,21 @@ } } }, - "node_modules/fontawesome": { - "version": "5.6.3", - "dev": true, - "license": "MIT" + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/fs-extra": { "version": "10.1.0", @@ -1843,11 +2175,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/globby": { "version": "12.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", @@ -1894,14 +2221,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -1926,12 +2245,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash-sum": { + "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/hasown": { "version": "2.0.2", @@ -1945,16 +2272,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -1964,28 +2281,17 @@ "react-is": "^16.7.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">= 6" } }, "node_modules/ignore": { @@ -2022,32 +2328,6 @@ "node": ">=4" } }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/interpret": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2115,43 +2395,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/isobject": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/jodit": { "version": "3.24.9", "resolved": "https://registry.npmjs.org/jodit/-/jodit-3.24.9.tgz", @@ -2196,24 +2439,6 @@ "version": "2.3.1", "license": "MIT" }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", @@ -2226,14 +2451,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -2261,60 +2478,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, - "node_modules/loader-runner": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.assign": { - "version": "4.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "dev": true, - "license": "MIT" - }, "node_modules/loose-envify": { "version": "1.4.0", "license": "MIT", @@ -2325,15 +2488,13 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/math-intrinsics": { @@ -2351,21 +2512,6 @@ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", "license": "MIT" }, - "node_modules/merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2390,7 +2536,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -2398,7 +2543,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -2407,16 +2551,6 @@ "node": ">= 0.6" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2424,9 +2558,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -2441,11 +2575,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "dev": true, - "license": "MIT" - }, "node_modules/node-polyglot": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-polyglot/-/node-polyglot-2.6.0.tgz", @@ -2460,11 +2589,6 @@ "node": ">= 0.4" } }, - "node_modules/node-releases": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2502,55 +2626,22 @@ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/openseadragon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-3.1.0.tgz", - "integrity": "sha512-0zCbRIWUbCto7xm1tv2ZLEiSl84cDU659W/sfs2zqqTqVRa4CRHzhy7i9nsv6dHA1DryFR8IzjStjmWOqRs9Rg==", - "license": "BSD-3-Clause", - "funding": { - "url": "https://opencollective.com/openseadragon" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "node_modules/openseadragon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-3.1.0.tgz", + "integrity": "sha512-0zCbRIWUbCto7xm1tv2ZLEiSl84cDU659W/sfs2zqqTqVRa4CRHzhy7i9nsv6dHA1DryFR8IzjStjmWOqRs9Rg==", + "license": "BSD-3-Clause", + "funding": { + "url": "https://opencollective.com/openseadragon" } }, "node_modules/parent-module": { @@ -2583,22 +2674,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-parse": { "version": "1.0.7", "license": "MIT" @@ -2619,7 +2694,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -2637,21 +2714,10 @@ "node": ">=0.10.0" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -2668,7 +2734,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2734,97 +2800,6 @@ } } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", - "dev": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/postcss-reporter": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz", @@ -2851,54 +2826,16 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, "node_modules/preact": { - "version": "10.27.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz", - "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==", + "version": "10.29.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz", + "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==", "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -2917,19 +2854,13 @@ "react-is": "^16.13.1" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/punycode": { - "version": "2.1.1", - "dev": true, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/queue-microtask": { @@ -2958,14 +2889,6 @@ "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", "license": "ISC" }, - "node_modules/randombytes": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/rbush": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", @@ -3055,17 +2978,6 @@ "node": ">=8.10.0" } }, - "node_modules/rechoir": { - "version": "0.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -3096,25 +3008,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -3125,6 +3018,51 @@ "node": ">=0.10.0" } }, + "node_modules/rollup": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3148,123 +3086,30 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "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" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, "node_modules/slash": { @@ -3279,14 +3124,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3296,35 +3133,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-loader": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.72.1" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3355,20 +3163,6 @@ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", "license": "MIT" }, - "node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "license": "MIT", @@ -3379,64 +3173,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tapable": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.17.3", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, "node_modules/thenby": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", @@ -3479,37 +3215,6 @@ "node": ">=8.0" } }, - "node_modules/ts-loader": { - "version": "9.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/typescript": { - "version": "5.2.2", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/uikit": { "version": "3.23.13", "resolved": "https://registry.npmjs.org/uikit/-/uikit-3.23.13.tgz", @@ -3548,46 +3253,6 @@ "node": ">= 10.0.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.4", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -3597,250 +3262,96 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/vue": { - "version": "2.6.14", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz", - "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==", - "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", - "license": "MIT" - }, - "node_modules/vue-hot-reload-api": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", - "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", - "dev": true, - "license": "MIT" - }, - "node_modules/vue-loader": { - "version": "15.11.1", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz", - "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/component-compiler-utils": "^3.1.0", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - }, - "peerDependencies": { - "css-loader": "*", - "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" - }, - "peerDependenciesMeta": { - "cache-loader": { - "optional": true - }, - "prettier": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/vue-style-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", - "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.6.14", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", - "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, "license": "MIT", "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "node_modules/vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true, - "license": "MIT" - }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.88.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { - "webpack": "bin/webpack.js" + "vite": "bin/vite.js" }, "engines": { - "node": ">=10.13.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-bundle-tracker": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.assign": "^4.2.0", - "lodash.defaults": "^4.2.0", - "lodash.foreach": "^4.5.0", - "lodash.get": "^4.4.2", - "strip-ansi": "^6.0.0" - } - }, - "node_modules/webpack-cli": { - "version": "4.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.2.0", - "@webpack-cli/info": "^1.5.0", - "@webpack-cli/serve": "^1.7.0", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "cross-spawn": "^7.0.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" + "url": "https://github.com/vitejs/vite?sponsor=1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x" + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { - "@webpack-cli/generators": { + "@types/node": { "optional": true }, - "@webpack-cli/migrate": { + "less": { "optional": true }, - "webpack-bundle-analyzer": { + "lightningcss": { "optional": true }, - "webpack-dev-server": { + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { "optional": true } } }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "dev": true, + "node_modules/vue": { + "version": "3.5.35", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.35.tgz", + "integrity": "sha512-cx89fnr+0kVGHiNFG6y6s0bdjypJRFNZn6x3WPstNdQR1bi1mbB7h4v5IBGTsPJU3nK1+0Iqj3Zf+hZWMieR4Q==", "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" + "@vue/compiler-dom": "3.5.35", + "@vue/compiler-sfc": "3.5.35", + "@vue/runtime-dom": "3.5.35", + "@vue/server-renderer": "3.5.35", + "@vue/shared": "3.5.35" }, - "engines": { - "node": ">=10.0.0" + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "dev": true, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "loose-envify": "^1.0.0" } }, - "node_modules/wildcard": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -3867,15 +3378,10 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", "license": "ISC", "engines": { "node": ">= 6" diff --git a/package.json b/package.json index 60a85864..8114ad27 100644 --- a/package.json +++ b/package.json @@ -8,33 +8,21 @@ }, "dependencies": { "@selectize/selectize": "^0.15.2", - "axios": "^0.23.0", + "axios": "^1.7.0", "ecds-annotator": "github:ecds/ecds-annotator#develop", "jquery": "^3.6.0", "nouislider": "^15.8.1", - "vue": "^2.6.14" + "vue": "^3.4.0" }, "devDependencies": { - "@vue/component-compiler-utils": "^3.3.0", - "css-loader": "^7.1.2", - "fontawesome": "^5.6.3", - "jquery": "^3.6.0", - "source-map-loader": "^4.0.0", - "terser-webpack-plugin": "^5.3.3", - "ts-loader": "^9.4.4", + "@vitejs/plugin-vue": "^5.0.0", "uikit": "^3.23.13", "uikit-icons": "^0.5.0", - "vue-loader": "^15.11.1", - "vue-style-loader": "^4.1.3", - "vue-template-compiler": "^2.6.14", - "webpack": "^5.88.2", - "webpack-bundle-tracker": "^1.5.0", - "webpack-cli": "^4.9.2" + "vite": "^5.0.0" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "webpack --config webpack.config.js", - "watch": "webpack --watch --config webpack.config.js" + "build": "vite build", + "dev": "vite build --watch" }, "repository": { "type": "git", diff --git a/readux-dev.conf b/readux-dev.conf new file mode 100644 index 00000000..511f7a44 --- /dev/null +++ b/readux-dev.conf @@ -0,0 +1,40 @@ +upstream readux { + server localhost:8000; +} + +upstream flower { + server localhost:5555; +} + +error_log /var/log/nginx/error.log error; + +server { + client_max_body_size 0; + listen 80 default_server; + listen [::]:80 default_server; + + keepalive_timeout 5; + + location / { + proxy_pass http://readux; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + } + + location /static/ { + alias /data/staticfiles/; + } + + location /media/ { + alias /data/media/; + } + + location /flower/ { + proxy_pass http://flower; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_set_header X-Script-Name /flower; + proxy_redirect off; + } +} \ No newline at end of file diff --git a/requirements/base.txt b/requirements/base.txt index ca3c58f3..347eccd2 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,8 +1,9 @@ +urllib3>=2 # required by elastic-transport; compatible with requests 2.31+ pytz==2023.3 # https://github.com/stub42/pytz python-slugify==8.0.1 # https://github.com/un33k/python-slugify -Pillow==9.4.0 # wagtail 4.2.4 depends on Pillow<10.0.0 and >=4.0.0 +Pillow # unpinned after Wagtail 6 upgrade argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi -beautifulsoup4==4.9.3 # CANNOT UPDATE DUE TO WAGTAIL +beautifulsoup4 # unpinned after Wagtail 6 upgrade lxml==4.9.3 pyyaml progress @@ -15,16 +16,17 @@ edtf # Django # ------------------------------------------------------------------------------ -# TODO: When we get to update, check this re: summernote https://github.com/summernote/django-summernote/issues/449 -Django>=4.0,<5.0 # https://www.djangoproject.com/ +# Replaced django-summernote with django-tinymce (see issue #449 — summernote not compatible with Django 5) +Django>=5.2,<6.0 # https://www.djangoproject.com/ django-environ==0.11.2 # https://github.com/joke2k/django-environ # git+https://github.com/joke2k/django-environ@develop django-model-utils==4.2.0 # https://github.com/jazzband/django-model-utils django-dirtyfields>=1.7.0 # https://github.com/romgar/django-dirtyfields -django-allauth>=0.63.6 # https://github.com/pennersr/django-allauth +django-allauth>=65.0 # https://github.com/pennersr/django-allauth pyjwt>=2.8.0 requests-oauthlib>=1.3.1 -django-crispy-forms==1.14.0 # https://github.com/django-crispy-forms/django-crispy-forms +django-crispy-forms>=2.0 # https://github.com/django-crispy-forms/django-crispy-forms +crispy-bootstrap4 # template pack now a separate package in crispy-forms 2.x django-redis==5.4.0 # https://github.com/niwinz/django-redis # beta version required for Django 2.x django-modeltranslation>=0.17.2 # https://github.com/deschler/django-modeltranslation @@ -33,7 +35,7 @@ django-taggit>=1.5.0 # https://github.com/jazzband/django-taggit django-cors-headers>=3.8.0 # https://github.com/ottoyiu/django-cors-headers #wysiwyg -django-summernote>=0.8.11.6 # https://github.com/summernote/django-summernote +django-tinymce>=4.0 # https://github.com/jazzband/django-tinymce # SCSS Support #-------------------------------------------------------------------------------- @@ -45,15 +47,14 @@ django-sass-processor pylint-django==2.5.5 # Wagtail -wagtail==5.2.8 -wagtailmenus==3.1.9 -wagtail-modeladmin==2.0.0 # replaces deprecated wagtail.contrib.modeladmin -#git+https://github.com/jcmundy/wagtail-autocomplete.git@master#egg=wagtail-autocomplete -wagtail-autocomplete==0.10.0 -wagtail-cache==2.3.0 +wagtail>=6.0 +wagtail-modeladmin # standalone package replacing wagtail.contrib.modeladmin removed in Wagtail 6 +wagtailmenus>=4.0 +# wagtail-autocomplete removed — replaced by FieldPanel(autocomplete=True) built into Wagtail 4+ +wagtail-cache # verify Wagtail 6 compat # Import/Export -django-import-export==2.8.0 +django-import-export>=4.0 # review admin import classes for 4.x API changes gitpython==3.1.40 # S3 Uploads @@ -74,13 +75,13 @@ stream-unzip>=0.0.58 bcp47==0.0.4 # https://github.com/highfestiva/bcp47.py # Elasticsearch -django-elasticsearch-dsl>7.0,<8.0 -elasticsearch<7.14.0 +django-elasticsearch-dsl>=8.0,<9.0 +elasticsearch-dsl>=8.0,<9.0 +elasticsearch>=8.13.0,<9.0 # used to unaccent strings for sorting unidecode -# TODO: Upgrade after https://github.com/django-extensions/django-extensions/issues/1715 is fixed -Werkzeug<2.4.0 # https://github.com/pallets/werkzeug +Werkzeug # https://github.com/pallets/werkzeug — cap removed, was only needed for Django 3 ipdb~=0.13.13 # https://github.com/gotcha/ipdb # TODO: Upgrade after moving to Django 3 psycopg2-binary==2.9.3 # https://github.com/psycopg/psycopg2 diff --git a/requirements/production.txt b/requirements/production.txt index 0d254500..b02cdf3f 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -4,7 +4,7 @@ gunicorn==21.2.0 # https://github.com/benoitc/gunicorn Collectfast==2.2.0 # https://github.com/antonagestam/collectfast -raven==6.10.0 # https://github.com/getsentry/raven-python +sentry-sdk[django] # replaces unmaintained raven # Django # ------------------------------------------------------------------------------ diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 00000000..625aae5b --- /dev/null +++ b/vite.config.js @@ -0,0 +1,37 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' + +export default defineConfig({ + plugins: [vue()], + + resolve: { + alias: { + "@": path.resolve(__dirname, "apps/static/js"), + // Full (runtime + compiler) build needed because the root Vue instance + // mounts to a Django-rendered DOM template rather than an SFC template. + vue: "vue/dist/vue.esm-bundler.js", + }, + }, + + build: { + // Write output alongside other static JS so Django's {% static %} tags + // continue to work without any template changes. + outDir: "apps/static/js", + // Don't wipe the output directory — other static files live here. + emptyOutDir: false, + rollupOptions: { + input: "./apps/static/js/index.js", + output: { + entryFileNames: "main.js", + // Keep chunk names stable so cached builds stay valid. + chunkFileNames: "[name]-[hash].js", + assetFileNames: "[name][extname]", + }, + }, + sourcemap: true, + }, + optimizeDeps: { + exclude: ["ecds-annotator"], + }, +}); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index e0e62051..00000000 --- a/webpack.config.js +++ /dev/null @@ -1,50 +0,0 @@ -const path = require("path"); -const webpack = require("webpack"); -const BundleTracker = require("webpack-bundle-tracker"); -const { VueLoaderPlugin } = require('vue-loader'); - -module.exports = { - context: __dirname, - mode: "production", - entry: "./apps/static/js/index", - watch: false, - output: { - path: path.resolve("./apps/static/js/"), - filename: "[name].js", - }, - resolve: { - extensions: ['.js', '.vue', '.json'], - alias: { - // Use compiler+runtime build of Vue 2 - 'vue$': 'vue/dist/vue.esm.js', - '@': path.resolve(__dirname, 'apps/static/js'), - }, - }, - devtool: "eval-cheap-module-source-map", // Dev: fastest reasonable source maps - // devtool: "source-map", // Dev: switch to full source maps for debugging if needed - plugins: [new BundleTracker({ filename: "./webpack-stats.json" }), new VueLoaderPlugin()], - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - }, - { - test: /\.js$/, - enforce: "pre", - use: ["source-map-loader"], - exclude: [ - /node_modules\/ecds-annotator/, - /node_modules\/uikit/, - /node_modules\/jquery/, - /node_modules\/@selectize\/selectize/, - /node_modules\/nouislider/, - ], - }, - { - test: /\.css$/i, - use: ["css-loader"], - }, - ], - }, -};