From 2e957f47af7ebba1a669124193aed465815bbe18 Mon Sep 17 00:00:00 2001 From: Frankie Dintino Date: Fri, 15 Nov 2024 12:01:59 -0500 Subject: [PATCH] Backport CI and test modernization --- .github/workflows/test.yml | 33 +- nested_admin/tests/admin_widgets/admin.py | 148 +- nested_admin/tests/admin_widgets/models.py | 199 +- nested_admin/tests/admin_widgets/tests.py | 225 +- nested_admin/tests/base.py | 214 +- nested_admin/tests/conftest.py | 7 +- nested_admin/tests/drag_drop.py | 176 +- nested_admin/tests/gfk/admin.py | 14 +- nested_admin/tests/gfk/models.py | 10 +- nested_admin/tests/gfk/tests.py | 356 +- .../grp_collapsible_tabular_inline/admin.py | 6 +- .../grp_collapsible_tabular_inline/models.py | 6 - .../grp_collapsible_tabular_inline/tests.py | 33 +- .../tests/identical_prefixes/admin.py | 22 +- .../tests/identical_prefixes/models.py | 34 +- .../tests/identical_prefixes/tests.py | 58 +- nested_admin/tests/issue_122/models.py | 6 - nested_admin/tests/issue_122/tests.py | 39 +- .../mixed_permissions_min_num_bug/admin.py | 12 +- .../mixed_permissions_min_num_bug/models.py | 10 +- .../mixed_permissions_min_num_bug/tests.py | 52 +- .../nested_delete_validationerrors/models.py | 14 +- .../nested_delete_validationerrors/tests.py | 27 +- nested_admin/tests/nested_polymorphic/base.py | 197 +- .../test_polymorphic_add_filtering/admin.py | 40 +- .../test_polymorphic_add_filtering/models.py | 15 +- .../test_polymorphic_add_filtering/tests.py | 181 +- .../test_polymorphic_mixed_nesting/admin.py | 38 +- .../test_polymorphic_mixed_nesting/models.py | 8 +- .../test_polymorphic_mixed_nesting/tests.py | 140 +- .../test_polymorphic_std/admin.py | 53 +- .../test_polymorphic_std/models.py | 59 +- .../test_polymorphic_std/tests.py | 106 +- .../tests/nested_recursive/__init__.py | 0 nested_admin/tests/nested_recursive/admin.py | 26 + nested_admin/tests/nested_recursive/models.py | 16 + nested_admin/tests/nested_recursive/tests.py | 42 + nested_admin/tests/one_deep/admin.py | 33 +- nested_admin/tests/one_deep/models.py | 29 +- nested_admin/tests/one_deep/tests.py | 147 +- nested_admin/tests/settings.py | 141 +- nested_admin/tests/three_deep/admin.py | 21 +- nested_admin/tests/three_deep/models.py | 14 +- nested_admin/tests/three_deep/tests.py | 190 +- nested_admin/tests/two_deep/admin.py | 32 +- nested_admin/tests/two_deep/models.py | 28 +- .../tests/two_deep/test_permissions.py | 45 +- nested_admin/tests/two_deep/tests.py | 1074 +- nested_admin/tests/urls.py | 7 +- nested_admin/tests/utils.py | 70 +- package-lock.json | 10871 +++++++++++++++- package.json | 17 +- pyproject.toml | 8 + pytest.ini | 2 + setup.cfg | 15 +- setup.py | 86 +- tox.ini | 49 +- 57 files changed, 13521 insertions(+), 1980 deletions(-) create mode 100644 nested_admin/tests/nested_recursive/__init__.py create mode 100644 nested_admin/tests/nested_recursive/admin.py create mode 100644 nested_admin/tests/nested_recursive/models.py create mode 100644 nested_admin/tests/nested_recursive/tests.py create mode 100644 pyproject.toml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dd019b4..013b33f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,15 +45,16 @@ jobs: NODE_ENV: test steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Setup chromedriver - uses: nanasess/setup-chromedriver@v1.0.5 + # uses: nanasess/setup-chromedriver@v2.2.2 + uses: nanasess/setup-chromedriver@42cc2998329f041de87dc3cfa33a930eacd57eaa - name: Install tox run: | @@ -61,31 +62,32 @@ jobs: - name: Cache instrumented static files id: cache-test-dist - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: nested_admin/tests/static - key: test-dist-${{ hashFiles('package-lock.json', '.github/workflows/test.yml', 'webpack.config.js', 'package.json', '.*rc*', 'frontend/**') }} + key: test-dist-${{ hashFiles('package-lock.json', '.github/workflows/test.yml', 'webpack.config.js', 'package.json', '.*rc*', 'nested_admin/static/nested_admin/src/**/*.*s') }} - name: Cache node_modules id: cache-node_modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: node_modules key: node_modules-${{ hashFiles('package-lock.json') }} - - name: Setup nodejs 12 - if: steps.cache-test-dist.outputs.cache-hit != 'true' || steps.cache-node_modules.outputs.cache-hit != 'true' - uses: actions/setup-node@v2 + - name: Setup nodejs + if: steps.cache-test-dist.outputs.cache-hit != 'true' + uses: actions/setup-node@v3 with: - node-version: '12' + node-version: '16' + cache: 'npm' - name: npm ci - if: steps.cache-test-dist.outputs.cache-hit != 'true' || steps.cache-node_modules.outputs.cache-hit != 'true' + if: steps.cache-test-dist.outputs.cache-hit != 'true' && steps.cache-node_modules.outputs.cache-hit != 'true' run: | npm ci || npm ci || npm ci - name: Build instrumented static files - if: steps.cache-test-dist.outputs.cache-hit != 'true' || steps.cache-node_modules.outputs.cache-hit != 'true' + if: steps.cache-test-dist.outputs.cache-hit != 'true' run: | npm run build @@ -98,7 +100,7 @@ jobs: - name: Upload junit xml if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: junit-reports path: reports/*.xml @@ -121,15 +123,14 @@ jobs: runs-on: ubuntu-latest name: "Report Test Results" steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v3 with: name: junit-reports - name: Publish tests report - uses: mikepenz/action-junit-report@5703ba1461f35871cde0208140d737d3e1eef38f + uses: mikepenz/action-junit-report@1a91e26932fb7ba410a31fab1f09266a96d29971 with: report_paths: ./*.xml - github_token: ${{ secrets.GITHUB_TOKEN }} require_tests: true fail_on_failure: true check_name: Test Report diff --git a/nested_admin/tests/admin_widgets/admin.py b/nested_admin/tests/admin_widgets/admin.py index 54e4cab..f97bd99 100644 --- a/nested_admin/tests/admin_widgets/admin.py +++ b/nested_admin/tests/admin_widgets/admin.py @@ -1,95 +1,116 @@ -from django.conf import settings from django.contrib import admin from nested_admin import NestedStackedInline, NestedTabularInline, NestedModelAdmin from .models import ( - WidgetsRoot, WidgetsM2M, WidgetsRelated1, - WidgetsRelated2, WidgetsA, WidgetsB, - WidgetsC0, WidgetsC1, WidgetsM2MTwo, - WidgetMediaOrderRoot, WidgetMediaOrderA, WidgetMediaOrderB, - WidgetMediaOrderC0, WidgetMediaOrderC1, - WidgetMediaOrderRootWithDateWidget) + WidgetsRoot, + WidgetsM2M, + WidgetsRelated1, + WidgetsRelated2, + WidgetsA, + WidgetsB, + WidgetsC0, + WidgetsC1, + WidgetsM2MTwo, + WidgetMediaOrderRoot, + WidgetMediaOrderA, + WidgetMediaOrderB, + WidgetMediaOrderC0, + WidgetMediaOrderC1, + WidgetMediaOrderRootWithDateWidget, +) class WidgetsC0Inline(NestedStackedInline): model = WidgetsC0 - prepopulated_fields = {'slug': ('name', )} - filter_horizontal = ['m2m'] + prepopulated_fields = {"slug": ("name",)} + filter_horizontal = ["m2m"] sortable_field_name = "position" extra = 0 - inline_classes = ("grp-collapse", "grp-open",) - raw_id_fields = ['fk2', 'fk4', 'm2m_two', 'm2m_three'] + inline_classes = ( + "grp-collapse", + "grp-open", + ) + raw_id_fields = ["fk2", "fk4", "m2m_two", "m2m_three"] autocomplete_lookup_fields = { - 'fk': ['fk2'], - 'm2m': ['m2m_three'], - 'generic': [['relation_type', 'relation_id']], + "fk": ["fk2"], + "m2m": ["m2m_three"], + "generic": [["relation_type", "relation_id"]], } - autocomplete_fields = ['fk3'] + autocomplete_fields = ["fk3"] related_lookup_fields = { - 'fk': ['fk4'], - 'm2m': ['m2m_two'], - 'generic': [['content_type', 'object_id']], + "fk": ["fk4"], + "m2m": ["m2m_two"], + "generic": [["content_type", "object_id"]], } class WidgetsC1Inline(NestedTabularInline): model = WidgetsC1 - prepopulated_fields = {'slug': ('name', )} - filter_horizontal = ['m2m'] + prepopulated_fields = {"slug": ("name",)} + filter_horizontal = ["m2m"] sortable_field_name = "position" extra = 0 - inline_classes = ("grp-collapse", "grp-open",) - raw_id_fields = ['fk2', 'fk4', 'm2m_two'] - autocomplete_lookup_fields = {'fk': ['fk2']} - autocomplete_fields = ['fk3'] + inline_classes = ( + "grp-collapse", + "grp-open", + ) + raw_id_fields = ["fk2", "fk4", "m2m_two"] + autocomplete_lookup_fields = {"fk": ["fk2"]} + autocomplete_fields = ["fk3"] related_lookup_fields = { - 'fk': ['fk4'], - 'm2m': ['m2m_two'], - 'generic': [['content_type', 'object_id']], + "fk": ["fk4"], + "m2m": ["m2m_two"], + "generic": [["content_type", "object_id"]], } class WidgetsBInline(NestedStackedInline): model = WidgetsB inlines = [WidgetsC0Inline, WidgetsC1Inline] - prepopulated_fields = {'slug': ('name', )} - filter_horizontal = ['m2m'] + prepopulated_fields = {"slug": ("name",)} + filter_horizontal = ["m2m"] sortable_field_name = "position" extra = 1 - inline_classes = ("grp-collapse", "grp-open",) - raw_id_fields = ['fk2', 'fk4', 'm2m_two', 'm2m_three'] + inline_classes = ( + "grp-collapse", + "grp-open", + ) + raw_id_fields = ["fk2", "fk4", "m2m_two", "m2m_three"] autocomplete_lookup_fields = { - 'fk': ['fk2'], - 'm2m': ['m2m_three'], - 'generic': [['relation_type', 'relation_id']], + "fk": ["fk2"], + "m2m": ["m2m_three"], + "generic": [["relation_type", "relation_id"]], } - autocomplete_fields = ['fk3'] + autocomplete_fields = ["fk3"] related_lookup_fields = { - 'fk': ['fk4'], - 'm2m': ['m2m_two'], - 'generic': [['content_type', 'object_id']], + "fk": ["fk4"], + "m2m": ["m2m_two"], + "generic": [["content_type", "object_id"]], } class WidgetsAInline(NestedStackedInline): model = WidgetsA inlines = [WidgetsBInline] - prepopulated_fields = {'slug': ('name', )} - filter_horizontal = ['m2m'] + prepopulated_fields = {"slug": ("name",)} + filter_horizontal = ["m2m"] sortable_field_name = "position" extra = 1 - inline_classes = ("grp-collapse", "grp-open",) - raw_id_fields = ['fk2', 'fk4', 'm2m_two', 'm2m_three'] + inline_classes = ( + "grp-collapse", + "grp-open", + ) + raw_id_fields = ["fk2", "fk4", "m2m_two", "m2m_three"] autocomplete_lookup_fields = { - 'fk': ['fk2'], - 'm2m': ['m2m_three'], - 'generic': [['relation_type', 'relation_id']], + "fk": ["fk2"], + "m2m": ["m2m_three"], + "generic": [["relation_type", "relation_id"]], } - autocomplete_fields = ['fk3'] + autocomplete_fields = ["fk3"] related_lookup_fields = { - 'fk': ['fk4'], - 'm2m': ['m2m_two'], - 'generic': [['content_type', 'object_id']], + "fk": ["fk4"], + "m2m": ["m2m_two"], + "generic": [["content_type", "object_id"]], } @@ -105,8 +126,8 @@ class WidgetsRootAdmin(NestedModelAdmin): @admin.register(WidgetsRelated2) class WidgetsRelated2Admin(NestedModelAdmin): - ordering = ['-date_created'] - search_fields = ['name'] + ordering = ["-date_created"] + search_fields = ["name"] class WidgetMediaOrderC0Inline(NestedStackedInline): @@ -117,13 +138,16 @@ class WidgetMediaOrderC0Inline(NestedStackedInline): class WidgetMediaOrderC1Inline(NestedTabularInline): model = WidgetMediaOrderC1 - prepopulated_fields = {'slug': ('name', )} - filter_horizontal = ['m2m'] + prepopulated_fields = {"slug": ("name",)} + filter_horizontal = ["m2m"] extra = 0 - inline_classes = ("grp-collapse", "grp-open",) - raw_id_fields = ['fk2'] - autocomplete_lookup_fields = {'fk': ['fk2']} - autocomplete_fields = ['fk3'] + inline_classes = ( + "grp-collapse", + "grp-open", + ) + raw_id_fields = ["fk2"] + autocomplete_lookup_fields = {"fk": ["fk2"]} + autocomplete_fields = ["fk3"] class WidgetMediaOrderBInline(NestedStackedInline): @@ -131,7 +155,10 @@ class WidgetMediaOrderBInline(NestedStackedInline): inlines = [WidgetMediaOrderC0Inline, WidgetMediaOrderC1Inline] sortable_field_name = "position" extra = 1 - inline_classes = ("grp-collapse", "grp-open",) + inline_classes = ( + "grp-collapse", + "grp-open", + ) class WidgetMediaOrderAInline(NestedStackedInline): @@ -139,7 +166,10 @@ class WidgetMediaOrderAInline(NestedStackedInline): inlines = [WidgetMediaOrderBInline] sortable_field_name = "position" extra = 1 - inline_classes = ("grp-collapse", "grp-open",) + inline_classes = ( + "grp-collapse", + "grp-open", + ) @admin.register(WidgetMediaOrderRoot) diff --git a/nested_admin/tests/admin_widgets/models.py b/nested_admin/tests/admin_widgets/models.py index b2e6e0f..18cf3ee 100644 --- a/nested_admin/tests/admin_widgets/models.py +++ b/nested_admin/tests/admin_widgets/models.py @@ -1,17 +1,13 @@ -from __future__ import unicode_literals - from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible class WidgetsRoot(models.Model): name = models.CharField(max_length=200) -@python_2_unicode_compatible class WidgetsRelated1(models.Model): name = models.CharField(max_length=200) @@ -23,16 +19,15 @@ def related_label(self): @staticmethod def autocomplete_search_fields(): - return ("name__icontains", ) + return ("name__icontains",) -@python_2_unicode_compatible class WidgetsRelated2(models.Model): name = models.CharField(max_length=200) date_created = models.DateTimeField(auto_now_add=True) class Meta: - ordering = ['-date_created'] + ordering = ["-date_created"] def __str__(self): return self.name @@ -42,10 +37,9 @@ def related_label(self): @staticmethod def autocomplete_search_fields(): - return ("name__icontains", ) + return ("name__icontains",) -@python_2_unicode_compatible class WidgetsM2M(models.Model): name = models.CharField(max_length=200) @@ -53,7 +47,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class WidgetsM2MTwo(models.Model): name = models.CharField(max_length=200) @@ -65,10 +58,9 @@ def related_label(self): @staticmethod def autocomplete_search_fields(): - return ("name__icontains", ) + return ("name__icontains",) -@python_2_unicode_compatible class WidgetsM2MThree(models.Model): name = models.CharField(max_length=200) @@ -80,25 +72,28 @@ def related_label(self): @staticmethod def autocomplete_search_fields(): - return ("name__icontains", ) + return ("name__icontains",) -@python_2_unicode_compatible class WidgetsA(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() parent = ForeignKey(WidgetsRoot, on_delete=CASCADE) position = models.PositiveIntegerField() date = models.DateTimeField(blank=True, null=True) - upload = models.FileField(blank=True, null=True, upload_to='foo') - fk1 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk2 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk3 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk4 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') + upload = models.FileField(blank=True, null=True, upload_to="foo") + fk1 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk2 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk3 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk4 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) m2m = models.ManyToManyField(WidgetsM2M, blank=True) m2m_two = models.ManyToManyField(WidgetsM2MTwo, blank=True) m2m_three = models.ManyToManyField(WidgetsM2MThree, blank=True) @@ -107,71 +102,79 @@ class WidgetsA(models.Model): object_id = models.PositiveIntegerField(null=True, blank=True) content_object = GenericForeignKey() - relation_type = ForeignKey(ContentType, null=True, blank=True, - on_delete=CASCADE, related_name='+') + relation_type = ForeignKey( + ContentType, null=True, blank=True, on_delete=CASCADE, related_name="+" + ) relation_id = models.PositiveIntegerField(null=True, blank=True) - relation_object = GenericForeignKey('relation_type', 'relation_id') + relation_object = GenericForeignKey("relation_type", "relation_id") class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): return self.name -@python_2_unicode_compatible class WidgetsB(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() parent = ForeignKey(WidgetsA, on_delete=CASCADE) position = models.PositiveIntegerField() date = models.DateTimeField(blank=True, null=True) - upload = models.FileField(blank=True, null=True, upload_to='foo') - fk1 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk2 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk3 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk4 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') + upload = models.FileField(blank=True, null=True, upload_to="foo") + fk1 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk2 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk3 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk4 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) m2m = models.ManyToManyField(WidgetsM2M, blank=True) m2m_two = models.ManyToManyField(WidgetsM2MTwo, blank=True) m2m_three = models.ManyToManyField(WidgetsM2MThree, blank=True) content_type = ForeignKey(ContentType, null=True, blank=True, on_delete=CASCADE) object_id = models.PositiveIntegerField(null=True, blank=True) - content_object = GenericForeignKey('content_type', 'object_id') + content_object = GenericForeignKey("content_type", "object_id") - relation_type = ForeignKey(ContentType, null=True, blank=True, - on_delete=CASCADE, related_name='+') + relation_type = ForeignKey( + ContentType, null=True, blank=True, on_delete=CASCADE, related_name="+" + ) relation_id = models.PositiveIntegerField(null=True, blank=True) - relation_object = GenericForeignKey('relation_type', 'relation_id') + relation_object = GenericForeignKey("relation_type", "relation_id") class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) -@python_2_unicode_compatible class WidgetsC0(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() parent = ForeignKey(WidgetsB, on_delete=CASCADE) position = models.PositiveIntegerField() date = models.DateTimeField(blank=True, null=True) - upload = models.FileField(blank=True, null=True, upload_to='foo') - fk1 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk2 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk3 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk4 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') + upload = models.FileField(blank=True, null=True, upload_to="foo") + fk1 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk2 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk3 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk4 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) m2m = models.ManyToManyField(WidgetsM2M, blank=True) m2m_two = models.ManyToManyField(WidgetsM2MTwo, blank=True) m2m_three = models.ManyToManyField(WidgetsM2MThree, blank=True) @@ -180,35 +183,39 @@ class WidgetsC0(models.Model): object_id = models.PositiveIntegerField(null=True, blank=True) content_object = GenericForeignKey() - relation_type = ForeignKey(ContentType, null=True, blank=True, - on_delete=CASCADE, related_name='+') + relation_type = ForeignKey( + ContentType, null=True, blank=True, on_delete=CASCADE, related_name="+" + ) relation_id = models.PositiveIntegerField(null=True, blank=True) - relation_object = GenericForeignKey('relation_type', 'relation_id') + relation_object = GenericForeignKey("relation_type", "relation_id") class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) -@python_2_unicode_compatible class WidgetsC1(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() parent = ForeignKey(WidgetsB, on_delete=CASCADE) position = models.PositiveIntegerField() date = models.DateTimeField(blank=True, null=True) - upload = models.FileField(blank=True, null=True, upload_to='foo') - fk1 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk2 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk3 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk4 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') + upload = models.FileField(blank=True, null=True, upload_to="foo") + fk1 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk2 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk3 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk4 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) m2m = models.ManyToManyField(WidgetsM2M, blank=True) m2m_two = models.ManyToManyField(WidgetsM2MTwo, blank=True) @@ -217,18 +224,17 @@ class WidgetsC1(models.Model): content_object = GenericForeignKey() class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) class WidgetMediaOrderRoot(models.Model): name = models.CharField(max_length=200) -@python_2_unicode_compatible class WidgetMediaOrderA(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() @@ -236,13 +242,12 @@ class WidgetMediaOrderA(models.Model): position = models.PositiveIntegerField() class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): return self.name -@python_2_unicode_compatible class WidgetMediaOrderB(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() @@ -250,14 +255,13 @@ class WidgetMediaOrderB(models.Model): position = models.PositiveIntegerField() class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) -@python_2_unicode_compatible class WidgetMediaOrderC0(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() @@ -265,37 +269,40 @@ class WidgetMediaOrderC0(models.Model): position = models.PositiveIntegerField() class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) -@python_2_unicode_compatible class WidgetMediaOrderC1(models.Model): name = models.CharField(max_length=200) slug = models.SlugField() parent = ForeignKey(WidgetMediaOrderB, on_delete=CASCADE) position = models.PositiveIntegerField() date = models.DateTimeField(blank=True, null=True) - upload = models.FileField(blank=True, null=True, upload_to='foo') - fk1 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk2 = models.ForeignKey(WidgetsRelated1, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk3 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') - fk4 = models.ForeignKey(WidgetsRelated2, blank=True, null=True, - on_delete=CASCADE, related_name='+') + upload = models.FileField(blank=True, null=True, upload_to="foo") + fk1 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk2 = models.ForeignKey( + WidgetsRelated1, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk3 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) + fk4 = models.ForeignKey( + WidgetsRelated2, blank=True, null=True, on_delete=CASCADE, related_name="+" + ) m2m = models.ManyToManyField(WidgetsM2M, blank=True) class Meta: - ordering = ('position', ) + ordering = ("position",) def __str__(self): - parent_name = self.parent.name if self.parent else '?' - return "%s - %s" % (parent_name, self.name) + parent_name = self.parent.name if self.parent else "?" + return "{} - {}".format(parent_name, self.name) class WidgetMediaOrderRootWithDateWidget(WidgetMediaOrderRoot): diff --git a/nested_admin/tests/admin_widgets/tests.py b/nested_admin/tests/admin_widgets/tests.py index ce6ca64..8f4527f 100644 --- a/nested_admin/tests/admin_widgets/tests.py +++ b/nested_admin/tests/admin_widgets/tests.py @@ -1,36 +1,40 @@ from contextlib import contextmanager +from html import unescape import time -from unittest import SkipTest -import django from django.contrib.contenttypes.models import ContentType from django.conf import settings from django.utils.text import slugify - -try: - from html import unescape -except ImportError: - from django.utils.text import unescape_entities as unescape - from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.support.ui import Select -import six -from nested_admin.tests.base import ( - skip_if_not_grappelli, BaseNestedAdminTestCase) +from nested_admin.tests.base import skip_if_not_grappelli, BaseNestedAdminTestCase from .models import ( - WidgetsRoot, WidgetsA, WidgetsB, - WidgetsC0, WidgetsC1, - WidgetMediaOrderRoot, WidgetMediaOrderA, WidgetMediaOrderB, - WidgetMediaOrderC0, WidgetMediaOrderC1, - WidgetMediaOrderRootWithDateWidget) + WidgetsRoot, + WidgetsA, + WidgetsB, + WidgetsC0, + WidgetsC1, + WidgetMediaOrderRoot, + WidgetMediaOrderA, + WidgetMediaOrderB, + WidgetMediaOrderC0, + WidgetMediaOrderC1, + WidgetMediaOrderRootWithDateWidget, +) from .admin import ( - WidgetsAInline, WidgetsBInline, WidgetsM2M, - WidgetsC0Inline, WidgetsC1Inline, - WidgetMediaOrderAInline, WidgetMediaOrderBInline, - WidgetMediaOrderC0Inline, WidgetMediaOrderC1Inline) + WidgetsAInline, + WidgetsBInline, + WidgetsM2M, + WidgetsC0Inline, + WidgetsC1Inline, + WidgetMediaOrderAInline, + WidgetMediaOrderBInline, + WidgetMediaOrderC0Inline, + WidgetMediaOrderC1Inline, +) class BaseWidgetTestCase(BaseNestedAdminTestCase): @@ -40,24 +44,24 @@ class BaseWidgetTestCase(BaseNestedAdminTestCase): root_model = None nested_models = [] - fixtures = ['admin-widgets.xml'] + fixtures = ["admin-widgets.xml"] @classmethod def setUpClass(cls): - super(BaseWidgetTestCase, cls).setUpClass() + super().setUpClass() if cls.nested_models: cls.a_model, cls.b_model, (cls.c0_model, cls.c1_model) = cls.nested_models @contextmanager def enable_inline_collapsing(self): """A context manager that configures the inline classes to be collapsible.""" - if 'grappelli' in settings.INSTALLED_APPS: + if "grappelli" in settings.INSTALLED_APPS: class_attr = "inline_classes" class_val = ("grp-collapse", "grp-closed") reset_val = ("grp-collapse", "grp-open") else: class_attr = "classes" - class_val = ("collapse", ) + class_val = ("collapse",) reset_val = None for admin in self.admin_classes: @@ -70,29 +74,32 @@ def enable_inline_collapsing(self): def get_name_for_indexes(self, indexes): name = "Item %s" % (" ABC"[len(indexes)]) - if name == 'Item C': + if name == "Item C": name += "%d%d" % (indexes[-1][0], indexes[-1][1]) else: name += "%d" % indexes[-1] - name += " (%s)" % " > ".join(["%s" % i[1] for i in self._normalize_indexes(indexes)]) + name += " (%s)" % " > ".join( + ["%s" % i[1] for i in self._normalize_indexes(indexes)] + ) return name def check_prepopulated(self, indexes): name = self.get_name_for_indexes(indexes) - expected_slug = slugify(six.text_type(name)) + expected_slug = slugify(name) - slug_sel = self.get_form_field_selector('slug', indexes) + slug_sel = self.get_form_field_selector("slug", indexes) - self.set_field('name', name, indexes) + self.set_field("name", name, indexes) time.sleep(0.2) - slug_val = self.selenium.execute_script( - 'return $("%s").val()' % slug_sel) - self.assertEqual(slug_val, expected_slug, "prepopulated slug field did not sync") + slug_val = self.selenium.execute_script('return $("%s").val()' % slug_sel) + self.assertEqual( + slug_val, expected_slug, "prepopulated slug field did not sync" + ) def check_datetime(self, indexes): - date_el = self.get_field('date_0', indexes) - time_el = self.get_field('date_1', indexes) + date_el = self.get_field("date_0", indexes) + time_el = self.get_field("date_1", indexes) if self.has_grappelli: now_link_xpath = "following-sibling::*[1]" @@ -100,43 +107,53 @@ def check_datetime(self, indexes): now_link_xpath = "following-sibling::*[1]/a[1]" date_el.clear() time_el.clear() - self.click(date_el.find_element_by_xpath(now_link_xpath)) + self.click(date_el.find_element(By.XPATH, now_link_xpath)) if self.has_grappelli: - selector = '#ui-datepicker-div .ui-state-highlight' + selector = "#ui-datepicker-div .ui-state-highlight" with self.clickable_selector(selector, timeout=1) as el: - self.selenium.execute_script('arguments[0].scrollIntoView()', date_el) + self.selenium.execute_script("arguments[0].scrollIntoView()", date_el) self.click(el) - self.wait_until_element_is('#ui-datepicker-div', ':not(:visible)', - 'Datepicker widget did not close') + self.wait_until_element_is( + "#ui-datepicker-div", + ":not(:visible)", + "Datepicker widget did not close", + ) time.sleep(0.2) - self.click(time_el.find_element_by_xpath(now_link_xpath)) + self.click(time_el.find_element(By.XPATH, now_link_xpath)) if self.has_grappelli: - selector = '#ui-timepicker .ui-state-active' + selector = "#ui-timepicker .ui-state-active" with self.clickable_selector(selector, timeout=1) as el: - self.selenium.execute_script('arguments[0].scrollIntoView()', time_el) + self.selenium.execute_script("arguments[0].scrollIntoView()", time_el) self.click(el) - self.wait_until_element_is('#ui-timepicker', ':not(:visible)', - 'Timepicker widget did not close') + self.wait_until_element_is( + "#ui-timepicker", + ":not(:visible)", + "Timepicker widget did not close", + ) time.sleep(0.2) - self.assertNotEqual(date_el.get_attribute('value'), '', 'Date was not set') - self.assertNotEqual(time_el.get_attribute('value'), '', 'Time was not set') + self.assertNotEqual(date_el.get_attribute("value"), "", "Date was not set") + self.assertNotEqual(time_el.get_attribute("value"), "", "Time was not set") def check_m2m(self, indexes): - add_all_link = self.get_field('m2m_add_all_link', indexes) - remove_all_link = self.get_field('m2m_remove_all_link', indexes) + add_all_link = self.get_field("m2m_add_all_link", indexes) + remove_all_link = self.get_field("m2m_remove_all_link", indexes) self.click(remove_all_link) self.click(add_all_link) - m2m_to_sel = self.get_form_field_selector('m2m_to', indexes) + m2m_to_sel = self.get_form_field_selector("m2m_to", indexes) time.sleep(0.2) - selected = self.selenium.execute_script(( - 'return $("%s").find("option").toArray().map(' - ' function(el) { return parseInt(el.value, 10); })') % m2m_to_sel) + selected = self.selenium.execute_script( + ( + 'return $("%s").find("option").toArray().map(' + " function(el) { return parseInt(el.value, 10); })" + ) + % m2m_to_sel + ) self.assertEqual(selected, [1, 2, 3]) def check_fk(self, indexes): - field = self.get_field('fk1', indexes) - parent = field.get_property('parentNode').get_property('parentNode') - add_related = parent.find_element_by_css_selector('.add-related') + field = self.get_field("fk1", indexes) + parent = field.get_property("parentNode").get_property("parentNode") + add_related = parent.find_element(By.CSS_SELECTOR, ".add-related") if self.has_grappelli: # Grappelli can be very slow to initialize fk bindings, particularly # when run on travis-ci @@ -144,73 +161,78 @@ def check_fk(self, indexes): self.click(add_related) name = self.get_name_for_indexes(indexes) with self.switch_to_popup_window(): - self.set_field('name', name) + self.set_field("name", name) self.save_form() time.sleep(0.1) - field_id = field.get_attribute('id') + field_id = field.get_attribute("id") current_val = self.selenium.execute_script( - 'return $("#%s").find("option:selected").html()' % field_id) + 'return $("#%s").find("option:selected").html()' % field_id + ) self.assertEqual(unescape(current_val), name) def check_gfk_related_lookup(self, indexes): - ctype_field = self.get_field('content_type', indexes) + ctype_field = self.get_field("content_type", indexes) select = Select(ctype_field) m2m_ctype_id = ContentType.objects.get_for_model(WidgetsM2M).pk select.select_by_value(str(m2m_ctype_id)) - object_id_field = self.get_field('object_id', indexes) - object_id_field_id = object_id_field.get_attribute('id') - related_lookup_selector = ( - "#%s + .related-lookup" % object_id_field_id) + object_id_field = self.get_field("object_id", indexes) + object_id_field_id = object_id_field.get_attribute("id") + related_lookup_selector = "#%s + .related-lookup" % object_id_field_id self.wait_until( ec.element_to_be_clickable((By.CSS_SELECTOR, related_lookup_selector)), - message="Timeout waiting for related lookup widget on '#%s'" % object_id_field_id) + message="Timeout waiting for related lookup widget on '#%s'" + % object_id_field_id, + ) - lookup_el = self.selenium.find_element_by_css_selector(related_lookup_selector) + lookup_el = self.selenium.find_element(By.CSS_SELECTOR, related_lookup_selector) lookup_el.click() with self.switch_to_popup_window(): with self.clickable_xpath('//tr//a[text()="Zither"]') as el: el.click() time.sleep(0.1) - z_pk = "%s" % WidgetsM2M.objects.get(name='Zither').pk + z_pk = "%s" % WidgetsM2M.objects.get(name="Zither").pk def element_value_populated(d): - el = d.find_element_by_css_selector("#%s" % object_id_field_id) - return el.get_attribute('value') + el = d.find_element(By.CSS_SELECTOR, "#%s" % object_id_field_id) + return el.get_attribute("value") self.wait_until( - element_value_populated, - message='Timeout waiting for gfk object_id value') - self.assertEqual(z_pk, object_id_field.get_attribute('value')) + element_value_populated, message="Timeout waiting for gfk object_id value" + ) + self.assertEqual(z_pk, object_id_field.get_attribute("value")) class Widgets(BaseWidgetTestCase): admin_classes = [ - WidgetsAInline, WidgetsBInline, - WidgetsC0Inline, WidgetsC1Inline, + WidgetsAInline, + WidgetsBInline, + WidgetsC0Inline, + WidgetsC1Inline, ] root_model = WidgetsRoot - nested_models = (WidgetsA, WidgetsB, - (WidgetsC0, WidgetsC1)) + nested_models = (WidgetsA, WidgetsB, (WidgetsC0, WidgetsC1)) def test_collapsible_inlines(self): with self.enable_inline_collapsing(): self.load_admin() - name_field = self.get_field('name', [0]) + name_field = self.get_field("name", [0]) self.assertFalse(name_field.is_displayed(), "Inline did not load collapsed") if self.has_grappelli: collapse_handler = self.selenium.execute_script( 'return $(arguments[0]).find("> .djn-collapse-handler")[0]', - self.get_item([0])) + self.get_item([0]), + ) else: collapse_handler = self.selenium.execute_script( 'return $(arguments[0]).find("> fieldset > h2 > .collapse-toggle")[0]', - self.get_group()) + self.get_group(), + ) self.click(collapse_handler) self.assertTrue(name_field.is_displayed(), "Inline did not expand") @@ -354,12 +376,15 @@ def test_autocomplete_single_init(self): self.load_admin() self.add_inline() self.add_inline([1]) - autocomplete_elements = self.selenium.find_elements_by_xpath( - '//*[@id="id_widgetsa_set-1-widgetsb_set-0-fk2-autocomplete"]') - self.assertNotEqual(len(autocomplete_elements), 0, - "Zero autocomplete fields initialized") - self.assertEqual(len(autocomplete_elements), 1, - "Too many autocomplete fields initialized") + autocomplete_elements = self.selenium.find_elements( + By.XPATH, '//*[@id="id_widgetsa_set-1-widgetsb_set-0-fk2-autocomplete"]' + ) + self.assertNotEqual( + len(autocomplete_elements), 0, "Zero autocomplete fields initialized" + ) + self.assertEqual( + len(autocomplete_elements), 1, "Too many autocomplete fields initialized" + ) @skip_if_not_grappelli def test_gfk_related_lookup_initial_extra(self): @@ -376,39 +401,43 @@ def test_gfk_related_lookup_add_three_deep(self): self.check_gfk_related_lookup([1, 0, [1, 0]]) def test_nested_autocomplete_extra(self): - if self.has_grappelli: - raise SkipTest("Not testing autocomplete on grappelli") - if django.VERSION < (2, 0): - raise SkipTest("autocomplete_fields not available in Django before 2.0") self.load_admin() self.add_inline([0, [0]]) self.add_inline([0, 1, [0]]) - select_field = self.get_field('fk3', indexes=[0, 1, [0, 0]]) - select_parent = select_field.find_element_by_xpath('parent::*') + select_field = self.get_field("fk3", indexes=[0, 1, [0, 0]]) + select_parent = select_field.find_element(By.XPATH, "parent::*") select_parent.click() select2_is_active = self.selenium.execute_script( - 'return $(".select2-search__field").length > 0') + 'return $(".select2-search__field").length > 0' + ) self.assertTrue(select2_is_active) - select2_input = self.selenium.execute_script('return $(".select2-search__field")[0]') + select2_input = self.selenium.execute_script( + 'return $(".select2-search__field")[0]' + ) self.assertIsNotNone(select2_input) time.sleep(0.2) - select2_input.send_keys('l') + select2_input.send_keys("l") time.sleep(0.5) select2_input.send_keys(Keys.ENTER) time.sleep(0.2) - self.assertEqual(select_field.get_attribute('value'), '2') + self.assertEqual(select_field.get_attribute("value"), "2") class WidgetMediaOrder(BaseWidgetTestCase): admin_classes = [ - WidgetMediaOrderAInline, WidgetMediaOrderBInline, - WidgetMediaOrderC0Inline, WidgetMediaOrderC1Inline, + WidgetMediaOrderAInline, + WidgetMediaOrderBInline, + WidgetMediaOrderC0Inline, + WidgetMediaOrderC1Inline, ] root_model = WidgetMediaOrderRoot - nested_models = (WidgetMediaOrderA, WidgetMediaOrderB, - (WidgetMediaOrderC0, WidgetMediaOrderC1)) + nested_models = ( + WidgetMediaOrderA, + WidgetMediaOrderB, + (WidgetMediaOrderC0, WidgetMediaOrderC1), + ) def test_add_three_deep_m2m(self): self.load_admin() diff --git a/nested_admin/tests/base.py b/nested_admin/tests/base.py index 21d06d2..9bd17a7 100644 --- a/nested_admin/tests/base.py +++ b/nested_admin/tests/base.py @@ -1,8 +1,5 @@ -from __future__ import absolute_import - from datetime import datetime import functools -import inspect import json import logging import os @@ -14,17 +11,18 @@ from django.conf import settings from django.contrib.admin.sites import site as admin_site -import six from selenosis import AdminSelenosisTestCase +from selenium.webdriver.common.by import By +from selenium.webdriver.common.actions.pointer_input import PointerInput from .drag_drop import DragAndDropAction -from .utils import ( - xpath_item, is_sequence, is_integer, is_str, ElementRect) +from .utils import xpath_item, is_sequence, is_integer, is_str, ElementRect logger = logging.getLogger(__name__) -get_model_name = lambda m: "-".join([m._meta.app_label, m._meta.model_name]) +def get_model_name(m): + return "-".join([m._meta.app_label, m._meta.model_name]) class BaseNestedAdminTestCase(AdminSelenosisTestCase): @@ -36,13 +34,27 @@ class BaseNestedAdminTestCase(AdminSelenosisTestCase): @classmethod def setUpClass(cls): - super(BaseNestedAdminTestCase, cls).setUpClass() + super().setUpClass() + + # Increase speed of move_to_element action + PointerInput.DEFAULT_MOVE_DURATION = 1 + + if not hasattr(PointerInput.create_pointer_move, "_patched"): + orig_create_pointer_move = PointerInput.create_pointer_move + + def create_pointer_move(self, *args, **kwargs): + kwargs["duration"] = 1 + return orig_create_pointer_move(self, *args, **kwargs) + + create_pointer_move._patched = True + + PointerInput.create_pointer_move = create_pointer_move root_admin = admin_site._registry[cls.root_model] def descend_admin_inlines(admin): data = [admin.model, []] - for inline in (getattr(admin, 'inlines', None) or []): + for inline in getattr(admin, "inlines", None) or []: data[1].append(descend_admin_inlines(inline)) return data @@ -57,7 +69,7 @@ def recursive_map_model_names(data): cls.model_names = recursive_map_model_names(cls.models) def setUp(self): - super(BaseNestedAdminTestCase, self).setUp() + super().setUp() self.server_exc_info = None app = self.server_thread.httpd.application.application.application if app._exception_middleware is None: @@ -68,7 +80,7 @@ def tearDown(self): app = self.server_thread.httpd.application.application.application app._exception_middleware = [] self.dump_js_coverage() - super(BaseNestedAdminTestCase, self).tearDown() + super().tearDown() def handle_server_error(self, request, exception): self.server_exc_info = sys.exc_info() @@ -76,36 +88,44 @@ def handle_server_error(self, request, exception): def load_admin(self, obj=None): if obj is None: obj = self.root_model - super(BaseNestedAdminTestCase, self).load_admin(obj) + super().load_admin(obj) def initialize_page(self): if self.server_exc_info: - six.reraise(*self.server_exc_info) + exc_type, exc_value, exc_traceback = self.server_exc_info + raise exc_value - super(BaseNestedAdminTestCase, self).initialize_page() + super().initialize_page() - browser_errors = [e for e in self.selenium.get_log('browser') - if 'favicon' not in e['message']] + browser_errors = [ + e for e in self.selenium.get_log("browser") if "favicon" not in e["message"] + ] if len(browser_errors) > 0: - logger.error("Found browser errors: %s" % json.dumps(browser_errors, indent=4)) + logger.error( + "Found browser errors: %s" % json.dumps(browser_errors, indent=4) + ) # Store last mousemove event, so we can track the mouse position - self.selenium.execute_script(""" + self.selenium.execute_script( + """ if (window.DJNesting) { document.body.addEventListener('mousemove', function(event) { DJNesting.lastMouseMove = event; }); } - """) + """ + ) self.selenium.execute_script("window.$ = window.django.jQuery") def wait_until_element_is(self, element, selector, timeout=None, message=None): def element_matches_selector(d): return d.execute_script( - 'return !!$(arguments[0]).is(arguments[1])', - element, selector) + "return !!$(arguments[0]).is(arguments[1])", element, selector + ) - message = message or "Timeout waiting for element to match selector %s" % selector + message = ( + message or "Timeout waiting for element to match selector %s" % selector + ) self.wait_until(element_matches_selector, message=message) # @property @@ -128,46 +148,55 @@ def get_test_filename_base(self): else: admin_type = "std" - return "py%(pyver)s_dj%(djver)s_%(type)s.%(cls)s.%(fn)s.%(ts)s%(usec)s" % { - 'pyver': "%s%s" % sys.version_info[:2], - 'djver': "%s%s" % django.VERSION[:2], - 'type': admin_type, - 'cls': type(self).__name__, - 'fn': self._testMethodName, - 'ts': datetime.now().strftime('%Y%m%d%H%M%S'), - 'usec': ("%.6f" % time.time()).split('.')[1], - } + return "py{pyver}_dj{djver}_{type}.{cls}.{fn}.{ts}{usec}".format( + pyver="%s%s" % sys.version_info[:2], + djver="%s%s" % django.VERSION[:2], + type=admin_type, + cls=type(self).__name__, + fn=self._testMethodName, + ts=datetime.now().strftime("%Y%m%d%H%M%S"), + usec=("%.6f" % time.time()).split(".")[1], + ) def dump_js_coverage(self): try: - coverage_dumped = self.selenium.execute_script('return window._coverage_dumped') + coverage_dumped = self.selenium.execute_script( + "return window._coverage_dumped" + ) if coverage_dumped: return else: - json = self.selenium.execute_script('return JSON.stringify(__coverage__)') - self.selenium.execute_script('window._coverage_dumped = true') + json = self.selenium.execute_script( + "return JSON.stringify(__coverage__)" + ) + self.selenium.execute_script("window._coverage_dumped = true") except: return - nyc_output_dir = os.path.join(os.getcwd(), '.nyc_output') + nyc_output_dir = os.path.join(os.getcwd(), ".nyc_output") if not os.path.exists(nyc_output_dir): os.makedirs(nyc_output_dir) filename = "%s.json" % self.get_test_filename_base() - with open(os.path.join(nyc_output_dir, filename), mode='w') as f: + with open(os.path.join(nyc_output_dir, filename), mode="w") as f: f.write(json) def save_form(self): - browser_errors = [e for e in self.selenium.get_log('browser') - if 'favicon' not in e['message']] + browser_errors = [ + e for e in self.selenium.get_log("browser") if "favicon" not in e["message"] + ] if len(browser_errors) > 0: - logger.error("Found browser errors: %s" % json.dumps(browser_errors, indent=4)) + logger.error( + "Found browser errors: %s" % json.dumps(browser_errors, indent=4) + ) self.dump_js_coverage() has_continue = bool( self.selenium.execute_script( - 'return django.jQuery("[name=_continue]").length')) + 'return django.jQuery("[name=_continue]").length' + ) + ) name_attr = "_continue" if has_continue else "_save" - self.click(self.selenium.find_element_by_xpath('//*[@name="%s"]' % name_attr)) + self.click(self.selenium.find_element(By.XPATH, '//*[@name="%s"]' % name_attr)) if has_continue: self.wait_page_loaded() self.initialize_page() @@ -231,7 +260,12 @@ def _normalize_indexes(self, indexes, is_group=False, named_models=True): if is_group: if len(indexes) and inline_type_check(indexes[-1]): try: - if all([inline_type_check(a) and is_integer(b) for a, b in indexes[:-1]]): + if all( + [ + inline_type_check(a) and is_integer(b) + for a, b in indexes[:-1] + ] + ): return indexes except: pass @@ -260,25 +294,34 @@ def _normalize_indexes(self, indexes, is_group=False, named_models=True): if len(inline_model_names) > 1: raise ValueError( "Terminal index to inline class omitted in group-level " - "operation, but parent has more than one inline") + "operation, but parent has more than one inline" + ) if named_models: norm_indexes.append(inline_model_names[0][0]) else: norm_indexes.append(0) break if not is_sequence(level_indexes) and not is_integer(level_indexes): - raise ValueError("Unexpected type %s in list of indexes" % ( - type(level_indexes).__name__)) + raise ValueError( + "Unexpected type %s in list of indexes" + % (type(level_indexes).__name__) + ) if is_integer(level_indexes): if len(inline_model_names) > 1: - raise ValueError(( - "indexes[%d] using shorthand integer value, but more " - "than one inline to choose from") % (level)) + raise ValueError( + ( + "indexes[%d] using shorthand integer value, but more " + "than one inline to choose from" + ) + % (level) + ) level_indexes = [0, level_indexes] if is_sequence(level_indexes): if len(level_indexes) != 2: - raise ValueError("Expected indexes[%d] to have len 2, got %d" % ( - level, len(level_indexes))) + raise ValueError( + "Expected indexes[%d] to have len 2, got %d" + % (level, len(level_indexes)) + ) if not all([is_integer(i) for i in level_indexes]): raise ValueError("indexes[%d] must have only integers" % level) inline_index, inline_item = level_indexes @@ -304,22 +347,25 @@ def click(self, element): rect = ElementRect(element) if rect.top < 0: self.selenium.execute_script( - 'document.documentElement.scrollTop += arguments[0]', rect.top) + "document.documentElement.scrollTop += arguments[0]", rect.top + ) else: - self.selenium.execute_script('arguments[0].scrollIntoView()', element) + self.selenium.execute_script("arguments[0].scrollIntoView()", element) element.click() def drag_and_drop_item(self, from_indexes, to_indexes, screenshot_hack=False): - action = DragAndDropAction(self, from_indexes=from_indexes, to_indexes=to_indexes) + action = DragAndDropAction( + self, from_indexes=from_indexes, to_indexes=to_indexes + ) action.move_to_target(screenshot_hack=screenshot_hack) def get_num_inlines(self, indexes=None): indexes = self._normalize_indexes(indexes, is_group=True) model_name = indexes[-1] group = self.get_group(indexes=indexes) - group_id = group.get_attribute('id') - selector = "#%s .djn-dynamic-form-%s" % (group_id, model_name) + group_id = group.get_attribute("id") + selector = "#{} .djn-dynamic-form-{}".format(group_id, model_name) return self.selenium.execute_script("return $('%s').length" % selector) def get_group(self, indexes=None): @@ -327,24 +373,33 @@ def get_group(self, indexes=None): model_name = indexes.pop() expr_parts = [] for parent_model, parent_item_index in indexes: - expr_parts += ["/*[%s][%d]" % (xpath_item(parent_model), parent_item_index + 1)] + expr_parts += [ + "/*[%s][%d]" % (xpath_item(parent_model), parent_item_index + 1) + ] expr_parts += ["/*[@data-inline-model='%s']" % model_name] expr = "/%s" % ("/".join(expr_parts)) - return self.selenium.find_element_by_xpath(expr) + return self.selenium.find_element(By.XPATH, expr) def get_item(self, indexes): indexes = self._normalize_indexes(indexes) model_name, item_index = indexes.pop() indexes.append(model_name) group = self.get_group(indexes=indexes) - return group.find_element_by_xpath(".//*[%s][%d]" % (xpath_item(model_name), item_index + 1)) + return group.find_element( + By.XPATH, ".//*[%s][%d]" % (xpath_item(model_name), item_index + 1) + ) def add_inline(self, indexes=None, name=None, slug=None): indexes = self._normalize_indexes(indexes, is_group=True) new_index = self.get_num_inlines(indexes) model_name = indexes[-1] - add_selector = "#%s .djn-add-item a.djn-add-handler.djn-model-%s" % ( - self.get_group(indexes).get_attribute('id'), model_name) + add_selector = ( + "#{} .djn-add-item a.djn-add-handler.djn-model-{}.djn-level-{}".format( + self.get_group(indexes).get_attribute("id"), + model_name, + len(indexes), + ) + ) with self.clickable_selector(add_selector) as el: self.click(el) indexes[-1] = [model_name, new_index] @@ -357,47 +412,53 @@ def add_inline(self, indexes=None, name=None, slug=None): def remove_inline(self, indexes): indexes = self._normalize_indexes(indexes) model_name = indexes[-1][0] - remove_selector = "#%s .djn-remove-handler.djn-model-%s" % ( - self.get_item(indexes).get_attribute('id'), model_name) + remove_selector = "#{} .djn-remove-handler.djn-model-{}.djn-level-{}".format( + self.get_item(indexes).get_attribute("id"), model_name, len(indexes) + ) with self.clickable_selector(remove_selector) as el: self.click(el) def delete_inline(self, indexes): indexes = self._normalize_indexes(indexes) model_name = indexes[-1][0] - item_id = self.get_item(indexes).get_attribute('id') - delete_selector = "#%s .djn-delete-handler.djn-model-%s" % ( - item_id, model_name) + item_id = self.get_item(indexes).get_attribute("id") + delete_selector = "#{} .djn-delete-handler.djn-model-{}.djn-level-{}".format( + item_id, model_name, len(indexes) + ) with self.clickable_selector(delete_selector) as el: self.click(el) if self.has_grappelli: - undelete_selector = "#%s.grp-predelete .grp-delete-handler.djn-model-%s" % ( - item_id, model_name) + undelete_selector = "#{}.grp-predelete .grp-delete-handler.djn-model-{}.djn-level-{}".format( + item_id, model_name, len(indexes) + ) self.wait_until_clickable_selector(undelete_selector) def undelete_inline(self, indexes): indexes = self._normalize_indexes(indexes) model_name = indexes[-1][0] - item_id = self.get_item(indexes).get_attribute('id') - undelete_selector = "#%s .djn-delete-handler.djn-model-%s" % (item_id, model_name) + item_id = self.get_item(indexes).get_attribute("id") + undelete_selector = "#{} .djn-delete-handler.djn-model-{}.djn-level-{}".format( + item_id, model_name, len(indexes) + ) with self.clickable_selector(undelete_selector) as el: self.click(el) if self.has_grappelli: - delete_selector = "#%s:not(.grp-predelete) .grp-delete-handler.djn-model-%s" % ( - item_id, model_name) + delete_selector = "#{}:not(.grp-predelete) .grp-delete-handler.djn-model-{}.djn-level-{}".format( + item_id, model_name, len(indexes) + ) self.wait_until_clickable_selector(delete_selector) def get_form_field_selector(self, attname, indexes=None): indexes = self._normalize_indexes(indexes) if not indexes: return "#id_%s" % attname - field_prefix = self.get_item(indexes=indexes).get_attribute('id') - return "#id_%s-%s" % (field_prefix, attname) + field_prefix = self.get_item(indexes=indexes).get_attribute("id") + return "#id_{}-{}".format(field_prefix, attname) def get_field(self, attname, indexes=None): indexes = self._normalize_indexes(indexes) field_selector = self.get_form_field_selector(attname, indexes=indexes) - return self.selenium.find_element_by_css_selector(field_selector) + return self.selenium.find_element(By.CSS_SELECTOR, field_selector) def set_field(self, attname, value, indexes=None): indexes = self._normalize_indexes(indexes) @@ -408,7 +469,7 @@ def set_field(self, attname, value, indexes=None): def expected_failure_if_grappelli(func): - if 'grappelli' in settings.INSTALLED_APPS: + if "grappelli" in settings.INSTALLED_APPS: return unittest.expectedFailure(func) return func @@ -416,7 +477,8 @@ def expected_failure_if_grappelli(func): def skip_if_not_grappelli(func): @functools.wraps(func) def wrapper(*args, **kwargs): - if 'grappelli' not in settings.INSTALLED_APPS: + if "grappelli" not in settings.INSTALLED_APPS: raise unittest.SkipTest("Skipping (grappelli required)") return func(*args, **kwargs) + return wrapper diff --git a/nested_admin/tests/conftest.py b/nested_admin/tests/conftest.py index 58e19ee..f3a3f33 100644 --- a/nested_admin/tests/conftest.py +++ b/nested_admin/tests/conftest.py @@ -11,8 +11,7 @@ def suppress_warnings(): warnings.simplefilter("error", Warning) warnings.filterwarnings( - "ignore", - "name used for saved screenshot does not match file type", - UserWarning) + "ignore", "name used for saved screenshot does not match file type", UserWarning + ) warnings.filterwarnings("ignore", "'grappelli' defines default_app_config") - warnings.filterwarnings("ignore", 'The distutils package') + warnings.filterwarnings("ignore", "The distutils package") diff --git a/nested_admin/tests/drag_drop.py b/nested_admin/tests/drag_drop.py index 7195f6b..5cd1827 100644 --- a/nested_admin/tests/drag_drop.py +++ b/nested_admin/tests/drag_drop.py @@ -2,13 +2,13 @@ import time from selenium.webdriver.common.action_chains import ActionChains -from selenium.common.exceptions import WebDriverException +from selenium.webdriver.common.by import By -from .utils import ( - xpath_cls, xpath_item, is_integer, Position, Size, ElementRect) +from .utils import xpath_cls, xpath_item, is_integer, Position, Size, ElementRect -if not hasattr(__builtins__, 'cmp'): +if not hasattr(__builtins__, "cmp"): + def cmp(a, b): return (a > b) - (a < b) @@ -17,8 +17,7 @@ def sign(x): return x and (1, -1)[x < 0] -class DragAndDropAction(object): - +class DragAndDropAction: def __init__(self, test_case, from_indexes, to_indexes): self.test_case = test_case self.selenium = test_case.selenium @@ -28,12 +27,16 @@ def __init__(self, test_case, from_indexes, to_indexes): else: self.target_is_empty = False - self.from_indexes = self.test_case._normalize_indexes(from_indexes, named_models=False) + self.from_indexes = self.test_case._normalize_indexes( + from_indexes, named_models=False + ) self.to_indexes = self.test_case._normalize_indexes( - to_indexes, is_group=self.target_is_empty, named_models=False) + to_indexes, is_group=self.target_is_empty, named_models=False + ) num_inlines_indexes = self.test_case._normalize_indexes( - to_indexes, is_group=self.target_is_empty, named_models=True) + to_indexes, is_group=self.target_is_empty, named_models=True + ) if not is_integer(num_inlines_indexes[-1]): num_inlines_indexes[-1] = num_inlines_indexes[-1][0] self.target_num_items = self.test_case.get_num_inlines(num_inlines_indexes) @@ -51,17 +54,22 @@ def __init__(self, test_case, from_indexes, to_indexes): if self.from_indexes[-1][1] < self.to_indexes[-1][1]: self.to_indexes[-1][1] += 1 - self.test_case.assertEqual(len(to_indexes), len(from_indexes), - "Depth of source and target must be the same") + self.test_case.assertEqual( + len(to_indexes), + len(from_indexes), + "Depth of source and target must be the same", + ) @property def viewport_size(self): - if not hasattr(self, '_viewport_size'): - dimensions = self.selenium.execute_script(""" + if not hasattr(self, "_viewport_size"): + dimensions = self.selenium.execute_script( + """ return { width: (window.innerWidth || document.documentElement.clientWidth), height: (window.innerHeight || document.documentElement.clientHeight) - }""") + }""" + ) self._viewport_size = Size(**dimensions) return self._viewport_size @@ -69,75 +77,93 @@ def viewport_size(self): # return Rect() def get_mouse_position(self): - pos_dict = self.selenium.execute_script(""" + pos_dict = self.selenium.execute_script( + """ return (function(m) { return m && {x: m.clientX, y: m.clientY}; - })(DJNesting.lastMouseMove)""") + })(DJNesting.lastMouseMove)""" + ) return Position(**pos_dict) @property def source(self): - if not hasattr(self, '_source'): + if not hasattr(self, "_source"): source_item = self.test_case.get_item(indexes=self.from_indexes) - if source_item.tag_name == 'div': + if source_item.tag_name == "div": drag_handler_xpath = "h3" elif self.test_case.has_grappelli: - drag_handler_xpath = "/".join([ - "*[%s]" % xpath_cls("djn-tr"), - "*[%s]" % xpath_cls("djn-td"), - "*[%s]" % xpath_cls("tools"), - "/*[%s]" % xpath_cls("djn-drag-handler"), - ]) + drag_handler_xpath = "/".join( + [ + "*[%s]" % xpath_cls("djn-tr"), + "*[%s]" % xpath_cls("djn-td"), + "*[%s]" % xpath_cls("tools"), + "/*[%s]" % xpath_cls("djn-drag-handler"), + ] + ) else: - drag_handler_xpath = "/".join([ - "*[%s]" % xpath_cls("djn-tr"), - "*[%s]" % xpath_cls("is-sortable"), - "*[%s]" % xpath_cls("djn-drag-handler"), - ]) - self._source = source_item.find_element_by_xpath(drag_handler_xpath) + drag_handler_xpath = "/".join( + [ + "*[%s]" % xpath_cls("djn-tr"), + "*[%s]" % xpath_cls("is-sortable"), + "*[%s]" % xpath_cls("djn-drag-handler"), + ] + ) + self._source = source_item.find_element(By.XPATH, drag_handler_xpath) return self._source @property def target(self): - if not hasattr(self, '_target'): + if not hasattr(self, "_target"): if len(self.to_indexes) > 1: target_inline_parent = self.test_case.get_item(self.to_indexes[:-1]) else: target_inline_parent = self.selenium target_xpath = ".//*[%s][%d]//*[%s]" % ( - xpath_cls('djn-group'), self.to_indexes[-1][0] + 1, xpath_cls("djn-items")) + xpath_cls("djn-group"), + self.to_indexes[-1][0] + 1, + xpath_cls("djn-items"), + ) if self.target_num_items != self.to_indexes[-1][1]: target_xpath += "/*[%(item_pred)s][%(item_pos)d]" % { - 'item_pred': xpath_item(), - 'item_pos': self.to_indexes[-1][1] + 1, + "item_pred": xpath_item(), + "item_pos": self.to_indexes[-1][1] + 1, } - self._target = target_inline_parent.find_element_by_xpath(target_xpath) + self._target = target_inline_parent.find_element(By.XPATH, target_xpath) return self._target def initialize_drag(self): source = self.source - self.selenium.execute_script(""" + self.selenium.execute_script( + """ var el = arguments[0], top = el.getBoundingClientRect().top; if (top <= 15) { document.documentElement.scrollTop += (top - 16); } else { el.scrollIntoView(); + top = el.getBoundingClientRect().top; + if (top <= 15) { + document.documentElement.scrollTop += (top - 16); + } } - """, source) + """, + source, + ) source.click() - (ActionChains(self.selenium) - .move_to_element_with_offset(source, 5, 5) + ( + ActionChains(self.selenium) + .move_to_element_with_offset(source, 3, 3) .click_and_hold() - .perform()) + .perform() + ) time.sleep(0.05) - ActionChains(self.selenium).move_by_offset(0, -15).perform() + ActionChains(self.selenium).move_by_offset(0, -10).perform() time.sleep(0.05) - ActionChains(self.selenium).move_by_offset(0, 15).perform() + ActionChains(self.selenium).move_by_offset(0, 10).perform() - with self.test_case.visible_selector('.ui-sortable-helper') as el: + with self.test_case.visible_selector(".ui-sortable-helper") as el: return el def release(self): @@ -149,21 +175,26 @@ def _match_helper_with_target(self, helper_element, target_element): desired_pos = tuple(self.to_indexes) # True if aiming for the bottom of the target - target_bottom = bool(0 < self.to_indexes[-1][1] == (self.target_num_items - 1) + target_bottom = bool( + 0 < self.to_indexes[-1][1] == (self.target_num_items - 1) and self.to_indexes[-1][0] == (self.target_num_inlines - 1) - and cmp(desired_pos[:-1], self.current_position[:-1]) > -1) + and cmp(desired_pos[:-1], self.current_position[:-1]) > -1 + ) helper = ElementRect(helper_element) - target = ElementRect(target_element, aliases={ - 'y': ('bottom' if target_bottom else 'top')}) + target = ElementRect( + target_element, aliases={"y": ("bottom" if target_bottom else "top")} + ) mouse_pos = self.get_mouse_position() viewport_height = self.viewport_size.height dy = target.y - helper.y inline_height = max(target.height, helper.height) - increment = max(15, min(viewport_height // 3, (2 * inline_height) // 3, abs(dy) // 2)) + increment = max( + 15, min(viewport_height // 3, (2 * inline_height) // 3, abs(dy) // 2) + ) - max_iter = 50 + max_iter = 120 i = 0 prev_pos_diff = None direction = None @@ -187,28 +218,29 @@ def _match_helper_with_target(self, helper_element, target_element): direction = pos_diff target.refresh() helper.refresh() - target_y = getattr(target, 'bottom' if direction == 1 else 'top') + target_y = getattr(target, "bottom" if direction == 1 else "top") dy = target_y - helper.y if sign(dy) != sign(pos_diff) * direction_flip and abs(dy) > inline_height: flip_count += 1 if flip_count > 3: increment = 10 elif flip_count > 5: - increment = 5 + increment = 2 else: - increment = max(abs(dy // 2), flip_count * flip_multiplier) + increment = min(abs(dy // 2), flip_count * flip_multiplier) direction_flip *= -1 direction = pos_diff * direction_flip inc = increment * direction mouse_pos = self.get_mouse_position() - mouse_edge_dy = mouse_pos.y if direction < 0 else viewport_height - mouse_pos.y + mouse_edge_dy = ( + mouse_pos.y if direction < 0 else viewport_height - mouse_pos.y + ) if mouse_edge_dy <= abs(inc): self.selenium.execute_script( - 'document.documentElement.scrollTop += arguments[0]', - inc + direction) - (ActionChains(self.selenium) - .move_by_offset(0, -direction) - .perform()) + "document.documentElement.scrollTop += arguments[0]", + inc + direction, + ) + (ActionChains(self.selenium).move_by_offset(0, -direction).perform()) else: ActionChains(self.selenium).move_by_offset(0, inc).perform() i += 1 @@ -225,7 +257,7 @@ def _num_preceding_siblings(self, ctx, condition): is extraordinarily slow. So we just grab all siblings and iterate through the elements in python. """ - siblings = ctx.find_element_by_xpath('parent::*').find_elements_by_xpath('*') + siblings = ctx.find_element(By.XPATH, "parent::*").find_elements(By.XPATH, "*") count = 0 for el in siblings: if el.id == ctx.id: @@ -236,32 +268,36 @@ def _num_preceding_siblings(self, ctx, condition): def _num_preceding_djn_items(self, ctx): def is_djn_item(el): - classes = set(re.split(r'\s+', el.get_attribute('class'))) - return (classes & {'djn-item'} and - not(classes & {'djn-no-drag', 'djn-thead', 'djn-item-dragging'})) + classes = set(re.split(r"\s+", el.get_attribute("class"))) + return classes & {"djn-item"} and not ( + classes & {"djn-no-drag", "djn-thead", "djn-item-dragging"} + ) return self._num_preceding_siblings(ctx, condition=is_djn_item) def _num_preceding_djn_groups(self, ctx): def is_djn_group(el): - return "djn-group" in re.split(r'\s+', el.get_attribute('class')) + return "djn-group" in re.split(r"\s+", el.get_attribute("class")) return self._num_preceding_siblings(ctx, condition=is_djn_group) @property def current_position(self): - placeholder = self.selenium.find_element_by_css_selector( - '.ui-sortable-placeholder') + placeholder = self.selenium.find_element( + By.CSS_SELECTOR, ".ui-sortable-placeholder" + ) pos = [] ctx = None - ancestor_xpath = 'ancestor::*[%s][1]' % xpath_cls("djn-item") + ancestor_xpath = "ancestor::*[%s][1]" % xpath_cls("djn-item") for i in range(0, len(self.to_indexes)): if ctx is None: ctx = placeholder else: - ctx = ctx.find_element_by_xpath(ancestor_xpath) + ctx = ctx.find_element(By.XPATH, ancestor_xpath) item_index = self._num_preceding_djn_items(ctx) - ctx = ctx.find_element_by_xpath('ancestor::*[%s][1]' % xpath_cls("djn-group")) + ctx = ctx.find_element( + By.XPATH, "ancestor::*[%s][1]" % xpath_cls("djn-group") + ) inline_index = self._num_preceding_djn_groups(ctx) pos.insert(0, (inline_index, item_index)) return tuple(pos) @@ -269,9 +305,9 @@ def current_position(self): def move_to_target(self, screenshot_hack=False): target = self.target helper = self.initialize_drag() - if screenshot_hack and 'phantomjs' in self.test_case.browser: + if screenshot_hack and "phantomjs" in self.test_case.browser: # I don't know why, but saving a screenshot fixes a weird bug # in phantomjs - self.selenium.save_screenshot('/dev/null') + self.selenium.save_screenshot("/dev/null") helper = self._match_helper_with_target(helper, target) self.release() diff --git a/nested_admin/tests/gfk/admin.py b/nested_admin/tests/gfk/admin.py index db8005f..bcee043 100644 --- a/nested_admin/tests/gfk/admin.py +++ b/nested_admin/tests/gfk/admin.py @@ -7,7 +7,12 @@ class GFKBInline(NestedGenericStackedInline): model = GFKB extra = 0 sortable_field_name = "position" - inline_classes = ("collapse", "open", "grp-collapse", "grp-open", ) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) class GFKAInline(NestedGenericStackedInline): @@ -15,7 +20,12 @@ class GFKAInline(NestedGenericStackedInline): extra = 0 sortable_field_name = "position" inlines = [GFKBInline] - inline_classes = ("collapse", "open", "grp-collapse", "grp-open", ) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) @admin.register(GFKRoot) diff --git a/nested_admin/tests/gfk/models.py b/nested_admin/tests/gfk/models.py index 33ffc81..1f2730d 100644 --- a/nested_admin/tests/gfk/models.py +++ b/nested_admin/tests/gfk/models.py @@ -1,13 +1,9 @@ -from __future__ import unicode_literals - from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class GFKB(models.Model): name = models.CharField(max_length=255) position = models.PositiveIntegerField() @@ -16,7 +12,7 @@ class GFKB(models.Model): content_object = GenericForeignKey() class Meta: - ordering = ['object_id', 'position'] + ordering = ["object_id", "position"] def __str__(self): parts = ["%s[%d]" % (self.name, self.position)] @@ -25,7 +21,6 @@ def __str__(self): return "/".join(parts) -@python_2_unicode_compatible class GFKA(models.Model): slug = models.CharField(max_length=255) position = models.PositiveIntegerField() @@ -35,7 +30,7 @@ class GFKA(models.Model): b_set = GenericRelation(GFKB) class Meta: - ordering = ['object_id', 'position'] + ordering = ["object_id", "position"] def __str__(self): parts = ["%s[%d]" % (self.slug, self.position)] @@ -44,7 +39,6 @@ def __str__(self): return "/".join(parts) -@python_2_unicode_compatible class GFKRoot(models.Model): slug = models.CharField(max_length=255) a_set = GenericRelation(GFKA) diff --git a/nested_admin/tests/gfk/tests.py b/nested_admin/tests/gfk/tests.py index caa0576..81ef8d3 100644 --- a/nested_admin/tests/gfk/tests.py +++ b/nested_admin/tests/gfk/tests.py @@ -9,7 +9,7 @@ class TestGenericInlineAdmin(BaseNestedAdminTestCase): root_model = GFKRoot def test_add_to_empty_one_deep(self): - root = self.root_model.objects.create(slug='test') + root = self.root_model.objects.create(slug="test") self.load_admin(root) @@ -19,12 +19,12 @@ def test_add_to_empty_one_deep(self): a_set = root.a_set.all() self.assertEqual(len(a_set), 1) - self.assertEqual(a_set[0].slug, 'test') + self.assertEqual(a_set[0].slug, "test") self.assertEqual(a_set[0].position, 0) def test_add_to_empty_two_deep(self): - root = self.root_model.objects.create(slug='test') - a = GFKA.objects.create(slug='test', content_object=root, position=0) + root = self.root_model.objects.create(slug="test") + a = GFKA.objects.create(slug="test", content_object=root, position=0) self.load_admin(root) self.add_inline([0], name="Test") @@ -37,116 +37,137 @@ def test_add_to_empty_two_deep(self): self.assertEqual(b_set[0].position, 0) def test_drag_existing_objs(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) - self.drag_and_drop_item(from_indexes=[1, 2], to_indexes=[0, 1], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 2], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - y_2 = GFKB.objects.get(name='Y 2') + y_2 = GFKB.objects.get(name="Y 2") - self.assertEqual(y_2.content_object, x, "item was not moved to the correct parent") + self.assertEqual( + y_2.content_object, x, "item was not moved to the correct parent" + ) self.assertEqual(y_2.position, 1, "item was not moved to the correct position") - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/Y 2[1]', - 'root/x[0]/X 1[2]', - 'root/x[0]/X 2[3]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], + [ + "root/x[0]/X 0[0]", + "root/x[0]/Y 2[1]", + "root/x[0]/X 1[2]", + "root/x[0]/X 2[3]", + ], + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 1[1]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 1[1]"] + ) def test_drag_add_drag(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) - self.add_inline(indexes=[0], name='X 3') - self.drag_and_drop_item(from_indexes=[1, 1], to_indexes=[0, 1], - screenshot_hack=True) + self.add_inline(indexes=[0], name="X 3") + self.drag_and_drop_item( + from_indexes=[1, 1], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - y_1 = GFKB.objects.get(name='Y 1') - self.assertEqual(y_1.content_object, x, "Y1 was not moved to the correct parent") + y_1 = GFKB.objects.get(name="Y 1") + self.assertEqual( + y_1.content_object, x, "Y1 was not moved to the correct parent" + ) self.assertEqual(y_1.position, 1, "Y1 was not moved to the correct position") - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/Y 1[1]', - 'root/x[0]/X 1[2]', - 'root/x[0]/X 2[3]', - 'root/x[0]/X 3[4]']) - - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 2[1]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], + [ + "root/x[0]/X 0[0]", + "root/x[0]/Y 1[1]", + "root/x[0]/X 1[2]", + "root/x[0]/X 2[3]", + "root/x[0]/X 3[4]", + ], + ) + + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 2[1]"] + ) def test_drag_new_item(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) self.load_admin(root) - self.add_inline(indexes=[1], name='Y 2') + self.add_inline(indexes=[1], name="Y 2") time.sleep(0.01) - self.drag_and_drop_item(from_indexes=[1, 2], to_indexes=[0, 1], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 2], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - y_2 = GFKB.objects.get(name='Y 2') + y_2 = GFKB.objects.get(name="Y 2") - self.assertEqual(y_2.content_object, x, "Y2 was not moved to the correct parent") + self.assertEqual( + y_2.content_object, x, "Y2 was not moved to the correct parent" + ) self.assertEqual(y_2.position, 1, "Y2 was not moved to the correct position") - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/Y 2[1]', - 'root/x[0]/X 1[2]', - 'root/x[0]/X 2[3]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], + [ + "root/x[0]/X 0[0]", + "root/x[0]/Y 2[1]", + "root/x[0]/X 1[2]", + "root/x[0]/X 2[3]", + ], + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 1[1]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 1[1]"] + ) def test_delete_two_deep(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) @@ -154,25 +175,25 @@ def test_delete_two_deep(self): self.save_form() - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/X 1[1]', - 'root/x[0]/X 2[2]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], + ["root/x[0]/X 0[0]", "root/x[0]/X 1[1]", "root/x[0]/X 2[2]"], + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 2[1]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 2[1]"] + ) def test_delete_one_deep(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) @@ -180,30 +201,31 @@ def test_delete_one_deep(self): self.save_form() - self.assertEqual(len(GFKA.objects.filter(slug='x')), 0, - "GFKA instance was not deleted") + self.assertEqual( + len(GFKA.objects.filter(slug="x")), 0, "GFKA instance was not deleted" + ) - y = GFKA.objects.get(slug='y') + y = GFKA.objects.get(slug="y") - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[0]/Y 0[0]', - 'root/y[0]/Y 1[1]', - 'root/y[0]/Y 2[2]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], + ["root/y[0]/Y 0[0]", "root/y[0]/Y 1[1]", "root/y[0]/Y 2[2]"], + ) def test_delete_two_deep_undelete_one_deep(self): """ Test that, if an item is deleted, then the parent is deleted, and then the parent is undeleted, that the item stays deleted. """ - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) @@ -213,51 +235,52 @@ def test_delete_two_deep_undelete_one_deep(self): self.save_form() - self.assertEqual(len(GFKA.objects.filter(slug='x')), 1, - "GFKA instance should not be deleted") + self.assertEqual( + len(GFKA.objects.filter(slug="x")), 1, "GFKA instance should not be deleted" + ) - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/X 2[1]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], ["root/x[0]/X 0[0]", "root/x[0]/X 2[1]"] + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 1[1]', - 'root/y[1]/Y 2[2]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], + ["root/y[1]/Y 0[0]", "root/y[1]/Y 1[1]", "root/y[1]/Y 2[2]"], + ) def test_remove_two_deep(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) self.load_admin(root) - self.add_inline(indexes=[1], name='Y 2') + self.add_inline(indexes=[1], name="Y 2") self.remove_inline(indexes=[1, 2]) self.save_form() - self.assertEqual(["%s" % i for i in x.b_set.all()], [ - 'root/x[0]/X 0[0]', - 'root/x[0]/X 1[1]', - 'root/x[0]/X 2[2]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], + ["root/x[0]/X 0[0]", "root/x[0]/X 1[1]", "root/x[0]/X 2[2]"], + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 1[1]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 1[1]"] + ) def test_drag_item_to_empty_parent(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - y = GFKA.objects.create(slug='y', content_object=root, position=1) - GFKB.objects.create(name='Y 0', content_object=y, position=0) - GFKB.objects.create(name='Y 1', content_object=y, position=1) - GFKB.objects.create(name='Y 2', content_object=y, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + y = GFKA.objects.create(slug="y", content_object=root, position=1) + GFKB.objects.create(name="Y 0", content_object=y, position=0) + GFKB.objects.create(name="Y 1", content_object=y, position=1) + GFKB.objects.create(name="Y 2", content_object=y, position=2) self.load_admin(root) @@ -265,23 +288,24 @@ def test_drag_item_to_empty_parent(self): self.save_form() - y_2 = GFKB.objects.get(name='Y 2') - self.assertEqual(y_2.content_object, x, "Y2 was not moved to the correct parent") + y_2 = GFKB.objects.get(name="Y 2") + self.assertEqual( + y_2.content_object, x, "Y2 was not moved to the correct parent" + ) self.assertEqual(y_2.position, 0, "Y2 was not moved to the correct position") - self.assertEqual(["%s" % i for i in x.b_set.all()], - ['root/x[0]/Y 2[0]']) + self.assertEqual(["%s" % i for i in x.b_set.all()], ["root/x[0]/Y 2[0]"]) - self.assertEqual(["%s" % i for i in y.b_set.all()], [ - 'root/y[1]/Y 0[0]', - 'root/y[1]/Y 1[1]']) + self.assertEqual( + ["%s" % i for i in y.b_set.all()], ["root/y[1]/Y 0[0]", "root/y[1]/Y 1[1]"] + ) def test_drag_item_to_new_empty_parent(self): - root = self.root_model.objects.create(slug='root') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - GFKB.objects.create(name='X 0', content_object=x, position=0) - GFKB.objects.create(name='X 1', content_object=x, position=1) - GFKB.objects.create(name='X 2', content_object=x, position=2) + root = self.root_model.objects.create(slug="root") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + GFKB.objects.create(name="X 0", content_object=x, position=0) + GFKB.objects.create(name="X 1", content_object=x, position=1) + GFKB.objects.create(name="X 2", content_object=x, position=2) self.load_admin(root) @@ -290,21 +314,23 @@ def test_drag_item_to_new_empty_parent(self): self.save_form() - x_2 = GFKB.objects.get(name='X 2') - y = GFKA.objects.get(slug='y') - self.assertEqual(x_2.content_object, y, "X2 was not moved to the correct parent") + x_2 = GFKB.objects.get(name="X 2") + y = GFKA.objects.get(slug="y") + self.assertEqual( + x_2.content_object, y, "X2 was not moved to the correct parent" + ) self.assertEqual(x_2.position, 0, "X2 was not moved to the correct position") - self.assertEqual(["%s" % i for i in x.b_set.all()], - ['root/x[0]/X 0[0]', 'root/x[0]/X 1[1]']) + self.assertEqual( + ["%s" % i for i in x.b_set.all()], ["root/x[0]/X 0[0]", "root/x[0]/X 1[1]"] + ) - self.assertEqual(["%s" % i for i in y.b_set.all()], - ['root/y[1]/X 2[0]']) + self.assertEqual(["%s" % i for i in y.b_set.all()], ["root/y[1]/X 2[0]"]) def test_drag_existing_gfkb_to_new_parent_and_back(self): - root = self.root_model.objects.create(slug='test') - x = GFKA.objects.create(slug='x', content_object=root, position=0) - GFKB.objects.create(name='X 0', content_object=x, position=0) + root = self.root_model.objects.create(slug="test") + x = GFKA.objects.create(slug="x", content_object=root, position=0) + GFKB.objects.create(name="X 0", content_object=x, position=0) self.load_admin(root) @@ -316,7 +342,7 @@ def test_drag_existing_gfkb_to_new_parent_and_back(self): self.assertEqual(len(GFKA.objects.all()), 2, "Save failed") - x_0 = GFKB.objects.get(name='X 0') + x_0 = GFKB.objects.get(name="X 0") self.assertEqual(x_0.content_object, x, "X0 is in the wrong parent") self.assertEqual(x_0.position, 0, "X0 has the wrong position") diff --git a/nested_admin/tests/grp_collapsible_tabular_inline/admin.py b/nested_admin/tests/grp_collapsible_tabular_inline/admin.py index b63829e..f0a1db3 100644 --- a/nested_admin/tests/grp_collapsible_tabular_inline/admin.py +++ b/nested_admin/tests/grp_collapsible_tabular_inline/admin.py @@ -6,7 +6,7 @@ class DocumentInline(nested_admin.NestedTabularInline): model = Document extra = 0 - classes = ('grp-collapse grp-closed',) + classes = ("grp-collapse grp-closed",) class ProjectInline(nested_admin.NestedStackedInline): @@ -22,8 +22,8 @@ class UserAdmin(nested_admin.NestedModelAdmin): class DocumentNonNestedInline(admin.TabularInline): model = Document extra = 0 - classes = ('grp-collapse grp-closed',) - sortable_field_name = '' + classes = ("grp-collapse grp-closed",) + sortable_field_name = "" @admin.register(Project) diff --git a/nested_admin/tests/grp_collapsible_tabular_inline/models.py b/nested_admin/tests/grp_collapsible_tabular_inline/models.py index 80a5698..4b3c327 100644 --- a/nested_admin/tests/grp_collapsible_tabular_inline/models.py +++ b/nested_admin/tests/grp_collapsible_tabular_inline/models.py @@ -1,11 +1,7 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class User(models.Model): name = models.CharField(max_length=10) @@ -13,7 +9,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class Project(models.Model): name = models.CharField(max_length=10) user = ForeignKey(User, on_delete=CASCADE) @@ -22,7 +17,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class Document(models.Model): name = models.CharField(max_length=10) project = ForeignKey(Project, on_delete=CASCADE) diff --git a/nested_admin/tests/grp_collapsible_tabular_inline/tests.py b/nested_admin/tests/grp_collapsible_tabular_inline/tests.py index 4e3a25e..e5998d8 100644 --- a/nested_admin/tests/grp_collapsible_tabular_inline/tests.py +++ b/nested_admin/tests/grp_collapsible_tabular_inline/tests.py @@ -16,33 +16,36 @@ def expand_collapsible(self, indexes, is_group=False): inline = self.get_group(indexes) else: inline = self.get_item(indexes) - inline_id = inline.get_attribute('id') - with self.visible_selector('#%s' % inline_id) as el: + inline_id = inline.get_attribute("id") + with self.visible_selector("#%s" % inline_id) as el: is_closed = self.selenium.execute_script( - 'return $(arguments[0]).is(".grp-closed")', el) - self.assertTrue(is_closed, "Cannot expand inline #%s, not currently closed" - % inline_id) + 'return $(arguments[0]).is(".grp-closed")', el + ) + self.assertTrue( + is_closed, "Cannot expand inline #%s, not currently closed" % inline_id + ) - with self.visible_selector('#%s > .djn-collapse-handler' % inline_id) as el: + with self.visible_selector("#%s > .djn-collapse-handler" % inline_id) as el: el.click() - self.wait_until_element_is(inline, '.grp-open', - message='Collapsible #%s did not open' % inline_id) + self.wait_until_element_is( + inline, ".grp-open", message="Collapsible #%s did not open" % inline_id + ) return inline def test_grappelli_tabular_collapse_bug(self): """Grappelli NestedTabularInline.classes grp-collapse should work""" - if 'grappelli' not in settings.INSTALLED_APPS: + if "grappelli" not in settings.INSTALLED_APPS: raise SkipTest("Only testing for grappelli") self.load_admin(self.root_model) - self.set_field('name', 'A') + self.set_field("name", "A") self.expand_collapsible([2]) - self.set_field('name', 'B', [2]) + self.set_field("name", "B", [2]) self.expand_collapsible([2], is_group=True) indexes = self.add_inline([2]) - self.set_field('name', 'C', indexes) + self.set_field("name", "C", indexes) self.save_form() users = self.root_model.objects.all() @@ -50,13 +53,13 @@ def test_grappelli_tabular_collapse_bug(self): self.assertEqual(1, len(users), "Form did not save") user = users[0] - self.assertEqual(user.name, 'A') + self.assertEqual(user.name, "A") projects = user.project_set.all() self.assertEqual(1, len(projects), "Project inline was not saved") project = projects[0] - self.assertEqual(project.name, 'B') + self.assertEqual(project.name, "B") documents = project.document_set.all() self.assertEqual(1, len(documents), "Document inline was not saved") - self.assertEqual(documents[0].name, 'C') + self.assertEqual(documents[0].name, "C") diff --git a/nested_admin/tests/identical_prefixes/admin.py b/nested_admin/tests/identical_prefixes/admin.py index 8993927..649f9e4 100644 --- a/nested_admin/tests/identical_prefixes/admin.py +++ b/nested_admin/tests/identical_prefixes/admin.py @@ -8,23 +8,26 @@ class BXModelForm(forms.ModelForm): class Meta: model = BX - exclude = ['b_type'] + exclude = ["b_type"] class BYModelForm(forms.ModelForm): class Meta: model = BY - exclude = ['b_type'] + exclude = ["b_type"] class BInline(nested_admin.NestedStackedInline): model = B extra = 0 sortable_field_name = "position" - inline_classes = ("collapse", "open", ) + inline_classes = ( + "collapse", + "open", + ) def get_queryset(self, request): - qset = super(BInline, self).get_queryset(request) + qset = super().get_queryset(request) return qset.filter(b_type=self.model.default_b_type) @@ -42,13 +45,13 @@ class BYInline(BInline): class AXModelForm(forms.ModelForm): class Meta: model = AX - exclude = ['a_type'] + exclude = ["a_type"] class AYModelForm(forms.ModelForm): class Meta: model = AY - exclude = ['a_type'] + exclude = ["a_type"] class AInline(nested_admin.NestedStackedInline): @@ -56,10 +59,13 @@ class AInline(nested_admin.NestedStackedInline): extra = 0 inlines = [BXInline, BYInline] sortable_field_name = "position" - inline_classes = ("collapse", "open", ) + inline_classes = ( + "collapse", + "open", + ) def get_queryset(self, request): - qset = super(AInline, self).get_queryset(request) + qset = super().get_queryset(request) return qset.filter(a_type=self.model.default_a_type) diff --git a/nested_admin/tests/identical_prefixes/models.py b/nested_admin/tests/identical_prefixes/models.py index 7de2d56..b911672 100644 --- a/nested_admin/tests/identical_prefixes/models.py +++ b/nested_admin/tests/identical_prefixes/models.py @@ -1,26 +1,23 @@ from django.db import models -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class Root(models.Model): slug = models.SlugField(max_length=10, blank=True, null=True) def __str__(self): - return "%s(%s)" % (type(self).__name__, self.slug) + return "{}({})".format(type(self).__name__, self.slug) -@python_2_unicode_compatible class A(models.Model): root = models.ForeignKey(Root, related_name="a_set", on_delete=models.CASCADE) position = models.PositiveIntegerField() foo = models.CharField(max_length=10, blank=True, null=True) - a_type = models.CharField(max_length=1, choices=(('X', 'X'), ('Y', 'Y'))) + a_type = models.CharField(max_length=1, choices=(("X", "X"), ("Y", "Y"))) default_a_type = None class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): parts = ["A%s[%d](%s)" % (self.a_type, self.position, self.foo)] @@ -30,20 +27,20 @@ def __str__(self): def save(self, **kwargs): self.a_type = self.default_a_type - super(A, self).save(**kwargs) + super().save(**kwargs) class AManager(models.Manager): def __init__(self, a_type): self.a_type = a_type - super(AManager, self).__init__() + super().__init__() def get_queryset(self): - return super(AManager, self).get_queryset().filter(a_type=self.a_type) + return super().get_queryset().filter(a_type=self.a_type) class AX(A): - default_a_type = 'X' + default_a_type = "X" objects = AManager(default_a_type) class Meta: @@ -51,24 +48,23 @@ class Meta: class AY(A): - default_a_type = 'Y' + default_a_type = "Y" objects = AManager(default_a_type) class Meta: proxy = True -@python_2_unicode_compatible class B(models.Model): a = models.ForeignKey(A, related_name="b_set", on_delete=models.CASCADE) position = models.PositiveIntegerField() bar = models.CharField(max_length=10, blank=True, null=True) - b_type = models.CharField(max_length=1, choices=(('X', 'X'), ('Y', 'Y'))) + b_type = models.CharField(max_length=1, choices=(("X", "X"), ("Y", "Y"))) default_b_type = None class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): parts = ["B%s[%d](%s)" % (self.b_type, self.position, self.bar)] @@ -78,20 +74,20 @@ def __str__(self): def save(self, **kwargs): self.b_type = self.default_b_type - super(B, self).save(**kwargs) + super().save(**kwargs) class BManager(models.Manager): def __init__(self, b_type): self.b_type = b_type - super(BManager, self).__init__() + super().__init__() def get_queryset(self): - return super(BManager, self).get_queryset().filter(b_type=self.b_type) + return super().get_queryset().filter(b_type=self.b_type) class BX(B): - default_b_type = 'X' + default_b_type = "X" objects = BManager(default_b_type) class Meta: @@ -99,7 +95,7 @@ class Meta: class BY(B): - default_b_type = 'Y' + default_b_type = "Y" objects = BManager(default_b_type) class Meta: diff --git a/nested_admin/tests/identical_prefixes/tests.py b/nested_admin/tests/identical_prefixes/tests.py index c62231c..59e7b3f 100644 --- a/nested_admin/tests/identical_prefixes/tests.py +++ b/nested_admin/tests/identical_prefixes/tests.py @@ -1,5 +1,3 @@ -import six - from nested_admin.tests.base import BaseNestedAdminTestCase from .models import Root, AX, AY, BX, BY @@ -9,9 +7,9 @@ class TestIdenticalPrefixes(BaseNestedAdminTestCase): root_model = Root def test_add_to_empty_one_deep(self): - root = self.root_model.objects.create(slug='test') - AX.objects.create(foo='1', root=root, position=0) - AY.objects.create(foo='2', root=root, position=0) + root = self.root_model.objects.create(slug="test") + AX.objects.create(foo="1", root=root, position=0) + AY.objects.create(foo="2", root=root, position=0) self.load_admin(root) self.delete_inline([(1, 0)]) @@ -20,32 +18,38 @@ def test_add_to_empty_one_deep(self): self.assertEqual(len(ay_objs), 0, "AY inline was not deleted") def test_drag_and_drop(self): - root = self.root_model.objects.create(slug='group') - ax0 = AX.objects.create(foo='x0', root=root, position=0) - ax1 = AX.objects.create(foo='x1', root=root, position=1) - ay = AY.objects.create(foo='y0', root=root, position=0) - - BX.objects.create(bar='ax0bx0', a=ax0, position=0) - BX.objects.create(bar='ax0bx1', a=ax0, position=1) - BY.objects.create(bar='ax0by0', a=ax0, position=0) - BY.objects.create(bar='ax0by1', a=ax0, position=1) - BX.objects.create(bar='ax1bx0', a=ax1, position=0) - BX.objects.create(bar='ax1bx1', a=ax1, position=1) - BY.objects.create(bar='ax1by0', a=ax1, position=0) - BY.objects.create(bar='ax1by1', a=ax1, position=1) - BX.objects.create(bar='ay0bx0', a=ay, position=0) - BX.objects.create(bar='ay0bx1', a=ay, position=1) - BY.objects.create(bar='ay0by0', a=ay, position=0) - BY.objects.create(bar='ay0by1', a=ay, position=1) + root = self.root_model.objects.create(slug="group") + ax0 = AX.objects.create(foo="x0", root=root, position=0) + ax1 = AX.objects.create(foo="x1", root=root, position=1) + ay = AY.objects.create(foo="y0", root=root, position=0) + + BX.objects.create(bar="ax0bx0", a=ax0, position=0) + BX.objects.create(bar="ax0bx1", a=ax0, position=1) + BY.objects.create(bar="ax0by0", a=ax0, position=0) + BY.objects.create(bar="ax0by1", a=ax0, position=1) + BX.objects.create(bar="ax1bx0", a=ax1, position=0) + BX.objects.create(bar="ax1bx1", a=ax1, position=1) + BY.objects.create(bar="ax1by0", a=ax1, position=0) + BY.objects.create(bar="ax1by1", a=ax1, position=1) + BX.objects.create(bar="ay0bx0", a=ay, position=0) + BX.objects.create(bar="ay0bx1", a=ay, position=1) + BY.objects.create(bar="ay0by0", a=ay, position=0) + BY.objects.create(bar="ay0by1", a=ay, position=1) self.load_admin(root) # Move 'ay0by0' to be the first inline in AX[0]/BY[0] - self.drag_and_drop_item(from_indexes=[(1, 0), (1, 0)], to_indexes=[(0, 0), (1, 0)], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[(1, 0), (1, 0)], + to_indexes=[(0, 0), (1, 0)], + screenshot_hack=True, + ) self.save_form() - moved_item = BY.objects.get(bar='ay0by0') - self.assertEqual(six.text_type(moved_item), 'Root(group)/AX[0](x0)/BY[0](ay0by0)', - "Item was not moved to the correct position") + moved_item = BY.objects.get(bar="ay0by0") + self.assertEqual( + str(moved_item), + "Root(group)/AX[0](x0)/BY[0](ay0by0)", + "Item was not moved to the correct position", + ) diff --git a/nested_admin/tests/issue_122/models.py b/nested_admin/tests/issue_122/models.py index 5154bd8..e7e3a4b 100644 --- a/nested_admin/tests/issue_122/models.py +++ b/nested_admin/tests/issue_122/models.py @@ -1,11 +1,7 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class Parent(models.Model): name = models.CharField(max_length=10) @@ -13,7 +9,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class Child1(models.Model): name = models.CharField(max_length=10) parent = ForeignKey(Parent, on_delete=CASCADE) @@ -22,7 +17,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class Child2(models.Model): name = models.CharField(max_length=10) child1 = ForeignKey(Child1, on_delete=CASCADE) diff --git a/nested_admin/tests/issue_122/tests.py b/nested_admin/tests/issue_122/tests.py index e51e45e..6623638 100644 --- a/nested_admin/tests/issue_122/tests.py +++ b/nested_admin/tests/issue_122/tests.py @@ -13,49 +13,60 @@ class TestIssue122(BaseNestedAdminTestCase): def test_grappelli_collapse_bug(self): """Deeply-nested grappelli collapsible inlines with min_num > 0 should expand""" - if 'grappelli' not in settings.INSTALLED_APPS: + if "grappelli" not in settings.INSTALLED_APPS: raise SkipTest("Only testing for grappelli") self.load_admin(self.root_model) self.add_inline() - with self.visible_selector('#child1_set-1 > .djn-collapse-handler') as el: + with self.visible_selector("#child1_set-1 > .djn-collapse-handler") as el: el.click() input_is_visible = self.selenium.execute_script( - 'return django.jQuery("#id_child1_set-1-name").is(":visible")') + 'return django.jQuery("#id_child1_set-1-name").is(":visible")' + ) self.assertTrue(input_is_visible) - with self.visible_selector('#child1_set-1-child2_set-0 > .djn-collapse-handler') as el: + with self.visible_selector( + "#child1_set-1-child2_set-0 > .djn-collapse-handler" + ) as el: el.click() input_is_visible = self.selenium.execute_script( - 'return django.jQuery("#id_child1_set-1-child2_set-0-name").is(":visible")') + 'return django.jQuery("#id_child1_set-1-child2_set-0-name").is(":visible")' + ) self.assertTrue(input_is_visible) def test_grappelli_duplicate_event_handler_registration(self): """Click handlers for grappelli collapse should only be registered once""" - if 'grappelli' not in settings.INSTALLED_APPS: + if "grappelli" not in settings.INSTALLED_APPS: raise SkipTest("Only testing for grappelli") # First repeat the steps in test_grappelli_collapse_bug self.test_grappelli_collapse_bug() self.add_inline() - with self.visible_selector('#child1_set-2') as el: + with self.visible_selector("#child1_set-2") as el: is_closed = self.selenium.execute_script( - 'return $(arguments[0]).is(".grp-closed")', el) - self.assertTrue(is_closed, "New inlines should initiate with class grp-closed") + 'return $(arguments[0]).is(".grp-closed")', el + ) + self.assertTrue( + is_closed, "New inlines should initiate with class grp-closed" + ) - with self.visible_selector('#child1_set-2 > .djn-collapse-handler') as el: + with self.visible_selector("#child1_set-2 > .djn-collapse-handler") as el: el.click() input_is_visible = self.selenium.execute_script( - 'return django.jQuery("#id_child1_set-2-name").is(":visible")') + 'return django.jQuery("#id_child1_set-2-name").is(":visible")' + ) self.assertTrue(input_is_visible) - with self.visible_selector('#child1_set-2-child2_set-0') as el: + with self.visible_selector("#child1_set-2-child2_set-0") as el: is_closed = self.selenium.execute_script( - 'return $(arguments[0]).is(".grp-closed")', el) - self.assertTrue(is_closed, "New inlines should initiate with class grp-closed") + 'return $(arguments[0]).is(".grp-closed")', el + ) + self.assertTrue( + is_closed, "New inlines should initiate with class grp-closed" + ) diff --git a/nested_admin/tests/mixed_permissions_min_num_bug/admin.py b/nested_admin/tests/mixed_permissions_min_num_bug/admin.py index f52c9da..593c9d4 100644 --- a/nested_admin/tests/mixed_permissions_min_num_bug/admin.py +++ b/nested_admin/tests/mixed_permissions_min_num_bug/admin.py @@ -8,28 +8,28 @@ class CuratedItemInline(NestedTabularInline): model = CuratedItem - sortable_field_name = 'position' + sortable_field_name = "position" extra = 0 - inline_classes = ['grp-open'] + inline_classes = ["grp-open"] class CuratedListInline(NestedStackedInline): model = CuratedList - sortable_field_name = 'position' + sortable_field_name = "position" inlines = [CuratedItemInline] min_num = 1 extra = 0 - inline_classes = ['grp-open'] + inline_classes = ["grp-open"] class CuratedGroupInline(NestedStackedInline): inlines = [CuratedListInline] model = CuratedGroup - sortable_field_name = 'position' + sortable_field_name = "position" extra = 0 - inline_classes = ['grp-open'] + inline_classes = ["grp-open"] @admin.register(CuratedGroupCollection) diff --git a/nested_admin/tests/mixed_permissions_min_num_bug/models.py b/nested_admin/tests/mixed_permissions_min_num_bug/models.py index ac81cda..79c6b9b 100644 --- a/nested_admin/tests/mixed_permissions_min_num_bug/models.py +++ b/nested_admin/tests/mixed_permissions_min_num_bug/models.py @@ -1,8 +1,6 @@ from django.db import models -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class CuratedGroupCollection(models.Model): slug = models.SlugField() name = models.CharField(max_length=64) @@ -11,7 +9,6 @@ def __str__(self): return self.name -@python_2_unicode_compatible class CuratedGroup(models.Model): slug = models.SlugField() name = models.CharField(max_length=64) @@ -19,7 +16,7 @@ class CuratedGroup(models.Model): position = models.PositiveSmallIntegerField() class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): return self.name @@ -31,10 +28,9 @@ class CuratedList(models.Model): group = models.ForeignKey(CuratedGroup, on_delete=models.CASCADE) class Meta: - ordering = ['position'] + ordering = ["position"] -@python_2_unicode_compatible class CuratedItem(models.Model): parent = models.ForeignKey(CuratedList, on_delete=models.CASCADE) @@ -42,7 +38,7 @@ class CuratedItem(models.Model): name = models.CharField(max_length=64, blank=True) class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): if self.name: diff --git a/nested_admin/tests/mixed_permissions_min_num_bug/tests.py b/nested_admin/tests/mixed_permissions_min_num_bug/tests.py index 9cdb08e..1138e91 100644 --- a/nested_admin/tests/mixed_permissions_min_num_bug/tests.py +++ b/nested_admin/tests/mixed_permissions_min_num_bug/tests.py @@ -1,14 +1,9 @@ -from unittest import SkipTest - -import django from django.contrib.auth import get_permission_codename from django.contrib.auth.models import Permission, User from django.contrib.contenttypes.models import ContentType from nested_admin.tests.base import BaseNestedAdminTestCase -from .models import ( - CuratedGroupCollection, - CuratedGroup, CuratedList, CuratedItem) +from .models import CuratedGroupCollection, CuratedGroup, CuratedList, CuratedItem def get_perm(Model, perm): @@ -32,53 +27,58 @@ def setUpClass(cls): def setUp(self): super(TestMixedPermissionsMinNumBug, self).setUp() self.collection = CuratedGroupCollection.objects.create( - slug='site-nav', name='Site Nav') + slug="site-nav", name="Site Nav" + ) lists = [] - for i, group_name in enumerate(('Sections', 'Magazine', 'More')): + for i, group_name in enumerate(("Sections", "Magazine", "More")): group = CuratedGroup.objects.create( name=group_name, slug=group_name.lower(), collection=self.collection, - position=i) - lists.append( - CuratedList.objects.create(group=group, position=0)) + position=i, + ) + lists.append(CuratedList.objects.create(group=group, position=0)) section_labels = [ - ('Politics', 'Culture', 'Podcasts'), - ('Current Issue', 'All Issues', 'Subscribe'), - ('Newsletters', 'Events'), + ("Politics", "Culture", "Podcasts"), + ("Current Issue", "All Issues", "Subscribe"), + ("Newsletters", "Events"), ] for list_obj, sections in zip(lists, section_labels): for i, section in enumerate(sections): - CuratedItem.objects.create( - parent=list_obj, position=i, name=section) + CuratedItem.objects.create(parent=list_obj, position=i, name=section) self.user = User.objects.create_user( - username='permissionuser', password='secret', - email='vuser@example.com', is_staff=True) + username="permissionuser", + password="secret", + email="vuser@example.com", + is_staff=True, + ) models = (self.root_model,) + tuple(self.nested_models) for model_cls in models: self.user.user_permissions.add( - get_perm(model_cls, get_permission_codename('change', model_cls._meta))) + get_perm(model_cls, get_permission_codename("change", model_cls._meta)) + ) for model_cls in (CuratedList, CuratedItem): self.user.user_permissions.add( - get_perm(model_cls, get_permission_codename('add', model_cls._meta))) + get_perm(model_cls, get_permission_codename("add", model_cls._meta)) + ) self.user.user_permissions.add( - get_perm(model_cls, get_permission_codename('delete', model_cls._meta))) + get_perm(model_cls, get_permission_codename("delete", model_cls._meta)) + ) - self.admin_login('permissionuser', 'secret') + self.admin_login("permissionuser", "secret") def test_mixed_no_top_level_add_permissions_save(self): self.load_admin(self.collection) - self.set_field('name', 'Politics!', [0, 0, 0]) + self.set_field("name", "Politics!", [0, 0, 0]) self.save_form() item = CuratedItem.objects.get( - parent__group__position=0, - parent__position=0, - position=0) + parent__group__position=0, parent__position=0, position=0 + ) self.assertEqual(item.name, "Politics!", "Item name did not update") diff --git a/nested_admin/tests/nested_delete_validationerrors/models.py b/nested_admin/tests/nested_delete_validationerrors/models.py index f97eb77..cdbd6bd 100644 --- a/nested_admin/tests/nested_delete_validationerrors/models.py +++ b/nested_admin/tests/nested_delete_validationerrors/models.py @@ -1,11 +1,7 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class Parent(models.Model): name = models.CharField(max_length=128) @@ -13,27 +9,25 @@ def __str__(self): return self.name -@python_2_unicode_compatible class Child(models.Model): name = models.CharField(max_length=128) - parent = ForeignKey(Parent, on_delete=CASCADE, related_name='children') + parent = ForeignKey(Parent, on_delete=CASCADE, related_name="children") position = models.PositiveIntegerField() class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): return self.name -@python_2_unicode_compatible class GrandChild(models.Model): name = models.CharField(max_length=128) - parent = ForeignKey(Child, on_delete=CASCADE, related_name='children') + parent = ForeignKey(Child, on_delete=CASCADE, related_name="children") position = models.PositiveIntegerField() class Meta: - ordering = ['position'] + ordering = ["position"] def __str__(self): return self.name diff --git a/nested_admin/tests/nested_delete_validationerrors/tests.py b/nested_admin/tests/nested_delete_validationerrors/tests.py index a1f2273..4e7571d 100644 --- a/nested_admin/tests/nested_delete_validationerrors/tests.py +++ b/nested_admin/tests/nested_delete_validationerrors/tests.py @@ -1,8 +1,3 @@ -import time -from unittest import SkipTest - -from django.conf import settings - from nested_admin.tests.base import BaseNestedAdminTestCase from .models import Parent, Child, GrandChild @@ -14,24 +9,28 @@ class TestDeleteNestedInlineMinNumRequirement(BaseNestedAdminTestCase): def test_min_num_delete_bug(self): """It should be possible to delete inlines, even if min_num requirement not met""" - rhea = Parent.objects.create(name='Rhea') - poseidon = Child.objects.create(name='Poseidon', parent=rhea, position=0) - zeus = Child.objects.create(name='Zeus', parent=rhea, position=1) - demeter = Child.objects.create(name='Demeter', parent=rhea, position=2) + rhea = Parent.objects.create(name="Rhea") + Child.objects.create(name="Poseidon", parent=rhea, position=0) + zeus = Child.objects.create(name="Zeus", parent=rhea, position=1) + demeter = Child.objects.create(name="Demeter", parent=rhea, position=2) - GrandChild.objects.create(name='Apollo', parent=zeus, position=0) - GrandChild.objects.create(name='Persephone', parent=demeter, position=0) + GrandChild.objects.create(name="Apollo", parent=zeus, position=0) + GrandChild.objects.create(name="Persephone", parent=demeter, position=0) self.load_admin(rhea) self.delete_inline([0]) self.save_form() validation_errors = self.selenium.execute_script( - "return $('ul.errorlist li').length") + "return $('ul.errorlist li').length" + ) self.assertEqual( - 0, validation_errors, "Save should have completed without validation errors") + 0, validation_errors, "Save should have completed without validation errors" + ) children = Child.objects.filter(parent=rhea) - self.assertNotEqual(3, len(children), "Child with empty grandchild was not deleted") + self.assertNotEqual( + 3, len(children), "Child with empty grandchild was not deleted" + ) self.assertEqual(2, len(children)) diff --git a/nested_admin/tests/nested_polymorphic/base.py b/nested_admin/tests/nested_polymorphic/base.py index 4cf6595..2331007 100644 --- a/nested_admin/tests/nested_polymorphic/base.py +++ b/nested_admin/tests/nested_polymorphic/base.py @@ -1,20 +1,22 @@ -import six -from unittest import SkipTest - -import django -from django.conf import settings from django.apps import apps from polymorphic.utils import get_base_polymorphic_model +from selenium.webdriver.common.by import By from nested_admin.tests.base import BaseNestedAdminTestCase -from nested_admin.tests.utils import xpath_item, xpath_cls, is_sequence, is_integer, is_str +from nested_admin.tests.utils import ( + xpath_item, + xpath_cls, + is_sequence, + is_integer, + is_str, +) from polymorphic.models import PolymorphicModel class BaseNestedPolymorphicTestCase(BaseNestedAdminTestCase): - def get_inline_model_names(self): - return self.selenium.execute_script(""" + return self.selenium.execute_script( + """ return (function getGroup($group) { $group = (typeof $group === 'undefined') ? $('.djn-group-root') : $($group); var $djnItems = $group.find([ @@ -31,7 +33,8 @@ def get_inline_model_names(self): g => getGroup(g)), })) } - })()""") + })()""" + ) def _normalize_indexes(self, indexes, is_group=False, named_models=True): norm_indexes = [] @@ -60,25 +63,34 @@ def _normalize_indexes(self, indexes, is_group=False, named_models=True): if len(inline_model_names) > 1: raise ValueError( "Terminal index to inline class omitted in group-level " - "operation, but parent has more than one inline") + "operation, but parent has more than one inline" + ) if named_models: - norm_indexes.append(inline_model_names[0]['model']) + norm_indexes.append(inline_model_names[0]["model"]) else: norm_indexes.append(0) break if not is_sequence(level_indexes) and not is_integer(level_indexes): - raise ValueError("Unexpected type %s in list of indexes" % ( - type(level_indexes).__name__)) + raise ValueError( + "Unexpected type %s in list of indexes" + % (type(level_indexes).__name__) + ) if is_integer(level_indexes): if len(inline_model_names) > 1: - raise ValueError(( - "indexes[%d] using shorthand integer value, but more " - "than one inline to choose from") % (level)) + raise ValueError( + ( + "indexes[%d] using shorthand integer value, but more " + "than one inline to choose from" + ) + % (level) + ) level_indexes = [0, level_indexes] if is_sequence(level_indexes): if len(level_indexes) != 2: - raise ValueError("Expected indexes[%d] to have len 2, got %d" % ( - level, len(level_indexes))) + raise ValueError( + "Expected indexes[%d] to have len 2, got %d" + % (level, len(level_indexes)) + ) inline_index, inline_item = level_indexes if is_str(inline_index): @@ -86,16 +98,16 @@ def _normalize_indexes(self, indexes, is_group=False, named_models=True): inline_index = None for i, group in enumerate(inline_model_names): - if group['model'] == lookup: + if group["model"] == lookup: inline_index = i break - if any(i for i in group['items'] if i['model'] == lookup): + if any(i for i in group["items"] if i["model"] == lookup): inline_index = i break - inline_data = inline_model_names[inline_index]['items'][inline_item] - inline_model_name = inline_data['model'] - inline_model_names = inline_data['groups'] + inline_data = inline_model_names[inline_index]["items"][inline_item] + inline_model_name = inline_data["model"] + inline_model_names = inline_data["groups"] if named_models: norm_indexes.append([inline_model_name, inline_item]) else: @@ -106,15 +118,15 @@ def _normalize_indexes(self, indexes, is_group=False, named_models=True): lookup = group_index group_index = None for i, group in enumerate(inline_model_names): - if group['model'] == lookup: + if group["model"] == lookup: group_index = i break - if any(i for i in group['items'] if i['model'] == lookup): + if any(i for i in group["items"] if i["model"] == lookup): group_index = i break if named_models: - norm_indexes.append(inline_model_names[group_index]['model']) + norm_indexes.append(inline_model_names[group_index]["model"]) else: norm_indexes.append(group_index) @@ -124,77 +136,96 @@ def get_item(self, indexes): indexes = self._normalize_indexes(indexes) group_indexes = indexes[:-1] model_id, item_index = indexes[-1] - app_label, model_name = model_id.split('-') + app_label, model_name = model_id.split("-") model_cls = apps.get_model(app_label, model_name) if issubclass(model_cls, PolymorphicModel): base_model_cls = get_base_polymorphic_model(model_cls) else: base_model_cls = model_cls - base_model_id = "%s-%s" % ( - base_model_cls._meta.app_label, base_model_cls._meta.model_name) + base_model_id = "{}-{}".format( + base_model_cls._meta.app_label, base_model_cls._meta.model_name + ) try: group = self.get_group(indexes=group_indexes + [base_model_id]) except TypeError: group = self.get_group(indexes=group_indexes + [model_id]) - group_id = group.get_attribute('id') - djn_items = self.selenium.find_element_by_css_selector( + group_id = group.get_attribute("id") + djn_items = self.selenium.find_element( + By.CSS_SELECTOR, "#%(id)s > .djn-fieldset > .djn-items, " "#%(id)s > .tabular.inline-related > .djn-fieldset > .djn-items, " - "#%(id)s > .djn-items" % {'id': group_id}) + "#%(id)s > .djn-items" % {"id": group_id}, + ) model_name, item_index = indexes[-1] - return djn_items.find_element_by_xpath( - "./*[%s][%d]" % (xpath_item(), item_index + 1)) + return djn_items.find_element( + By.XPATH, "./*[%s][%d]" % (xpath_item(), item_index + 1) + ) def delete_inline(self, indexes): indexes = self._normalize_indexes(indexes) model_id = indexes[-1][0] - app_label, model_name = model_id.split('-') + app_label, model_name = model_id.split("-") model_cls = apps.get_model(app_label, model_name) if issubclass(model_cls, PolymorphicModel): base_model_cls = get_base_polymorphic_model(model_cls) else: base_model_cls = model_cls - base_model_id = "%s-%s" % ( - base_model_cls._meta.app_label, base_model_cls._meta.model_name) - item_id = self.get_item(indexes).get_attribute('id') - delete_selector = "#%s .djn-delete-handler.djn-model-%s" % ( - item_id, base_model_id) + base_model_id = "{}-{}".format( + base_model_cls._meta.app_label, base_model_cls._meta.model_name + ) + item_id = self.get_item(indexes).get_attribute("id") + delete_selector = "#{} .djn-delete-handler.djn-model-{}".format( + item_id, base_model_id + ) with self.clickable_selector(delete_selector) as el: self.click(el) if self.has_grappelli: - undelete_selector = "#%s.grp-predelete .grp-delete-handler.djn-model-%s" % ( - item_id, base_model_id) + undelete_selector = ( + "#{}.grp-predelete .grp-delete-handler.djn-model-{}".format( + item_id, base_model_id + ) + ) self.wait_until_clickable_selector(undelete_selector) def add_inline(self, indexes=None, model=None, **kwargs): - model_name = "%s-%s" % (model._meta.app_label, model._meta.model_name) + model_name = "{}-{}".format(model._meta.app_label, model._meta.model_name) if issubclass(model, PolymorphicModel): base_model = get_base_polymorphic_model(model) else: base_model = model - base_model_identifier = "%s-%s" % ( - base_model._meta.app_label, base_model._meta.model_name) + base_model_identifier = "{}-{}".format( + base_model._meta.app_label, base_model._meta.model_name + ) if indexes: + level = len(self._normalize_indexes(indexes, is_group=True)) item = self.get_item(indexes) ctx_id = item.get_attribute("id") group_el = self.selenium.execute_script( - 'return $(arguments[0]).closest(".djn-group")[0]', item) + 'return $(arguments[0]).closest(".djn-group")[0]', item + ) else: group_el = self.get_group([base_model_identifier]) - ctx_id = group_el.get_attribute('id') - - error_desc = "%s in inline %s" % (model, indexes) - - add_selector = "#%s .djn-add-item a.djn-add-handler.djn-model-%s" % ( - ctx_id, base_model_identifier) - add_els = self.selenium.find_elements_by_css_selector(add_selector) - self.assertNotEqual(len(add_els), 0, - "No inline add handlers found for %s" % (error_desc)) + ctx_id = group_el.get_attribute("id") + level = 1 + + error_desc = "{} in inline {}".format(model, indexes) + + add_selector = ( + "#{} .djn-add-item a.djn-add-handler.djn-model-{}.djn-level-{}".format( + ctx_id, base_model_identifier, level + ) + ) + add_els = self.selenium.find_elements(By.CSS_SELECTOR, add_selector) + self.assertNotEqual( + len(add_els), 0, "No inline add handlers found for %s" % (error_desc) + ) self.click(add_els[0]) - add_link_selector = "return $('.polymorphic-type-menu:visible [data-type=\"%s\"]')[0]" % ( - model_name) + add_link_selector = ( + "return $('.polymorphic-type-menu:visible [data-type=\"%s\"]')[0]" + % (model_name) + ) poly_add_link = self.selenium.execute_script(add_link_selector) if poly_add_link: @@ -203,51 +234,63 @@ def add_inline(self, indexes=None, model=None, **kwargs): indexes = self._normalize_indexes(indexes) group_el = self.selenium.execute_script( - 'return $(arguments[0]).closest(".djn-group")[0]', add_els[0]) - group_id = group_el.get_attribute('id') + 'return $(arguments[0]).closest(".djn-group")[0]', add_els[0] + ) + group_id = group_el.get_attribute("id") - items_el = self.selenium.find_element_by_css_selector( - '#%(id)s > .djn-fieldset > .djn-items, ' + items_el = self.selenium.find_element( + By.CSS_SELECTOR, + "#%(id)s > .djn-fieldset > .djn-items, " "#%(id)s > .tabular.inline-related > .djn-fieldset > .djn-items, " - '#%(id)s > .djn-items' % {'id': group_id}) + "#%(id)s > .djn-items" % {"id": group_id}, + ) - num_inlines = len(items_el.find_elements_by_xpath( - './*[%s and not(%s)]' % (xpath_item(), xpath_cls('djn-empty-form')))) + num_inlines = len( + items_el.find_elements( + By.XPATH, + "./*[{} and not({})]".format(xpath_item(), xpath_cls("djn-empty-form")), + ) + ) new_index = num_inlines - 1 indexes.append([model_name, new_index]) - for field_name, val in six.iteritems(kwargs): + for field_name, val in kwargs.items(): self.set_field(field_name, val, indexes=indexes) return indexes def remove_inline(self, indexes): item = self.get_item(indexes) remove_handler = self.selenium.execute_script( - "return $(arguments[0]).nearest('.djn-remove-handler')[0]", - item) + "return $(arguments[0]).nearest('.djn-remove-handler')[0]", item + ) self.click(remove_handler) def get_num_inlines(self, indexes=None): group = self.get_group(indexes=indexes) - group_id = group.get_attribute('id') - djn_items = self.selenium.find_element_by_css_selector( + group_id = group.get_attribute("id") + djn_items = self.selenium.find_element( + By.CSS_SELECTOR, "#%(id)s > .djn-fieldset > .djn-items, " "#%(id)s > .tabular.inline-related > .djn-fieldset > .djn-items, " - "#%(id)s > .djn-items" % {'id': group_id}) + "#%(id)s > .djn-items" % {"id": group_id}, + ) selector = "> .djn-item:not(.djn-no-drag,.djn-item-dragging,.djn-thead,.djn-empty-form)" return self.selenium.execute_script( - "return $(arguments[0]).find(arguments[1]).length", - djn_items, selector) + "return $(arguments[0]).find(arguments[1]).length", djn_items, selector + ) def get_group(self, indexes=None): indexes = self._normalize_indexes(indexes, is_group=True) model_name = indexes.pop() expr_parts = [] for parent_model, parent_item_index in indexes: - expr_parts += ["/*[%s][count(preceding-sibling::*[%s]) = %d]" % ( - xpath_item(parent_model), xpath_item(), parent_item_index)] - expr_parts += ["/*[@data-inline-model='%s' and %s]" - % (model_name, xpath_cls('djn-group'))] + expr_parts += [ + "/*[%s][count(preceding-sibling::*[%s]) = %d]" + % (xpath_item(parent_model), xpath_item(), parent_item_index) + ] + expr_parts += [ + "/*[@data-inline-model='%s' and %s]" % (model_name, xpath_cls("djn-group")) + ] expr = "/%s" % ("/".join(expr_parts)) - return self.selenium.find_element_by_xpath(expr) + return self.selenium.find_element(By.XPATH, expr) diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/admin.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/admin.py index 64078d9..b650b32 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/admin.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/admin.py @@ -5,7 +5,15 @@ import nested_admin from .models import ( - FreeText, Poll, Question, MultipleChoiceGroup, MultipleChoice, Survey, Text, Textarea) + FreeText, + Poll, + Question, + MultipleChoiceGroup, + MultipleChoice, + Survey, + Text, + Textarea, +) class TextInline(nested_admin.NestedTabularInline): @@ -15,7 +23,7 @@ class TextInline(nested_admin.NestedTabularInline): max_num = 1 sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -26,7 +34,7 @@ class TextareaInline(nested_admin.NestedTabularInline): max_num = 1 sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -36,9 +44,9 @@ class RadioInline(nested_admin.NestedTabularInline): extra = 0 min_num = 1 max_num = 8 - radio_fields = {'style': admin.HORIZONTAL} + radio_fields = {"style": admin.HORIZONTAL} formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -50,7 +58,7 @@ class RadioGroupInline(nested_admin.NestedTabularInline): max_num = 1 sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -61,7 +69,7 @@ class DropDownInline(nested_admin.NestedTabularInline): min_num = 1 max_num = 8 formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -73,7 +81,7 @@ class DropDownGroupInline(nested_admin.NestedTabularInline): max_num = 1 sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } @@ -83,23 +91,29 @@ class FreeTextInline(nested_admin.NestedStackedPolymorphicInline.Child): inlines = (TextInline, TextareaInline, DropDownGroupInline) sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } class PollInline(nested_admin.NestedStackedPolymorphicInline.Child): model = Poll - inlines = (TextInline, RadioGroupInline,) + inlines = ( + TextInline, + RadioGroupInline, + ) sortable_field_name = "position" formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } model = Question extra = 0 sortable_field_name = "position" - child_inlines = (FreeTextInline, PollInline,) + child_inlines = ( + FreeTextInline, + PollInline, + ) formfield_overrides = { - models.PositiveSmallIntegerField: {'widget': forms.HiddenInput}, + models.PositiveSmallIntegerField: {"widget": forms.HiddenInput}, } diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/models.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/models.py index 3aefaff..7cc7001 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/models.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/models.py @@ -59,13 +59,16 @@ class MultipleChoiceGroup(QuestionComponent): class MultipleChoice(models.Model): group = ForeignKey(MultipleChoiceGroup, on_delete=NON_POLYMORPHIC_CASCADE) label = models.CharField(max_length=255) - style = models.CharField(max_length=255, choices=( - ('radio', 'radio'), - ('dropdown', 'dropdown'), - ('checkboxes', 'checkboxes'), - )) + style = models.CharField( + max_length=255, + choices=( + ("radio", "radio"), + ("dropdown", "dropdown"), + ("checkboxes", "checkboxes"), + ), + ) value = models.CharField(max_length=255) position = models.PositiveSmallIntegerField(null=True) class Meta: - ordering = ['position'] + ordering = ["position"] diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/tests.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/tests.py index 883d545..70190bd 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/tests.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_add_filtering/tests.py @@ -5,7 +5,14 @@ from nested_admin.nested import get_model_id from .models import ( - FreeText, Poll, Question, MultipleChoiceGroup, Survey, Text, Textarea) + FreeText, + Poll, + Question, + MultipleChoiceGroup, + Survey, + Text, + Textarea, +) try: from nested_admin.tests.nested_polymorphic.base import BaseNestedPolymorphicTestCase @@ -23,38 +30,39 @@ class PolymorphicAddFilteringTestCase(BaseNestedPolymorphicTestCase): @classmethod def setUpClass(cls): if not has_polymorphic: - raise SkipTest('django-polymorphic unavailable') - super(PolymorphicAddFilteringTestCase, cls).setUpClass() + raise SkipTest("django-polymorphic unavailable") + super().setUpClass() def add_inline(self, indexes=None, model=None, **kwargs): - indexes = super(PolymorphicAddFilteringTestCase, self).add_inline( - indexes, model, **kwargs) + indexes = super().add_inline(indexes, model, **kwargs) if self.has_grappelli: item = self.get_item(indexes) - item_id = item.get_attribute('id') + item_id = item.get_attribute("id") with self.clickable_selector("#%s > .djn-collapse-handler" % item_id) as el: el.click() - self.wait_until_element_is(item, '.grp-open', - message='Collapsible #%s did not open' % item_id) + self.wait_until_element_is( + item, ".grp-open", message="Collapsible #%s did not open" % item_id + ) return indexes def get_element_by_id(self, id): return self.selenium.execute_script( - "return document.getElementById(arguments[0])", id) + "return document.getElementById(arguments[0])", id + ) def test_polymorphic_add_inline_filtering(self): - survey = Survey.objects.create(title='my survey') + survey = Survey.objects.create(title="my survey") self.load_admin(survey) self.add_inline(model=FreeText) - self.set_field('value', 'a', indexes=[[0, 0], [0, 0]]) - self.set_field('value', 'b', indexes=[[0, 0], [1, 0]]) - self.set_field('title', 'c', indexes=[[0, 0], [2, 0]]) - self.set_field('label', 'd', indexes=[[0, 0], [2, 0], [0, 0]]) - select_field = self.get_field('style', indexes=[[0, 0], [2, 0], [0, 0]]) - Select(select_field).select_by_visible_text('radio') - self.set_field('value', 'e', indexes=[[0, 0], [2, 0], [0, 0]]) + self.set_field("value", "a", indexes=[[0, 0], [0, 0]]) + self.set_field("value", "b", indexes=[[0, 0], [1, 0]]) + self.set_field("title", "c", indexes=[[0, 0], [2, 0]]) + self.set_field("label", "d", indexes=[[0, 0], [2, 0], [0, 0]]) + select_field = self.get_field("style", indexes=[[0, 0], [2, 0], [0, 0]]) + Select(select_field).select_by_visible_text("radio") + self.set_field("value", "e", indexes=[[0, 0], [2, 0], [0, 0]]) self.save_form() questions = Question.objects.all() @@ -66,25 +74,28 @@ def test_polymorphic_add_inline_filtering(self): self.assertEqual(len(free_text_components), 3) free_text_text = free_text.questioncomponent_set.instance_of(Text).get() free_text_textarea = free_text.questioncomponent_set.instance_of(Textarea).get() - free_text_multichoice_group = ( - free_text.questioncomponent_set.instance_of(MultipleChoiceGroup).get()) - self.assertEqual(free_text_text.value, 'a') - self.assertEqual(free_text_textarea.value, 'b') - self.assertEqual(free_text_multichoice_group.title, 'c') + free_text_multichoice_group = free_text.questioncomponent_set.instance_of( + MultipleChoiceGroup + ).get() + self.assertEqual(free_text_text.value, "a") + self.assertEqual(free_text_textarea.value, "b") + self.assertEqual(free_text_multichoice_group.title, "c") free_text_multi_choices = free_text_multichoice_group.multiplechoice_set.all() self.assertEqual(len(free_text_multi_choices), 1) - self.assertEqual(free_text_multi_choices[0].label, 'd') - self.assertEqual(free_text_multi_choices[0].style, 'radio') - self.assertEqual(free_text_multi_choices[0].value, 'e') + self.assertEqual(free_text_multi_choices[0].label, "d") + self.assertEqual(free_text_multi_choices[0].style, "radio") + self.assertEqual(free_text_multi_choices[0].value, "e") self.add_inline(model=Poll) - self.set_field('value', 'f', indexes=[[0, 1], [0, 0]]) - self.set_field('title', 'g', indexes=[[0, 1], [1, 0]]) - form_prefix = self.get_item(indexes=[[0, 1], [1, 0], [0, 0]]).get_attribute('id') - self.get_element_by_id('id_%s-label' % form_prefix).send_keys('h') - self.get_element_by_id('id_%s-style_0' % form_prefix).click() - self.get_element_by_id('id_%s-value' % form_prefix).send_keys('i') + self.set_field("value", "f", indexes=[[0, 1], [0, 0]]) + self.set_field("title", "g", indexes=[[0, 1], [1, 0]]) + form_prefix = self.get_item(indexes=[[0, 1], [1, 0], [0, 0]]).get_attribute( + "id" + ) + self.get_element_by_id("id_%s-label" % form_prefix).send_keys("h") + self.get_element_by_id("id_%s-style_0" % form_prefix).click() + self.get_element_by_id("id_%s-value" % form_prefix).send_keys("i") self.save_form() questions = Question.objects.all() self.assertEqual(len(questions), 2) @@ -96,74 +107,89 @@ def test_polymorphic_add_inline_filtering(self): self.assertEqual(len(free_text_components), 3) free_text_text = free_text.questioncomponent_set.instance_of(Text).get() free_text_textarea = free_text.questioncomponent_set.instance_of(Textarea).get() - free_text_multichoice_group = ( - free_text.questioncomponent_set.instance_of(MultipleChoiceGroup).get()) - self.assertEqual(free_text_text.value, 'a') - self.assertEqual(free_text_textarea.value, 'b') - self.assertEqual(free_text_multichoice_group.title, 'c') + free_text_multichoice_group = free_text.questioncomponent_set.instance_of( + MultipleChoiceGroup + ).get() + self.assertEqual(free_text_text.value, "a") + self.assertEqual(free_text_textarea.value, "b") + self.assertEqual(free_text_multichoice_group.title, "c") free_text_multi_choices = free_text_multichoice_group.multiplechoice_set.all() self.assertEqual(len(free_text_multi_choices), 1) - self.assertEqual(free_text_multi_choices[0].label, 'd') - self.assertEqual(free_text_multi_choices[0].style, 'radio') - self.assertEqual(free_text_multi_choices[0].value, 'e') + self.assertEqual(free_text_multi_choices[0].label, "d") + self.assertEqual(free_text_multi_choices[0].style, "radio") + self.assertEqual(free_text_multi_choices[0].value, "e") poll = questions[1] poll_components = poll.questioncomponent_set.all() self.assertEqual(len(poll_components), 2) poll_text = poll.questioncomponent_set.instance_of(Text).get() - poll_multichoice_group = ( - poll.questioncomponent_set.instance_of(MultipleChoiceGroup).get()) - self.assertEqual(poll_text.value, 'f') - self.assertEqual(poll_multichoice_group.title, 'g') + poll_multichoice_group = poll.questioncomponent_set.instance_of( + MultipleChoiceGroup + ).get() + self.assertEqual(poll_text.value, "f") + self.assertEqual(poll_multichoice_group.title, "g") poll_multi_choices = poll_multichoice_group.multiplechoice_set.all() self.assertEqual(len(poll_multi_choices), 1) - self.assertEqual(poll_multi_choices[0].label, 'h') - self.assertEqual(poll_multi_choices[0].style, 'radio') - self.assertEqual(poll_multi_choices[0].value, 'i') + self.assertEqual(poll_multi_choices[0].label, "h") + self.assertEqual(poll_multi_choices[0].style, "radio") + self.assertEqual(poll_multi_choices[0].value, "i") def test_polymorphic_add_validation_error(self): """It should be possible to save a new inline after fixing a ValidationError""" - survey = Survey.objects.create(title='my survey') + survey = Survey.objects.create(title="my survey") self.load_admin(survey) self.add_inline(model=Poll) - self.set_field('value', 'f', indexes=[[0, 0], [0, 0]]) - self.set_field('title', 'g', indexes=[[0, 0], [1, 0]]) + self.set_field("value", "f", indexes=[[0, 0], [0, 0]]) + self.set_field("title", "g", indexes=[[0, 0], [1, 0]]) self.save_form() - errors = self.selenium.execute_script('return $(".djn-group-root .errorlist").toArray()') + errors = self.selenium.execute_script( + 'return $(".djn-group-root .errorlist").toArray()' + ) num_errors = len(errors) - self.assertNotEqual(num_errors, 0, "Validation errors should be present, but are not") + self.assertNotEqual( + num_errors, 0, "Validation errors should be present, but are not" + ) self.assertEqual(num_errors, 3, "Expected 3 errors, found %d" % num_errors) if self.has_grappelli: item = self.get_item([[0, 0]]) - item_id = item.get_attribute('id') - is_open = self.selenium.execute_script('return $("#%s").is(".grp-open")' % item_id) + item_id = item.get_attribute("id") + is_open = self.selenium.execute_script( + 'return $("#%s").is(".grp-open")' % item_id + ) if not is_open: - with self.clickable_selector("#%s > .djn-collapse-handler" % item_id) as el: + with self.clickable_selector( + "#%s > .djn-collapse-handler" % item_id + ) as el: el.click() - self.wait_until_element_is(item, '.grp-open', - message='Collapsible #%s did not open' % item_id) + self.wait_until_element_is( + item, ".grp-open", message="Collapsible #%s did not open" % item_id + ) error_parent_poll_id = self.selenium.execute_script( """return $(arguments[0]).closest( '.djn-item[data-inline-model="%s"]').attr('id') - """ % get_model_id(Poll), - errors[0]) + """ + % get_model_id(Poll), + errors[0], + ) self.assertNotEqual( error_parent_poll_id, - 'question_set-empty-test_polymorphic_add_filtering-poll', - 'Invalid inline id bug found') - self.assertEqual( - error_parent_poll_id, 'question_set-0') - - form_prefix = self.get_item(indexes=[[0, 0], [1, 0], [0, 0]]).get_attribute('id') - self.get_element_by_id('id_%s-label' % form_prefix).send_keys('h') - self.get_element_by_id('id_%s-style_0' % form_prefix).click() - self.get_element_by_id('id_%s-value' % form_prefix).send_keys('i') + "question_set-empty-test_polymorphic_add_filtering-poll", + "Invalid inline id bug found", + ) + self.assertEqual(error_parent_poll_id, "question_set-0") + + form_prefix = self.get_item(indexes=[[0, 0], [1, 0], [0, 0]]).get_attribute( + "id" + ) + self.get_element_by_id("id_%s-label" % form_prefix).send_keys("h") + self.get_element_by_id("id_%s-style_0" % form_prefix).click() + self.get_element_by_id("id_%s-value" % form_prefix).send_keys("i") self.save_form() questions = Question.objects.all() @@ -175,21 +201,22 @@ def test_polymorphic_add_validation_error(self): poll_components = poll.questioncomponent_set.all() self.assertEqual(len(poll_components), 2) poll_text = poll.questioncomponent_set.instance_of(Text).get() - poll_multichoice_group = ( - poll.questioncomponent_set.instance_of(MultipleChoiceGroup).get()) - self.assertEqual(poll_text.value, 'f') - self.assertEqual(poll_multichoice_group.title, 'g') + poll_multichoice_group = poll.questioncomponent_set.instance_of( + MultipleChoiceGroup + ).get() + self.assertEqual(poll_text.value, "f") + self.assertEqual(poll_multichoice_group.title, "g") poll_multi_choices = poll_multichoice_group.multiplechoice_set.all() self.assertEqual(len(poll_multi_choices), 1) - self.assertEqual(poll_multi_choices[0].label, 'h') - self.assertEqual(poll_multi_choices[0].style, 'radio') - self.assertEqual(poll_multi_choices[0].value, 'i') + self.assertEqual(poll_multi_choices[0].label, "h") + self.assertEqual(poll_multi_choices[0].style, "radio") + self.assertEqual(poll_multi_choices[0].value, "i") def test_polymorphic_delete(self): - survey = Survey.objects.create(title='my survey') + survey = Survey.objects.create(title="my survey") poll = Poll.objects.create(survey=survey, position=0) - Text.objects.create(question=poll, position=0, value='a') - Textarea.objects.create(question=poll, position=0, value='b') + Text.objects.create(question=poll, position=0, value="a") + Textarea.objects.create(question=poll, position=0, value="b") self.load_admin(survey) self.delete_inline([[0, 0]]) self.save_form() diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/admin.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/admin.py index aebc00e..4d1d2a9 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/admin.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/admin.py @@ -2,19 +2,38 @@ from django.contrib import admin from .models import ( - Block, BlockMarkdown, BlockRadioGroup, BlockRadioButton, - Questionnaire, SurveyStep) + Block, + BlockMarkdown, + BlockRadioGroup, + BlockRadioButton, + Questionnaire, + SurveyStep, +) -class BlockRadioButtonInline(nested_admin.SortableHiddenMixin, nested_admin.NestedTabularInline): +class BlockRadioButtonInline( + nested_admin.SortableHiddenMixin, nested_admin.NestedTabularInline +): model = BlockRadioButton - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) extra = 0 -class BlockInline(nested_admin.SortableHiddenMixin, nested_admin.NestedStackedPolymorphicInline): +class BlockInline( + nested_admin.SortableHiddenMixin, nested_admin.NestedStackedPolymorphicInline +): model = Block - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) extra = 0 sortable_field_name = "position" @@ -34,7 +53,12 @@ class BlockRadioGroupInline(nested_admin.NestedStackedPolymorphicInline.Child): class SurveyStepInline(nested_admin.NestedStackedInline): model = SurveyStep inlines = [BlockInline] - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) extra = 0 sortable_field_name = "position" diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/models.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/models.py index dad89f2..67de919 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/models.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/models.py @@ -1,7 +1,6 @@ import django from django.db import models -from nested_admin.tests.compat import python_2_unicode_compatible try: from polymorphic.models import PolymorphicModel @@ -19,7 +18,7 @@ class SurveyStep(models.Model): title = models.CharField(max_length=255) class Meta: - ordering = ['position'] + ordering = ["position"] def serialize(self): blocks = [b.serialize() for b in self.block_set.all()] @@ -34,7 +33,7 @@ class Block(PolymorphicModel): survey_step = models.ForeignKey("SurveyStep", models.CASCADE) class Meta: - ordering = ['position'] + ordering = ["position"] class BlockMarkdown(Block): @@ -65,13 +64,12 @@ class BlockRadioButton(models.Model): position = models.PositiveIntegerField() class Meta: - ordering = ['position'] + ordering = ["position"] def serialize(self): return self.label -@python_2_unicode_compatible class Questionnaire(models.Model): title = models.CharField(max_length=255) diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/tests.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/tests.py index 678ac49..aa63369 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/tests.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_mixed_nesting/tests.py @@ -1,9 +1,15 @@ from unittest import SkipTest from django.test import TestCase +from selenium.webdriver.common.by import By from .models import ( - Block, BlockMarkdown, BlockRadioGroup, BlockRadioButton, - Questionnaire, SurveyStep) + Block, + BlockMarkdown, + BlockRadioGroup, + BlockRadioButton, + Questionnaire, + SurveyStep, +) try: @@ -19,51 +25,60 @@ class PolymorphicMixedNestingTestCase(BaseNestedPolymorphicTestCase): """ Tests for polymorphic inlines that are nested inside non-polymorphic inlines. """ + root_model = Questionnaire @classmethod def setUpClass(cls): if not has_polymorphic: - raise SkipTest('django-polymorphic unavailable') - super(PolymorphicMixedNestingTestCase, cls).setUpClass() + raise SkipTest("django-polymorphic unavailable") + super().setUpClass() def test_polymorphic_child_formset_rendering(self): """The admin should only display one child inline for polymorphic instances""" - obj = self.root_model.objects.create(title='test') + obj = self.root_model.objects.create(title="test") self.load_admin(obj) - step_indexes = self.add_inline(model=SurveyStep, title='Step 1') + step_indexes = self.add_inline(model=SurveyStep, title="Step 1") self.add_inline(step_indexes, model=BlockMarkdown, value="Some instructions") - group_indexes = self.add_inline(step_indexes, model=BlockRadioGroup, label="Select one") + group_indexes = self.add_inline( + step_indexes, model=BlockRadioGroup, label="Select one" + ) self.add_inline(group_indexes, BlockRadioButton, label="Choice 1") self.add_inline(group_indexes, BlockRadioButton, label="Choice 2") inline_ids = [ - el.get_attribute('id') for el in - self.selenium.find_elements_by_css_selector( - '.djn-group:not([id*="-empty-"]')] + el.get_attribute("id") + for el in self.selenium.find_elements( + By.CSS_SELECTOR, '.djn-group:not([id*="-empty-"]' + ) + ] expected_inline_ids = [ "surveystep_set-group", "surveystep_set-0-block_set-group", - "surveystep_set-0-block_set-1-blockradiobutton_set-group"] + "surveystep_set-0-block_set-1-blockradiobutton_set-group", + ] assert inline_ids == expected_inline_ids self.save_form() inline_ids = [ - el.get_attribute('id') for el in - self.selenium.find_elements_by_css_selector( - '.djn-group:not([id*="-empty-"]')] - - assert "surveystep_set-0-block_set-0-blockradiobutton_set-group" not in inline_ids, ( - "Nested polymorphic model erroneously has inlines for both child models") + el.get_attribute("id") + for el in self.selenium.find_elements( + By.CSS_SELECTOR, '.djn-group:not([id*="-empty-"]' + ) + ] + + assert ( + "surveystep_set-0-block_set-0-blockradiobutton_set-group" not in inline_ids + ), "Nested polymorphic model erroneously has inlines for both child models" assert inline_ids == expected_inline_ids def test_add_step_to_empty_survey(self): - survey = self.root_model.objects.create(title='test') + survey = self.root_model.objects.create(title="test") self.load_admin(survey) - self.add_inline(model=SurveyStep, title='Step 1') + self.add_inline(model=SurveyStep, title="Step 1") self.save_form() steps = survey.surveystep_set.all() @@ -72,11 +87,13 @@ def test_add_step_to_empty_survey(self): assert steps[0].title == "Step 1" def test_add_blocks_to_empty_survey(self): - survey = self.root_model.objects.create(title='test') + survey = self.root_model.objects.create(title="test") self.load_admin(survey) - step_indexes = self.add_inline(model=SurveyStep, title='Step 1') + step_indexes = self.add_inline(model=SurveyStep, title="Step 1") self.add_inline(step_indexes, model=BlockMarkdown, value="Some instructions") - group_indexes = self.add_inline(step_indexes, model=BlockRadioGroup, label="Select one") + group_indexes = self.add_inline( + step_indexes, model=BlockRadioGroup, label="Select one" + ) self.add_inline(group_indexes, BlockRadioButton, label="Choice 1") self.add_inline(group_indexes, BlockRadioButton, label="Choice 2") self.save_form() @@ -90,58 +107,65 @@ def test_add_blocks_to_empty_survey(self): assert len(blocks) == 2 assert isinstance(blocks[0], BlockMarkdown) assert isinstance(blocks[1], BlockRadioGroup) - assert blocks[0].value == 'Some instructions' - assert blocks[1].label == 'Select one' + assert blocks[0].value == "Some instructions" + assert blocks[1].label == "Select one" buttons = blocks[1].blockradiobutton_set.all() assert len(buttons) == 2 - assert list(buttons.values_list('label', flat=True)) == ["Choice 1", "Choice 2"] + assert list(buttons.values_list("label", flat=True)) == ["Choice 1", "Choice 2"] def test_add_blocks_to_existing_survey(self): - survey = self.root_model.objects.create(title='test') - step = SurveyStep.objects.create(survey=survey, title='Step 1', position=0) - BlockMarkdown.objects.create(survey_step=step, position=0, value='Some instructions') - group = BlockRadioGroup.objects.create(survey_step=step, position=1, label='Select one') - - BlockRadioButton.objects.create(radio_group=group, position=0, label='Choice 1') - BlockRadioButton.objects.create(radio_group=group, position=1, label='Choice 2') + survey = self.root_model.objects.create(title="test") + step = SurveyStep.objects.create(survey=survey, title="Step 1", position=0) + BlockMarkdown.objects.create( + survey_step=step, position=0, value="Some instructions" + ) + group = BlockRadioGroup.objects.create( + survey_step=step, position=1, label="Select one" + ) + + BlockRadioButton.objects.create(radio_group=group, position=0, label="Choice 1") + BlockRadioButton.objects.create(radio_group=group, position=1, label="Choice 2") self.load_admin(survey) self.add_inline([[0, 0], [0, 1]], model=BlockRadioButton, label="Choice 3") self.add_inline([[0, 0]], model=BlockMarkdown, value="More instructions") - step_indexes = self.add_inline(model=SurveyStep, title='Step 2') + step_indexes = self.add_inline(model=SurveyStep, title="Step 2") self.add_inline(step_indexes, model=BlockMarkdown, value="Other instructions") - group_indexes = self.add_inline(step_indexes, model=BlockRadioGroup, label="Please choose") + group_indexes = self.add_inline( + step_indexes, model=BlockRadioGroup, label="Please choose" + ) self.add_inline(group_indexes, BlockRadioButton, label="Choice A") self.add_inline(group_indexes, BlockRadioButton, label="Choice B") self.save_form() assert survey.serialize() == { "title": "test", - "steps": [{ - "title": "Step 1", - "blocks": [{ - "type": "markdown", - "value": "Some instructions" - }, { - "type": "radiogroup", - "label": "Select one", - "buttons": ["Choice 1", "Choice 2", "Choice 3"], - }, { - "type": "markdown", - "value": "More instructions" - }], - }, { - "title": "Step 2", - "blocks": [{ - "type": "markdown", - "value": "Other instructions" - }, { - "type": "radiogroup", - "label": "Please choose", - "buttons": ["Choice A", "Choice B"], - }], - }], + "steps": [ + { + "title": "Step 1", + "blocks": [ + {"type": "markdown", "value": "Some instructions"}, + { + "type": "radiogroup", + "label": "Select one", + "buttons": ["Choice 1", "Choice 2", "Choice 3"], + }, + {"type": "markdown", "value": "More instructions"}, + ], + }, + { + "title": "Step 2", + "blocks": [ + {"type": "markdown", "value": "Other instructions"}, + { + "type": "radiogroup", + "label": "Please choose", + "buttons": ["Choice A", "Choice B"], + }, + ], + }, + ], } diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/admin.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/admin.py index 331af01..c405011 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/admin.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/admin.py @@ -2,14 +2,32 @@ import nested_admin from .models import ( - TopLevel, LevelOne, LevelOneA, LevelOneB, LevelTwo, LevelTwoC, LevelTwoD, - ALevelTwo, ALevelTwoC, ALevelTwoD, BLevelTwo, BLevelTwoC, BLevelTwoD, GFKX) + TopLevel, + LevelOne, + LevelOneA, + LevelOneB, + LevelTwo, + LevelTwoC, + LevelTwoD, + ALevelTwo, + ALevelTwoC, + ALevelTwoD, + BLevelTwo, + BLevelTwoC, + BLevelTwoD, + GFKX, +) class LevelTwoInline(nested_admin.NestedStackedPolymorphicInline): model = LevelTwo extra = 0 - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" class LevelTwoCInline(nested_admin.NestedStackedPolymorphicInline.Child): @@ -21,18 +39,27 @@ class LevelTwoDInline(nested_admin.NestedStackedPolymorphicInline.Child): child_inlines = (LevelTwoCInline, LevelTwoDInline) - class GFKXInline(nested_admin.NestedGenericStackedInline): model = GFKX extra = 1 sortable_field_name = "position" - inline_classes = ("collapse", "open", "grp-collapse", "grp-open", ) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) class ALevelTwoInline(nested_admin.NestedStackedPolymorphicInline): model = ALevelTwo extra = 0 - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" class ALevelTwoCInline(nested_admin.NestedStackedPolymorphicInline.Child): @@ -48,7 +75,12 @@ class ALevelTwoDInline(nested_admin.NestedStackedPolymorphicInline.Child): class BLevelTwoInline(nested_admin.NestedStackedPolymorphicInline): model = BLevelTwo extra = 0 - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" class BLevelTwoCInline(nested_admin.NestedStackedPolymorphicInline.Child): @@ -63,7 +95,12 @@ class BLevelTwoDInline(nested_admin.NestedStackedPolymorphicInline.Child): class LevelOneInline(nested_admin.NestedStackedPolymorphicInline): model = LevelOne extra = 0 - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" inlines = [LevelTwoInline] diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/models.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/models.py index 08fe4f9..f5771c2 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/models.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/models.py @@ -1,11 +1,8 @@ -from __future__ import unicode_literals - import django from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible try: from polymorphic.models import PolymorphicModel @@ -17,7 +14,6 @@ PolymorphicModel = models.Model -@python_2_unicode_compatible class TopLevel(models.Model): name = models.CharField(max_length=200) @@ -26,20 +22,19 @@ def __str__(self): return self.name -@python_2_unicode_compatible class LevelOne(PolymorphicModel): name = models.CharField(max_length=200, blank=True) position = models.PositiveIntegerField() - parent_level = ForeignKey(TopLevel, related_name='children', on_delete=CASCADE) + parent_level = ForeignKey(TopLevel, related_name="children", on_delete=CASCADE) def __str__(self): - if 'A' in type(self).__name__: - prefix = '(A) ' - if 'B' in type(self).__name__: - prefix = '(B) ' + if "A" in type(self).__name__: + prefix = "(A) " + if "B" in type(self).__name__: + prefix = "(B) " else: - prefix = '' + prefix = "" parts = ["%s%s[%d]" % (prefix, self.name, self.position)] if self.parent_level: parts.insert(0, "%s" % self.parent_level) @@ -54,20 +49,19 @@ class LevelOneB(LevelOne): b = models.CharField(max_length=200) -@python_2_unicode_compatible class LevelTwo(PolymorphicModel): name = models.CharField(max_length=200, blank=True) position = models.PositiveIntegerField() - parent_level = ForeignKey(LevelOne, related_name='children', on_delete=CASCADE) + parent_level = ForeignKey(LevelOne, related_name="children", on_delete=CASCADE) def __str__(self): - if 'C' in type(self).__name__: - prefix = '(C) ' - if 'D' in type(self).__name__: - prefix = '(D) ' + if "C" in type(self).__name__: + prefix = "(C) " + if "D" in type(self).__name__: + prefix = "(D) " else: - prefix = '' + prefix = "" parts = ["%s%s[%d]" % (prefix, self.name, self.position)] if self.parent_level: parts.insert(0, "%s" % self.parent_level) @@ -82,20 +76,19 @@ class LevelTwoD(LevelTwo): d = models.CharField(max_length=200) -@python_2_unicode_compatible class ALevelTwo(PolymorphicModel): name = models.CharField(max_length=200, blank=True) position = models.PositiveIntegerField() - polymorphic_parent = ForeignKey(LevelOneA, related_name='a_set', on_delete=CASCADE) + polymorphic_parent = ForeignKey(LevelOneA, related_name="a_set", on_delete=CASCADE) def __str__(self): - if 'C' in type(self).__name__: - prefix = '(C) ' - if 'D' in type(self).__name__: - prefix = '(D) ' + if "C" in type(self).__name__: + prefix = "(C) " + if "D" in type(self).__name__: + prefix = "(D) " else: - prefix = '' + prefix = "" parts = ["%s%s[%d]" % (prefix, self.name, self.position)] if self.polymorphic_parent: parts.insert(0, "%s" % self.polymorphic_parent) @@ -106,7 +99,6 @@ class ALevelTwoC(ALevelTwo): ac = models.CharField(max_length=200) -@python_2_unicode_compatible class GFKX(models.Model): name = models.CharField(max_length=255) position = models.PositiveIntegerField() @@ -115,7 +107,7 @@ class GFKX(models.Model): content_object = GenericForeignKey() class Meta: - ordering = ['object_id', 'position'] + ordering = ["object_id", "position"] def __str__(self): parts = ["%s[%d]" % (self.name, self.position)] @@ -129,20 +121,19 @@ class ALevelTwoD(ALevelTwo): x_set = GenericRelation(GFKX) -@python_2_unicode_compatible class BLevelTwo(PolymorphicModel): name = models.CharField(max_length=200, blank=True) position = models.PositiveIntegerField() - polymorphic_parent = ForeignKey(LevelOneB, related_name='b_set', on_delete=CASCADE) + polymorphic_parent = ForeignKey(LevelOneB, related_name="b_set", on_delete=CASCADE) def __str__(self): - if 'C' in type(self).__name__: - prefix = '(C) ' - if 'D' in type(self).__name__: - prefix = '(D) ' + if "C" in type(self).__name__: + prefix = "(C) " + if "D" in type(self).__name__: + prefix = "(D) " else: - prefix = '' + prefix = "" parts = ["%s%s[%d]" % (prefix, self.name, self.position)] if self.polymorphic_parent: parts.insert(0, "%s" % self.polymorphic_parent) diff --git a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/tests.py b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/tests.py index 84c5ade..b35970b 100644 --- a/nested_admin/tests/nested_polymorphic/test_polymorphic_std/tests.py +++ b/nested_admin/tests/nested_polymorphic/test_polymorphic_std/tests.py @@ -3,8 +3,17 @@ from .models import ( # ALevelTwoC, LevelTwoC, LevelTwoD, ALevelTwo, BLevelTwo, LevelTwoC, - LevelOneA, ALevelTwoC, ALevelTwoD, TopLevel, LevelOne, LevelOneB, - LevelTwo, BLevelTwoC, BLevelTwoD, GFKX) + LevelOneA, + ALevelTwoC, + ALevelTwoD, + TopLevel, + LevelOne, + LevelOneB, + LevelTwo, + BLevelTwoC, + BLevelTwoD, + GFKX, +) try: @@ -23,28 +32,28 @@ class PolymorphicStdTestCase(BaseNestedPolymorphicTestCase): @classmethod def setUpClass(cls): if not has_polymorphic: - raise SkipTest('django-polymorphic unavailable') - super(PolymorphicStdTestCase, cls).setUpClass() + raise SkipTest("django-polymorphic unavailable") + super().setUpClass() def test_add_level_one_to_empty(self): - obj = self.root_model.objects.create(name='test') + obj = self.root_model.objects.create(name="test") self.load_admin(obj) - self.add_inline(model=LevelOneB, name='x', b='bx') + self.add_inline(model=LevelOneB, name="x", b="bx") self.save_form() children = obj.children.all() self.assertEqual(len(children), 1) self.assertIsInstance(children[0], LevelOneB) - self.assertEqual(children[0].name, 'x') - self.assertEqual(children[0].b, 'bx') + self.assertEqual(children[0].name, "x") + self.assertEqual(children[0].b, "bx") def test_add_level_two_to_empty(self): - obj = self.root_model.objects.create(name='test') + obj = self.root_model.objects.create(name="test") self.load_admin(obj) - indexes = self.add_inline(model=LevelOneB, name='x', b='bx') + indexes = self.add_inline(model=LevelOneB, name="x", b="bx") - self.add_inline(indexes, model=BLevelTwoC, name='y', bc='bcy') + self.add_inline(indexes, model=BLevelTwoC, name="y", bc="bcy") self.save_form() @@ -52,27 +61,27 @@ def test_add_level_two_to_empty(self): self.assertEqual(len(children), 1) self.assertIsInstance(children[0], LevelOneB) b = children[0] - self.assertEqual(b.name, 'x') - self.assertEqual(b.b, 'bx') + self.assertEqual(b.name, "x") + self.assertEqual(b.b, "bx") b_children = b.b_set.all() self.assertEqual(len(b_children), 1) self.assertIsInstance(b_children[0], BLevelTwoC) - self.assertEqual(b_children[0].name, 'y') - self.assertEqual(b_children[0].bc, 'bcy') + self.assertEqual(b_children[0].name, "y") + self.assertEqual(b_children[0].bc, "bcy") def test_add_level_two_to_empty_with_validation_error(self): - obj = self.root_model.objects.create(name='test') + obj = self.root_model.objects.create(name="test") self.load_admin(obj) - l1_indexes_a = self.add_inline(model=LevelOneA, name='k', a='ak') - l2_indexes_a = self.add_inline(l1_indexes_a, model=ALevelTwoC, name='l') + l1_indexes_a = self.add_inline(model=LevelOneA, name="k", a="ak") + l2_indexes_a = self.add_inline(l1_indexes_a, model=ALevelTwoC, name="l") self.save_form() self.remove_inline(l2_indexes_a) - l1_indexes_b = self.add_inline(model=LevelOneB, name='m', b='bm') - self.add_inline(l1_indexes_b, model=BLevelTwoD, name='n', bd='bdn') + l1_indexes_b = self.add_inline(model=LevelOneB, name="m", b="bm") + self.add_inline(l1_indexes_b, model=BLevelTwoD, name="n", bd="bdn") self.save_form() children = obj.children.all() @@ -83,26 +92,26 @@ def test_add_level_two_to_empty_with_validation_error(self): self.assertIsInstance(a, LevelOneA) self.assertIsInstance(b, LevelOneB) - self.assertEqual(a.name, 'k') - self.assertEqual(a.a, 'ak') + self.assertEqual(a.name, "k") + self.assertEqual(a.a, "ak") self.assertEqual(len(a.a_set.all()), 0) - self.assertEqual(b.name, 'm') - self.assertEqual(b.b, 'bm') + self.assertEqual(b.name, "m") + self.assertEqual(b.b, "bm") b_children = b.b_set.all() self.assertEqual(len(b_children), 1) self.assertIsInstance(b_children[0], BLevelTwoD) - self.assertEqual(b_children[0].name, 'n') - self.assertEqual(b_children[0].bd, 'bdn') + self.assertEqual(b_children[0].name, "n") + self.assertEqual(b_children[0].bd, "bdn") def test_add_level_two_to_empty_drag_and_drop(self): - obj = self.root_model.objects.create(name='test') + obj = self.root_model.objects.create(name="test") self.load_admin(obj) - indexes = self.add_inline(model=LevelOneB, name='x', b='bx') - from_indexes = self.add_inline(indexes, model=BLevelTwoC, name='y', bc='bcy') - to_indexes = self.add_inline(indexes, model=BLevelTwoD, name='z', bd='bdz') + indexes = self.add_inline(model=LevelOneB, name="x", b="bx") + from_indexes = self.add_inline(indexes, model=BLevelTwoC, name="y", bc="bcy") + to_indexes = self.add_inline(indexes, model=BLevelTwoD, name="z", bd="bdz") self.drag_and_drop_item(from_indexes, to_indexes) @@ -112,30 +121,31 @@ def test_add_level_two_to_empty_drag_and_drop(self): self.assertEqual(len(children), 1) self.assertIsInstance(children[0], LevelOneB) b = children[0] - self.assertEqual(b.name, 'x') - self.assertEqual(b.b, 'bx') + self.assertEqual(b.name, "x") + self.assertEqual(b.b, "bx") b_children = b.b_set.all() self.assertEqual(len(b_children), 2) self.assertIsInstance(b_children[0], BLevelTwoD) - self.assertNotEqual(b_children[0].name, 'y', 'Dragged BLevelTwoD inline did not move') - self.assertEqual(b_children[0].name, 'z') - self.assertEqual(b_children[0].bd, 'bdz') + self.assertNotEqual( + b_children[0].name, "y", "Dragged BLevelTwoD inline did not move" + ) + self.assertEqual(b_children[0].name, "z") + self.assertEqual(b_children[0].bd, "bdz") self.assertIsInstance(b_children[1], BLevelTwoC) - self.assertEqual(b_children[1].name, 'y') - self.assertEqual(b_children[1].bc, 'bcy') + self.assertEqual(b_children[1].name, "y") + self.assertEqual(b_children[1].bc, "bcy") def test_add_level_two_child_gfk_inline(self): - obj = self.root_model.objects.create(name='test') + obj = self.root_model.objects.create(name="test") self.load_admin(obj) - idx_a = self.add_inline(model=LevelOneA, name='x', a='ax') - idx_a_d = self.add_inline(idx_a, model=ALevelTwoD, name='y', ad='ady') + idx_a = self.add_inline(model=LevelOneA, name="x", a="ax") + idx_a_d = self.add_inline(idx_a, model=ALevelTwoD, name="y", ad="ady") self.add_inline(idx_a_d, model=GFKX) - gfk_name_selector = ( - '#id_children-0-a_set-0-test_polymorphic_std-gfkx-content_type-object_id-0-name') + gfk_name_selector = "#id_children-0-a_set-0-test_polymorphic_std-gfkx-content_type-object_id-0-name" with self.available_selector(gfk_name_selector) as el: el.clear() - el.send_keys('Z') + el.send_keys("Z") self.save_form() @@ -143,15 +153,15 @@ def test_add_level_two_child_gfk_inline(self): self.assertEqual(len(children), 1) self.assertIsInstance(children[0], LevelOneA) a = children[0] - self.assertEqual(a.name, 'x') - self.assertEqual(a.a, 'ax') + self.assertEqual(a.name, "x") + self.assertEqual(a.a, "ax") a_children = a.a_set.all() self.assertEqual(len(a_children), 1) self.assertIsInstance(a_children[0], ALevelTwoD) - self.assertEqual(a_children[0].name, 'y') - self.assertEqual(a_children[0].ad, 'ady') + self.assertEqual(a_children[0].name, "y") + self.assertEqual(a_children[0].ad, "ady") gfk_children = a_children[0].x_set.all() self.assertEqual(len(gfk_children), 1) - self.assertEqual(gfk_children[0].name, 'Z') + self.assertEqual(gfk_children[0].name, "Z") diff --git a/nested_admin/tests/nested_recursive/__init__.py b/nested_admin/tests/nested_recursive/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/nested_admin/tests/nested_recursive/admin.py b/nested_admin/tests/nested_recursive/admin.py new file mode 100644 index 0000000..d6d7dd7 --- /dev/null +++ b/nested_admin/tests/nested_recursive/admin.py @@ -0,0 +1,26 @@ +from django.contrib import admin +import nested_admin +from .models import MenuItem + + +class Level2Inline(nested_admin.NestedTabularInline): + model = MenuItem + extra = 0 + min_num = 0 + title = "Level 2" + + +class Level1Inline(nested_admin.NestedTabularInline): + model = MenuItem + inlines = [Level2Inline] + extra = 0 + min_num = 1 + max_num = 2 + title = "Level 1" + + +@admin.register(MenuItem) +class ParentAdmin(nested_admin.NestedModelAdmin): + inlines = [Level1Inline] + title = "Menu" + fields = ["label"] diff --git a/nested_admin/tests/nested_recursive/models.py b/nested_admin/tests/nested_recursive/models.py new file mode 100644 index 0000000..ff55ef9 --- /dev/null +++ b/nested_admin/tests/nested_recursive/models.py @@ -0,0 +1,16 @@ +from django.db import models +from django.db.models import ForeignKey, CASCADE + + +class MenuItem(models.Model): + label = models.CharField(max_length=255) + parent = ForeignKey( + "MenuItem", related_name="children", on_delete=CASCADE, null=True + ) + position = models.PositiveIntegerField(default=0) + + class Meta: + ordering = ["position"] + + def __str__(self): + return self.name diff --git a/nested_admin/tests/nested_recursive/tests.py b/nested_admin/tests/nested_recursive/tests.py new file mode 100644 index 0000000..c67f717 --- /dev/null +++ b/nested_admin/tests/nested_recursive/tests.py @@ -0,0 +1,42 @@ +# from unittest import SkipTest + +# from django.conf import settings + +from nested_admin.tests.base import BaseNestedAdminTestCase +from .models import MenuItem + + +class TestRecursiveNesting(BaseNestedAdminTestCase): + + root_model = MenuItem + nested_models = (MenuItem, MenuItem) + + def test_max_num_nested_add_handlers_hide(self): + self.load_admin(self.root_model) + level1_add_handler = self.selenium.execute_script( + """ + return django.jQuery( + '.djn-add-handler.djn-model-nested_recursive-menuitem.djn-level-1' + )[0]""" + ) + level2_add_handler = self.selenium.execute_script( + """ + return django.jQuery( + '.djn-add-handler.djn-model-nested_recursive-menuitem.djn-level-2' + )[0]""" + ) + self.add_inline() + self.wait_until_element_is( + level1_add_handler, + ":not(:visible)", + "handler did not hide after max_num reached", + ) + assert ( + level2_add_handler.is_displayed() is True + ), "level2 add handler should not be hidden" + self.remove_inline([0]) + self.wait_until_element_is( + level1_add_handler, + ":visible", + "handler did not unhide after max_num inline removed", + ) diff --git a/nested_admin/tests/one_deep/admin.py b/nested_admin/tests/one_deep/admin.py index 70804a7..9848827 100644 --- a/nested_admin/tests/one_deep/admin.py +++ b/nested_admin/tests/one_deep/admin.py @@ -4,43 +4,55 @@ import nested_admin from .models import ( - PlainStackedRoot, PlainStackedChild, PlainTabularRoot, PlainTabularChild, - NestedStackedRoot, NestedStackedChild, NestedTabularRoot, NestedTabularChild) - - -class InlineMixin(object): + PlainStackedRoot, + PlainStackedChild, + PlainTabularRoot, + PlainTabularChild, + NestedStackedRoot, + NestedStackedChild, + NestedTabularRoot, + NestedTabularChild, +) + + +class InlineMixin: extra = 0 - if 'grappelli' in settings.INSTALLED_APPS: + if "grappelli" in settings.INSTALLED_APPS: sortable_field_name = "position" else: is_sortable = False - inline_classes = ("collapse", "open", ) - readonly_fields = ("readonly", ) + inline_classes = ( + "collapse", + "open", + ) + readonly_fields = ("readonly",) class PlainTabularChildInline(InlineMixin, admin.TabularInline): model = PlainTabularChild + @admin.register(PlainTabularRoot) class PlainTabularRootAdmin(admin.ModelAdmin): inlines = [PlainTabularChildInline] class Media: - css = {'all': ['one_deep/grp-normalize.css']} + css = {"all": ["one_deep/grp-normalize.css"]} class PlainStackedChildInline(InlineMixin, admin.StackedInline): model = PlainStackedChild + @admin.register(PlainStackedRoot) class PlainStackedRootAdmin(admin.ModelAdmin): inlines = [PlainStackedChildInline] - class NestedStackedChildInline(InlineMixin, nested_admin.NestedStackedInline): model = NestedStackedChild + @admin.register(NestedStackedRoot) class NestedStackedRootAdmin(nested_admin.NestedModelAdmin): inlines = [NestedStackedChildInline] @@ -49,6 +61,7 @@ class NestedStackedRootAdmin(nested_admin.NestedModelAdmin): class NestedTabularChildInline(InlineMixin, nested_admin.NestedTabularInline): model = NestedTabularChild + @admin.register(NestedTabularRoot) class NestedTabularRootAdmin(nested_admin.NestedModelAdmin): inlines = [NestedTabularChildInline] diff --git a/nested_admin/tests/one_deep/models.py b/nested_admin/tests/one_deep/models.py index 51356a0..d80921c 100644 --- a/nested_admin/tests/one_deep/models.py +++ b/nested_admin/tests/one_deep/models.py @@ -1,11 +1,7 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class RootAbstract(models.Model): slug = models.CharField(max_length=128) @@ -17,14 +13,13 @@ def __str__(self): return self.slug -@python_2_unicode_compatible class ChildAbstract(models.Model): slug = models.CharField(max_length=128, help_text="Halp") position = models.PositiveIntegerField() boolean = models.BooleanField(default=False) readonly = models.CharField(max_length=255) - text = models.TextField(default='') + text = models.TextField(default="") class Meta: abstract = True @@ -37,64 +32,60 @@ def __str__(self): class PlainStackedRoot(RootAbstract): - class Meta: verbose_name = "Stacked Root" verbose_name_plural = "Stacked Roots" class PlainStackedChild(ChildAbstract): - root = ForeignKey(PlainStackedRoot, related_name='children', on_delete=CASCADE) + root = ForeignKey(PlainStackedRoot, related_name="children", on_delete=CASCADE) class Meta: - ordering = ('root', 'position') + ordering = ("root", "position") verbose_name = "Stacked Child" verbose_name_plural = "Stacked Children" -class PlainTabularRoot(RootAbstract): +class PlainTabularRoot(RootAbstract): class Meta: verbose_name = "Tabular Root" verbose_name_plural = "Tabular Roots" - class PlainTabularChild(ChildAbstract): - root = ForeignKey(PlainTabularRoot, related_name='children', on_delete=CASCADE) + root = ForeignKey(PlainTabularRoot, related_name="children", on_delete=CASCADE) class Meta: - ordering = ('root', 'position') + ordering = ("root", "position") verbose_name = "Tabular Child" verbose_name_plural = "Tabular Children" class NestedStackedRoot(RootAbstract): - class Meta: verbose_name = "Stacked Root" verbose_name_plural = "Stacked Roots" class NestedStackedChild(ChildAbstract): - root = ForeignKey(NestedStackedRoot, related_name='children', on_delete=CASCADE) + root = ForeignKey(NestedStackedRoot, related_name="children", on_delete=CASCADE) class Meta: - ordering = ('root', 'position') + ordering = ("root", "position") verbose_name = "Stacked Child" verbose_name_plural = "Stacked Children" class NestedTabularRoot(RootAbstract): - class Meta: verbose_name = "Tabular Root" verbose_name_plural = "Tabular Roots" class NestedTabularChild(ChildAbstract): - root = ForeignKey(NestedTabularRoot, related_name='children', on_delete=CASCADE) + root = ForeignKey(NestedTabularRoot, related_name="children", on_delete=CASCADE) class Meta: - ordering = ('root', 'position') + ordering = ("root", "position") verbose_name = "Tabular Child" verbose_name_plural = "Tabular Children" diff --git a/nested_admin/tests/one_deep/tests.py b/nested_admin/tests/one_deep/tests.py index c6eba96..b818d93 100644 --- a/nested_admin/tests/one_deep/tests.py +++ b/nested_admin/tests/one_deep/tests.py @@ -1,7 +1,11 @@ try: from distutils.spawn import find_executable except: - find_executable = lambda f: None + + def find_executable(arg): + return None + + import inspect import logging import os @@ -12,6 +16,7 @@ import tempfile import time from unittest import SkipTest +from urllib.parse import urlparse, urlunparse, ParseResult import PIL.Image import PIL.ImageDraw @@ -20,18 +25,20 @@ from django.conf import settings from django.contrib.admin.sites import site as admin_site from django.test import override_settings -import six -from six.moves.urllib.parse import urlparse, urlunparse, ParseResult +from selenium.webdriver.common.by import By try: from storages.backends.s3boto3 import S3Boto3Storage except: S3Boto3Storage = None -from nested_admin.tests.base import ( - BaseNestedAdminTestCase, get_model_name) +from nested_admin.tests.base import BaseNestedAdminTestCase, get_model_name from .models import ( - PlainStackedRoot, PlainTabularRoot, NestedStackedRoot, NestedTabularRoot) + PlainStackedRoot, + PlainTabularRoot, + NestedStackedRoot, + NestedTabularRoot, +) logger = logging.getLogger(__name__) @@ -39,45 +46,47 @@ def strip_query_from_url(url): parts = list(urlparse(url)) - parts[ParseResult._fields.index('query')] = '' + parts[ParseResult._fields.index("query")] = "" return urlunparse(parts) class disable_string_if_invalid_for_grappelli(override_settings): - def __init__(self): self.options = {"TEMPLATES": [settings.TEMPLATES[0].copy()]} - if 'grappelli' in settings.INSTALLED_APPS: - self.options['TEMPLATES'][0]['OPTIONS'].pop('string_if_invalid') + if "grappelli" in settings.INSTALLED_APPS: + self.options["TEMPLATES"][0]["OPTIONS"].pop("string_if_invalid") @disable_string_if_invalid_for_grappelli() class VisualComparisonTestCase(BaseNestedAdminTestCase): root_model = None - root_models = [PlainStackedRoot, PlainTabularRoot, NestedStackedRoot, NestedTabularRoot] + root_models = [ + PlainStackedRoot, + PlainTabularRoot, + NestedStackedRoot, + NestedTabularRoot, + ] storage = None window_size = (1200, 800) @classmethod def setUpClass(cls): - if six.PY2: - raise SkipTest("Skipping redundant test") - cls.pixelmatch_bin = os.environ.get('PIXELMATCH_BIN') + cls.pixelmatch_bin = os.environ.get("PIXELMATCH_BIN") if not cls.pixelmatch_bin: - cls.pixelmatch_bin = find_executable('pixelmatch') + cls.pixelmatch_bin = find_executable("pixelmatch") if not cls.pixelmatch_bin or not os.path.exists(cls.pixelmatch_bin): raise SkipTest("pixelmatch not installed") - cls.screenshot_output_dir = os.environ.get('SCREENSHOT_OUTPUT_DIR', '/tmp/djn-tests') + cls.screenshot_output_dir = os.environ.get( + "SCREENSHOT_OUTPUT_DIR", "/tmp/djn-tests" + ) super(BaseNestedAdminTestCase, cls).setUpClass() cls.root_temp_dir = tempfile.mkdtemp() - if os.environ.get('TRAVIS_BUILD_NUMBER'): + if os.environ.get("TRAVIS_BUILD_NUMBER"): # For some reason these tests fail on travis when Django > 1.11 - if django.VERSION > (1, 11): - raise SkipTest("Issue with travis and Django >= 1.11") - cls.path_prefix = "travis_%s" % os.environ['TRAVIS_BUILD_NUMBER'] + raise SkipTest("Issue with travis and Django >= 1.11") else: cls.path_prefix = "local" @@ -88,7 +97,9 @@ def setUpClass(cls): if not os.path.exists(screenshot_path): os.makedirs(screenshot_path) - if all(os.environ.get(k) for k in ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY']): + if all( + os.environ.get(k) for k in ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] + ): try: storage = S3Boto3Storage() bucket = storage.bucket # noqa @@ -105,7 +116,7 @@ def setUpClass(cls): def descend_admin_inlines(admin): data = [admin.model, []] - for inline in (getattr(admin, 'inlines', None) or []): + for inline in getattr(admin, "inlines", None) or []: data[1].append(descend_admin_inlines(inline)) return data @@ -121,7 +132,7 @@ def recursive_map_model_names(data): @classmethod def tearDownClass(cls): - super(VisualComparisonTestCase, cls).tearDownClass() + super().tearDownClass() shutil.rmtree(cls.root_temp_dir) @property @@ -137,22 +148,27 @@ def _block_out_arg(self, selector): Generate the --block-out argument passed to pixelmatch that excludes an element from the diff """ - el = self.selenium.find_element_by_css_selector(selector) - return ['--block-out', "%(x)s,%(y)s,%(w)s,%(h)s" % { - 'x': el.location['x'], - 'y': el.location['y'], - 'w': el.size['width'], - 'h': el.size['height'], - }] + el = self.selenium.find_element(By.CSS_SELECTOR, selector) + return [ + "--block-out", + "{x},{y},{w},{h}".format( + x=el.location["x"], + y=el.location["y"], + w=el.size["width"], + h=el.size["height"], + ), + ] def exclude_from_screenshots(self, imgs, exclude=None): - pixel_density = self.selenium.execute_script('return window.devicePixelRatio') or 1 + pixel_density = ( + self.selenium.execute_script("return window.devicePixelRatio") or 1 + ) exclude = exclude or [] rects = [] for selector in exclude: - el = self.selenium.find_element_by_css_selector(selector) - x0, y0 = el.location['x'], el.location['y'] - w, h = el.size['width'], el.size['height'] + el = self.selenium.find_element(By.CSS_SELECTOR, selector) + x0, y0 = el.location["x"], el.location["y"] + w, h = el.size["width"], el.size["height"] x1, y1 = x0 + w, y0 + h coords = [v * pixel_density for v in [x0, y0, x1, y1]] rects.append(coords) @@ -160,20 +176,20 @@ def exclude_from_screenshots(self, imgs, exclude=None): im = PIL.Image.open(img_path) draw = PIL.ImageDraw.Draw(im) for rect in rects: - draw.rectangle(rect, fill='black') + draw.rectangle(rect, fill="black") im.save(img_path) def assertSameScreenshot(self, a, b, exclude=None): - diff_output_path = a.replace('_a.png', '_diff.png') - args = [self.pixelmatch_bin, a, b, diff_output_path, 'threshold=0'] + diff_output_path = a.replace("_a.png", "_diff.png") + args = [self.pixelmatch_bin, a, b, diff_output_path, "threshold=0"] exclude = exclude or [] self.exclude_from_screenshots([a, b], exclude) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, _ = p.communicate() - stdout = stdout.decode('utf-8') - diff_pixels = int(re.search(r'different pixels: (\d+)', stdout).group(1)) + stdout = stdout.decode("utf-8") + diff_pixels = int(re.search(r"different pixels: (\d+)", stdout).group(1)) if diff_pixels == 0: # No differences found if self.screenshot_output_dir: @@ -184,27 +200,32 @@ def assertSameScreenshot(self, a, b, exclude=None): else: msg = "Screenshots do not match (%d pixels differ)" % diff_pixels if self.storage: - s3_name = "%s/%s" % (self.path_prefix, os.path.basename(diff_output_path)) - with open(diff_output_path, 'rb') as f: + s3_name = "{}/{}".format( + self.path_prefix, os.path.basename(diff_output_path) + ) + with open(diff_output_path, "rb") as f: s3_name = self.storage.save(s3_name, f) s3_url = strip_query_from_url(self.storage.url(s3_name)) - msg = "%s (See <%s>)" % (msg, s3_url) + msg = "{} (See <{}>)".format(msg, s3_url) elif self.screenshot_output_dir: - msg = "%s (See %s)" % (msg, diff_output_path) + msg = "{} (See {})".format(msg, diff_output_path) raise AssertionError(msg) def get_admin_screenshot(self): name = inspect.stack()[1][3] prefix = "%s/py%s%s_dj%s%s" % ( - (self.path_prefix,) + sys.version_info[:2] + django.VERSION[:2]) + (self.path_prefix,) + sys.version_info[:2] + django.VERSION[:2] + ) if self.has_grappelli: prefix += "_grp" output_dir = self.screenshot_output_dir or self.temp_dir - suffix = ('a' if self.root_model.__name__.startswith('Plain') else 'b') - image_path = os.path.join(output_dir, "%s_%s_%s.png" % (prefix, name, suffix)) + suffix = "a" if self.root_model.__name__.startswith("Plain") else "b" + image_path = os.path.join( + output_dir, "{}_{}_{}.png".format(prefix, name, suffix) + ) # Move mouse to a consistent place, to avoid hover styles confusing things # body_element = self.selenium.execute_script('return document.body') - self.selenium.execute_script('document.body.scrollTop = 0') + self.selenium.execute_script("document.body.scrollTop = 0") self.selenium.execute_script('$("*:focus").blur()') time.sleep(0.2) self.selenium.save_screenshot(image_path) @@ -213,7 +234,9 @@ def get_admin_screenshot(self): def add_inline(self): child_model = self.models[1][0][0] verbose_name = child_model._meta.verbose_name.title() - with self.clickable_xpath('//a[contains(string(.), "Add another %s")]' % verbose_name) as el: + with self.clickable_xpath( + '//a[contains(string(.), "Add another %s")]' % verbose_name + ) as el: el.click() def test_stacked_empty(self): @@ -237,8 +260,8 @@ def test_tabular_one_item(self): for model in [PlainTabularRoot, NestedTabularRoot]: self.root_model = model child_model = self.models[1][0][0] - root = model.objects.create(slug='a') - child_model.objects.create(slug='b', root=root, position=0) + root = model.objects.create(slug="a") + child_model.objects.create(slug="b", root=root, position=0) self.load_admin(obj=root) screenshots.append(self.get_admin_screenshot()) self.assertSameScreenshot(*screenshots) @@ -248,8 +271,8 @@ def test_stacked_one_item(self): for model in [PlainStackedRoot, NestedStackedRoot]: self.root_model = model child_model = self.models[1][0][0] - root = model.objects.create(slug='a') - child_model.objects.create(slug='b', root=root, position=0) + root = model.objects.create(slug="a") + child_model.objects.create(slug="b", root=root, position=0) self.load_admin(obj=root) screenshots.append(self.get_admin_screenshot()) self.assertSameScreenshot(*screenshots) @@ -278,10 +301,10 @@ def test_tabular_validation_error(self): self.root_model = model self.load_admin() self.add_inline() - with self.clickable_selector('#id_slug') as el: - el.send_keys('a') - with self.clickable_selector('#id_children-0-slug') as el: - el.send_keys('b') + with self.clickable_selector("#id_slug") as el: + el.send_keys("a") + with self.clickable_selector("#id_children-0-slug") as el: + el.send_keys("b") self.save_form() screenshots.append(self.get_admin_screenshot()) exclude = [] @@ -289,7 +312,7 @@ def test_tabular_validation_error(self): # django has a bug where it doesn't show the 'Remove' link # if there is a validationerror on a newly added inline # see - exclude += ['#children-0 .delete'] + exclude += ["#children-0 .delete"] self.assertSameScreenshot(*screenshots, exclude=exclude) def test_stacked_validation_error(self): @@ -298,10 +321,10 @@ def test_stacked_validation_error(self): self.root_model = model self.load_admin() self.add_inline() - with self.clickable_selector('#id_slug') as el: - el.send_keys('a') - with self.clickable_selector('#id_children-0-slug') as el: - el.send_keys('b') + with self.clickable_selector("#id_slug") as el: + el.send_keys("a") + with self.clickable_selector("#id_children-0-slug") as el: + el.send_keys("b") self.save_form() screenshots.append(self.get_admin_screenshot()) exclude = [] @@ -309,5 +332,5 @@ def test_stacked_validation_error(self): # django has a bug where it doesn't show the 'Remove' link # if there is a validationerror on a newly added inline # see - exclude += ['.inline-related:not(.empty-form) > h3'] + exclude += [".inline-related:not(.empty-form) > h3"] self.assertSameScreenshot(*screenshots, exclude=exclude) diff --git a/nested_admin/tests/settings.py b/nested_admin/tests/settings.py index 6f813e9..93e4119 100644 --- a/nested_admin/tests/settings.py +++ b/nested_admin/tests/settings.py @@ -12,16 +12,18 @@ DEBUG = NESTED_ADMIN_DEBUG = True DATABASES = { - 'default': dj_database_url.parse(os.environ.get('DATABASE_URL', 'sqlite://:memory:')), + "default": dj_database_url.parse( + os.environ.get("DATABASE_URL", "sqlite://:memory:") + ), } -DATABASES['default']['TEST'] = dict(DATABASES['default']) +DATABASES["default"]["TEST"] = dict(DATABASES["default"]) -SECRET_KEY = 'z-i*xqqn)r0i7leak^#clq6y5j8&tfslp^a4duaywj2$**s*0_' +SECRET_KEY = "z-i*xqqn)r0i7leak^#clq6y5j8&tfslp^a4duaywj2$**s*0_" MIGRATION_MODULES = { - 'auth': None, - 'contenttypes': None, - 'sessions': None, + "auth": None, + "contenttypes": None, + "sessions": None, } try: @@ -29,88 +31,95 @@ except ImportError: INSTALLED_APPS = tuple([]) else: - INSTALLED_APPS = tuple(['grappelli']) - -TEMPLATES = [{ - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': selenosis.settings.TEMPLATES[0]['DIRS'], - 'APP_DIRS': True, - 'OPTIONS': { - 'debug': True, - 'string_if_invalid': 'INVALID {{ %s }}', - 'context_processors': [ - 'django.contrib.auth.context_processors.auth', - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.template.context_processors.request', - 'django.contrib.messages.context_processors.messages', - ], - }, -}] + INSTALLED_APPS = tuple(["grappelli"]) + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": selenosis.settings.TEMPLATES[0]["DIRS"], + "APP_DIRS": True, + "OPTIONS": { + "debug": True, + "string_if_invalid": "INVALID {{ %s }}", + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.static", + "django.template.context_processors.tz", + "django.template.context_processors.request", + "django.contrib.messages.context_processors.messages", + ], + }, + } +] INSTALLED_APPS += ( - 'polymorphic', - 'selenosis', - 'nested_admin.tests', - 'nested_admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.messages', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.staticfiles', - 'django.contrib.admin', + "polymorphic", + "selenosis", + "nested_admin.tests", + "nested_admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.messages", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.staticfiles", + "django.contrib.admin", ) # Add apps within the tests folder -for p in glob.glob(os.path.join(current_dir, '*', 'models.py')): - INSTALLED_APPS += tuple(["nested_admin.tests.%s" % - os.path.basename(os.path.dirname(p))]) +for p in glob.glob(os.path.join(current_dir, "*", "models.py")): + INSTALLED_APPS += tuple( + ["nested_admin.tests.%s" % os.path.basename(os.path.dirname(p))] + ) -for p in glob.glob(os.path.join(current_dir, 'nested_polymorphic/*/models.py')): - INSTALLED_APPS += tuple(["nested_admin.tests.nested_polymorphic.%s" % - os.path.basename(os.path.dirname(p))]) +for p in glob.glob(os.path.join(current_dir, "nested_polymorphic/*/models.py")): + INSTALLED_APPS += tuple( + [ + "nested_admin.tests.nested_polymorphic.%s" + % os.path.basename(os.path.dirname(p)) + ] + ) MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ] LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', + "version": 1, + "disable_existing_loggers": False, + "handlers": { + "console": { + "class": "logging.StreamHandler", }, }, - 'loggers': { - 'nested_admin.tests': { - 'handlers': ['console'], - 'level': 'WARNING', + "loggers": { + "nested_admin.tests": { + "handlers": ["console"], + "level": "WARNING", }, }, } SITE_ID = 1 -ROOT_URLCONF = 'nested_admin.tests.urls' -MEDIA_ROOT = os.path.join(temp_dir, 'media') -MEDIA_URL = '/media/' -STATIC_URL = '/static/' +ROOT_URLCONF = "nested_admin.tests.urls" +MEDIA_ROOT = os.path.join(temp_dir, "media") +MEDIA_URL = "/media/" +STATIC_URL = "/static/" DEBUG_PROPAGATE_EXCEPTIONS = True USE_TZ = True -TEST_RUNNER = 'selenosis.DiscoverRunner' +TEST_RUNNER = "selenosis.DiscoverRunner" AWS_S3_REGION_NAME = "us-east-1" -AWS_STORAGE_BUCKET_NAME = 'django-nested-admin-artifacts' +AWS_STORAGE_BUCKET_NAME = "django-nested-admin-artifacts" AWS_DEFAULT_ACL = None diff --git a/nested_admin/tests/three_deep/admin.py b/nested_admin/tests/three_deep/admin.py index 320996f..1992d6b 100644 --- a/nested_admin/tests/three_deep/admin.py +++ b/nested_admin/tests/three_deep/admin.py @@ -7,7 +7,12 @@ class LevelThreeInline(NestedStackedInline): model = LevelThree extra = 1 - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" @@ -15,7 +20,12 @@ class LevelTwoInline(NestedStackedInline): model = LevelTwo extra = 1 inlines = [LevelThreeInline] - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" @@ -23,7 +33,12 @@ class LevelOneInline(NestedStackedInline): model = LevelOne extra = 1 inlines = [LevelTwoInline] - inline_classes = ("collapse", "open", "grp-collapse", "grp-open",) + inline_classes = ( + "collapse", + "open", + "grp-collapse", + "grp-open", + ) sortable_field_name = "position" diff --git a/nested_admin/tests/three_deep/models.py b/nested_admin/tests/three_deep/models.py index ee8f501..e2d5461 100644 --- a/nested_admin/tests/three_deep/models.py +++ b/nested_admin/tests/three_deep/models.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE @@ -10,26 +8,26 @@ class TopLevel(models.Model): class LevelOne(models.Model): name = models.CharField(max_length=200) - parent_level = ForeignKey(TopLevel, related_name='children', on_delete=CASCADE) + parent_level = ForeignKey(TopLevel, related_name="children", on_delete=CASCADE) position = models.PositiveIntegerField() class Meta: - ordering = ('position', ) + ordering = ("position",) class LevelTwo(models.Model): name = models.CharField(max_length=200, blank=True) - parent_level = ForeignKey(LevelOne, related_name='children', on_delete=CASCADE) + parent_level = ForeignKey(LevelOne, related_name="children", on_delete=CASCADE) position = models.PositiveIntegerField(blank=True, null=True) class Meta: - ordering = ('position', ) + ordering = ("position",) class LevelThree(models.Model): name = models.CharField(max_length=200) - parent_level = ForeignKey(LevelTwo, related_name='children', on_delete=CASCADE) + parent_level = ForeignKey(LevelTwo, related_name="children", on_delete=CASCADE) position = models.PositiveIntegerField() class Meta: - ordering = ('position', ) + ordering = ("position",) diff --git a/nested_admin/tests/three_deep/tests.py b/nested_admin/tests/three_deep/tests.py index e0c40cb..a735e26 100644 --- a/nested_admin/tests/three_deep/tests.py +++ b/nested_admin/tests/three_deep/tests.py @@ -1,5 +1,4 @@ from django.contrib.auth.models import Permission, User -from django.contrib.contenttypes.models import ContentType from nested_admin.tests.base import BaseNestedAdminTestCase from .models import TopLevel, LevelOne, LevelTwo, LevelThree @@ -12,93 +11,144 @@ class TestDeepNesting(BaseNestedAdminTestCase): @classmethod def setUpClass(cls): - super(TestDeepNesting, cls).setUpClass() + super().setUpClass() cls.l1_model, cls.l2_model, cls.l3_model = cls.nested_models def test_validationerror_on_empty_extra_parent_form(self): - toplevel = TopLevel.objects.create(name='a') + toplevel = TopLevel.objects.create(name="a") self.load_admin(toplevel) - self.set_field('name', 'c', indexes=[0, 0]) - self.set_field('name', 'd', indexes=[0, 0, 0]) + self.set_field("name", "c", indexes=[0, 0]) + self.set_field("name", "d", indexes=[0, 0, 0]) self.save_form() field_id_with_error = self.selenium.execute_script( - "return $('ul.errorlist li').closest('.form-row').find('input').attr('id')") + "return $('ul.errorlist li').closest('.form-row').find('input').attr('id')" + ) self.assertEqual(field_id_with_error, "id_children-0-name") def test_create_new(self): self.load_admin() - self.set_field('name', 'a') - self.set_field('name', 'b', [0]) - self.set_field('name', 'c', [0, 0]) - self.set_field('name', 'd', [0, 0, 0]) + self.set_field("name", "a") + self.set_field("name", "b", [0]) + self.set_field("name", "c", [0, 0]) + self.set_field("name", "d", [0, 0, 0]) self.save_form() root_instances = self.root_model.objects.all() - self.assertNotEqual(len(root_instances), 0, "%s did not save" % self.root_model.__name__) - self.assertEqual(len(root_instances), 1, "Too many %s found" % self.root_model.__name__) + self.assertNotEqual( + len(root_instances), 0, "%s did not save" % self.root_model.__name__ + ) + self.assertEqual( + len(root_instances), 1, "Too many %s found" % self.root_model.__name__ + ) root = root_instances[0] - self.assertEqual(root.name, 'a', "%s.name has wrong value" % self.root_model.__name__) + self.assertEqual( + root.name, "a", "%s.name has wrong value" % self.root_model.__name__ + ) l1_instances = root.children.all() - self.assertNotEqual(len(l1_instances), 0, "%s did not save" % self.l1_model.__name__) - self.assertEqual(len(l1_instances), 1, "Too many %s found" % self.l1_model.__name__) + self.assertNotEqual( + len(l1_instances), 0, "%s did not save" % self.l1_model.__name__ + ) + self.assertEqual( + len(l1_instances), 1, "Too many %s found" % self.l1_model.__name__ + ) l1_instance = l1_instances[0] - self.assertEqual(l1_instance.name, 'b', "%s.name has wrong value" % self.l1_model.__name__) + self.assertEqual( + l1_instance.name, "b", "%s.name has wrong value" % self.l1_model.__name__ + ) l2_instances = l1_instance.children.all() - self.assertNotEqual(len(l2_instances), 0, "%s did not save" % self.l2_model.__name__) - self.assertEqual(len(l2_instances), 1, "Too many %s found" % self.l2_model.__name__) + self.assertNotEqual( + len(l2_instances), 0, "%s did not save" % self.l2_model.__name__ + ) + self.assertEqual( + len(l2_instances), 1, "Too many %s found" % self.l2_model.__name__ + ) l2_instance = l2_instances[0] - self.assertEqual(l2_instance.name, 'c', "%s.name has wrong value" % self.l2_model.__name__) + self.assertEqual( + l2_instance.name, "c", "%s.name has wrong value" % self.l2_model.__name__ + ) l3_instances = l2_instance.children.all() - self.assertNotEqual(len(l3_instances), 0, "%s did not save" % self.l3_model.__name__) - self.assertEqual(len(l3_instances), 1, "Too many %s found" % self.l3_model.__name__) + self.assertNotEqual( + len(l3_instances), 0, "%s did not save" % self.l3_model.__name__ + ) + self.assertEqual( + len(l3_instances), 1, "Too many %s found" % self.l3_model.__name__ + ) l3_instance = l3_instances[0] - self.assertEqual(l3_instance.name, 'd', "%s.name has wrong value" % self.l3_model.__name__) + self.assertEqual( + l3_instance.name, "d", "%s.name has wrong value" % self.l3_model.__name__ + ) def test_create_new_no_extras(self): self.load_admin() - self.set_field('name', 'a') + self.set_field("name", "a") self.remove_inline([0]) - self.add_inline(name='b') + self.add_inline(name="b") self.remove_inline([0, 0]) - self.add_inline([0], name='c') + self.add_inline([0], name="c") self.remove_inline([0, 0, 0]) - self.add_inline([0, 0], name='d') + self.add_inline([0, 0], name="d") self.save_form() root_instances = self.root_model.objects.all() - self.assertNotEqual(len(root_instances), 0, "%s did not save" % self.root_model.__name__) - self.assertEqual(len(root_instances), 1, "Too many %s found" % self.root_model.__name__) + self.assertNotEqual( + len(root_instances), 0, "%s did not save" % self.root_model.__name__ + ) + self.assertEqual( + len(root_instances), 1, "Too many %s found" % self.root_model.__name__ + ) root = root_instances[0] - self.assertEqual(root.name, 'a', "%s.name has wrong value" % self.root_model.__name__) + self.assertEqual( + root.name, "a", "%s.name has wrong value" % self.root_model.__name__ + ) l1_instances = root.children.all() - self.assertNotEqual(len(l1_instances), 0, "%s did not save" % self.l1_model.__name__) - self.assertEqual(len(l1_instances), 1, "Too many %s found" % self.l1_model.__name__) + self.assertNotEqual( + len(l1_instances), 0, "%s did not save" % self.l1_model.__name__ + ) + self.assertEqual( + len(l1_instances), 1, "Too many %s found" % self.l1_model.__name__ + ) l1_instance = l1_instances[0] - self.assertEqual(l1_instance.name, 'b', "%s.name has wrong value" % self.l1_model.__name__) + self.assertEqual( + l1_instance.name, "b", "%s.name has wrong value" % self.l1_model.__name__ + ) l2_instances = l1_instance.children.all() - self.assertNotEqual(len(l2_instances), 0, "%s did not save" % self.l2_model.__name__) - self.assertEqual(len(l2_instances), 1, "Too many %s found" % self.l2_model.__name__) + self.assertNotEqual( + len(l2_instances), 0, "%s did not save" % self.l2_model.__name__ + ) + self.assertEqual( + len(l2_instances), 1, "Too many %s found" % self.l2_model.__name__ + ) l2_instance = l2_instances[0] - self.assertEqual(l2_instance.name, 'c', "%s.name has wrong value" % self.l2_model.__name__) + self.assertEqual( + l2_instance.name, "c", "%s.name has wrong value" % self.l2_model.__name__ + ) l3_instances = l2_instance.children.all() - self.assertNotEqual(len(l3_instances), 0, "%s did not save" % self.l3_model.__name__) - self.assertEqual(len(l3_instances), 1, "Too many %s found" % self.l3_model.__name__) + self.assertNotEqual( + len(l3_instances), 0, "%s did not save" % self.l3_model.__name__ + ) + self.assertEqual( + len(l3_instances), 1, "Too many %s found" % self.l3_model.__name__ + ) l3_instance = l3_instances[0] - self.assertEqual(l3_instance.name, 'd', "%s.name has wrong value" % self.l3_model.__name__) + self.assertEqual( + l3_instance.name, "d", "%s.name has wrong value" % self.l3_model.__name__ + ) def test_save_missing_intermediate_inline(self): self.load_admin() - self.set_field('name', 'a') - self.set_field('name', 'b', [0]) - self.set_field('name', 'd', [0, 0, 0]) + self.set_field("name", "a") + self.set_field("name", "b", [0]) + self.set_field("name", "d", [0, 0, 0]) self.save_form() root_instances = self.root_model.objects.all() - self.assertNotEqual(len(root_instances), 0, "%s did not save" % self.root_model.__name__) + self.assertNotEqual( + len(root_instances), 0, "%s did not save" % self.root_model.__name__ + ) class TestNestedPermissions(BaseNestedAdminTestCase): @@ -109,14 +159,14 @@ class TestNestedPermissions(BaseNestedAdminTestCase): @classmethod def setUpClass(cls): - super(TestNestedPermissions, cls).setUpClass() + super().setUpClass() cls.l1_model, cls.l2_model, cls.l3_model = cls.nested_models def setUp(self): - super(TestNestedPermissions, self).setUp() + super().setUp() - self.user = User(username='user', is_staff=True, is_active=True) - self.user.set_password('password') + self.user = User(username="user", is_staff=True, is_active=True) + self.user.set_password("password") self.user.save() models = (self.root_model,) + self.nested_models @@ -125,16 +175,18 @@ def setUp(self): for model in models: app_label = model._meta.app_label model_name = model._meta.model_name - for perm_type in ['add', 'change', 'delete']: - codename = "%s_%s" % (perm_type, model_name) + for perm_type in ["add", "change", "delete"]: + codename = "{}_{}".format(perm_type, model_name) self.permissions[codename] = Permission.objects.get_by_natural_key( - codename, app_label, model_name) + codename, app_label, model_name + ) self.user.user_permissions.add(self.permissions["change_%s" % model_name]) try: view_perm = Permission.objects.get_by_natural_key( - 'view_%s' % model_name, app_label, model_name) + "view_%s" % model_name, app_label, model_name + ) except Permission.DoesNotExist: pass else: @@ -142,39 +194,41 @@ def setUp(self): self.user.user_permissions.add(view_perm) def test_user_lacks_parent_permissions_can_add(self): - for perm_type in ['add', 'delete']: + for perm_type in ["add", "delete"]: self.user.user_permissions.add( - self.permissions['%s_levelthree' % perm_type]) + self.permissions["%s_levelthree" % perm_type] + ) - toplevel = TopLevel.objects.create(name='root') - l1 = LevelOne.objects.create(name='a1', parent_level=toplevel, position=0) - l2_1 = LevelTwo.objects.create(name='b1', parent_level=l1, position=0) - LevelTwo.objects.create(name='b2', parent_level=l1, position=1) - LevelThree.objects.create(name='c1', parent_level=l2_1, position=0) + toplevel = TopLevel.objects.create(name="root") + l1 = LevelOne.objects.create(name="a1", parent_level=toplevel, position=0) + l2_1 = LevelTwo.objects.create(name="b1", parent_level=l1, position=0) + LevelTwo.objects.create(name="b2", parent_level=l1, position=1) + LevelThree.objects.create(name="c1", parent_level=l2_1, position=0) self.admin_login("user", "password") self.load_admin(toplevel) - self.set_field('name', 'c2', [0, 1, 0]) + self.set_field("name", "c2", [0, 1, 0]) self.save_form() - l3_objs = LevelThree.objects.all().order_by('name') - self.assertEqual(l3_objs[0].name, 'c1') + l3_objs = LevelThree.objects.all().order_by("name") + self.assertEqual(l3_objs[0].name, "c1") self.assertNotEqual(len(l3_objs), 1, "New LevelThree inline was not saved") self.assertEqual(len(l3_objs), 2) self.assertEqual(l3_objs[1].name, "c2") def test_user_lacks_parent_permissions_can_delete(self): - for perm_type in ['add', 'delete']: + for perm_type in ["add", "delete"]: self.user.user_permissions.add( - self.permissions['%s_levelthree' % perm_type]) + self.permissions["%s_levelthree" % perm_type] + ) - toplevel = TopLevel.objects.create(name='root') - l1 = LevelOne.objects.create(name='a1', parent_level=toplevel, position=0) - l2_1 = LevelTwo.objects.create(name='b1', parent_level=l1, position=0) - LevelTwo.objects.create(name='b2', parent_level=l1, position=1) - LevelThree.objects.create(name='c1', parent_level=l2_1, position=0) + toplevel = TopLevel.objects.create(name="root") + l1 = LevelOne.objects.create(name="a1", parent_level=toplevel, position=0) + l2_1 = LevelTwo.objects.create(name="b1", parent_level=l1, position=0) + LevelTwo.objects.create(name="b2", parent_level=l1, position=1) + LevelThree.objects.create(name="c1", parent_level=l2_1, position=0) self.admin_login("user", "password") @@ -183,5 +237,5 @@ def test_user_lacks_parent_permissions_can_delete(self): self.delete_inline([0, 0, 0]) self.save_form() - l3_objs = LevelThree.objects.all().order_by('name') + l3_objs = LevelThree.objects.all().order_by("name") self.assertEqual(len(l3_objs), 0, "LevelThree inline did not delete") diff --git a/nested_admin/tests/two_deep/admin.py b/nested_admin/tests/two_deep/admin.py index 26d1738..9e5d7b2 100644 --- a/nested_admin/tests/two_deep/admin.py +++ b/nested_admin/tests/two_deep/admin.py @@ -1,18 +1,26 @@ from django.contrib import admin -from nested_admin import ( - NestedStackedInline, NestedTabularInline, NestedModelAdmin) +from nested_admin import NestedStackedInline, NestedTabularInline, NestedModelAdmin from .models import ( - StackedGroup, StackedSection, StackedItem, - TabularGroup, TabularSection, TabularItem, - SortableWithExtraRoot, SortableWithExtraChild) + StackedGroup, + StackedSection, + StackedItem, + TabularGroup, + TabularSection, + TabularItem, + SortableWithExtraRoot, + SortableWithExtraChild, +) class StackedItemInline(NestedStackedInline): model = StackedItem extra = 0 sortable_field_name = "position" - inline_classes = ("collapse", "open", ) + inline_classes = ( + "collapse", + "open", + ) class StackedSectionInline(NestedStackedInline): @@ -20,7 +28,10 @@ class StackedSectionInline(NestedStackedInline): extra = 0 sortable_field_name = "position" inlines = [StackedItemInline] - inline_classes = ("collapse", "open", ) + inline_classes = ( + "collapse", + "open", + ) @admin.register(StackedGroup) @@ -50,8 +61,11 @@ class SortableWithExtraChildInline(NestedStackedInline): model = SortableWithExtraChild extra = 2 sortable_field_name = "position" - inline_classes = ("collapse", "open", ) - sortable_excludes = ['foo'] + inline_classes = ( + "collapse", + "open", + ) + sortable_excludes = ["foo"] @admin.register(SortableWithExtraRoot) diff --git a/nested_admin/tests/two_deep/models.py b/nested_admin/tests/two_deep/models.py index c70b9f8..a64c6a4 100644 --- a/nested_admin/tests/two_deep/models.py +++ b/nested_admin/tests/two_deep/models.py @@ -1,11 +1,7 @@ -from __future__ import unicode_literals - from django.db import models from django.db.models import ForeignKey, CASCADE -from nested_admin.tests.compat import python_2_unicode_compatible -@python_2_unicode_compatible class GroupAbstract(models.Model): slug = models.CharField(max_length=128) @@ -17,7 +13,6 @@ def __str__(self): return self.slug -@python_2_unicode_compatible class SectionAbstract(models.Model): slug = models.CharField(max_length=128) @@ -33,7 +28,6 @@ def __str__(self): return "/".join(parts) -@python_2_unicode_compatible class ItemAbstract(models.Model): name = models.CharField(max_length=128) @@ -54,18 +48,18 @@ class StackedGroup(GroupAbstract): class StackedSection(SectionAbstract): - group = ForeignKey(StackedGroup, related_name='section_set', on_delete=CASCADE) + group = ForeignKey(StackedGroup, related_name="section_set", on_delete=CASCADE) class Meta: - ordering = ('group', 'position') + ordering = ("group", "position") class StackedItem(ItemAbstract): - section = ForeignKey(StackedSection, related_name='item_set', on_delete=CASCADE) - upload = models.FileField(blank=True, null=True, upload_to='foo') + section = ForeignKey(StackedSection, related_name="item_set", on_delete=CASCADE) + upload = models.FileField(blank=True, null=True, upload_to="foo") class Meta: - ordering = ('section', 'position') + ordering = ("section", "position") class TabularGroup(GroupAbstract): @@ -73,17 +67,17 @@ class TabularGroup(GroupAbstract): class TabularSection(SectionAbstract): - group = ForeignKey(TabularGroup, related_name='section_set', on_delete=CASCADE) + group = ForeignKey(TabularGroup, related_name="section_set", on_delete=CASCADE) class Meta: - ordering = ('group', 'position') + ordering = ("group", "position") class TabularItem(ItemAbstract): - section = ForeignKey(TabularSection, related_name='item_set', on_delete=CASCADE) + section = ForeignKey(TabularSection, related_name="item_set", on_delete=CASCADE) class Meta: - ordering = ('section', 'position') + ordering = ("section", "position") class SortableWithExtraRoot(models.Model): @@ -94,7 +88,7 @@ class SortableWithExtraChild(models.Model): slug = models.CharField(max_length=128) root = ForeignKey(SortableWithExtraRoot, on_delete=CASCADE) position = models.PositiveIntegerField() - foo = models.CharField(max_length=128, default='bar') + foo = models.CharField(max_length=128, default="bar") class Meta: - ordering = ('position', ) + ordering = ("position",) diff --git a/nested_admin/tests/two_deep/test_permissions.py b/nested_admin/tests/two_deep/test_permissions.py index 071f328..29890d5 100644 --- a/nested_admin/tests/two_deep/test_permissions.py +++ b/nested_admin/tests/two_deep/test_permissions.py @@ -1,6 +1,3 @@ -from unittest import SkipTest - -import django from django.contrib.auth import get_permission_codename from django.contrib.auth.models import Permission, User from django.contrib.contenttypes.models import ContentType @@ -24,33 +21,38 @@ class SeleniumTestInlinePermissions(BaseNestedAdminTestCase): @classmethod def setUpClass(cls): - if django.VERSION < (2, 1): - raise SkipTest("View permissions not available before django 2.1") - - super(SeleniumTestInlinePermissions, cls).setUpClass() + super().setUpClass() cls.section_cls, cls.item_cls = cls.nested_models def setUp(self): - super(SeleniumTestInlinePermissions, self).setUp() - self.group = StackedGroup.objects.create(pk=1, slug='group') + super().setUp() + self.group = StackedGroup.objects.create(pk=1, slug="group") self.section_a = StackedSection.objects.create( - pk=1, slug='a', group=self.group, position=0) + pk=1, slug="a", group=self.group, position=0 + ) self.section_b = StackedSection.objects.create( - pk=2, slug='b', group=self.group, position=1) + pk=2, slug="b", group=self.group, position=1 + ) self.item_a0 = StackedItem.objects.create( - pk=1, name='A 0', section=self.section_a, position=0) + pk=1, name="A 0", section=self.section_a, position=0 + ) self.item_b0 = StackedItem.objects.create( - pk=2, name='B 0', section=self.section_b, position=0) + pk=2, name="B 0", section=self.section_b, position=0 + ) self.user = User.objects.create_user( - username='permissionuser', password='secret', - email='vuser@example.com', is_staff=True) + username="permissionuser", + password="secret", + email="vuser@example.com", + is_staff=True, + ) for model_cls in [StackedGroup, StackedSection, StackedItem]: self.user.user_permissions.add( - get_perm(model_cls, get_permission_codename('view', model_cls._meta))) + get_perm(model_cls, get_permission_codename("view", model_cls._meta)) + ) - self.admin_login('permissionuser', 'secret') + self.admin_login("permissionuser", "secret") def test_view_permissions_readonly_fields(self): self.load_admin(self.group) @@ -65,7 +67,10 @@ def element_is_present(d): return d.execute_script( """return !!document.evaluate( 'count(' + arguments[0] + ')', document).numberValue""", - xpath) + xpath, + ) - self.wait_until(element_is_present, - message="Timeout waiting for element with xpath %s" % xpath) + self.wait_until( + element_is_present, + message="Timeout waiting for element with xpath %s" % xpath, + ) diff --git a/nested_admin/tests/two_deep/tests.py b/nested_admin/tests/two_deep/tests.py index 0124639..9025a78 100644 --- a/nested_admin/tests/two_deep/tests.py +++ b/nested_admin/tests/two_deep/tests.py @@ -1,26 +1,30 @@ import os import tempfile import time -from unittest import skipIf, SkipTest - -import django +from unittest import SkipTest +from selenium.webdriver.common.by import By from nested_admin.tests.base import BaseNestedAdminTestCase from .models import ( - StackedGroup, StackedSection, StackedItem, - TabularGroup, TabularSection, TabularItem, - SortableWithExtraRoot, SortableWithExtraChild) - - -class InlineAdminTestCaseMixin(object): - + StackedGroup, + StackedSection, + StackedItem, + TabularGroup, + TabularSection, + TabularItem, + SortableWithExtraRoot, + SortableWithExtraChild, +) + + +class InlineAdminTestCaseMixin: @classmethod def setUpClass(cls): - super(InlineAdminTestCaseMixin, cls).setUpClass() + super().setUpClass() cls.section_cls, cls.item_cls = cls.nested_models def test_add_section_to_empty(self): - group = self.root_model.objects.create(slug='test') + group = self.root_model.objects.create(slug="test") self.load_admin(group) @@ -30,19 +34,23 @@ def test_add_section_to_empty(self): sections = group.section_set.all() self.assertEqual(len(sections), 1) - self.assertEqual(sections[0].slug, 'test') + self.assertEqual(sections[0].slug, "test") self.assertEqual(sections[0].position, 0) def test_add_item_to_empty(self): - group = self.root_model.objects.create(slug='test') - section = self.section_cls.objects.create(slug='test', group=group, position=0) + group = self.root_model.objects.create(slug="test") + section = self.section_cls.objects.create(slug="test", group=group, position=0) self.load_admin(group) item_verbose_name = self.item_cls._meta.verbose_name.title() - with self.clickable_xpath('//a[contains(string(.), "Add another %s")]' % item_verbose_name) as el: + with self.clickable_xpath( + '//a[contains(string(.), "Add another %s")]' % item_verbose_name + ) as el: el.click() - with self.clickable_xpath('//input[@name="section_set-0-item_set-0-name"]') as el: + with self.clickable_xpath( + '//input[@name="section_set-0-item_set-0-name"]' + ) as el: el.send_keys("Test") self.save_form() @@ -53,45 +61,55 @@ def test_add_item_to_empty(self): self.assertEqual(items[0].position, 0) def test_drag_last_item_between_sections(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) - self.drag_and_drop_item(from_indexes=[1, 2], to_indexes=[0, 1], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 2], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - item_b_2 = self.item_cls.objects.get(name='B 2') - self.assertEqual(item_b_2.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_2.position, 1, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/B 2[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + item_b_2 = self.item_cls.objects.get(name="B 2") + self.assertEqual( + item_b_2.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_2.position, 1, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/B 2[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_middle_item_between_sections(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -99,133 +117,173 @@ def test_drag_middle_item_between_sections(self): self.save_form() - item_b_1 = self.item_cls.objects.get(name='B 1') - self.assertEqual(item_b_1.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_1.position, 1, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/B 1[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 2[1]']) + item_b_1 = self.item_cls.objects.get(name="B 1") + self.assertEqual( + item_b_1.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_1.position, 1, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/B 1[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 2[1]"], + ) def test_drag_middle_item_between_sections_after_adding_new_item(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) - self.add_inline(indexes=[1], name='B 3') - self.drag_and_drop_item(from_indexes=[1, 1], to_indexes=[0, 1], - screenshot_hack=True) + self.add_inline(indexes=[1], name="B 3") + self.drag_and_drop_item( + from_indexes=[1, 1], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - item_b_1 = self.item_cls.objects.get(name='B 1') - self.assertEqual(item_b_1.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_1.position, 1, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/B 1[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 2[1]', - 'group/b[1]/B 3[2]']) - - def test_drag_middle_item_between_sections_after_adding_new_item_to_other_section(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + item_b_1 = self.item_cls.objects.get(name="B 1") + self.assertEqual( + item_b_1.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_1.position, 1, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/B 1[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 2[1]", "group/b[1]/B 3[2]"], + ) + + def test_drag_middle_item_between_sections_after_adding_new_item_to_other_section( + self, + ): + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) - self.add_inline(indexes=[0], name='A 3') - self.drag_and_drop_item(from_indexes=[1, 1], to_indexes=[0, 1], - screenshot_hack=True) + self.add_inline(indexes=[0], name="A 3") + self.drag_and_drop_item( + from_indexes=[1, 1], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - item_b_1 = self.item_cls.objects.get(name='B 1') - self.assertEqual(item_b_1.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_1.position, 1, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/B 1[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]', - 'group/a[0]/A 3[4]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 2[1]']) + item_b_1 = self.item_cls.objects.get(name="B 1") + self.assertEqual( + item_b_1.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_1.position, 1, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/B 1[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + "group/a[0]/A 3[4]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 2[1]"], + ) def test_drag_new_item_between_sections(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) - self.add_inline(indexes=[1], name='B 2') + self.add_inline(indexes=[1], name="B 2") time.sleep(0.01) - self.drag_and_drop_item(from_indexes=[1, 2], to_indexes=[0, 1], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 2], to_indexes=[0, 1], screenshot_hack=True + ) self.save_form() - item_b_2 = self.item_cls.objects.get(name='B 2') - - self.assertEqual(item_b_2.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_2.position, 1, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/B 2[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + item_b_2 = self.item_cls.objects.get(name="B 2") + + self.assertEqual( + item_b_2.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_2.position, 1, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/B 2[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_delete_item(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -233,25 +291,26 @@ def test_delete_item(self): self.save_form() - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/A 1[1]', - 'group/a[0]/A 2[2]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 0[0]", "group/a[0]/A 1[1]", "group/a[0]/A 2[2]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 2[1]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 2[1]"], + ) def test_delete_section(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -259,29 +318,31 @@ def test_delete_section(self): self.save_form() - self.assertEqual(len(self.section_cls.objects.filter(slug='a')), 0, "Section was not deleted") + self.assertEqual( + len(self.section_cls.objects.filter(slug="a")), 0, "Section was not deleted" + ) - section_b = self.section_cls.objects.get(slug='b') + section_b = self.section_cls.objects.get(slug="b") - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[0]/B 0[0]', - 'group/b[0]/B 1[1]', - 'group/b[0]/B 2[2]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[0]/B 0[0]", "group/b[0]/B 1[1]", "group/b[0]/B 2[2]"], + ) def test_delete_item_undelete_section(self): """ Test that, if an item is deleted, then the section is deleted, and then the section is undeleted, that the item stays deleted. """ - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -291,50 +352,56 @@ def test_delete_item_undelete_section(self): self.save_form() - self.assertEqual(len(self.section_cls.objects.filter(slug='a')), 1, "Section should not be deleted") + self.assertEqual( + len(self.section_cls.objects.filter(slug="a")), + 1, + "Section should not be deleted", + ) - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/A 2[1]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 0[0]", "group/a[0]/A 2[1]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]', - 'group/b[1]/B 2[2]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]", "group/b[1]/B 2[2]"], + ) def test_remove_item(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) - self.add_inline(indexes=[1], name='B 2') + self.add_inline(indexes=[1], name="B 2") self.remove_inline(indexes=[1, 2]) self.save_form() - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/A 1[1]', - 'group/a[0]/A 2[2]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 0[0]", "group/a[0]/A 1[1]", "group/a[0]/A 2[2]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_item_to_empty_section(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -342,59 +409,76 @@ def test_drag_item_to_empty_section(self): self.save_form() - item_b_2 = self.item_cls.objects.get(name='B 2') - self.assertEqual(item_b_2.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_2.position, 0, "item was not moved to the correct position") + item_b_2 = self.item_cls.objects.get(name="B 2") + self.assertEqual( + item_b_2.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_2.position, 0, "item was not moved to the correct position" + ) - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], - ['group/a[0]/B 2[0]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/B 2[0]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_item_to_first_position(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) - self.drag_and_drop_item(from_indexes=[1, 2], to_indexes=[0, 0], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 2], to_indexes=[0, 0], screenshot_hack=True + ) self.save_form() - item_b_2 = self.item_cls.objects.get(name='B 2') - self.assertEqual(item_b_2.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_2.position, 0, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/B 2[0]', - 'group/a[0]/A 0[1]', - 'group/a[0]/A 1[2]', - 'group/a[0]/A 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + item_b_2 = self.item_cls.objects.get(name="B 2") + self.assertEqual( + item_b_2.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_2.position, 0, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/B 2[0]", + "group/a[0]/A 0[1]", + "group/a[0]/A 1[2]", + "group/a[0]/A 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_item_to_last_position(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -402,30 +486,39 @@ def test_drag_item_to_last_position(self): self.save_form() - item_b_2 = self.item_cls.objects.get(name='B 2') - self.assertEqual(item_b_2.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_2.position, 3, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/A 1[1]', - 'group/a[0]/A 2[2]', - 'group/a[0]/B 2[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 0[0]', - 'group/b[1]/B 1[1]']) + item_b_2 = self.item_cls.objects.get(name="B 2") + self.assertEqual( + item_b_2.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_2.position, 3, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/A 1[1]", + "group/a[0]/A 2[2]", + "group/a[0]/B 2[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_item_from_last_position(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) - self.item_cls.objects.create(name='B 2', section=section_b, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) + self.item_cls.objects.create(name="B 2", section=section_b, position=2) self.load_admin(group) @@ -442,26 +535,33 @@ def test_drag_item_from_last_position(self): self.assertEqual(section_b.position, 0, "section b did not change position") self.assertEqual(section_a.position, 1, "section a did not change position") - item_a_2 = self.item_cls.objects.get(name='A 2') + item_a_2 = self.item_cls.objects.get(name="A 2") self.assertEqual(item_a_2.section, section_b, "item is in incorrect section") - self.assertEqual(item_a_2.position, 3, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[1]/A 0[0]', - 'group/a[1]/A 1[1]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[0]/B 0[0]', - 'group/b[0]/B 1[1]', - 'group/b[0]/B 2[2]', - 'group/b[0]/A 2[3]']) + self.assertEqual( + item_a_2.position, 3, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[1]/A 0[0]", "group/a[1]/A 1[1]"], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + [ + "group/b[0]/B 0[0]", + "group/b[0]/B 1[1]", + "group/b[0]/B 2[2]", + "group/b[0]/A 2[3]", + ], + ) def test_drag_item_to_new_empty_section(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='A 2', section=section_a, position=2) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="A 2", section=section_a, position=2) self.load_admin(group) @@ -470,29 +570,37 @@ def test_drag_item_to_new_empty_section(self): self.save_form() - item_a_2 = self.item_cls.objects.get(name='A 2') - section_b = self.section_cls.objects.get(slug='b') - self.assertEqual(item_a_2.section, section_b, "item was not moved to the correct section") - self.assertEqual(item_a_2.position, 0, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], - ['group/a[0]/A 0[0]', 'group/a[0]/A 1[1]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], - ['group/b[1]/A 2[0]']) + item_a_2 = self.item_cls.objects.get(name="A 2") + section_b = self.section_cls.objects.get(slug="b") + self.assertEqual( + item_a_2.section, section_b, "item was not moved to the correct section" + ) + self.assertEqual( + item_a_2.position, 0, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 0[0]", "group/a[0]/A 1[1]"], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/A 2[0]"], + ) def test_position_update_bug(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) self.load_admin(group) - self.add_inline(indexes=[0], name='A 0') - self.add_inline(indexes=[0], name='A 1') - self.add_inline(indexes=[0], name='A 2') + self.add_inline(indexes=[0], name="A 0") + self.add_inline(indexes=[0], name="A 1") + self.add_inline(indexes=[0], name="A 2") # Move to second position of the first section self.drag_and_drop_item(from_indexes=[1, 0], to_indexes=[0, 1]) @@ -500,34 +608,45 @@ def test_position_update_bug(self): # Move to the last position of the first section self.drag_and_drop_item(from_indexes=[0, 1], to_indexes=[0, 3]) - position_selector = self.get_form_field_selector('position', indexes=[0, 3]) + position_selector = self.get_form_field_selector("position", indexes=[0, 3]) def check_position_is_correct(d): val = d.execute_script('return $("%s").val()' % position_selector) - return val == '3' + return val == "3" self.wait_until( check_position_is_correct, - message="Timeout waiting for position to update to correct value") + message="Timeout waiting for position to update to correct value", + ) self.save_form() - item_b_0 = self.item_cls.objects.get(name='B 0') - self.assertEqual(item_b_0.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_0.position, 3, "item was not moved to the correct position") - - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 0[0]', - 'group/a[0]/A 1[1]', - 'group/a[0]/A 2[2]', - 'group/a[0]/B 0[3]']) - - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], []) + item_b_0 = self.item_cls.objects.get(name="B 0") + self.assertEqual( + item_b_0.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_0.position, 3, "item was not moved to the correct position" + ) + + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + [ + "group/a[0]/A 0[0]", + "group/a[0]/A 1[1]", + "group/a[0]/A 2[2]", + "group/a[0]/B 0[3]", + ], + ) + + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], [] + ) def test_drag_existing_item_to_new_section_and_back(self): - group = self.root_model.objects.create(slug='test') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) + group = self.root_model.objects.create(slug="test") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) self.load_admin(group) @@ -539,12 +658,14 @@ def test_drag_existing_item_to_new_section_and_back(self): self.assertEqual(len(self.section_cls.objects.all()), 2, "Save failed") - item_a_0 = self.item_cls.objects.get(name='A 0') + item_a_0 = self.item_cls.objects.get(name="A 0") self.assertEqual(item_a_0.section, section_a, "Item is in the wrong section") self.assertEqual(item_a_0.position, 0, "Item has the wrong position") - def test_drag_item_create_invalid_new_item_then_drag_back_after_validation_error_removing_invalid_item(self): + def test_drag_item_create_invalid_new_item_then_drag_back_after_validation_error_removing_invalid_item( + self, + ): """ Tests regression of a scenario after encountering a validation error. @@ -557,13 +678,13 @@ def test_drag_item_create_invalid_new_item_then_drag_back_after_validation_error 6. Remove the invalid item 7. Save, get a 500 Internal Server Error """ - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) @@ -574,62 +695,71 @@ def test_drag_item_create_invalid_new_item_then_drag_back_after_validation_error # We need to manually set the position to trigger the validation error, # otherwise it will be skipped as an empty inline on save - self.set_field('position', '1', indexes=[1, 1]) + self.set_field("position", "1", indexes=[1, 1]) # Save self.save_form() - self.drag_and_drop_item(from_indexes=[1, 1], to_indexes=[0, 0], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 1], to_indexes=[0, 0], screenshot_hack=True + ) # Remove invalid item self.remove_inline(indexes=[0, 0]) # Make a change to test whether save succeeds - self.set_field("name", 'A 0_changed', indexes=[0, 0]) + self.set_field("name", "A 0_changed", indexes=[0, 0]) self.save_form() item_a_0 = self.item_cls.objects.get(section=section_a, position=0) - self.assertEqual(item_a_0.name, 'A 0_changed', 'Save failed') + self.assertEqual(item_a_0.name, "A 0_changed", "Save failed") def test_swap_first_two_items_between_sections(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) - self.drag_and_drop_item(from_indexes=[1, 0], to_indexes=[0, 0], - screenshot_hack=True) - self.drag_and_drop_item(from_indexes=[0, 1], to_indexes=[1, 0], - screenshot_hack=True) + self.drag_and_drop_item( + from_indexes=[1, 0], to_indexes=[0, 0], screenshot_hack=True + ) + self.drag_and_drop_item( + from_indexes=[0, 1], to_indexes=[1, 0], screenshot_hack=True + ) self.save_form() - item_b_0 = self.item_cls.objects.get(name='B 0') - self.assertEqual(item_b_0.section, section_a, "item was not moved to the correct section") - self.assertEqual(item_b_0.position, 0, "item was not moved to the correct position") + item_b_0 = self.item_cls.objects.get(name="B 0") + self.assertEqual( + item_b_0.section, section_a, "item was not moved to the correct section" + ) + self.assertEqual( + item_b_0.position, 0, "item was not moved to the correct position" + ) - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/B 0[0]', - 'group/a[0]/A 1[1]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/B 0[0]", "group/a[0]/A 1[1]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/A 0[0]', - 'group/b[1]/B 1[1]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/A 0[0]", "group/b[1]/B 1[1]"], + ) def test_drag_first_item_to_new_section(self): """ Test dragging the first of several items in a pre-existing section into a newly created section. """ - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) self.load_admin(group) @@ -640,17 +770,21 @@ def test_drag_first_item_to_new_section(self): self.assertEqual(len(self.section_cls.objects.all()), 2, "Save failed") - section_b = self.section_cls.objects.get(slug='b') - item_a_0 = self.item_cls.objects.get(name='A 0') + section_b = self.section_cls.objects.get(slug="b") + item_a_0 = self.item_cls.objects.get(name="A 0") self.assertEqual(item_a_0.section, section_b, "Item is in the wrong section") self.assertEqual(item_a_0.position, 0, "Item has the wrong position") - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 1[0]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 1[0]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/A 0[0]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/A 0[0]"], + ) def test_drag_first_item_to_new_section_after_removing_item(self): """ @@ -658,16 +792,16 @@ def test_drag_first_item_to_new_section_after_removing_item(self): a newly created section after having added two items and then removing one of those items. """ - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='A 1', section=section_a, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="A 1", section=section_a, position=1) self.load_admin(group) self.add_inline(slug="b") - self.add_inline(indexes=[1], name='B 0') - self.add_inline(indexes=[1], name='B 1') + self.add_inline(indexes=[1], name="B 0") + self.add_inline(indexes=[1], name="B 1") self.remove_inline(indexes=[1, 0]) self.drag_and_drop_item(from_indexes=[0, 0], to_indexes=[1, 0]) @@ -675,21 +809,27 @@ def test_drag_first_item_to_new_section_after_removing_item(self): self.assertEqual(len(self.section_cls.objects.all()), 2, "Save failed") - section_b = self.section_cls.objects.get(slug='b') - item_a_0 = self.item_cls.objects.get(name='A 0') - item_a_1 = self.item_cls.objects.get(name='A 1') - item_b_1 = self.item_cls.objects.get(name='B 1') + section_b = self.section_cls.objects.get(slug="b") + item_a_0 = self.item_cls.objects.get(name="A 0") + item_a_1 = self.item_cls.objects.get(name="A 1") + item_b_1 = self.item_cls.objects.get(name="B 1") - self.assertNotEqual(item_a_0.section, section_a, "A0 did not move to new section") + self.assertNotEqual( + item_a_0.section, section_a, "A0 did not move to new section" + ) self.assertEqual(item_a_0.position, 0, "A0 has the wrong position") self.assertEqual(item_a_1.position, 0, "A1 has the wrong position") self.assertEqual(item_b_1.position, 1, "B1 has the wrong position") - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/A 1[0]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/A 1[0]"], + ) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/A 0[0]', 'group/b[1]/B 1[1]']) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/A 0[0]", "group/b[1]/B 1[1]"], + ) def test_add_remove_items_in_new_section_dragging_existing_items(self): """ @@ -711,41 +851,47 @@ def test_add_remove_items_in_new_section_dragging_existing_items(self): Outcome with bug: The item has not moved. """ - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) self.load_admin(group) self.add_inline(slug="b") - self.add_inline(indexes=[1], name='B 0') - self.add_inline(indexes=[1], name='B 1') - self.add_inline(indexes=[1], name='B 2') + self.add_inline(indexes=[1], name="B 0") + self.add_inline(indexes=[1], name="B 1") + self.add_inline(indexes=[1], name="B 2") self.remove_inline(indexes=[1, 0]) self.drag_and_drop_item(from_indexes=[0, 0], to_indexes=[1, 0]) self.remove_inline(indexes=[1, 1]) self.save_form() - section_b = self.section_cls.objects.get(slug='b') - item_a_0 = self.item_cls.objects.get(name='A 0') - item_b_2 = self.item_cls.objects.get(name='B 2') + section_b = self.section_cls.objects.get(slug="b") + item_a_0 = self.item_cls.objects.get(name="A 0") + item_b_2 = self.item_cls.objects.get(name="B 2") - self.assertNotEqual(item_a_0.section, section_a, "A0 did not move to new section") + self.assertNotEqual( + item_a_0.section, section_a, "A0 did not move to new section" + ) self.assertEqual(item_a_0.position, 0, "A0 has the wrong position") self.assertEqual(item_b_2.position, 1, "B2 has the wrong position") - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], []) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/A 0[0]', 'group/b[1]/B 2[1]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], [] + ) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/A 0[0]", "group/b[1]/B 2[1]"], + ) def test_delete_section_after_dragging_item_away(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) @@ -759,16 +905,18 @@ def test_delete_section_after_dragging_item_away(self): self.assertNotEqual(len(self.section_cls.objects.all()), 2, "Save failed") - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/B 0[0]', 'group/a[0]/A 0[1]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/B 0[0]", "group/a[0]/A 0[1]"], + ) def test_delete_undelete_section_after_dragging_item_away(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - section_b = self.section_cls.objects.create(slug='b', group=group, position=1) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) - self.item_cls.objects.create(name='B 0', section=section_b, position=0) - self.item_cls.objects.create(name='B 1', section=section_b, position=1) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + section_b = self.section_cls.objects.create(slug="b", group=group, position=1) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) + self.item_cls.objects.create(name="B 0", section=section_b, position=0) + self.item_cls.objects.create(name="B 1", section=section_b, position=1) self.load_admin(group) @@ -783,15 +931,19 @@ def test_delete_undelete_section_after_dragging_item_away(self): self.assertEqual(len(self.section_cls.objects.all()), 2) - self.assertEqual(["%s" % i for i in section_a.item_set.all().order_by('position')], [ - 'group/a[0]/B 0[0]', 'group/a[0]/A 0[1]']) - self.assertEqual(["%s" % i for i in section_b.item_set.all().order_by('position')], [ - 'group/b[1]/B 1[0]']) + self.assertEqual( + ["%s" % i for i in section_a.item_set.all().order_by("position")], + ["group/a[0]/B 0[0]", "group/a[0]/A 0[1]"], + ) + self.assertEqual( + ["%s" % i for i in section_b.item_set.all().order_by("position")], + ["group/b[1]/B 1[0]"], + ) def test_drag_into_new_section_after_adding_and_removing_preceding_section(self): - group = self.root_model.objects.create(slug='group') - section_a = self.section_cls.objects.create(slug='a', group=group, position=0) - self.item_cls.objects.create(name='A 0', section=section_a, position=0) + group = self.root_model.objects.create(slug="group") + section_a = self.section_cls.objects.create(slug="a", group=group, position=0) + self.item_cls.objects.create(name="A 0", section=section_a, position=0) self.load_admin(group) @@ -802,12 +954,18 @@ def test_drag_into_new_section_after_adding_and_removing_preceding_section(self) self.save_form() - self.assertEqual(len(self.section_cls.objects.all()), 2, "Save failed (new section wasn't added)") + self.assertEqual( + len(self.section_cls.objects.all()), + 2, + "Save failed (new section wasn't added)", + ) - item_a0 = self.item_cls.objects.get(name='A 0') - section_c = self.section_cls.objects.get(slug='c') + item_a0 = self.item_cls.objects.get(name="A 0") + section_c = self.section_cls.objects.get(slug="c") - self.assertEqual(item_a0.section, section_c, "Item was not moved to new section") + self.assertEqual( + item_a0.section, section_c, "Item was not moved to new section" + ) class TestStackedInlineAdmin(InlineAdminTestCaseMixin, BaseNestedAdminTestCase): @@ -818,45 +976,55 @@ class TestStackedInlineAdmin(InlineAdminTestCaseMixin, BaseNestedAdminTestCase): def test_add_item_inline_label_update(self): if self.has_grappelli: raise SkipTest("Test does not apply if using django-grappelli") - group = self.root_model.objects.create(slug='test') - self.section_cls.objects.create(slug='test', group=group, position=0) + group = self.root_model.objects.create(slug="test") + self.section_cls.objects.create(slug="test", group=group, position=0) self.load_admin(group) item_verbose_name = self.item_cls._meta.verbose_name.title() - with self.clickable_xpath('//a[contains(string(.), "Add another %s")]' % item_verbose_name) as el: + with self.clickable_xpath( + '//a[contains(string(.), "Add another %s")]' % item_verbose_name + ) as el: el.click() - with self.clickable_xpath('//input[@name="section_set-0-item_set-0-name"]') as el: + with self.clickable_xpath( + '//input[@name="section_set-0-item_set-0-name"]' + ) as el: el.send_keys("Test 1") - with self.clickable_xpath('//a[contains(string(.), "Add another %s")]' % item_verbose_name) as el: + with self.clickable_xpath( + '//a[contains(string(.), "Add another %s")]' % item_verbose_name + ) as el: el.click() - with self.clickable_xpath('//input[@name="section_set-0-item_set-0-name"]') as el: + with self.clickable_xpath( + '//input[@name="section_set-0-item_set-0-name"]' + ) as el: el.send_keys("Test 2") - inline_label = self.get_item([0, 1]).find_element_by_class_name('inline_label') - self.assertEqual(inline_label.text, '#2') + inline_label = self.get_item([0, 1]).find_element(By.CLASS_NAME, "inline_label") + self.assertEqual(inline_label.text, "#2") def test_upload_file(self): - group = self.root_model.objects.create(slug='group') + group = self.root_model.objects.create(slug="group") self.load_admin(group) self.add_inline(slug="a") - self.add_inline(indexes=[0], name='A 0') + self.add_inline(indexes=[0], name="A 0") fd, path = tempfile.mkstemp() try: - with os.fdopen(fd, 'w') as tmp: - tmp.write('Test file. Used as a payload for testing file uploads.') - with self.clickable_xpath('//input[@name="section_set-0-item_set-0-upload"]') as el: + with os.fdopen(fd, "w") as tmp: + tmp.write("Test file. Used as a payload for testing file uploads.") + with self.clickable_xpath( + '//input[@name="section_set-0-item_set-0-upload"]' + ) as el: el.send_keys(path) self.save_form() finally: os.remove(path) - item_a_0 = self.item_cls.objects.get(name='A 0') - upload_name = 'foo/' + os.path.basename(path) + item_a_0 = self.item_cls.objects.get(name="A 0") + upload_name = "foo/" + os.path.basename(path) - self.assertEqual(item_a_0.upload.name, upload_name, 'File upload failed') + self.assertEqual(item_a_0.upload.name, upload_name, "File upload failed") class TestTabularInlineAdmin(InlineAdminTestCaseMixin, BaseNestedAdminTestCase): @@ -868,37 +1036,43 @@ class TestTabularInlineAdmin(InlineAdminTestCaseMixin, BaseNestedAdminTestCase): class TestSortablesWithExtra(BaseNestedAdminTestCase): root_model = SortableWithExtraRoot - nested_models = (SortableWithExtraChild, ) + nested_models = (SortableWithExtraChild,) def test_blank_extra_inlines_validation(self): - root = self.root_model.objects.create(slug='a') + root = self.root_model.objects.create(slug="a") self.load_admin(root) - self.set_field('slug', 'b') + self.set_field("slug", "b") self.save_form() validation_errors = self.selenium.execute_script( - "return $('ul.errorlist li').length") + "return $('ul.errorlist li').length" + ) - self.assertEqual(validation_errors, 0, "Unexpected validation errors encountered") + self.assertEqual( + validation_errors, 0, "Unexpected validation errors encountered" + ) def test_blank_extra_inlines_validation_with_change(self): - root = self.root_model.objects.create(slug='a') + root = self.root_model.objects.create(slug="a") self.load_admin(root) - self.set_field('slug', 'b') - self.set_field('slug', 'a', indexes=[0]) + self.set_field("slug", "b") + self.set_field("slug", "a", indexes=[0]) self.save_form() validation_errors = self.selenium.execute_script( - "return $('ul.errorlist li').length") + "return $('ul.errorlist li').length" + ) - self.assertEqual(validation_errors, 0, "Unexpected validation errors encountered") + self.assertEqual( + validation_errors, 0, "Unexpected validation errors encountered" + ) # refetch from the database root = self.root_model.objects.get(pk=root.pk) - self.assertEqual(root.slug, 'b', "Root slug did not change") + self.assertEqual(root.slug, "b", "Root slug did not change") children = self.nested_models[0].objects.all() diff --git a/nested_admin/tests/urls.py b/nested_admin/tests/urls.py index 74bc57b..83d9719 100644 --- a/nested_admin/tests/urls.py +++ b/nested_admin/tests/urls.py @@ -1,5 +1,6 @@ from django.conf import settings from django.contrib import admin + try: from django.urls import re_path, include except ImportError: @@ -7,13 +8,13 @@ # Explicitly import to register the admins for the test models for app in settings.INSTALLED_APPS: - if app.startswith('nested_admin.tests.'): + if app.startswith("nested_admin.tests."): __import__("%s.admin" % app) urlpatterns = [ - re_path(r'^_nesting/', include('nested_admin.urls')), - re_path(r'^admin/', admin.site.urls), + re_path(r"^_nesting/", include("nested_admin.urls")), + re_path(r"^admin/", admin.site.urls), ] try: diff --git a/nested_admin/tests/utils.py b/nested_admin/tests/utils.py index 150ab00..5258ec1 100644 --- a/nested_admin/tests/utils.py +++ b/nested_admin/tests/utils.py @@ -1,11 +1,5 @@ from collections import namedtuple -try: - from collections.abc import Sequence -except ImportError: - from collections import Sequence - -import six -from nested_admin.tests.compat import python_2_unicode_compatible +from collections.abc import Sequence def xpath_cls(classname): @@ -13,11 +7,15 @@ def xpath_cls(classname): def xpath_item(model_name=None): - xpath_item_predicate = 'not(contains(@class, "-drag")) and not(contains(@class, "thead"))' - expr = "%s and %s" % (xpath_cls('djn-item'), xpath_item_predicate) + xpath_item_predicate = ( + 'not(contains(@class, "-drag")) and not(contains(@class, "thead"))' + ) + expr = "{} and {}".format(xpath_cls("djn-item"), xpath_item_predicate) if model_name: - expr += (' and (@data-inline-model="%s" or %s)' - % (model_name, xpath_cls("djn-dynamic-form-%s" % model_name))) + expr += ' and (@data-inline-model="%s" or %s)' % ( + model_name, + xpath_cls("djn-dynamic-form-%s" % model_name), + ) return expr @@ -26,23 +24,24 @@ def is_sequence(o): def is_integer(o): - return isinstance(o, six.integer_types) + return isinstance(o, int) def is_str(o): - return isinstance(o, six.string_types) + return isinstance(o, str) -Position = namedtuple('Position', ['x', 'y']) +Position = namedtuple("Position", ["x", "y"]) -class Size(namedtuple('Size', ['width', 'height'])): +class Size(namedtuple("Size", ["width", "height"])): w = property(lambda self: self.width) h = property(lambda self: self.height) -class Rect(namedtuple('Rect', [ - 'left', 'top', 'right', 'bottom', 'width', 'height', 'visible'])): +class Rect( + namedtuple("Rect", ["left", "top", "right", "bottom", "width", "height", "visible"]) +): x = property(lambda self: self.left) y = property(lambda self: self.top) r = property(lambda self: self.right) @@ -51,23 +50,21 @@ class Rect(namedtuple('Rect', [ h = property(lambda self: self.height) -@python_2_unicode_compatible -class ElementRect(object): - +class ElementRect: def __init__(self, element, aliases=None): default_aliases = { - 't': 'top', - 'l': 'left', - 'x': 'left', - 'y': 'top', - 'w': 'width', - 'h': 'height', - 'r': 'right', - 'b': 'bottom', + "t": "top", + "l": "left", + "x": "left", + "y": "top", + "w": "width", + "h": "height", + "r": "right", + "b": "bottom", } aliases = dict(default_aliases, **(aliases or {})) self.alias_map = {} - for k, v in six.iteritems(aliases): + for k, v in aliases.items(): self.alias_map.setdefault(v, []) self.alias_map[v].append(k) @@ -76,7 +73,8 @@ def __init__(self, element, aliases=None): self.refresh() def refresh(self): - rect_dict = (self.selenium.execute_script(""" + rect_dict = self.selenium.execute_script( + """ return (function(e, w, de) { var r = e.getBoundingClientRect(), wh = (w.innerHeight || de.clientHeight), @@ -93,11 +91,13 @@ def refresh(self): bottom: r.bottom }; })(arguments[0], window, document.documentElement) - """, self._element)) + """, + self._element, + ) self.rect = Rect(**rect_dict) - for k, v in six.iteritems(rect_dict): + for k, v in rect_dict.items(): setattr(self, k, v) - for alias in (self.alias_map.get(k) or []): + for alias in self.alias_map.get(k) or []: setattr(self, alias, v) def __str__(self): @@ -109,6 +109,4 @@ def __repr__(self): def ensure_element_is_in_view(element): if not ElementRect(element).visible: - element.parent.execute_script( - 'arguments[0].scrollIntoView()', - element) + element.parent.execute_script("arguments[0].scrollIntoView()", element) diff --git a/package-lock.json b/package-lock.json index 62cb3eb..84ab8a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,10256 @@ { "name": "django-nested-admin", + "lockfileVersion": 2, "requires": true, - "lockfileVersion": 1, + "packages": { + "": { + "name": "django-nested-admin", + "license": "BSD-2-Clause", + "devDependencies": { + "@babel/cli": "^7.16.0", + "@babel/core": "^7.16.5", + "@babel/eslint-parser": "^7.19.1", + "@babel/plugin-transform-runtime": "^7.16.5", + "@babel/preset-env": "^7.16.5", + "@babel/register": "^7.16.5", + "babel-loader": "^8.2.3", + "babel-plugin-istanbul": "^6.1.1", + "babel-plugin-module-resolver": "^4.1.0", + "codecov": "^3.8.3", + "core-js": "^2.6.12", + "css-loader": "^6.5.1", + "eslint": "^7.32.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-prettier": "^4.2.1", + "mini-css-extract-plugin": "^2.4.5", + "node-sass": "^7.0.0", + "nyc": "^15.1.0", + "pixelmatch": "^5.2.1", + "postcss-loader": "^6.2.1", + "postcss-preset-env": "^7.0.2", + "postcss-scss": "^4.0.5", + "prettier": "^2.7.1", + "sass-loader": "^12.4.0", + "style-loader": "^3.3.1", + "stylelint": "^14.13.0", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-recommended-scss": "^7.0.0", + "stylelint-prettier": "^2.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.1", + "webpack-merge": "^5.8.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@babel/cli": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.16.0.tgz", + "integrity": "sha512-WLrM42vKX/4atIoQB+eb0ovUof53UUvecb4qGjU2PDDWRiZr50ZpiV8NpcLo7iSxeGYrRG0Mqembsa+UrTAV6Q==", + "dev": true, + "dependencies": { + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "bin": { + "babel": "bin/babel.js", + "babel-external-helpers": "bin/babel-external-helpers.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "optionalDependencies": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", + "chokidar": "^3.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", + "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.5.tgz", + "integrity": "sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helpers": "^7.16.5", + "@babel/parser": "^7.16.5", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.5", + "@babel/types": "^7.16.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz", + "integrity": "sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz", + "integrity": "sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.5.tgz", + "integrity": "sha512-3JEA9G5dmmnIWdzaT9d0NmFRgYnWUThLsDaL7982H0XqqWr56lRrsmwheXFMjR+TMl7QMBb6mzy9kvgr1lRLUA==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.0", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", + "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.0", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.5.tgz", + "integrity": "sha512-NEohnYA7mkB8L5JhU7BLwcBdU3j83IziR9aseMueWGeAjblbul3zzb8UvJ3a1zuBiqCMObzCJHFqKIQE6hTVmg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-member-expression-to-functions": "^7.16.5", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.5", + "@babel/helper-split-export-declaration": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz", + "integrity": "sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "regexpu-core": "^4.7.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz", + "integrity": "sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz", + "integrity": "sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz", + "integrity": "sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", + "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", + "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", + "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.5.tgz", + "integrity": "sha512-7fecSXq7ZrLE+TWshbGT+HyCLkxloWNhTbU2QM1NTI/tDqyf0oZiMcEfYtDuUDCo528EOlt39G1rftea4bRZIw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz", + "integrity": "sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-simple-access": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.5", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz", + "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz", + "integrity": "sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.5.tgz", + "integrity": "sha512-X+aAJldyxrOmN9v3FKp+Hu1NO69VWgYgDGq6YDykwRPzxs5f2N+X988CBXS7EQahDU+Vpet5QYMqLk+nsp+Qxw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-wrap-function": "^7.16.5", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.5.tgz", + "integrity": "sha512-ao3seGVa/FZCMCCNDuBcqnBFSbdr8N2EW35mzojx3TwfIbdPmNK+JV6+2d5bR0Z71W5ocLnQp9en/cTF7pBJiQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-member-expression-to-functions": "^7.16.5", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/traverse": "^7.16.5", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", + "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", + "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.5.tgz", + "integrity": "sha512-2J2pmLBqUqVdJw78U0KPNdeE2qeuIyKoG4mKV7wAq3mc4jJG282UgjZw4ZYDnqiWQuS3Y3IYdF/AQ6CpyBV3VA==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.5", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.5.tgz", + "integrity": "sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.5", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.15.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.16.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.6.tgz", + "integrity": "sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz", + "integrity": "sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz", + "integrity": "sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.5.tgz", + "integrity": "sha512-C/FX+3HNLV6sz7AqbTQqEo1L9/kfrKjxcVtgyBCmvIgOjvuBVUWooDoi7trsLxOzCEo5FccjRvKHkfDsJFZlfA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.5.tgz", + "integrity": "sha512-pJD3HjgRv83s5dv1sTnDbZOaTjghKEz8KUn1Kbh2eAIRhGuyQ1XSeI4xVXU3UlIEVA3DAyIdxqT1eRn7Wcn55A==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.5.tgz", + "integrity": "sha512-EEFzuLZcm/rNJ8Q5krK+FRKdVkd6FjfzT9tuSZql9sQn64K0hHA2KLJ0DqVot9/iV6+SsuadC5yI39zWnm+nmQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.5.tgz", + "integrity": "sha512-P05/SJZTTvHz79LNYTF8ff5xXge0kk5sIIWAypcWgX4BTRUgyHc8wRxJ/Hk+mU0KXldgOOslKaeqnhthcDJCJQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.5.tgz", + "integrity": "sha512-i+sltzEShH1vsVydvNaTRsgvq2vZsfyrd7K7vPLUU/KgS0D5yZMe6uipM0+izminnkKrEfdUnz7CxMRb6oHZWw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.5.tgz", + "integrity": "sha512-QQJueTFa0y9E4qHANqIvMsuxM/qcLQmKttBACtPCQzGUEizsXDACGonlPiSwynHfOa3vNw0FPMVvQzbuXwh4SQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.5.tgz", + "integrity": "sha512-xqibl7ISO2vjuQM+MzR3rkd0zfNWltk7n9QhaD8ghMmMceVguYrNDt7MikRyj4J4v3QehpnrU8RYLnC7z/gZLA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.5.tgz", + "integrity": "sha512-YwMsTp/oOviSBhrjwi0vzCUycseCYwoXnLiXIL3YNjHSMBHicGTz7GjVU/IGgz4DtOEXBdCNG72pvCX22ehfqg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.5.tgz", + "integrity": "sha512-DvB9l/TcsCRvsIV9v4jxR/jVP45cslTVC0PMVHvaJhhNuhn2Y1SOhCSFlPK777qLB5wb8rVDaNoqMTyOqtY5Iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.5.tgz", + "integrity": "sha512-UEd6KpChoyPhCoE840KRHOlGhEZFutdPDMGj+0I56yuTTOaT51GzmnEl/0uT41fB/vD2nT+Pci2KjezyE3HmUw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.5.tgz", + "integrity": "sha512-ihCMxY1Iljmx4bWy/PIMJGXN4NS4oUj1MKynwO07kiKms23pNvIn1DMB92DNB2R0EA882sw0VXIelYGdtF7xEQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.5.tgz", + "integrity": "sha512-kzdHgnaXRonttiTfKYnSVafbWngPPr2qKw9BWYBESl91W54e+9R5pP70LtWxV56g0f05f/SQrwHYkfvbwcdQ/A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.5.tgz", + "integrity": "sha512-+yFMO4BGT3sgzXo+lrq7orX5mAZt57DwUK6seqII6AcJnJOIhBJ8pzKH47/ql/d426uQ7YhN8DpUFirQzqYSUA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.5.tgz", + "integrity": "sha512-+YGh5Wbw0NH3y/E5YMu6ci5qTDmAEVNoZ3I54aB6nVEOZ5BQ7QJlwKq5pYVucQilMByGn/bvX0af+uNaPRCabA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-create-class-features-plugin": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.5.tgz", + "integrity": "sha512-s5sKtlKQyFSatt781HQwv1hoM5BQ9qRH30r+dK56OLDsHmV74mzwJNX7R1yMuE7VZKG5O6q/gmOGSAO6ikTudg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.5.tgz", + "integrity": "sha512-8bTHiiZyMOyfZFULjsCnYOWG059FVMes0iljEHSfARhNgFfpsqE92OrCffv3veSw9rwMkYcFe9bj0ZoXU2IGtQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.5.tgz", + "integrity": "sha512-TMXgfioJnkXU+XRoj7P2ED7rUm5jbnDWwlCuFVTpQboMfbSya5WrmubNBAMlk7KXvywpo8rd8WuYZkis1o2H8w==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-remap-async-to-generator": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.5.tgz", + "integrity": "sha512-BxmIyKLjUGksJ99+hJyL/HIxLIGnLKtw772zYDER7UuycDZ+Xvzs98ZQw6NGgM2ss4/hlFAaGiZmMNKvValEjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.5.tgz", + "integrity": "sha512-JxjSPNZSiOtmxjX7PBRBeRJTUKTyJ607YUYeT0QJCNdsedOe+/rXITjP08eG8xUpsLfPirgzdCFN+h0w6RI+pQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.5.tgz", + "integrity": "sha512-DzJ1vYf/7TaCYy57J3SJ9rV+JEuvmlnvvyvYKFbk5u46oQbBvuB9/0w+YsVsxkOv8zVWKpDmUoj4T5ILHoXevA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5", + "@babel/helper-split-export-declaration": "^7.16.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.5.tgz", + "integrity": "sha512-n1+O7xtU5lSLraRzX88CNcpl7vtGdPakKzww74bVwpAIRgz9JVLJJpOLb0uYqcOaXVM0TL6X0RVeIJGD2CnCkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.5.tgz", + "integrity": "sha512-GuRVAsjq+c9YPK6NeTkRLWyQskDC099XkBSVO+6QzbnOnH2d/4mBVXYStaPrZD3dFRfg00I6BFJ9Atsjfs8mlg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.5.tgz", + "integrity": "sha512-iQiEMt8Q4/5aRGHpGVK2Zc7a6mx7qEAO7qehgSug3SDImnuMzgmm/wtJALXaz25zUj1PmnNHtShjFgk4PDx4nw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.5.tgz", + "integrity": "sha512-81tijpDg2a6I1Yhj4aWY1l3O1J4Cg/Pd7LfvuaH2VVInAkXtzibz9+zSPdUM1WvuUi128ksstAP0hM5w48vQgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.5.tgz", + "integrity": "sha512-12rba2HwemQPa7BLIKCzm1pT2/RuQHtSFHdNl41cFiC6oi4tcrp7gjB07pxQvFpcADojQywSjblQth6gJyE6CA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.5.tgz", + "integrity": "sha512-+DpCAJFPAvViR17PIMi9x2AE34dll5wNlXO43wagAX2YcRGgEVHCNFC4azG85b4YyyFarvkc/iD5NPrz4Oneqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.5.tgz", + "integrity": "sha512-Fuec/KPSpVLbGo6z1RPw4EE1X+z9gZk1uQmnYy7v4xr4TO9p41v1AoUuXEtyqAI7H+xNJYSICzRqZBhDEkd3kQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.5.tgz", + "integrity": "sha512-B1j9C/IfvshnPcklsc93AVLTrNVa69iSqztylZH6qnmiAsDDOmmjEYqOm3Ts2lGSgTSywnBNiqC949VdD0/gfw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.5.tgz", + "integrity": "sha512-d57i3vPHWgIde/9Y8W/xSFUndhvhZN5Wu2TjRrN1MVz5KzdUihKnfDVlfP1U7mS5DNj/WHHhaE4/tTi4hIyHwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.5.tgz", + "integrity": "sha512-oHI15S/hdJuSCfnwIz+4lm6wu/wBn7oJ8+QrkzPPwSFGXk8kgdI/AIKcbR/XnD1nQVMg/i6eNaXpszbGuwYDRQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.5.tgz", + "integrity": "sha512-ABhUkxvoQyqhCWyb8xXtfwqNMJD7tx+irIRnUh6lmyFud7Jln1WzONXKlax1fg/ey178EXbs4bSGNd6PngO+SQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-simple-access": "^7.16.0", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.5.tgz", + "integrity": "sha512-53gmLdScNN28XpjEVIm7LbWnD/b/TpbwKbLk6KV4KqC9WyU6rq1jnNmVG6UgAdQZVVGZVoik3DqHNxk4/EvrjA==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-validator-identifier": "^7.15.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.5.tgz", + "integrity": "sha512-qTFnpxHMoenNHkS3VoWRdwrcJ3FhX567GvDA3hRZKF0Dj8Fmg0UzySZp3AP2mShl/bzcywb/UWAMQIjA1bhXvw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.5", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.5.tgz", + "integrity": "sha512-/wqGDgvFUeKELW6ex6QB7dLVRkd5ehjw34tpXu1nhKC0sFfmaLabIswnpf8JgDyV2NeDmZiwoOb0rAmxciNfjA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.5.tgz", + "integrity": "sha512-ZaIrnXF08ZC8jnKR4/5g7YakGVL6go6V9ql6Jl3ecO8PQaQqFE74CuM384kezju7Z9nGCCA20BqZaR1tJ/WvHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.5.tgz", + "integrity": "sha512-tded+yZEXuxt9Jdtkc1RraW1zMF/GalVxaVVxh41IYwirdRgyAxxxCKZ9XB7LxZqmsjfjALxupNE1MIz9KH+Zg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-replace-supers": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.5.tgz", + "integrity": "sha512-B3O6AL5oPop1jAVg8CV+haeUte9oFuY85zu0jwnRNZZi3tVAbJriu5tag/oaO2kGaQM/7q7aGPBlTI5/sr9enA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.5.tgz", + "integrity": "sha512-+IRcVW71VdF9pEH/2R/Apab4a19LVvdVsr/gEeotH00vSDVlKD+XgfSIw+cgGWsjDB/ziqGv/pGoQZBIiQVXHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.5.tgz", + "integrity": "sha512-2z+it2eVWU8TtQQRauvGUqZwLy4+7rTfo6wO4npr+fvvN1SW30ZF3O/ZRCNmTuu4F5MIP8OJhXAhRV5QMJOuYg==", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.14.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.5.tgz", + "integrity": "sha512-aIB16u8lNcf7drkhXJRoggOxSTUAuihTSTfAcpynowGJOZiGf+Yvi7RuTwFzVYSYPmWyARsPqUGoZWWWxLiknw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.5.tgz", + "integrity": "sha512-gxpfS8XQWDbQ8oP5NcmpXxtEgCJkbO+W9VhZlOhr0xPyVaRjAQPOv7ZDj9fg0d5s9+NiVvMCE6gbkEkcsxwGRw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.4.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.5.tgz", + "integrity": "sha512-ZbuWVcY+MAXJuuW7qDoCwoxDUNClfZxoo7/4swVbOW1s/qYLOMHlm9YRWMsxMFuLs44eXsv4op1vAaBaBaDMVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.5.tgz", + "integrity": "sha512-5d6l/cnG7Lw4tGHEoga4xSkYp1euP7LAtrah1h1PgJ3JY7yNsjybsxQAnVK4JbtReZ/8z6ASVmd3QhYYKLaKZw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.5.tgz", + "integrity": "sha512-usYsuO1ID2LXxzuUxifgWtJemP7wL2uZtyrTVM4PKqsmJycdS4U4mGovL5xXkfUheds10Dd2PjoQLXw6zCsCbg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.5.tgz", + "integrity": "sha512-gnyKy9RyFhkovex4BjKWL3BVYzUDG6zC0gba7VMLbQoDuqMfJ1SDXs8k/XK41Mmt1Hyp4qNAvGFb9hKzdCqBRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.5.tgz", + "integrity": "sha512-ldxCkW180qbrvyCVDzAUZqB0TAeF8W/vGJoRcaf75awm6By+PxfJKvuqVAnq8N9wz5Xa6mSpM19OfVKKVmGHSQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.5.tgz", + "integrity": "sha512-shiCBHTIIChGLdyojsKQjoAyB8MBwat25lKM7MJjbe1hE0bgIppD+LX9afr41lLHOhqceqeWl4FkLp+Bgn9o1Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.5.tgz", + "integrity": "sha512-GTJ4IW012tiPEMMubd7sD07iU9O/LOo8Q/oU4xNhcaq0Xn8+6TcUQaHtC8YxySo1T+ErQ8RaWogIEeFhKGNPzw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.0", + "@babel/helper-plugin-utils": "^7.16.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.5.tgz", + "integrity": "sha512-MiJJW5pwsktG61NDxpZ4oJ1CKxM1ncam9bzRtx9g40/WkLRkxFP6mhpkYV0/DxcciqoiHicx291+eUQrXb/SfQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-compilation-targets": "^7.16.3", + "@babel/helper-plugin-utils": "^7.16.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.2", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-async-generator-functions": "^7.16.5", + "@babel/plugin-proposal-class-properties": "^7.16.5", + "@babel/plugin-proposal-class-static-block": "^7.16.5", + "@babel/plugin-proposal-dynamic-import": "^7.16.5", + "@babel/plugin-proposal-export-namespace-from": "^7.16.5", + "@babel/plugin-proposal-json-strings": "^7.16.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.5", + "@babel/plugin-proposal-numeric-separator": "^7.16.5", + "@babel/plugin-proposal-object-rest-spread": "^7.16.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.5", + "@babel/plugin-proposal-optional-chaining": "^7.16.5", + "@babel/plugin-proposal-private-methods": "^7.16.5", + "@babel/plugin-proposal-private-property-in-object": "^7.16.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.5", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.5", + "@babel/plugin-transform-async-to-generator": "^7.16.5", + "@babel/plugin-transform-block-scoped-functions": "^7.16.5", + "@babel/plugin-transform-block-scoping": "^7.16.5", + "@babel/plugin-transform-classes": "^7.16.5", + "@babel/plugin-transform-computed-properties": "^7.16.5", + "@babel/plugin-transform-destructuring": "^7.16.5", + "@babel/plugin-transform-dotall-regex": "^7.16.5", + "@babel/plugin-transform-duplicate-keys": "^7.16.5", + "@babel/plugin-transform-exponentiation-operator": "^7.16.5", + "@babel/plugin-transform-for-of": "^7.16.5", + "@babel/plugin-transform-function-name": "^7.16.5", + "@babel/plugin-transform-literals": "^7.16.5", + "@babel/plugin-transform-member-expression-literals": "^7.16.5", + "@babel/plugin-transform-modules-amd": "^7.16.5", + "@babel/plugin-transform-modules-commonjs": "^7.16.5", + "@babel/plugin-transform-modules-systemjs": "^7.16.5", + "@babel/plugin-transform-modules-umd": "^7.16.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.5", + "@babel/plugin-transform-new-target": "^7.16.5", + "@babel/plugin-transform-object-super": "^7.16.5", + "@babel/plugin-transform-parameters": "^7.16.5", + "@babel/plugin-transform-property-literals": "^7.16.5", + "@babel/plugin-transform-regenerator": "^7.16.5", + "@babel/plugin-transform-reserved-words": "^7.16.5", + "@babel/plugin-transform-shorthand-properties": "^7.16.5", + "@babel/plugin-transform-spread": "^7.16.5", + "@babel/plugin-transform-sticky-regex": "^7.16.5", + "@babel/plugin-transform-template-literals": "^7.16.5", + "@babel/plugin-transform-typeof-symbol": "^7.16.5", + "@babel/plugin-transform-unicode-escapes": "^7.16.5", + "@babel/plugin-transform-unicode-regex": "^7.16.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.0", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.4.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.19.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.16.5.tgz", + "integrity": "sha512-NpluD+cToBiZiDsG3y9rtIcqDyivsahpaM9csfyfiq1qQWduSmihUZ+ruIqqSDGjZKZMJfgAElo9x2YWlOQuRw==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.0", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz", + "integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", + "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.5.tgz", + "integrity": "sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.5", + "@babel/helper-environment-visitor": "^7.16.5", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/parser": "^7.16.5", + "@babel/types": "^7.16.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", + "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.15.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", + "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", + "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", + "dev": true, + "optional": true + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/eslint": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz", + "integrity": "sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.2.tgz", + "integrity": "sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz", + "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", + "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", + "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", + "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", + "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "dev": true, + "engines": { + "node": ">=0.6.10" + } + }, + "node_modules/array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/babel-loader": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", + "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/babel-loader/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "dev": true, + "dependencies": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz", + "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.0", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz", + "integrity": "sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.0", + "core-js-compat": "^3.18.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz", + "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "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, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", + "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001286", + "electron-to-chromium": "^1.4.17", + "escalade": "^3.1.1", + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/caching-transform/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caching-transform/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001291", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001291.tgz", + "integrity": "sha512-roMV5V0HNGgJ88s42eE70sstqGW/gwFndosYrikHthw98N5tLnOTxFqMLQjZVRxTWFlJ4rn+MsgXrR7MDPY4jA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codecov": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.3.tgz", + "integrity": "sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==", + "deprecated": "https://about.codecov.io/blog/codecov-uploader-deprecation-plan/", + "dev": true, + "dependencies": { + "argv": "0.0.2", + "ignore-walk": "3.0.4", + "js-yaml": "3.14.1", + "teeny-request": "7.1.1", + "urlgrey": "1.0.0" + }, + "bin": { + "codecov": "bin/codecov" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "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==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true + }, + "node_modules/core-js-compat": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.0.tgz", + "integrity": "sha512-relrah5h+sslXssTTOkvqcC/6RURifB0W5yhYBdBkaPYa5/2KBMiog3XiD+s3TwEHWxInWVv4Jx2/Lw0vng+IQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.19.1", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.0.tgz", + "integrity": "sha512-lBG90FEc4A2lZeRoFkJHYnJlQFgR49hTo3E8HA6oGN+mN66EIslimxtcAYx4xlkBR0c3eNCOjqQ2ACHaav+7Qw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "css-blank-pseudo": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.0.tgz", + "integrity": "sha512-1LlqZebDVJXvLPP0RZ8U1jrpFEHWqttBlWz46PVNN6tD65O3IgooDkGEAhfhHTJUGHJHrXzH+ANIC0/1bD9l+A==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "css-has-pseudo": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/css-loader": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.5.1.tgz", + "integrity": "sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.0.tgz", + "integrity": "sha512-Ko2uKO81GbDgV1DG0OywofFy8Oz3/beGryi3ohmXAGo3duZI2HCz6MCQq85WdiKhWE7N3pMjUByIh137Xp5v6g==", + "dev": true, + "bin": { + "css-prefers-color-scheme": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/cssdb": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-5.0.0.tgz", + "integrity": "sha512-Q7982SynYCtcLUBCPgUPFy2TZmDiFyimpdln8K2v4w2c07W4rXL7q5F1ksVAqOAQfxKyyUGCKSsioezKT5bU1Q==", + "dev": 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, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.24.tgz", + "integrity": "sha512-erwx5r69B/WFfFuF2jcNN0817BfDBdC4765kQ6WltOMuwsimlQo3JTEq0Cle+wpHralwdeX3OfAtw/mHxPK0Wg==", + "dev": true + }, + "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==", + "dev": true + }, + "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, + "engines": { + "node": ">= 4" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", + "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", + "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "find-up": "^2.1.0", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.25.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", + "integrity": "sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.1", + "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.11.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "dev": true, + "dependencies": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-babel-config/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", + "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fraction.js": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", + "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/globule": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", + "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==", + "dev": true, + "dependencies": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/globule/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.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, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "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", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", + "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "27.4.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz", + "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/known-css-properties": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/loader-utils/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.5.tgz", + "integrity": "sha512-oEIhRucyn1JbT/1tU2BhnwO6ft1jjH1iCX9Gc59WFMg0n5773rQU0oyQ0zzeYFFuBfONaRbQJyGoPtuNseMxjA==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", + "dev": true + }, + "node_modules/node-sass": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.0.tgz", + "integrity": "sha512-6yUnsD3L8fVbgMX6nKQqZkjRcG7a/PpmF0pEyeWf+BgbTj2ToJlCYrnUifL2KbjV5gIY22I3oppahBWA3B+jUg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "async-foreach": "^0.1.3", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "lodash": "^4.17.15", + "meow": "^9.0.0", + "nan": "^2.13.2", + "node-gyp": "^7.1.0", + "npmlog": "^5.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "bin": { + "node-sass": "bin/node-sass" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/node-sass/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-sass/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/node-sass/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-sass/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/node-sass/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-sass/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/npmlog/node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npmlog/node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npmlog/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npmlog/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nyc/node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", + "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pixelmatch": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.2.1.tgz", + "integrity": "sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==", + "dev": true, + "dependencies": { + "pngjs": "^4.0.1" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pngjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-4.0.1.tgz", + "integrity": "sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss": { + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.0.tgz", + "integrity": "sha512-b4g9eagFGq9T5SWX4+USfVyjIb3liPnjhHHRMP7FMB2kFVpYyfEscV0wP3eaXhKlcHKUut8lt5BGoeylWA/dBQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.2" + }, + "peerDependencies": { + "postcss": "^8.0.2" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.1.0.tgz", + "integrity": "sha512-bBB64p3Fzo0DaxGfVp6ELRjOx+MysN1DlvkWtXwZr25i8SZLAEL+QAV6ttX5iraN+e3fdCxaVm7sHobNyy6qug==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-color-functional-notation": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.1.tgz", + "integrity": "sha512-kzp95xRLSFnFdmVIWwbWa3QohE3v/G/wNBvW4U66Lt4wq119I6Bz1EVErrARWZ5+7HskgQ6M4mpiwjo+jOdApA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-color-hex-alpha": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.1.tgz", + "integrity": "sha512-uA5MAOoCwCK32VgYXWwPD3vBDDOi1oMOkLnO+U1Af6ex7JOE0xHVJqnc9w5QS+fPJ9yveXeHKVtdVqzP2WiCsQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-color-rebeccapurple": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", + "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.0.1.tgz", + "integrity": "sha512-Z3WjuML7qn6ehesWD4vDqOmM5CZO/qfVknpI9/gDOwMNhcLg3OSgT5wENR4kFDZtCricAE7cxL97bsj5lFnuZQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-custom-properties": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.0.tgz", + "integrity": "sha512-/1iyBhz/W8jUepjGyu7V1OPcGbc636snN1yXEQCinb6Bwt7KxsiU7/bLQlp8GwAXzCh7cobBU5odNn/2zQWR8Q==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.2" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.1.tgz", + "integrity": "sha512-nA6+XVUc5VDe6LrJ5KWFqJ05dxZXzoYiUQJFZSuwLW/8aI462w7gCEhB+RnOA+N3dtrj8B2WTSfcjCac6RJW0A==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "postcss-dir-pseudo-class": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.0.3.tgz", + "integrity": "sha512-x3DYDhCsKS/sjH6t+sM9R+pq4lCwdHGVeUOpE/gDybfY33acJJie+NzRigKJVze7E/jH/1WGl/qPRV90Lso7Mg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-double-position-gradients": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.3.tgz", + "integrity": "sha512-RQ0CwXX161FLuC525Lx7VqsHXSPQvgErgOMcbfuAKPq1hgHDPJLemowVaPuWF4E3IO8rgUbStaRLGTM5VlN/vw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-env-function": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.2.tgz", + "integrity": "sha512-KYztrdQRRr+pPJQRAyr9HAEr8I8TUfpSyqOo8qddrjtMLap7Ud1FAF8szi4ZWrhMmch3EwL4RQMqsneOByWZIA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "postcss-focus-visible": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.2.tgz", + "integrity": "sha512-0zm8gM/fpFZtWM8drbj5M6HKVztHgLqtHygCMB494SOkudtnePpq5nv0ie2Jx/BrD+A5nhj0uK3tuMnEpjKonA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "postcss-focus-within": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.1.tgz", + "integrity": "sha512-t7ztwUmG17KQRTHDWeekeSQ41ZsjYK+OJagee3E3hFS46n9RD5QcT/NRxwbc2DWjVSL5GQf46al3wEiH6FRSKg==", + "dev": true, + "bin": { + "postcss-gap-properties": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.3.tgz", + "integrity": "sha512-+EZRaCg/MzsKW2ggTy26mG/uoHnEAjCcGICCkUYgg2PPguZaRjSBKY4KHiWcdH6ydsR7enlnO3i7bQ+Fpbx7vQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-image-set-function": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.0.2.tgz", + "integrity": "sha512-IkX1S1CROQF9uCu5F4/Ib5SRFDJXlJg3ig9x4OJkKIF16y0o7WRKfFje2ym+yThfwYjozwHZgf37Xwbnscpipg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-lab-function": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.1.tgz", + "integrity": "sha512-cKekWCoZrxdQktbj8PyCOqQWxsYAPyHjoeBPedkQzfWuEqRm0KVFRHypsHAiH2dDVUae52yx8PBtWS+V3BqT5w==", + "dev": true, + "bin": { + "postcss-logical": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.0.3.tgz", + "integrity": "sha512-Dshtj57d5ytK1AeVNpQHp8gINgdjsRJaRjH1QmJHGcfOQIP4TNtlrrrh5o3i3bBTwge2+nh1D9xbI2wrckz5Xw==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "postcss-nesting": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.1.tgz", + "integrity": "sha512-/ajDNoTF+LiuhIZjenjb/ndBoKP/WYy/dTT8BCCtLU1wrezkax+lXw5r3c5qR4cadNNMbksAnhWJXNjd9xNTHA==", + "dev": true, + "bin": { + "postcss-overflow-shorthand": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.2.tgz", + "integrity": "sha512-XsZCU8X8M9dHKGlxdycihxPajSkRd4u+cIUJz/FgC61Mr/swStI3xAvsYai9Fh22kU+VVAn7ihoZk8h9pQhDfA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "postcss-place": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.0.2.tgz", + "integrity": "sha512-xgmkS+H2xhjPQWewnH4ViKBCHIZ15FfpldGZuBFaBIi/iipxHTLnBHKtkCp1L531SdNEPwo9md2psjOU1G77lw==", + "dev": true, + "dependencies": { + "autoprefixer": "^10.4.0", + "browserslist": "^4.19.1", + "caniuse-lite": "^1.0.30001287", + "css-blank-pseudo": "^3.0.0", + "css-has-pseudo": "^3.0.0", + "css-prefers-color-scheme": "^6.0.0", + "cssdb": "^5.0.0", + "postcss-attribute-case-insensitive": "^5.0.0", + "postcss-color-functional-notation": "^4.1.0", + "postcss-color-hex-alpha": "^8.0.1", + "postcss-color-rebeccapurple": "^7.0.1", + "postcss-custom-media": "^8.0.0", + "postcss-custom-properties": "^12.0.1", + "postcss-custom-selectors": "^6.0.0", + "postcss-dir-pseudo-class": "^6.0.1", + "postcss-double-position-gradients": "^3.0.3", + "postcss-env-function": "^4.0.3", + "postcss-focus-visible": "^6.0.2", + "postcss-focus-within": "^5.0.2", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.1", + "postcss-image-set-function": "^4.0.3", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.0.2", + "postcss-logical": "^5.0.1", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.0.3", + "postcss-overflow-shorthand": "^3.0.1", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.2", + "postcss-pseudo-class-any-link": "^7.0.1", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^5.0.0" + }, + "bin": { + "postcss-preset-env": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-preset-env/node_modules/autoprefixer": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz", + "integrity": "sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==", + "dev": true, + "dependencies": { + "browserslist": "^4.17.5", + "caniuse-lite": "^1.0.30001272", + "fraction.js": "^4.1.1", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.0.1.tgz", + "integrity": "sha512-Zt+VMw9qX7Um/cYOaywOQvXipDw/U3U83L6MFHocbjVIhLd+x5G4SSDmKm8sW2/HlaTno2Cazub8USrDvJ4DLA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.7" + }, + "bin": { + "postcss-pseudo-class-any-link": "dist/cli.mjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.5.tgz", + "integrity": "sha512-F7xpB6TrXyqUh3GKdyB4Gkp3QL3DDW1+uI+gxx/oJnUt/qXI4trj5OGlp9rOKdoABGULuqtqeG+3HEVQk4DjmA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz", + "integrity": "sha512-/2K3A4TCP9orP4TNS7u3tGdRFVKqz/E6pX3aGnriPG0jU78of8wsUcqE4QAhWEU0d+WnMSF93Ah3F//vUtK+iQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "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 + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz", + "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz", + "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^9.0.0", + "regjsgen": "^0.5.2", + "regjsparser": "^0.7.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz", + "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + }, + "bin": { + "sassgraph": "bin/sassgraph" + } + }, + "node_modules/sass-loader": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.4.0.tgz", + "integrity": "sha512-7xN+8khDIzym1oL9XyS6zP6Ges+Bo2B2xbPrjdMHEYyV3AQYhd/wXeru++3ODHF0zMjYmVadblSKrPrjEkL8mg==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "dependencies": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + } + }, + "node_modules/scss-tokenizer/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/spawn-wrap/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, + "node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.0.1", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.0", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.25.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.16", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.0", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-prettier": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz", + "integrity": "sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==", + "dev": true, + "bin": { + "stylelint-config-prettier": "bin/check.js", + "stylelint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "stylelint": ">=11.0.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-8.0.0.tgz", + "integrity": "sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^14.8.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-7.0.0.tgz", + "integrity": "sha512-rGz1J4rMAyJkvoJW4hZasuQBB7y9KIrShb20l9DVEKKZSEi1HAy0vuNlR8HyCKy/jveb/BdaQFcoiYnmx4HoiA==", + "dev": true, + "dependencies": { + "postcss-scss": "^4.0.2", + "stylelint-config-recommended": "^8.0.0", + "stylelint-scss": "^4.0.0" + }, + "peerDependencies": { + "stylelint": "^14.4.0" + } + }, + "node_modules/stylelint-prettier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-2.0.0.tgz", + "integrity": "sha512-jvT3G+9lopkeB0ARmDPszyfaOnvnIF+30QCjZxyt7E6fynI1T9mOKgYDNb9bXX17M7PXMZaX3j/26wqakjp1tw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "prettier": ">=2.0.0", + "stylelint": ">=14.0.0" + } + }, + "node_modules/stylelint-scss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.3.0.tgz", + "integrity": "sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.6", + "postcss-value-parser": "^4.1.0" + }, + "peerDependencies": { + "stylelint": "^14.5.1" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylelint/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", + "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/teeny-request": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.1.1.tgz", + "integrity": "sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "acorn": "^8.5.0" + }, + "peerDependenciesMeta": { + "acorn": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz", + "integrity": "sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ==", + "dev": true, + "dependencies": { + "jest-worker": "^27.4.1", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "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/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "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/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "dependencies": { + "glob": "^7.1.2" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urlgrey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz", + "integrity": "sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==", + "dev": true, + "dependencies": { + "fast-url-parser": "^1.1.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/webpack": { + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz", + "integrity": "sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.2" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.0", + "@webpack-cli/info": "^1.4.0", + "@webpack-cli/serve": "^1.6.0", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "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" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.2.tgz", + "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "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/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + }, "dependencies": { "@babel/cli": { "version": "7.16.0", @@ -66,6 +10315,25 @@ } } }, + "@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/generator": { "version": "7.16.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz", @@ -1167,6 +11435,13 @@ "to-fast-properties": "^2.0.0" } }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "requires": {} + }, "@discoveryjs/json-ext": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", @@ -1280,6 +11555,41 @@ "dev": true, "optional": true }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1498,7 +11808,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "1.4.0", @@ -1513,7 +11824,8 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -1543,13 +11855,15 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true + "dev": true, + "requires": {} }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "agent-base": { "version": "6.0.2", @@ -1615,7 +11929,8 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "amdefine": { "version": "1.0.1", @@ -1714,6 +12029,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array.prototype.flat": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", @@ -1975,7 +12296,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, - "optional": true, "requires": { "fill-range": "^7.0.1" } @@ -2221,6 +12541,12 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, "colorette": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", @@ -2338,6 +12664,12 @@ "postcss-selector-parser": "^6.0.7" } }, + "css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true + }, "css-has-pseudo": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.0.tgz", @@ -2378,7 +12710,8 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.0.tgz", "integrity": "sha512-Ko2uKO81GbDgV1DG0OywofFy8Oz3/beGryi3ohmXAGo3duZI2HCz6MCQq85WdiKhWE7N3pMjUByIh137Xp5v6g==", - "dev": true + "dev": true, + "requires": {} }, "cssdb": { "version": "5.0.0", @@ -2402,9 +12735,9 @@ } }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -2478,6 +12811,15 @@ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2770,6 +13112,13 @@ } } }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, "eslint-import-resolver-node": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", @@ -2912,6 +13261,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -3055,6 +13413,25 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3085,11 +13462,20 @@ } }, "fastest-levenshtein": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", - "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3104,7 +13490,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "optional": true, "requires": { "to-regex-range": "^5.0.1" } @@ -3373,12 +13758,77 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, "globule": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", @@ -3509,6 +13959,12 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -3551,7 +14007,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "ignore": { "version": "4.0.6", @@ -3586,6 +14043,12 @@ } } }, + "import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true + }, "import-local": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", @@ -3669,6 +14132,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -3779,8 +14248,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true + "dev": true }, "is-number-object": { "version": "1.0.6", @@ -4162,6 +14630,12 @@ "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", "dev": true }, + "known-css-properties": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4271,6 +14745,12 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, "meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -4305,6 +14785,22 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -4446,9 +14942,9 @@ "dev": true }, "nanoid": { - "version": "3.1.30", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz", - "integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "natural-compare": { @@ -4638,8 +15134,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true + "dev": true }, "normalize-range": { "version": "0.1.2", @@ -5140,11 +15635,10 @@ "dev": true }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "optional": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "pify": { "version": "4.0.1", @@ -5192,14 +15686,14 @@ "dev": true }, "postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", + "version": "8.4.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", + "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", "dev": true, "requires": { - "nanoid": "^3.1.30", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" + "source-map-js": "^1.0.2" } }, "postcss-attribute-case-insensitive": { @@ -5242,7 +15736,8 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz", "integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==", - "dev": true + "dev": true, + "requires": {} }, "postcss-custom-properties": { "version": "12.0.1", @@ -5311,13 +15806,15 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "dev": true + "dev": true, + "requires": {} }, "postcss-gap-properties": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.1.tgz", "integrity": "sha512-t7ztwUmG17KQRTHDWeekeSQ41ZsjYK+OJagee3E3hFS46n9RD5QcT/NRxwbc2DWjVSL5GQf46al3wEiH6FRSKg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-image-set-function": { "version": "4.0.3", @@ -5332,7 +15829,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-lab-function": { "version": "4.0.2", @@ -5369,19 +15867,28 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.1.tgz", "integrity": "sha512-cKekWCoZrxdQktbj8PyCOqQWxsYAPyHjoeBPedkQzfWuEqRm0KVFRHypsHAiH2dDVUae52yx8PBtWS+V3BqT5w==", - "dev": true + "dev": true, + "requires": {} }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "requires": {} + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", "dev": true }, "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -5425,13 +15932,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.1.tgz", "integrity": "sha512-/ajDNoTF+LiuhIZjenjb/ndBoKP/WYy/dTT8BCCtLU1wrezkax+lXw5r3c5qR4cadNNMbksAnhWJXNjd9xNTHA==", - "dev": true + "dev": true, + "requires": {} }, "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-place": { "version": "7.0.2", @@ -5512,8 +16021,29 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "requires": {} + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", "dev": true }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "requires": {} + }, + "postcss-scss": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.5.tgz", + "integrity": "sha512-F7xpB6TrXyqUh3GKdyB4Gkp3QL3DDW1+uI+gxx/oJnUt/qXI4trj5OGlp9rOKdoABGULuqtqeG+3HEVQk4DjmA==", + "dev": true, + "requires": {} + }, "postcss-selector-not": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-5.0.0.tgz", @@ -5524,9 +16054,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.7.tgz", - "integrity": "sha512-U+b/Deoi4I/UmE6KOVPpnhS7I7AYdKbhGcat+qTQ27gycvaACvNEw11ba6RrkwVmDVRW7sigWgLj4/KbbJjeDA==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -5545,6 +16075,21 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -5584,6 +16129,12 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -5893,6 +16444,12 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5902,6 +16459,15 @@ "glob": "^7.1.3" } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -6025,9 +16591,9 @@ } }, "signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "slash": { @@ -6086,9 +16652,9 @@ "dev": true }, "source-map-js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz", - "integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, "source-map-support": { @@ -6213,6 +16779,15 @@ "stubs": "^3.0.0" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -6261,15 +16836,6 @@ "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6316,8 +16882,155 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "requires": {} + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "dev": true }, + "stylelint": { + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.13.0.tgz", + "integrity": "sha512-NJSAdloiAB/jgVJKxMR90mWlctvmeBFGFVUvyKngi9+j/qPSJ5ZB+u8jOmGbLTnS7OHrII9NFGehPRyar8U5vg==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^7.0.1", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.0", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.25.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.16", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.3.0", + "svg-tags": "^1.0.0", + "table": "^6.8.0", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + } + } + }, + "stylelint-config-prettier": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz", + "integrity": "sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==", + "dev": true, + "requires": {} + }, + "stylelint-config-recommended": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-8.0.0.tgz", + "integrity": "sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==", + "dev": true, + "requires": {} + }, + "stylelint-config-recommended-scss": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-7.0.0.tgz", + "integrity": "sha512-rGz1J4rMAyJkvoJW4hZasuQBB7y9KIrShb20l9DVEKKZSEi1HAy0vuNlR8HyCKy/jveb/BdaQFcoiYnmx4HoiA==", + "dev": true, + "requires": { + "postcss-scss": "^4.0.2", + "stylelint-config-recommended": "^8.0.0", + "stylelint-scss": "^4.0.0" + } + }, + "stylelint-prettier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-2.0.0.tgz", + "integrity": "sha512-jvT3G+9lopkeB0ARmDPszyfaOnvnIF+30QCjZxyt7E6fynI1T9mOKgYDNb9bXX17M7PXMZaX3j/26wqakjp1tw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "stylelint-scss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.3.0.tgz", + "integrity": "sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==", + "dev": true, + "requires": { + "lodash": "^4.17.21", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.6", + "postcss-value-parser": "^4.1.0" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6327,10 +17040,43 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, "table": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", - "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", "dev": true, "requires": { "ajv": "^8.0.1", @@ -6503,7 +17249,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "optional": true, "requires": { "is-number": "^7.0.0" } diff --git a/package.json b/package.json index d188378..f220d0c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "devDependencies": { "@babel/cli": "^7.16.0", "@babel/core": "^7.16.5", + "@babel/eslint-parser": "^7.19.1", "@babel/plugin-transform-runtime": "^7.16.5", "@babel/preset-env": "^7.16.5", "@babel/register": "^7.16.5", @@ -14,15 +15,23 @@ "css-loader": "^6.5.1", "eslint": "^7.32.0", "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.25.3", + "eslint-plugin-prettier": "^4.2.1", "mini-css-extract-plugin": "^2.4.5", "node-sass": "^7.0.0", "nyc": "^15.1.0", "pixelmatch": "^5.2.1", "postcss-loader": "^6.2.1", "postcss-preset-env": "^7.0.2", + "postcss-scss": "^4.0.5", + "prettier": "^2.7.1", "sass-loader": "^12.4.0", "style-loader": "^3.3.1", + "stylelint": "^14.13.0", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-recommended-scss": "^7.0.0", + "stylelint-prettier": "^2.0.0", "webpack": "^5.65.0", "webpack-cli": "^4.9.1", "webpack-merge": "^5.8.0" @@ -30,10 +39,14 @@ "scripts": { "report": "nyc report -r lcovonly", "build": "webpack", - "codecov": "codecov -f coverage/lcov.info -F javascript" + "codecov": "codecov -f coverage/lcov.info -F javascript", + "lint": "npm run lint:stylelint; npm run lint:eslint", + "lint:fix": "npm run lint:stylelint -- --fix; npm run lint:eslint -- --fix", + "lint:stylelint": "node_modules/.bin/stylelint 'nested_admin/**/*.scss'", + "lint:eslint": "node_modules/.bin/eslint nested_admin/static/nested_admin/src --ext .js" }, "engines": { - "node": ">=12" + "node": ">=14" }, "main": "nested_admin/static/nested_admin/src/nested_admin", "repository": { diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e47875c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[tool.black] +target-version = ['py37'] +extend-exclude = ''' +( + /\.tox + | /.*?venv.*?/ +) +''' diff --git a/pytest.ini b/pytest.ini index 576dadf..946209f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,5 +2,7 @@ DJANGO_SETTINGS_MODULE = nested_admin.tests.settings addopts = --tb=short --create-db --cov=nested_admin django_find_project = false +markers = + selenium python_files = tests.py test_*.py *_tests.py testpaths = nested_admin/tests diff --git a/setup.cfg b/setup.cfg index b7f0e16..d3fe206 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,15 +1,6 @@ -[bumpversion] -current_version = 3.0.21 -commit = True -tag = True -message = v{new_version} [ci skip] - -[bdist_wheel] -universal = 1 - -[bumpversion:file:setup.py] - [flake8] exclude = build,.git,.tox -ignore = W504,W601 +extend-ignore = W504,W601,E203,E501,E741 max-line-length = 100 +per-file-ignores = + nested_admin/tests/*: E722 \ No newline at end of file diff --git a/setup.py b/setup.py index a146da3..bf92827 100755 --- a/setup.py +++ b/setup.py @@ -6,60 +6,78 @@ from setuptools import setup, find_packages except ImportError: from ez_setup import use_setuptools + use_setuptools() from setuptools import setup, find_packages # Find the package version in __init__.py without importing it # (which we cannot do because it has extensive dependencies). -init_file = os.path.join(os.path.dirname(__file__), - 'nested_admin', '__init__.py') -with open(init_file, 'r') as f: +init_file = os.path.join(os.path.dirname(__file__), "nested_admin", "__init__.py") +with open(init_file) as f: for line in f: - m = re.search(r'''^__version__ = (['"])(.+?)\1$''', line) + m = re.search(r"""^__version__ = (['"])(.+?)\1$""", line) if m is not None: version = m.group(2) break else: - raise LookupError('Unable to find __version__ in ' + init_file) + raise LookupError("Unable to find __version__ in " + init_file) + + +tests_require = [ + "pytest", + "pytest-cov", + "pytest-xdist", + "pytest-django", + "Pillow", + "dj-database-url", + "django-selenosis", + "selenium", +] + +dev_require = [ + "black", + "flake8", +] + tests_require setup( - name='django-nested-admin', + name="django-nested-admin", version=version, + python_requires=">=3.6", install_requires=[ - 'python-monkey-business>=1.0.0', - 'six', + "python-monkey-business>=1.0.0", ], + tests_require=tests_require, + extras_require={ + "test": tests_require, + "dev": dev_require, + }, description="Django admin classes that allow for nested inlines", - author='The Atlantic', - author_email='programmers@theatlantic.com', - url='https://github.com/theatlantic/django-nested-admin', + author="The Atlantic", + author_email="programmers@theatlantic.com", + url="https://github.com/theatlantic/django-nested-admin", packages=find_packages(), - license='BSD', - platforms='any', + license="BSD", + platforms="any", classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Web Environment', - 'Intended Audience :: Developers', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - "Programming Language :: Python :: 2", - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Framework :: Django', - 'Framework :: Django :: 1.11', - 'Framework :: Django :: 2.2', - 'Framework :: Django :: 3.2', - 'Framework :: Django :: 4.0', + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Framework :: Django", + "Framework :: Django :: 3.2", + "Framework :: Django :: 4.0", + "Framework :: Django :: 4.1", ], include_package_data=True, zip_safe=False, - long_description=''.join(list(open('README.rst'))[3:])) + long_description="".join(list(open("README.rst"))[3:]), +) diff --git a/tox.ini b/tox.ini index a2ffaec..6f1843b 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,12 @@ envlist = py{36,37,38,39}-dj22-{grp,nogrp} py{36,37,38,39,310}-dj32-{grp,nogrp} - py{38,39,310}-dj40-nogrp + py{38,39,310}-dj40-{grp,nogrp} + py{38,39,310,311}-dj41-{grp,nogrp} + py{38,39,310,311,312}-dj42-{grp,nogrp} + py{310,311,312}-dj50-{grp,nogrp} + py{310,311,312}-dj51-nogrp + black,flake8 skipsdist=True [testenv] @@ -21,24 +26,42 @@ passenv = AWS_SECRET_ACCESS_KEY DATABASE_URL deps = - selenium==3.141.0 + -e.[test] + selenium coverage - django-selenosis - dj-database-url - python-monkey-business django-polymorphic + # setuptools is required until a django-polymorphic release includes + # the fix for jazzband/django-polymorphic#599 + setuptools boto3 django-storages - Pillow dj22: Django>=2.2,<3.0 dj32: Django>=3.2,<4.0 dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 + dj42: Django>=4.2,<4.3 + dj50: Django>=5.0,<5.1 + dj51: Django>=5.1a1,<5.2 dj22-grp: django-grappelli>=2.13,<2.14 dj32-grp: django-grappelli>=2.15,<2.16 - pytest - pytest-cov - pytest-xdist - pytest-django + dj40-grp: django-grappelli==3.0.8 + dj41-grp: django-grappelli==3.0.8 + dj42-grp: django-grappelli>=3.0,<3.1 + dj50-grp: django-grappelli>=4.0,<4.1 + +[testenv:black] +basepython = python3.9 +deps = + black +commands = + black nested_admin docs setup.py {posargs:--diff} + +[testenv:flake8] +basepython = python3.9 +deps = + flake8 +commands = + flake8 nested_admin docs setup.py [testenv:coverage-report] skip_install = true @@ -69,12 +92,18 @@ python = 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 + 3.12: py312 [gh-actions:env] DJANGO = 2.2: dj22 3.2: dj32 4.0: dj40 + 4.1: dj41 + 4.2: dj42 + 5.0: dj50 + 5.1: dj51 GRAPPELLI = 0: nogrp 1: grp