From 24ec18c439f2cb0d66b84fcbfbcd1736d68c07af Mon Sep 17 00:00:00 2001 From: CocoByte Date: Wed, 8 May 2024 15:13:03 -0600 Subject: [PATCH 01/56] Added logic to prevent creation of DomainInvitation if invite fails to send --- src/registrar/views/domain.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 9134080a1..2d67fc477 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -776,15 +776,23 @@ class DomainAddUserView(DomainFormBaseView): def _make_invitation(self, email_address: str, requestor: User): """Make a Domain invitation for this email and redirect with a message.""" - invitation, created = DomainInvitation.objects.get_or_create(email=email_address, domain=self.object) - if not created: + # Check to see if an invite has already been sent (NOTE: we do not want to create an invite just yet.) + invite_exists = DomainInvitation.objects.get(email=email_address, domain=self.object) + if invite_exists: # that invitation already existed messages.warning( self.request, f"{email_address} has already been invited to this domain.", ) else: - self._send_domain_invitation_email(email=email_address, requestor=requestor) + #Try to send the invitation. If it succeeds, add it to the DomainInvitation table. + try: + self._send_domain_invitation_email(email=email_address, requestor=requestor) + except Exception as exc: + raise EmailSendingError("Could not send SES email.") from exc + else: + #(NOTE: if the invitation fails to send, no invitation should be added to the DomainInvitation table) + DomainInvitation.objects.get_or_create(email=email_address, domain=self.object) return redirect(self.get_success_url()) def form_valid(self, form): From 5b8cf13eb183aeebbf474d91fe1458edc00446f5 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Wed, 8 May 2024 16:04:16 -0600 Subject: [PATCH 02/56] Fixed exception chain --- src/registrar/views/domain.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 2d67fc477..eb6f7d2c5 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -762,14 +762,14 @@ class DomainAddUserView(DomainFormBaseView): "requestor_email": requestor_email, }, ) - except EmailSendingError: - messages.warning(self.request, "Could not send email invitation.") + except EmailSendingError as exc: logger.warn( "Could not sent email invitation to %s for domain %s", email, self.object, exc_info=True, ) + raise EmailSendingError("Could not send email invitation.") from exc else: if add_success: messages.success(self.request, f"{email} has been invited to this domain.") @@ -777,21 +777,21 @@ class DomainAddUserView(DomainFormBaseView): def _make_invitation(self, email_address: str, requestor: User): """Make a Domain invitation for this email and redirect with a message.""" # Check to see if an invite has already been sent (NOTE: we do not want to create an invite just yet.) - invite_exists = DomainInvitation.objects.get(email=email_address, domain=self.object) - if invite_exists: + try: + invite = DomainInvitation.objects.get(email=email_address, domain=self.object) # that invitation already existed messages.warning( self.request, f"{email_address} has already been invited to this domain.", ) - else: + except DomainInvitation.DoesNotExist: #Try to send the invitation. If it succeeds, add it to the DomainInvitation table. try: self._send_domain_invitation_email(email=email_address, requestor=requestor) - except Exception as exc: - raise EmailSendingError("Could not send SES email.") from exc + except EmailSendingError as exc: + messages.warning(self.request, "Could not send email invitation.") else: - #(NOTE: if the invitation fails to send, no invitation should be added to the DomainInvitation table) + #(NOTE: only create a domainInvitation if the e-mail sends correctly) DomainInvitation.objects.get_or_create(email=email_address, domain=self.object) return redirect(self.get_success_url()) @@ -807,7 +807,10 @@ class DomainAddUserView(DomainFormBaseView): return self._make_invitation(requested_email, requestor) else: # if user already exists then just send an email - self._send_domain_invitation_email(requested_email, requestor, add_success=False) + try: + self._send_domain_invitation_email(requested_email, requestor, add_success=False) + except Exception as exc: + messages.warning(self.request, "Could not send email invitation.") try: UserDomainRole.objects.create( From 948afab1662a81cac1afbc26728529da521ac1fe Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 9 May 2024 11:14:49 -0400 Subject: [PATCH 03/56] wip --- src/registrar/config/urls.py | 5 +++ src/registrar/templates/base.html | 5 ++- src/registrar/templates/profile.html | 41 ++++++++++++------- src/registrar/views/__init__.py | 1 + src/registrar/views/user_profile.py | 36 ++++++++++++++++ src/registrar/views/utility/mixins.py | 15 +++++++ .../views/utility/permission_views.py | 23 ++++++++++- 7 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 src/registrar/views/user_profile.py diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 720034150..380cdb803 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -178,6 +178,11 @@ urlpatterns = [ views.DomainAddUserView.as_view(), name="domain-users-add", ), + path( + "user-profile", + views.UserProfileView.as_view(), + name="user-profile", + ), path( "invitation//delete", views.DomainInvitationDeleteView.as_view(http_method_names=["post"]), diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index c0702e78f..efaf46dfa 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -158,8 +158,11 @@
  • | - Sign out + Your profile
  • +
  • + | + Sign out {% else %} Sign in {% endif %} diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index 6a051bfe4..26fa34163 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -3,25 +3,36 @@ {% block title %} Edit your User Profile | {% endblock title %} +{% load static url_helpers %} {% block content %}
    -
    -
    - Your profile -

    - Required fields are marked with an asterisk (*). +

    - - +
    +

    Your profile

    +

    We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

    +

    Contact information

    +

    Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.

    + {% include "includes/required_fields.html" %} + +
    +
    + Your profile + {% for field in profile_form %} + + {{ field }} + {% endfor %} +
    + +
    {% endblock content %} diff --git a/src/registrar/views/__init__.py b/src/registrar/views/__init__.py index bd15196d4..4ed5bfa75 100644 --- a/src/registrar/views/__init__.py +++ b/src/registrar/views/__init__.py @@ -14,5 +14,6 @@ from .domain import ( DomainInvitationDeleteView, DomainDeleteUserView, ) +from .user_profile import UserProfileView from .health import * from .index import * diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py new file mode 100644 index 000000000..e24982965 --- /dev/null +++ b/src/registrar/views/user_profile.py @@ -0,0 +1,36 @@ +"""Views for a User Profile. + +""" + +import logging + +from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin +from django.db import IntegrityError +from django.http import HttpResponseRedirect +from django.shortcuts import redirect +from django.urls import reverse +from django.views.generic.edit import FormMixin +from django.conf import settings + +from registrar.models import ( + User, +) +from registrar.views.utility.permission_views import UserProfilePermissionView + + +logger = logging.getLogger(__name__) + + +class UserProfileView(UserProfilePermissionView): + """ + Base View for the Domain. Handles getting and setting the domain + in session cache on GETs. Also provides methods for getting + and setting the domain in cache + """ + + template_name = "profile.html" + + # Override get_object to return the logged-in user + def get_object(self, queryset=None): + return self.request.user # Returns the logged-in user \ No newline at end of file diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index c7083ce48..2208b7570 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -382,3 +382,18 @@ class DomainInvitationPermission(PermissionsLoginMixin): return False return True + + +class UserProfilePermission(PermissionsLoginMixin): + """Permission mixin that redirects to user profile if user + has access, otherwise 403""" + + def has_permission(self): + """Check if this user has access. + + If the user is authenticated, they have access + """ + if not self.request.user.is_authenticated: + return False + + return True diff --git a/src/registrar/views/utility/permission_views.py b/src/registrar/views/utility/permission_views.py index f2752c3b5..6f59cc032 100644 --- a/src/registrar/views/utility/permission_views.py +++ b/src/registrar/views/utility/permission_views.py @@ -2,8 +2,9 @@ import abc # abstract base class +from django.contrib.auth import get_user_model from django.views.generic import DetailView, DeleteView, TemplateView -from registrar.models import Domain, DomainRequest, DomainInvitation +from registrar.models import Domain, DomainRequest, DomainInvitation, User from registrar.models.user_domain_role import UserDomainRole from .mixins import ( @@ -13,6 +14,7 @@ from .mixins import ( DomainInvitationPermission, DomainRequestWizardPermission, UserDeleteDomainRolePermission, + UserProfilePermission, ) import logging @@ -142,3 +144,22 @@ class UserDomainRolePermissionDeleteView(UserDeleteDomainRolePermission, DeleteV # variable name in template context for the model object context_object_name = "userdomainrole" + + +class UserProfilePermissionView(UserProfilePermission, DetailView, abc.ABC): + """Abstract base view for user profile view that enforces permissions. + + This abstract view cannot be instantiated. Actual views must specify + `template_name`. + """ + + # DetailView property for what model this is viewing + model = get_user_model() + # variable name in template context for the model object + context_object_name = "user" + + # Abstract property enforces NotImplementedError on an attribute. + @property + @abc.abstractmethod + def template_name(self): + raise NotImplementedError From aa5b574d01cb785e661f0c4f7e83b0f5f81586c8 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 9 May 2024 11:54:16 -0400 Subject: [PATCH 04/56] wip --- src/registrar/templates/profile.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index 26fa34163..9b43bcec1 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -25,7 +25,6 @@ Edit your User Profile |
    - Your profile {% for field in profile_form %} {{ field }} From f9249f88cdd8f1f2b741f4a39f3d826621508e58 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 14 May 2024 14:19:08 -0400 Subject: [PATCH 05/56] wip but not working, adding in pk --- src/registrar/config/urls.py | 2 +- src/registrar/forms/user_profile.py | 54 +++++++++++++++++++ src/registrar/templates/base.html | 2 +- src/registrar/templates/profile.html | 26 +++++++-- src/registrar/views/user_profile.py | 42 ++++++++++----- .../views/utility/permission_views.py | 11 ++-- 6 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 src/registrar/forms/user_profile.py diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 380cdb803..08383b797 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -179,7 +179,7 @@ urlpatterns = [ name="domain-users-add", ), path( - "user-profile", + "user-profile/", views.UserProfileView.as_view(), name="user-profile", ), diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py new file mode 100644 index 000000000..f436b5fe4 --- /dev/null +++ b/src/registrar/forms/user_profile.py @@ -0,0 +1,54 @@ +from django import forms + +from registrar.models.contact import Contact + +from django.core.validators import MaxLengthValidator +from phonenumber_field.widgets import RegionalPhoneNumberWidget + +class UserProfileForm(forms.ModelForm): + """Form for updating user profile.""" + + class Meta: + model = Contact + fields = ["first_name", "middle_name", "last_name", "title", "email", "phone"] + widgets = { + "first_name": forms.TextInput, + "middle_name": forms.TextInput, + "last_name": forms.TextInput, + "title": forms.TextInput, + "email": forms.EmailInput, + "phone": RegionalPhoneNumberWidget, + } + + # the database fields have blank=True so ModelForm doesn't create + # required fields by default. Use this list in __init__ to mark each + # of these fields as required + required = ["first_name", "last_name", "title", "email", "phone"] + + # def __init__(self, *args, **kwargs): + # super().__init__(*args, **kwargs) + # # take off maxlength attribute for the phone number field + # # which interferes with out input_with_errors template tag + # self.fields["phone"].widget.attrs.pop("maxlength", None) + + # # Define a custom validator for the email field with a custom error message + # email_max_length_validator = MaxLengthValidator(320, message="Response must be less than 320 characters.") + # self.fields["email"].validators.append(email_max_length_validator) + + # for field_name in self.required: + # self.fields[field_name].required = True + + # # Set custom form label + # self.fields["middle_name"].label = "Middle name (optional)" + + # # Set custom error messages + # self.fields["first_name"].error_messages = {"required": "Enter your first name / given name."} + # self.fields["last_name"].error_messages = {"required": "Enter your last name / family name."} + # self.fields["title"].error_messages = { + # "required": "Enter your title or role in your organization (e.g., Chief Information Officer)" + # } + # self.fields["email"].error_messages = { + # "required": "Enter your email address in the required format, like name@example.com." + # } + # self.fields["phone"].error_messages["required"] = "Enter your phone number." + # self.domainInfo = None \ No newline at end of file diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index efaf46dfa..4756f5976 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -158,7 +158,7 @@
  • | - Your profile + Your profile
  • | diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index 9b43bcec1..e91a68042 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -1,9 +1,11 @@ {% extends 'base.html' %} + {% block title %} Edit your User Profile | {% endblock title %} {% load static url_helpers %} +{% load field_helpers %} {% block content %}
    @@ -23,12 +25,26 @@ Edit your User Profile |

    Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.

    {% include "includes/required_fields.html" %} - + + {% csrf_token %}
    - {% for field in profile_form %} - - {{ field }} - {% endfor %} + + {% input_with_errors form.first_name %} + + {% input_with_errors form.middle_name %} + + {% input_with_errors form.last_name %} + + {% input_with_errors form.title %} + + {% input_with_errors form.email %} + + {% with add_class="usa-input--medium" %} + {% input_with_errors form.phone %} + {% endwith %} + + +
    diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index e24982965..b6ec2289d 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -4,17 +4,10 @@ import logging -from django.contrib import messages -from django.contrib.messages.views import SuccessMessageMixin -from django.db import IntegrityError -from django.http import HttpResponseRedirect -from django.shortcuts import redirect -from django.urls import reverse -from django.views.generic.edit import FormMixin -from django.conf import settings - +from registrar.forms.user_profile import UserProfileForm from registrar.models import ( User, + Contact, ) from registrar.views.utility.permission_views import UserProfilePermissionView @@ -29,8 +22,33 @@ class UserProfileView(UserProfilePermissionView): and setting the domain in cache """ + model = Contact template_name = "profile.html" + form_class = UserProfileForm + + # def get(self, request, *args, **kwargs): + # logger.info("in get") + # return super().get(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + logger.info("in get()") + self.object = self.get_object() + context = self.get_context_data(object=self.object) + logger.info(context) + return self.render_to_response(context) - # Override get_object to return the logged-in user - def get_object(self, queryset=None): - return self.request.user # Returns the logged-in user \ No newline at end of file + # def get_context_data(self, **kwargs): + # logger.info("in get_context_data") + # kwargs.setdefault("view", self) + # if self.extra_context is not None: + # kwargs.update(self.extra_context) + # return kwargs + + # # Override get_object to return the logged-in user + # def get_object(self, queryset=None): + # logger.info("in get_object") + # user = self.request.user # get the logged in user + # if hasattr(user, 'contact'): # Check if the user has a contact instance + # logger.info(user.contact) + # return user.contact + # return None \ No newline at end of file diff --git a/src/registrar/views/utility/permission_views.py b/src/registrar/views/utility/permission_views.py index 6f59cc032..5ea9e1590 100644 --- a/src/registrar/views/utility/permission_views.py +++ b/src/registrar/views/utility/permission_views.py @@ -5,6 +5,7 @@ import abc # abstract base class from django.contrib.auth import get_user_model from django.views.generic import DetailView, DeleteView, TemplateView from registrar.models import Domain, DomainRequest, DomainInvitation, User +from registrar.models.contact import Contact from registrar.models.user_domain_role import UserDomainRole from .mixins import ( @@ -153,10 +154,12 @@ class UserProfilePermissionView(UserProfilePermission, DetailView, abc.ABC): `template_name`. """ - # DetailView property for what model this is viewing - model = get_user_model() - # variable name in template context for the model object - context_object_name = "user" + # # DetailView property for what model this is viewing + # model = get_user_model() + # # variable name in template context for the model object + # context_object_name = "user" + model = Contact + context_object_name = "contact" # Abstract property enforces NotImplementedError on an attribute. @property From 5ed20c09c38271f93c7fb5d780afd7d90f45704f Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Tue, 14 May 2024 15:34:45 -0400 Subject: [PATCH 06/56] forms now working --- src/registrar/config/urls.py | 2 +- src/registrar/forms/user_profile.py | 46 ++++++++++++++--------------- src/registrar/templates/base.html | 2 +- src/registrar/views/user_profile.py | 19 ++++++------ 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 08383b797..380cdb803 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -179,7 +179,7 @@ urlpatterns = [ name="domain-users-add", ), path( - "user-profile/", + "user-profile", views.UserProfileView.as_view(), name="user-profile", ), diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index f436b5fe4..fe4d6d609 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -25,30 +25,30 @@ class UserProfileForm(forms.ModelForm): # of these fields as required required = ["first_name", "last_name", "title", "email", "phone"] - # def __init__(self, *args, **kwargs): - # super().__init__(*args, **kwargs) - # # take off maxlength attribute for the phone number field - # # which interferes with out input_with_errors template tag - # self.fields["phone"].widget.attrs.pop("maxlength", None) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # take off maxlength attribute for the phone number field + # which interferes with out input_with_errors template tag + self.fields["phone"].widget.attrs.pop("maxlength", None) - # # Define a custom validator for the email field with a custom error message - # email_max_length_validator = MaxLengthValidator(320, message="Response must be less than 320 characters.") - # self.fields["email"].validators.append(email_max_length_validator) + # Define a custom validator for the email field with a custom error message + email_max_length_validator = MaxLengthValidator(320, message="Response must be less than 320 characters.") + self.fields["email"].validators.append(email_max_length_validator) - # for field_name in self.required: - # self.fields[field_name].required = True + for field_name in self.required: + self.fields[field_name].required = True - # # Set custom form label - # self.fields["middle_name"].label = "Middle name (optional)" + # Set custom form label + self.fields["middle_name"].label = "Middle name (optional)" - # # Set custom error messages - # self.fields["first_name"].error_messages = {"required": "Enter your first name / given name."} - # self.fields["last_name"].error_messages = {"required": "Enter your last name / family name."} - # self.fields["title"].error_messages = { - # "required": "Enter your title or role in your organization (e.g., Chief Information Officer)" - # } - # self.fields["email"].error_messages = { - # "required": "Enter your email address in the required format, like name@example.com." - # } - # self.fields["phone"].error_messages["required"] = "Enter your phone number." - # self.domainInfo = None \ No newline at end of file + # Set custom error messages + self.fields["first_name"].error_messages = {"required": "Enter your first name / given name."} + self.fields["last_name"].error_messages = {"required": "Enter your last name / family name."} + self.fields["title"].error_messages = { + "required": "Enter your title or role in your organization (e.g., Chief Information Officer)" + } + self.fields["email"].error_messages = { + "required": "Enter your email address in the required format, like name@example.com." + } + self.fields["phone"].error_messages["required"] = "Enter your phone number." + self.domainInfo = None \ No newline at end of file diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index 4756f5976..efaf46dfa 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -158,7 +158,7 @@
  • | - Your profile + Your profile
  • | diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index b6ec2289d..3530cccb7 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -33,7 +33,8 @@ class UserProfileView(UserProfilePermissionView): def get(self, request, *args, **kwargs): logger.info("in get()") self.object = self.get_object() - context = self.get_context_data(object=self.object) + form = self.form_class(instance=self.object) + context = self.get_context_data(object=self.object, form=form) logger.info(context) return self.render_to_response(context) @@ -44,11 +45,11 @@ class UserProfileView(UserProfilePermissionView): # kwargs.update(self.extra_context) # return kwargs - # # Override get_object to return the logged-in user - # def get_object(self, queryset=None): - # logger.info("in get_object") - # user = self.request.user # get the logged in user - # if hasattr(user, 'contact'): # Check if the user has a contact instance - # logger.info(user.contact) - # return user.contact - # return None \ No newline at end of file + # Override get_object to return the logged-in user + def get_object(self, queryset=None): + logger.info("in get_object") + user = self.request.user # get the logged in user + if hasattr(user, 'contact'): # Check if the user has a contact instance + logger.info(user.contact) + return user.contact + return None \ No newline at end of file From f34da8029a8cb14c5bb93508ec936fb37a79d755 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 14 May 2024 18:35:58 -0400 Subject: [PATCH 07/56] Active class on Your profile link --- src/registrar/templates/base.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index efaf46dfa..03b7c0f2a 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -134,7 +134,7 @@ {% block usa_overlay %}
    {% endblock %} {% block banner %} -
    +
    {% block logo %} @@ -147,7 +147,7 @@
    {% block usa_nav %} -
  • | - Your profile + {% url 'user-profile' as user_profile_url %} +
  • -
  • +
  • | Sign out {% else %} From b77b5ae689de457f46702146fdf5b4b7c4064755 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 15 May 2024 08:13:19 -0400 Subject: [PATCH 08/56] working code for form submission --- src/registrar/forms/user_profile.py | 5 +++- src/registrar/templates/profile.html | 11 +++++++ src/registrar/views/user_profile.py | 45 +++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index fe4d6d609..c04baa9e5 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -4,6 +4,7 @@ from registrar.models.contact import Contact from django.core.validators import MaxLengthValidator from phonenumber_field.widgets import RegionalPhoneNumberWidget +from registrar.models.utility.domain_helper import DomainHelper class UserProfileForm(forms.ModelForm): """Form for updating user profile.""" @@ -51,4 +52,6 @@ class UserProfileForm(forms.ModelForm): "required": "Enter your email address in the required format, like name@example.com." } self.fields["phone"].error_messages["required"] = "Enter your phone number." - self.domainInfo = None \ No newline at end of file + self.domainInfo = None + + DomainHelper.disable_field(self.fields["email"], disable_required=True) \ No newline at end of file diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index e91a68042..c4c5c5db6 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -19,6 +19,17 @@ Edit your User Profile | Back to manage your domains

    + {# messages block is under the back breadcrumb link #} + {% if messages %} + {% for message in messages %} +
    +
    + {{ message }} +
    +
    + {% endfor %} + {% endif %} + {% include "includes/form_errors.html" with form=form %}

    Your profile

    We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

    Contact information

    diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index 3530cccb7..ea1f1ffdf 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -4,7 +4,10 @@ import logging +from django.contrib import messages +from django.views.generic.edit import FormMixin from registrar.forms.user_profile import UserProfileForm +from django.urls import reverse from registrar.models import ( User, Contact, @@ -15,7 +18,7 @@ from registrar.views.utility.permission_views import UserProfilePermissionView logger = logging.getLogger(__name__) -class UserProfileView(UserProfilePermissionView): +class UserProfileView(UserProfilePermissionView, FormMixin): """ Base View for the Domain. Handles getting and setting the domain in session cache on GETs. Also provides methods for getting @@ -38,13 +41,39 @@ class UserProfileView(UserProfilePermissionView): logger.info(context) return self.render_to_response(context) - # def get_context_data(self, **kwargs): - # logger.info("in get_context_data") - # kwargs.setdefault("view", self) - # if self.extra_context is not None: - # kwargs.update(self.extra_context) - # return kwargs - + def get_success_url(self): + """Redirect to the overview page for the domain.""" + return reverse("user-profile") + + # def post(self, request, *args, **kwargs): + # # Handle POST request logic here + # form = self.get_form() + # if form.is_valid(): + # # Save form data or perform other actions + # return HttpResponseRedirect(reverse('profile_success')) # Redirect to a success page + # else: + # # Form is not valid, re-render the page with errors + # return self.render_to_response(self.get_context_data(form=form)) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + form = self.get_form() + form.instance.id = self.object.id + form.instance.created_at = self.object.created_at + form.instance.user = self.request.user + if form.is_valid(): + return self.form_valid(form) + else: + return self.form_invalid(form) + + def form_valid(self, form): + form.save() + + messages.success(self.request, "Your profile has been updated.") + + # superclass has the redirect + return super().form_valid(form) + # Override get_object to return the logged-in user def get_object(self, queryset=None): logger.info("in get_object") From 58fe2524f338c53de9bc6c27696e67ac566a638e Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 15 May 2024 15:00:21 -0400 Subject: [PATCH 09/56] wip --- src/registrar/config/urls.py | 1 + src/registrar/forms/user_profile.py | 1 + src/registrar/templates/base.html | 2 ++ src/registrar/templates/domain_detail.html | 2 ++ src/registrar/templates/domain_sidebar.html | 2 ++ src/registrar/views/domain.py | 20 +++++++++++++- src/registrar/views/domain_request.py | 21 +++++++++++++-- src/registrar/views/user_profile.py | 29 +++++++-------------- src/registrar/views/utility/error_views.py | 21 ++++++++++----- 9 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py index 380cdb803..158f8e812 100644 --- a/src/registrar/config/urls.py +++ b/src/registrar/config/urls.py @@ -211,6 +211,7 @@ urlpatterns = [ # Rather than dealing with that, we keep everything centralized in one location. # This way, we can share a view for djangooidc, and other pages as we see fit. handler500 = "registrar.views.utility.error_views.custom_500_error_view" +handler403 = "registrar.views.utility.error_views.custom_403_error_view" # we normally would guard these with `if settings.DEBUG` but tests run with # DEBUG = False even when these apps have been loaded because settings.DEBUG diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index c04baa9e5..c825c6352 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -51,6 +51,7 @@ class UserProfileForm(forms.ModelForm): self.fields["email"].error_messages = { "required": "Enter your email address in the required format, like name@example.com." } + # self.fields["email"].widget.attrs["readonly"] = "readonly" self.fields["phone"].error_messages["required"] = "Enter your phone number." self.domainInfo = None diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index 03b7c0f2a..d3a7e3e48 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -156,6 +156,7 @@ {% if user.is_authenticated %} {{ user.email }}
  • + {% if has_profile_feature_flag %}
  • | {% url 'user-profile' as user_profile_url %} @@ -163,6 +164,7 @@ Your profile
  • + {% endif %}
  • | Sign out diff --git a/src/registrar/templates/domain_detail.html b/src/registrar/templates/domain_detail.html index 2b2d45695..67837196f 100644 --- a/src/registrar/templates/domain_detail.html +++ b/src/registrar/templates/domain_detail.html @@ -59,8 +59,10 @@ {% url 'domain-authorizing-official' pk=domain.id as url %} {% include "includes/summary_item.html" with title='Authorizing official' value=domain.domain_info.authorizing_official contact='true' edit_link=url editable=domain.is_editable %} + {% if not has_profile_feature_flag %} {% url 'domain-your-contact-information' pk=domain.id as url %} {% include "includes/summary_item.html" with title='Your contact information' value=request.user.contact contact='true' edit_link=url editable=domain.is_editable %} + {% endif %} {% url 'domain-security-email' pk=domain.id as url %} {% if security_email is not None and security_email not in hidden_security_emails%} diff --git a/src/registrar/templates/domain_sidebar.html b/src/registrar/templates/domain_sidebar.html index 9e00fafa9..7453909a8 100644 --- a/src/registrar/templates/domain_sidebar.html +++ b/src/registrar/templates/domain_sidebar.html @@ -73,6 +73,7 @@
  • + {% if not has_profile_feature_flag %}
  • {% url 'domain-your-contact-information' pk=domain.id as url %}
  • + {% endif %}
  • {% url 'domain-security-email' pk=domain.id as url %} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 9134080a1..2dc096083 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -59,7 +59,7 @@ from epplibwrapper import ( from ..utility.email import send_templated_email, EmailSendingError from .utility import DomainPermissionView, DomainInvitationPermissionDeleteView - +from waffle.decorators import flag_is_active logger = logging.getLogger(__name__) @@ -102,6 +102,13 @@ class DomainBaseView(DomainPermissionView): domain_pk = "domain:" + str(self.kwargs.get("pk")) self.session[domain_pk] = self.object + def get_context_data(self, **kwargs): + """Adjust context from FormMixin for formsets.""" + context = super().get_context_data(**kwargs) + # This is a django waffle flag which toggles features based off of the "flag" table + context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") + return context + class DomainFormBaseView(DomainBaseView, FormMixin): """ @@ -588,6 +595,17 @@ class DomainYourContactInformationView(DomainFormBaseView): # superclass has the redirect return super().form_valid(form) + + def has_permission(self): + """Check if this user has access to this domain. + + The user is in self.request.user and the domain needs to be looked + up from the domain's primary key in self.kwargs["pk"] + """ + if flag_is_active(self.request, "profile_feature"): + return False + + return super().has_permission() class DomainSecurityEmailView(DomainFormBaseView): diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index f93976138..5d1e234a6 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -22,6 +22,8 @@ from .utility import ( DomainRequestWizardPermissionView, ) +from waffle.decorators import flag_is_active + logger = logging.getLogger(__name__) @@ -225,14 +227,14 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView): # will NOT be redirected. The purpose of this is to allow code to # send users "to the domain request wizard" without needing to # know which view is first in the list of steps. + context = self.get_context_data() if self.__class__ == DomainRequestWizard: if request.path_info == self.NEW_URL_NAME: - return render(request, "domain_request_intro.html") + return render(request, "domain_request_intro.html", context) else: return self.goto(self.steps.first) self.steps.current = current_url - context = self.get_context_data() context["forms"] = self.get_forms() # if pending requests exist and user does not have approved domains, @@ -392,6 +394,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView): "is_federal": self.domain_request.is_federal(), "modal_button": modal_button, "modal_heading": modal_heading, + "has_profile_feature_flag": flag_is_active(self.request, "profile_feature") } def get_step_list(self) -> list: @@ -695,6 +698,13 @@ class Finished(DomainRequestWizard): class DomainRequestStatus(DomainRequestPermissionView): template_name = "domain_request_status.html" + def get_context_data(self, **kwargs): + """Adjust context from FormMixin for formsets.""" + context = super().get_context_data(**kwargs) + # This is a django waffle flag which toggles features based off of the "flag" table + context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") + return context + class DomainRequestWithdrawConfirmation(DomainRequestPermissionWithdrawView): """This page will ask user to confirm if they want to withdraw @@ -705,6 +715,13 @@ class DomainRequestWithdrawConfirmation(DomainRequestPermissionWithdrawView): template_name = "domain_request_withdraw_confirmation.html" + def get_context_data(self, **kwargs): + """Adjust context from FormMixin for formsets.""" + context = super().get_context_data(**kwargs) + # This is a django waffle flag which toggles features based off of the "flag" table + context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") + return context + class DomainRequestWithdrawn(DomainRequestPermissionWithdrawView): # this view renders no template diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index ea1f1ffdf..cddb51e48 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -13,7 +13,7 @@ from registrar.models import ( Contact, ) from registrar.views.utility.permission_views import UserProfilePermissionView - +from waffle.decorators import flag_is_active logger = logging.getLogger(__name__) @@ -29,10 +29,6 @@ class UserProfileView(UserProfilePermissionView, FormMixin): template_name = "profile.html" form_class = UserProfileForm - # def get(self, request, *args, **kwargs): - # logger.info("in get") - # return super().get(request, *args, **kwargs) - def get(self, request, *args, **kwargs): logger.info("in get()") self.object = self.get_object() @@ -41,26 +37,21 @@ class UserProfileView(UserProfilePermissionView, FormMixin): logger.info(context) return self.render_to_response(context) + def get_context_data(self, **kwargs): + """Adjust context from FormMixin for formsets.""" + context = super().get_context_data(**kwargs) + # This is a django waffle flag which toggles features based off of the "flag" table + context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") + return context + def get_success_url(self): """Redirect to the overview page for the domain.""" return reverse("user-profile") - # def post(self, request, *args, **kwargs): - # # Handle POST request logic here - # form = self.get_form() - # if form.is_valid(): - # # Save form data or perform other actions - # return HttpResponseRedirect(reverse('profile_success')) # Redirect to a success page - # else: - # # Form is not valid, re-render the page with errors - # return self.render_to_response(self.get_context_data(form=form)) - def post(self, request, *args, **kwargs): self.object = self.get_object() - form = self.get_form() - form.instance.id = self.object.id - form.instance.created_at = self.object.created_at - form.instance.user = self.request.user + form = self.form_class(request.POST, instance=self.object) + if form.is_valid(): return self.form_valid(form) else: diff --git a/src/registrar/views/utility/error_views.py b/src/registrar/views/utility/error_views.py index 48ae628a4..2374277d5 100644 --- a/src/registrar/views/utility/error_views.py +++ b/src/registrar/views/utility/error_views.py @@ -14,19 +14,28 @@ Rather than dealing with that, we keep everything centralized in one location. """ from django.shortcuts import render +from waffle.decorators import flag_is_active def custom_500_error_view(request, context=None): """Used to redirect 500 errors to a custom view""" if context is None: - return render(request, "500.html", status=500) - else: - return render(request, "500.html", context=context, status=500) + context = {} + context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature") + return render(request, "500.html", context=context, status=500) def custom_401_error_view(request, context=None): """Used to redirect 401 errors to a custom view""" if context is None: - return render(request, "401.html", status=401) - else: - return render(request, "401.html", context=context, status=401) + context = {} + context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature") + return render(request, "401.html", context=context, status=401) + + +def custom_403_error_view(request, exception=None, context=None): + """Used to redirect 403 errors to a custom view""" + if context is None: + context = {} + context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature") + return render(request, "403.html", context=context, status=403) From 0a0a251d771e0d94a2516f433dd7f140c7c42627 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 15 May 2024 15:40:32 -0400 Subject: [PATCH 10/56] fix nav --- src/registrar/assets/sass/_theme/_base.scss | 31 +++++++++++++++++++++ src/registrar/templates/base.html | 10 +++---- src/registrar/templates/profile.html | 3 +- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/registrar/assets/sass/_theme/_base.scss b/src/registrar/assets/sass/_theme/_base.scss index 212df992f..de5a200c5 100644 --- a/src/registrar/assets/sass/_theme/_base.scss +++ b/src/registrar/assets/sass/_theme/_base.scss @@ -46,6 +46,37 @@ body { margin-top:units(1); } +.usa-nav__primary-username { + display: inline-block; + padding: units(1) units(2); + max-width: 208px; + overflow: hidden; + text-overflow: ellipsis; + @include at-media(desktop) { + padding: units(2); + max-width: 500px; + } +} + +@include at-media(desktop) { + + .usa-nav__primary-item:not(:first-child) { + position: relative; + } + + .usa-nav__primary-item:not(:first-child)::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + width: 0; /* No width since it's a border */ + height: 50%; + border-left: solid 1px color('base-light'); + transform: translateY(-50%); + } + +} + .section--outlined { background-color: color('white'); border: 1px solid color('base-lighter'); diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index d3a7e3e48..71f89fc14 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -151,22 +151,20 @@ -
      +
      • {% if user.is_authenticated %} - {{ user.email }} + {{ user.email }}
      • {% if has_profile_feature_flag %} -
      • - | +
      • {% url 'user-profile' as user_profile_url %}
      • {% endif %} -
      • - | +
      • Sign out {% else %} Sign in diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index c4c5c5db6..eec905acf 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -32,8 +32,7 @@ Edit your User Profile | {% include "includes/form_errors.html" with form=form %}

        Your profile

        We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

        -

        Contact information

        -

        Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.

        +

        Please note that updating your contact information here will update the contact information for all domains in your account. However, it won’t affect your Login.gov account information.

        {% include "includes/required_fields.html" %}
        From aeef0b76e1096541b2e2d0200c418413767bf196 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Wed, 15 May 2024 15:44:10 -0400 Subject: [PATCH 11/56] cleanup --- src/registrar/assets/sass/_theme/_base.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/registrar/assets/sass/_theme/_base.scss b/src/registrar/assets/sass/_theme/_base.scss index de5a200c5..dc115d69e 100644 --- a/src/registrar/assets/sass/_theme/_base.scss +++ b/src/registrar/assets/sass/_theme/_base.scss @@ -59,7 +59,6 @@ body { } @include at-media(desktop) { - .usa-nav__primary-item:not(:first-child) { position: relative; } @@ -74,7 +73,6 @@ body { border-left: solid 1px color('base-light'); transform: translateY(-50%); } - } .section--outlined { From fef606c1dc9f70b27d21eb68f588b6e36a86010f Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Wed, 15 May 2024 17:10:08 -0400 Subject: [PATCH 12/56] cleaned up code as well as comments --- src/registrar/forms/user_profile.py | 6 ++++-- src/registrar/templates/domain_sidebar.html | 1 + src/registrar/views/domain.py | 8 ++++---- src/registrar/views/domain_request.py | 4 ++-- src/registrar/views/user_profile.py | 19 +++++++++---------- .../views/utility/permission_views.py | 6 ++---- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index c825c6352..a4d3d1d5b 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -27,6 +27,8 @@ class UserProfileForm(forms.ModelForm): required = ["first_name", "last_name", "title", "email", "phone"] def __init__(self, *args, **kwargs): + """Override the inerited __init__ method to update the fields.""" + super().__init__(*args, **kwargs) # take off maxlength attribute for the phone number field # which interferes with out input_with_errors template tag @@ -51,8 +53,8 @@ class UserProfileForm(forms.ModelForm): self.fields["email"].error_messages = { "required": "Enter your email address in the required format, like name@example.com." } - # self.fields["email"].widget.attrs["readonly"] = "readonly" self.fields["phone"].error_messages["required"] = "Enter your phone number." self.domainInfo = None - DomainHelper.disable_field(self.fields["email"], disable_required=True) \ No newline at end of file + DomainHelper.disable_field(self.fields["email"], disable_required=True) + \ No newline at end of file diff --git a/src/registrar/templates/domain_sidebar.html b/src/registrar/templates/domain_sidebar.html index 7453909a8..f99cfd0cf 100644 --- a/src/registrar/templates/domain_sidebar.html +++ b/src/registrar/templates/domain_sidebar.html @@ -74,6 +74,7 @@
      • {% if not has_profile_feature_flag %} + {% comment %}Conditionally display profile link in main nav{% endcomment %}
      • {% url 'domain-your-contact-information' pk=domain.id as url %} Date: Wed, 15 May 2024 17:15:04 -0400 Subject: [PATCH 13/56] formatted for linter --- src/registrar/forms/user_profile.py | 6 +++--- src/registrar/views/domain.py | 4 ++-- src/registrar/views/domain_request.py | 2 +- src/registrar/views/user_profile.py | 11 +++++------ src/registrar/views/utility/mixins.py | 2 +- src/registrar/views/utility/permission_views.py | 3 +-- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index a4d3d1d5b..036b03751 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -6,6 +6,7 @@ from django.core.validators import MaxLengthValidator from phonenumber_field.widgets import RegionalPhoneNumberWidget from registrar.models.utility.domain_helper import DomainHelper + class UserProfileForm(forms.ModelForm): """Form for updating user profile.""" @@ -20,7 +21,7 @@ class UserProfileForm(forms.ModelForm): "email": forms.EmailInput, "phone": RegionalPhoneNumberWidget, } - + # the database fields have blank=True so ModelForm doesn't create # required fields by default. Use this list in __init__ to mark each # of these fields as required @@ -54,7 +55,6 @@ class UserProfileForm(forms.ModelForm): "required": "Enter your email address in the required format, like name@example.com." } self.fields["phone"].error_messages["required"] = "Enter your phone number." - self.domainInfo = None + self.domainInfo = None DomainHelper.disable_field(self.fields["email"], disable_required=True) - \ No newline at end of file diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 8e1edec29..1aed38dc1 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -595,7 +595,7 @@ class DomainYourContactInformationView(DomainFormBaseView): # superclass has the redirect return super().form_valid(form) - + def has_permission(self): """Check if this user has permission to see this view. @@ -604,7 +604,7 @@ class DomainYourContactInformationView(DomainFormBaseView): """ if flag_is_active(self.request, "profile_feature"): return False - + return super().has_permission() diff --git a/src/registrar/views/domain_request.py b/src/registrar/views/domain_request.py index 3b1332709..a90eaf271 100644 --- a/src/registrar/views/domain_request.py +++ b/src/registrar/views/domain_request.py @@ -394,7 +394,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView): "is_federal": self.domain_request.is_federal(), "modal_button": modal_button, "modal_heading": modal_heading, - "has_profile_feature_flag": flag_is_active(self.request, "profile_feature") + "has_profile_feature_flag": flag_is_active(self.request, "profile_feature"), } def get_step_list(self) -> list: diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index bf2af7a3b..231d463ff 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -9,7 +9,6 @@ from django.views.generic.edit import FormMixin from registrar.forms.user_profile import UserProfileForm from django.urls import reverse from registrar.models import ( - User, Contact, ) from registrar.views.utility.permission_views import UserProfilePermissionView @@ -34,7 +33,7 @@ class UserProfileView(UserProfilePermissionView, FormMixin): form = self.form_class(instance=self.object) context = self.get_context_data(object=self.object, form=form) return self.render_to_response(context) - + def get_context_data(self, **kwargs): """Extend get_context_data to include has_profile_feature_flag""" self.get() @@ -42,7 +41,7 @@ class UserProfileView(UserProfilePermissionView, FormMixin): # This is a django waffle flag which toggles features based off of the "flag" table context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") return context - + def get_success_url(self): """Redirect to the user's profile page.""" return reverse("user-profile") @@ -65,10 +64,10 @@ class UserProfileView(UserProfilePermissionView, FormMixin): # superclass has the redirect return super().form_valid(form) - + def get_object(self, queryset=None): """Override get_object to return the logged-in user's contact""" user = self.request.user # get the logged in user - if hasattr(user, 'contact'): # Check if the user has a contact instance + if hasattr(user, "contact"): # Check if the user has a contact instance return user.contact - return None \ No newline at end of file + return None diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index 2208b7570..78bdf0fd7 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -382,7 +382,7 @@ class DomainInvitationPermission(PermissionsLoginMixin): return False return True - + class UserProfilePermission(PermissionsLoginMixin): """Permission mixin that redirects to user profile if user diff --git a/src/registrar/views/utility/permission_views.py b/src/registrar/views/utility/permission_views.py index ee86c3f29..d35647af2 100644 --- a/src/registrar/views/utility/permission_views.py +++ b/src/registrar/views/utility/permission_views.py @@ -2,9 +2,8 @@ import abc # abstract base class -from django.contrib.auth import get_user_model from django.views.generic import DetailView, DeleteView, TemplateView -from registrar.models import Domain, DomainRequest, DomainInvitation, User +from registrar.models import Domain, DomainRequest, DomainInvitation from registrar.models.contact import Contact from registrar.models.user_domain_role import UserDomainRole From 5bfd6c867fc489d85370492cb660ed4516f36fbf Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Wed, 15 May 2024 15:25:00 -0600 Subject: [PATCH 14/56] Add initial setting config --- src/djangooidc/views.py | 2 ++ src/registrar/config/settings.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index 815df4ecf..a50a83cc9 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -95,6 +95,8 @@ def login_callback(request): # if not satisfied, redirect user to login with stepped up acr_value if _requires_step_up_auth(userinfo): # add acr_value to request.session + + # LOOK HERE this is basically the flag that indicates that we should proceed request.session["acr_value"] = CLIENT.get_step_up_acr_value() return CLIENT.create_authn_request(request.session) user = authenticate(request=request, **userinfo) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 9f31ffc2c..7bda5e10d 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -563,6 +563,8 @@ OIDC_PROVIDERS = { "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", + "vtr": ["Pb","P1"], + "vtm": "https://developer.login.gov/vot-trust-framework", }, "client_registration": { "client_id": "cisa_dotgov_registrar", @@ -581,6 +583,10 @@ OIDC_PROVIDERS = { "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", + # "P1" is the current IdV option; "Pb" stands for 'biometric' + "vtr": ["Pb","P1"], + # Stand in replacement for the step_up_acr_value for ial2 + "vtm": "https://developer.login.gov/vot-trust-framework", }, "client_registration": { "client_id": ("urn:gov:cisa:openidconnect.profiles:sp:sso:cisa:dotgov_registrar"), From 10ae65c0b09b7062c10ab21907e81a4ce2f8f098 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Wed, 15 May 2024 16:06:49 -0600 Subject: [PATCH 15/56] linted --- src/registrar/views/domain.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index eb6f7d2c5..b9ade278b 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -778,20 +778,19 @@ class DomainAddUserView(DomainFormBaseView): """Make a Domain invitation for this email and redirect with a message.""" # Check to see if an invite has already been sent (NOTE: we do not want to create an invite just yet.) try: - invite = DomainInvitation.objects.get(email=email_address, domain=self.object) # that invitation already existed messages.warning( self.request, f"{email_address} has already been invited to this domain.", ) except DomainInvitation.DoesNotExist: - #Try to send the invitation. If it succeeds, add it to the DomainInvitation table. + # Try to send the invitation. If it succeeds, add it to the DomainInvitation table. try: self._send_domain_invitation_email(email=email_address, requestor=requestor) - except EmailSendingError as exc: + except EmailSendingError: messages.warning(self.request, "Could not send email invitation.") else: - #(NOTE: only create a domainInvitation if the e-mail sends correctly) + # (NOTE: only create a domainInvitation if the e-mail sends correctly) DomainInvitation.objects.get_or_create(email=email_address, domain=self.object) return redirect(self.get_success_url()) @@ -809,7 +808,7 @@ class DomainAddUserView(DomainFormBaseView): # if user already exists then just send an email try: self._send_domain_invitation_email(requested_email, requestor, add_success=False) - except Exception as exc: + except Exception: messages.warning(self.request, "Could not send email invitation.") try: From d1e0381886a5c142097a172f341b2ec5ad822d1b Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 16 May 2024 08:03:29 -0400 Subject: [PATCH 16/56] started unit tests, fixed bug in user_profile --- src/registrar/tests/test_views.py | 72 +++++++++++++++++++++++++++++ src/registrar/views/user_profile.py | 12 ++++- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index 217e24b9a..c32927012 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -18,6 +18,7 @@ from registrar.models import ( DomainRequest, DomainInformation, ) +from waffle.testutils import override_flag import logging logger = logging.getLogger(__name__) @@ -505,3 +506,74 @@ class HomeTests(TestWithUser): with less_console_noise(): response = self.client.get("/request/", follow=True) self.assertEqual(response.status_code, 403) + +class UserProfileTests(TestWithUser): + """A series of tests that target your profile functionality""" + + def setUp(self): + super().setUp() + self.client.force_login(self.user) + + def tearDown(self): + super().tearDown() + Contact.objects.all().delete() + + + +# - domain_your_contact_403_when_profile_feature_turned_on +# - profile_submission (see your contact tests) +# - profile_page_403_when_profile_feature_turned_off +# - request_withdraw_main_nav_with_profile_feature_turned_on +# - domain_main_nav_with_profile_feature_turned_on +# - error_500_main_nav_with_profile_feature_turned_on +# - error_403_main_nav_with_profile_feature_turned_on +# - error_401_main_nav_with_profile_feature_turned_on +# - request_withdraw_main_nav_with_profile_feature_turned_off +# - domain_main_nav_with_profile_feature_turned_off +# - error_500_main_nav_with_profile_feature_turned_off +# - error_403_main_nav_with_profile_feature_turned_off +# - error_401_main_nav_with_profile_feature_turned_off + + + @less_console_noise_decorator + def test_home_page_main_nav_with_profile_feature_on(self): + """test that Your profile is in main nave when profile_feature is on""" + with override_flag('profile_feature', active=True): + response = self.client.get("/") + self.assertContains(response, "Your profile") + + @less_console_noise_decorator + def test_home_page_main_nav_with_profile_feature_off(self): + """test that Your profile is not in main nave when profile_feature is off""" + with override_flag('profile_feature', active=False): + response = self.client.get("/") + self.assertNotContains(response, "Your profile") + + @less_console_noise_decorator + def test_new_request_main_nav_with_profile_feature_on(self): + """test that Your profile is in main nave when profile_feature is on""" + with override_flag('profile_feature', active=True): + response = self.client.get("/request/") + self.assertContains(response, "Your profile") + + @less_console_noise_decorator + def test_new_request_main_nav_with_profile_feature_off(self): + """test that Your profile is not in main nave when profile_feature is off""" + with override_flag('profile_feature', active=False): + response = self.client.get("/request/") + self.assertNotContains(response, "Your profile") + + @less_console_noise_decorator + def test_user_profile_main_nav_with_profile_feature_on(self): + """test that Your profile is in main nave when profile_feature is on""" + with override_flag('profile_feature', active=True): + response = self.client.get("/user-profile") + self.assertContains(response, "Your profile") + + @less_console_noise_decorator + def test_user_profile_returns_403_when_feature_off(self): + """test that Your profile is not in main nave when profile_feature is off""" + with override_flag('profile_feature', active=False): + response = self.client.get("/user-profile") + self.assertEqual(response.status_code, 403) + diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index 231d463ff..d40103519 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -36,7 +36,6 @@ class UserProfileView(UserProfilePermissionView, FormMixin): def get_context_data(self, **kwargs): """Extend get_context_data to include has_profile_feature_flag""" - self.get() context = super().get_context_data(**kwargs) # This is a django waffle flag which toggles features based off of the "flag" table context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") @@ -71,3 +70,14 @@ class UserProfileView(UserProfilePermissionView, FormMixin): if hasattr(user, "contact"): # Check if the user has a contact instance return user.contact return None + + def has_permission(self): + """Check if this user has permission to see this view. + + In addition to permissions for the user, check that the profile_feature waffle flag + is not turned on. + """ + if not flag_is_active(self.request, "profile_feature"): + return False + + return super().has_permission() From 164abe06aa80beb21442d9e493390f1d9e72b57d Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 16 May 2024 08:43:38 -0400 Subject: [PATCH 17/56] added more tests --- src/registrar/tests/test_views.py | 45 +++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index c32927012..544107951 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -6,6 +6,7 @@ from api.tests.common import less_console_noise_decorator from registrar.models.contact import Contact from registrar.models.domain import Domain from registrar.models.draft_domain import DraftDomain +from registrar.models.public_contact import PublicContact from registrar.models.user import User from registrar.models.user_domain_role import UserDomainRole from registrar.views.domain import DomainNameserversView @@ -513,16 +514,22 @@ class UserProfileTests(TestWithUser): def setUp(self): super().setUp() self.client.force_login(self.user) + self.domain, _ = Domain.objects.get_or_create(name="sampledomain.gov", state=Domain.State.READY) + self.role, _ = UserDomainRole.objects.get_or_create( + user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER + ) def tearDown(self): super().tearDown() + PublicContact.objects.filter(domain=self.domain).delete() + self.role.delete() + self.domain.delete() Contact.objects.all().delete() # - domain_your_contact_403_when_profile_feature_turned_on # - profile_submission (see your contact tests) -# - profile_page_403_when_profile_feature_turned_off # - request_withdraw_main_nav_with_profile_feature_turned_on # - domain_main_nav_with_profile_feature_turned_on # - error_500_main_nav_with_profile_feature_turned_on @@ -537,43 +544,65 @@ class UserProfileTests(TestWithUser): @less_console_noise_decorator def test_home_page_main_nav_with_profile_feature_on(self): - """test that Your profile is in main nave when profile_feature is on""" + """test that Your profile is in main nav of home page when profile_feature is on""" with override_flag('profile_feature', active=True): response = self.client.get("/") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_home_page_main_nav_with_profile_feature_off(self): - """test that Your profile is not in main nave when profile_feature is off""" + """test that Your profile is not in main nav of home page when profile_feature is off""" with override_flag('profile_feature', active=False): response = self.client.get("/") self.assertNotContains(response, "Your profile") @less_console_noise_decorator def test_new_request_main_nav_with_profile_feature_on(self): - """test that Your profile is in main nave when profile_feature is on""" + """test that Your profile is in main nav of new request when profile_feature is on""" with override_flag('profile_feature', active=True): response = self.client.get("/request/") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_new_request_main_nav_with_profile_feature_off(self): - """test that Your profile is not in main nave when profile_feature is off""" + """test that Your profile is not in main nav of new request when profile_feature is off""" with override_flag('profile_feature', active=False): response = self.client.get("/request/") self.assertNotContains(response, "Your profile") @less_console_noise_decorator def test_user_profile_main_nav_with_profile_feature_on(self): - """test that Your profile is in main nave when profile_feature is on""" + """test that Your profile is in main nav of user profile when profile_feature is on""" with override_flag('profile_feature', active=True): response = self.client.get("/user-profile") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_user_profile_returns_403_when_feature_off(self): - """test that Your profile is not in main nave when profile_feature is off""" + """test that Your profile returns 403 when profile_feature is off""" with override_flag('profile_feature', active=False): response = self.client.get("/user-profile") - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 403) + # TODO: Having trouble testing the content of the 403 response for inclusion of Your profile + @less_console_noise_decorator + def test_domain_detail_profile_feature_on(self): + """test that domain detail view when profile_feature is on""" + with override_flag('profile_feature', active=True): + response = self.client.get(reverse("domain", args=[self.domain.pk])) + self.assertContains(response, "Your profile") + self.assertNotContains(response, "Your contact information") + + @less_console_noise_decorator + def test_domain_your_contact_information_when_profile_feature_off(self): + """test that Your contact information is accessible when profile_feature is off""" + with override_flag('profile_feature', active=False): + response = self.client.get(f"/domain/{self.domain.id}/your-contact-information") + self.assertContains(response, "Your contact information") + + @less_console_noise_decorator + def test_domain_your_contact_information_when_profile_feature_on(self): + """test that Your contact information is not accessible when profile feature is on""" + with override_flag('profile_feature', active=True): + response = self.client.get(f"/domain/{self.domain.id}/your-contact-information") + self.assertEqual(response.status_code, 403) From 28e18e705bdadef4bfdb0195c2016718d61ad04d Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 12:14:03 -0600 Subject: [PATCH 18/56] Add biometric --- src/djangooidc/oidc.py | 16 +++++++++++++--- src/djangooidc/views.py | 10 +++++++--- src/registrar/config/settings.py | 4 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 95ed322f5..1133a8b39 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -14,6 +14,7 @@ from oic.oic import AuthorizationRequest, AuthorizationResponse, RegistrationRes from oic.oic.message import AccessTokenResponse from oic.utils.authn.client import CLIENT_AUTHN_METHOD from oic.utils import keyio +from urllib.parse import urlparse, urlunparse, urlencode, parse_qs from . import exceptions as o_e @@ -84,6 +85,7 @@ class Client(oic.Client): def create_authn_request( self, session, + add_acr=True, extra_args=None, ): """Step 2: Construct a login URL at OP's domain and send the user to it.""" @@ -100,10 +102,10 @@ class Client(oic.Client): "state": session["state"], "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0], - # acr_value may be passed in session if overriding, as in the case - # of step up auth, otherwise get from settings.py - "acr_values": session.get("acr_value") or self.behaviour.get("acr_value"), } + if add_acr: + request_args["acr_values"] = session.get("acr_value") or self.behaviour.get("acr_value") + request_args["vtr"] = json.dumps(self.behaviour.get("vtr")) if extra_args is not None: request_args.update(extra_args) @@ -126,6 +128,7 @@ class Client(oic.Client): method="GET", request_args=request_args, ) + logger.debug("body: %s" % body) logger.debug("URL: %s" % url) logger.debug("headers: %s" % headers) @@ -141,6 +144,7 @@ class Client(oic.Client): if headers: for key, value in headers.items(): response[key] = value + print(f"create auth => response is {response}") except Exception as err: logger.error(err) logger.error("Failed to create redirect object for %s" % state) @@ -294,6 +298,12 @@ class Client(oic.Client): this helper function is called from djangooidc views""" return self.behaviour.get("step_up_acr_value") + def get_vtm_value(self): + return self.behaviour.get("vtm") + + def get_vtr_value(self): + return self.behaviour.get("vtr") + def __repr__(self): return "Client {} {} {}".format( self.client_id, diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index a50a83cc9..05984e938 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -96,9 +96,13 @@ def login_callback(request): if _requires_step_up_auth(userinfo): # add acr_value to request.session - # LOOK HERE this is basically the flag that indicates that we should proceed - request.session["acr_value"] = CLIENT.get_step_up_acr_value() - return CLIENT.create_authn_request(request.session) + if "acr_value" in request.session: + request.session.pop("acr_value") + extra_args = { + "vtm": CLIENT.get_vtm_value(), + } + print(f"session is: {request.session}") + return CLIENT.create_authn_request(request.session, add_acr=False, extra_args=extra_args) user = authenticate(request=request, **userinfo) if user: diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 7bda5e10d..781b67d5a 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -497,13 +497,13 @@ LOGGING = { # OpenID Connect logger "oic": { "handlers": ["console"], - "level": "INFO", + "level": "DEBUG", "propagate": False, }, # Django wrapper for OpenID Connect "djangooidc": { "handlers": ["console"], - "level": "INFO", + "level": "DEBUG", "propagate": False, }, # Our app! From a90b124b93b820c29d1ce268edb1f4f01dc8594c Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 16 May 2024 14:19:01 -0400 Subject: [PATCH 19/56] updated tests, updated waffle_flag decorator to replace has_permission --- src/registrar/tests/test_views.py | 87 +++++++++++++++++++++++++---- src/registrar/views/domain.py | 17 ++---- src/registrar/views/user_profile.py | 18 ++---- 3 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index 544107951..ad1745605 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -1,6 +1,8 @@ from datetime import date from django.test import Client, TestCase, override_settings from django.contrib.auth import get_user_model +from django_webtest import WebTest # type: ignore +from django.conf import settings from api.tests.common import less_console_noise_decorator from registrar.models.contact import Contact @@ -508,7 +510,7 @@ class HomeTests(TestWithUser): response = self.client.get("/request/", follow=True) self.assertEqual(response.status_code, 403) -class UserProfileTests(TestWithUser): +class UserProfileTests(TestWithUser, WebTest): """A series of tests that target your profile functionality""" def setUp(self): @@ -528,15 +530,10 @@ class UserProfileTests(TestWithUser): -# - domain_your_contact_403_when_profile_feature_turned_on # - profile_submission (see your contact tests) -# - request_withdraw_main_nav_with_profile_feature_turned_on -# - domain_main_nav_with_profile_feature_turned_on # - error_500_main_nav_with_profile_feature_turned_on # - error_403_main_nav_with_profile_feature_turned_on # - error_401_main_nav_with_profile_feature_turned_on -# - request_withdraw_main_nav_with_profile_feature_turned_off -# - domain_main_nav_with_profile_feature_turned_off # - error_500_main_nav_with_profile_feature_turned_off # - error_403_main_nav_with_profile_feature_turned_off # - error_401_main_nav_with_profile_feature_turned_off @@ -578,12 +575,11 @@ class UserProfileTests(TestWithUser): self.assertContains(response, "Your profile") @less_console_noise_decorator - def test_user_profile_returns_403_when_feature_off(self): - """test that Your profile returns 403 when profile_feature is off""" + def test_user_profile_returns_404_when_feature_off(self): + """test that Your profile returns 404 when profile_feature is off""" with override_flag('profile_feature', active=False): response = self.client.get("/user-profile") - self.assertEqual(response.status_code, 403) - # TODO: Having trouble testing the content of the 403 response for inclusion of Your profile + self.assertEqual(response.status_code, 404) @less_console_noise_decorator def test_domain_detail_profile_feature_on(self): @@ -605,4 +601,73 @@ class UserProfileTests(TestWithUser): """test that Your contact information is not accessible when profile feature is on""" with override_flag('profile_feature', active=True): response = self.client.get(f"/domain/{self.domain.id}/your-contact-information") - self.assertEqual(response.status_code, 403) + self.assertEqual(response.status_code, 404) + + @less_console_noise_decorator + def test_request_when_profile_feature_on(self): + """test that Your profile is in request page when profile feature is on""" + + contact_user, _ = Contact.objects.get_or_create(user=self.user) + site = DraftDomain.objects.create(name="igorville.gov") + domain_request = DomainRequest.objects.create( + creator=self.user, + requested_domain=site, + status=DomainRequest.DomainRequestStatus.SUBMITTED, + authorizing_official=contact_user, + submitter=contact_user, + ) + with override_flag('profile_feature', active=True): + response = self.client.get(f"/domain-request/{domain_request.id}") + self.assertContains(response, "Your profile") + response = self.client.get(f"/domain-request/{domain_request.id}/withdraw") + self.assertContains(response, "Your profile") + # cleanup + domain_request.delete() + site.delete() + + @less_console_noise_decorator + def test_request_when_profile_feature_off(self): + """test that Your profile is not in request page when profile feature is off""" + + contact_user, _ = Contact.objects.get_or_create(user=self.user) + site = DraftDomain.objects.create(name="igorville.gov") + domain_request = DomainRequest.objects.create( + creator=self.user, + requested_domain=site, + status=DomainRequest.DomainRequestStatus.SUBMITTED, + authorizing_official=contact_user, + submitter=contact_user, + ) + with override_flag('profile_feature', active=False): + response = self.client.get(f"/domain-request/{domain_request.id}") + self.assertNotContains(response, "Your profile") + response = self.client.get(f"/domain-request/{domain_request.id}/withdraw") + self.assertNotContains(response, "Your profile") + # cleanup + domain_request.delete() + site.delete() + + @less_console_noise_decorator + def test_user_profile_form_submission(self): + """test user profile form submission""" + self.app.set_user(self.user.username) + with override_flag('profile_feature', active=True): + profile_page = self.app.get(reverse("user-profile")) + session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + profile_form = profile_page.form + profile_page = profile_form.submit() + + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + # assert that first result contains errors + self.assertContains(profile_page, "Enter your title") + self.assertContains(profile_page, "Enter your phone number") + profile_form = profile_page.form + profile_form["title"] = "sample title" + profile_form["phone"] = "(201) 555-1212" + profile_page = profile_form.submit() + self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) + profile_page = profile_page.follow() + self.assertEqual(profile_page.status_code, 200) + self.assertContains(profile_page, "Your profile has been updated") + diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 1aed38dc1..0e8804fe4 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -59,7 +59,7 @@ from epplibwrapper import ( from ..utility.email import send_templated_email, EmailSendingError from .utility import DomainPermissionView, DomainInvitationPermissionDeleteView -from waffle.decorators import flag_is_active +from waffle.decorators import flag_is_active, waffle_flag logger = logging.getLogger(__name__) @@ -575,6 +575,10 @@ class DomainYourContactInformationView(DomainFormBaseView): template_name = "domain_your_contact_information.html" form_class = ContactForm + @waffle_flag("!profile_feature") + def dispatch(self, request, *args, **kwargs): + return super().dispatch(request, *args, **kwargs) + def get_form_kwargs(self, *args, **kwargs): """Add domain_info.submitter instance to make a bound form.""" form_kwargs = super().get_form_kwargs(*args, **kwargs) @@ -596,17 +600,6 @@ class DomainYourContactInformationView(DomainFormBaseView): # superclass has the redirect return super().form_valid(form) - def has_permission(self): - """Check if this user has permission to see this view. - - In addition to permissions for the user, check that the profile_feature waffle flag - is not turned on. - """ - if flag_is_active(self.request, "profile_feature"): - return False - - return super().has_permission() - class DomainSecurityEmailView(DomainFormBaseView): """Domain security email editing view.""" diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index d40103519..865a1bd52 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -12,11 +12,10 @@ from registrar.models import ( Contact, ) from registrar.views.utility.permission_views import UserProfilePermissionView -from waffle.decorators import flag_is_active +from waffle.decorators import flag_is_active, waffle_flag logger = logging.getLogger(__name__) - class UserProfileView(UserProfilePermissionView, FormMixin): """ Base View for the User Profile. Handles getting and setting the User Profile @@ -34,6 +33,10 @@ class UserProfileView(UserProfilePermissionView, FormMixin): context = self.get_context_data(object=self.object, form=form) return self.render_to_response(context) + @waffle_flag("profile_feature") + def dispatch(self, request, *args, **kwargs): + return super().dispatch(request, *args, **kwargs) + def get_context_data(self, **kwargs): """Extend get_context_data to include has_profile_feature_flag""" context = super().get_context_data(**kwargs) @@ -70,14 +73,3 @@ class UserProfileView(UserProfilePermissionView, FormMixin): if hasattr(user, "contact"): # Check if the user has a contact instance return user.contact return None - - def has_permission(self): - """Check if this user has permission to see this view. - - In addition to permissions for the user, check that the profile_feature waffle flag - is not turned on. - """ - if not flag_is_active(self.request, "profile_feature"): - return False - - return super().has_permission() From f3f1b896bba3679c2957cc4a2cc81b9f723411c5 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 12:37:14 -0600 Subject: [PATCH 20/56] Fix infinite loop --- src/djangooidc/oidc.py | 15 +++++++++++---- src/djangooidc/views.py | 5 +++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 1133a8b39..404bc96c2 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -104,8 +104,9 @@ class Client(oic.Client): "redirect_uri": self.registration_response["redirect_uris"][0], } if add_acr: - request_args["acr_values"] = session.get("acr_value") or self.behaviour.get("acr_value") - request_args["vtr"] = json.dumps(self.behaviour.get("vtr")) + request_args["acr_values"] = self.behaviour.get("acr_value") + else: + request_args["vtr"] = json.dumps(self.behaviour.get("vtr")) if extra_args is not None: request_args.update(extra_args) @@ -228,9 +229,15 @@ class Client(oic.Client): if isinstance(info_response, ErrorResponse): logger.error("Unable to get user info (%s) for %s" % (info_response.get("error", ""), state)) raise o_e.AuthenticationFailed(locator=state) + info_response_dict = info_response.to_dict() - logger.debug("user info: %s" % info_response) - return info_response.to_dict() + if "needs_biometric_validation" in session and session["needs_biometric_validation"]: + if "vtm" in session: + info_response_dict["vtm"] = session.get("vtm") + if "vtr" in session: + info_response_dict["vtr"] = session.get("vtr") + logger.debug("user info: %s" % info_response_dict) + return info_response_dict def _request_token(self, state, code, session): """Request a token from OP to allow us to then request user info.""" diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index 05984e938..f817cc4d0 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -93,14 +93,15 @@ def login_callback(request): userinfo = CLIENT.callback(query, request.session) # test for need for identity verification and if it is satisfied # if not satisfied, redirect user to login with stepped up acr_value + request.session["needs_biometric_validation"] = False if _requires_step_up_auth(userinfo): # add acr_value to request.session - if "acr_value" in request.session: request.session.pop("acr_value") extra_args = { "vtm": CLIENT.get_vtm_value(), } + request.session["needs_biometric_validation"] = True print(f"session is: {request.session}") return CLIENT.create_authn_request(request.session, add_acr=False, extra_args=extra_args) user = authenticate(request=request, **userinfo) @@ -151,7 +152,7 @@ def _requires_step_up_auth(userinfo): acr_value = userinfo.get("ial", "") uuid = userinfo.get("sub", "") email = userinfo.get("email", "") - if acr_value != step_up_acr_value: + if acr_value != step_up_acr_value and (not userinfo.get("vtm") and not userinfo.get("vtr")): # The acr of this attempt is not at the highest level # so check if the user needs the higher level return User.needs_identity_verification(email, uuid) From cd94342d5caea141d89fae25937f6a115d1f0ec2 Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 16 May 2024 14:38:03 -0400 Subject: [PATCH 21/56] formatted for linter --- src/registrar/tests/test_views.py | 52 +++++++++++++---------------- src/registrar/views/domain.py | 6 ++-- src/registrar/views/user_profile.py | 6 ++-- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index ad1745605..793be94a6 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -510,6 +510,7 @@ class HomeTests(TestWithUser): response = self.client.get("/request/", follow=True) self.assertEqual(response.status_code, 403) + class UserProfileTests(TestWithUser, WebTest): """A series of tests that target your profile functionality""" @@ -528,63 +529,59 @@ class UserProfileTests(TestWithUser, WebTest): self.domain.delete() Contact.objects.all().delete() + # - error_500_main_nav_with_profile_feature_turned_on + # - error_403_main_nav_with_profile_feature_turned_on + # - error_401_main_nav_with_profile_feature_turned_on + # - error_500_main_nav_with_profile_feature_turned_off + # - error_403_main_nav_with_profile_feature_turned_off + # - error_401_main_nav_with_profile_feature_turned_off - -# - profile_submission (see your contact tests) -# - error_500_main_nav_with_profile_feature_turned_on -# - error_403_main_nav_with_profile_feature_turned_on -# - error_401_main_nav_with_profile_feature_turned_on -# - error_500_main_nav_with_profile_feature_turned_off -# - error_403_main_nav_with_profile_feature_turned_off -# - error_401_main_nav_with_profile_feature_turned_off - - @less_console_noise_decorator def test_home_page_main_nav_with_profile_feature_on(self): """test that Your profile is in main nav of home page when profile_feature is on""" - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get("/") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_home_page_main_nav_with_profile_feature_off(self): """test that Your profile is not in main nav of home page when profile_feature is off""" - with override_flag('profile_feature', active=False): + with override_flag("profile_feature", active=False): response = self.client.get("/") self.assertNotContains(response, "Your profile") @less_console_noise_decorator def test_new_request_main_nav_with_profile_feature_on(self): """test that Your profile is in main nav of new request when profile_feature is on""" - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get("/request/") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_new_request_main_nav_with_profile_feature_off(self): """test that Your profile is not in main nav of new request when profile_feature is off""" - with override_flag('profile_feature', active=False): + with override_flag("profile_feature", active=False): response = self.client.get("/request/") self.assertNotContains(response, "Your profile") @less_console_noise_decorator def test_user_profile_main_nav_with_profile_feature_on(self): """test that Your profile is in main nav of user profile when profile_feature is on""" - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get("/user-profile") self.assertContains(response, "Your profile") @less_console_noise_decorator def test_user_profile_returns_404_when_feature_off(self): """test that Your profile returns 404 when profile_feature is off""" - with override_flag('profile_feature', active=False): + with override_flag("profile_feature", active=False): response = self.client.get("/user-profile") self.assertEqual(response.status_code, 404) @less_console_noise_decorator def test_domain_detail_profile_feature_on(self): """test that domain detail view when profile_feature is on""" - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get(reverse("domain", args=[self.domain.pk])) self.assertContains(response, "Your profile") self.assertNotContains(response, "Your contact information") @@ -592,21 +589,21 @@ class UserProfileTests(TestWithUser, WebTest): @less_console_noise_decorator def test_domain_your_contact_information_when_profile_feature_off(self): """test that Your contact information is accessible when profile_feature is off""" - with override_flag('profile_feature', active=False): + with override_flag("profile_feature", active=False): response = self.client.get(f"/domain/{self.domain.id}/your-contact-information") self.assertContains(response, "Your contact information") @less_console_noise_decorator def test_domain_your_contact_information_when_profile_feature_on(self): """test that Your contact information is not accessible when profile feature is on""" - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get(f"/domain/{self.domain.id}/your-contact-information") - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 404) @less_console_noise_decorator def test_request_when_profile_feature_on(self): """test that Your profile is in request page when profile feature is on""" - + contact_user, _ = Contact.objects.get_or_create(user=self.user) site = DraftDomain.objects.create(name="igorville.gov") domain_request = DomainRequest.objects.create( @@ -616,9 +613,9 @@ class UserProfileTests(TestWithUser, WebTest): authorizing_official=contact_user, submitter=contact_user, ) - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): response = self.client.get(f"/domain-request/{domain_request.id}") - self.assertContains(response, "Your profile") + self.assertContains(response, "Your profile") response = self.client.get(f"/domain-request/{domain_request.id}/withdraw") self.assertContains(response, "Your profile") # cleanup @@ -628,7 +625,7 @@ class UserProfileTests(TestWithUser, WebTest): @less_console_noise_decorator def test_request_when_profile_feature_off(self): """test that Your profile is not in request page when profile feature is off""" - + contact_user, _ = Contact.objects.get_or_create(user=self.user) site = DraftDomain.objects.create(name="igorville.gov") domain_request = DomainRequest.objects.create( @@ -638,9 +635,9 @@ class UserProfileTests(TestWithUser, WebTest): authorizing_official=contact_user, submitter=contact_user, ) - with override_flag('profile_feature', active=False): + with override_flag("profile_feature", active=False): response = self.client.get(f"/domain-request/{domain_request.id}") - self.assertNotContains(response, "Your profile") + self.assertNotContains(response, "Your profile") response = self.client.get(f"/domain-request/{domain_request.id}/withdraw") self.assertNotContains(response, "Your profile") # cleanup @@ -651,7 +648,7 @@ class UserProfileTests(TestWithUser, WebTest): def test_user_profile_form_submission(self): """test user profile form submission""" self.app.set_user(self.user.username) - with override_flag('profile_feature', active=True): + with override_flag("profile_feature", active=True): profile_page = self.app.get(reverse("user-profile")) session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) @@ -670,4 +667,3 @@ class UserProfileTests(TestWithUser, WebTest): profile_page = profile_page.follow() self.assertEqual(profile_page.status_code, 200) self.assertContains(profile_page, "Your profile has been updated") - diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 0e8804fe4..e5903a854 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -575,10 +575,10 @@ class DomainYourContactInformationView(DomainFormBaseView): template_name = "domain_your_contact_information.html" form_class = ContactForm - @waffle_flag("!profile_feature") - def dispatch(self, request, *args, **kwargs): + @waffle_flag("!profile_feature") # type: ignore + def dispatch(self, request, *args, **kwargs): # type: ignore return super().dispatch(request, *args, **kwargs) - + def get_form_kwargs(self, *args, **kwargs): """Add domain_info.submitter instance to make a bound form.""" form_kwargs = super().get_form_kwargs(*args, **kwargs) diff --git a/src/registrar/views/user_profile.py b/src/registrar/views/user_profile.py index 865a1bd52..b386e6a62 100644 --- a/src/registrar/views/user_profile.py +++ b/src/registrar/views/user_profile.py @@ -14,8 +14,10 @@ from registrar.models import ( from registrar.views.utility.permission_views import UserProfilePermissionView from waffle.decorators import flag_is_active, waffle_flag + logger = logging.getLogger(__name__) + class UserProfileView(UserProfilePermissionView, FormMixin): """ Base View for the User Profile. Handles getting and setting the User Profile @@ -33,8 +35,8 @@ class UserProfileView(UserProfilePermissionView, FormMixin): context = self.get_context_data(object=self.object, form=form) return self.render_to_response(context) - @waffle_flag("profile_feature") - def dispatch(self, request, *args, **kwargs): + @waffle_flag("profile_feature") # type: ignore + def dispatch(self, request, *args, **kwargs): # type: ignore return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): From 2002429fb95903dcd8632cdf820858b85b5a1392 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 16 May 2024 14:52:45 -0400 Subject: [PATCH 22/56] finish template --- .../templates/includes/input_with_errors.html | 2 +- src/registrar/templates/profile.html | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/registrar/templates/includes/input_with_errors.html b/src/registrar/templates/includes/input_with_errors.html index 56bd0b111..e47c9cc53 100644 --- a/src/registrar/templates/includes/input_with_errors.html +++ b/src/registrar/templates/includes/input_with_errors.html @@ -76,7 +76,7 @@ error messages, if necessary. {% endif %} -{% if widget.attrs.maxlength %} +{% if widget.attrs.maxlength and do_not_show_max_chars == "false" %} Your profile -

        We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

        -

        Please note that updating your contact information here will update the contact information for all domains in your account. However, it won’t affect your Login.gov account information.

        +

        We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

        + +

        Contact information

        +

        Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.

        + {% include "includes/required_fields.html" %} @@ -47,14 +51,22 @@ Edit your User Profile | {% input_with_errors form.title %} - {% input_with_errors form.email %} + {% with sublabel_text="We recommend using your work email for your .gov account. If the wrong email is displayed below, you’ll need to update your Login.gov account and log back in. Get help with your Login.gov account." %} + {% with link_text="Get help with your Login.gov account" %} + {% with link_href="http://Login.gov" %} + {% with target_blank="true" %} + {% with do_not_show_max_chars="true" %} + {% input_with_errors form.email %} + {% endwith %} + {% endwith %} + {% endwith %} + {% endwith %} + {% endwith %} {% with add_class="usa-input--medium" %} {% input_with_errors form.phone %} {% endwith %} - - From bd7660de27fe5a628f5dc205108b417de629cc79 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 13:18:45 -0600 Subject: [PATCH 23/56] Remove step up acr check --- src/djangooidc/oidc.py | 24 +++++++++++++----------- src/djangooidc/views.py | 22 +++++++--------------- src/registrar/config/settings.py | 2 -- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 404bc96c2..0f52c0688 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -85,7 +85,7 @@ class Client(oic.Client): def create_authn_request( self, session, - add_acr=True, + do_biometric_auth=False, extra_args=None, ): """Step 2: Construct a login URL at OP's domain and send the user to it.""" @@ -103,10 +103,10 @@ class Client(oic.Client): "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0], } - if add_acr: - request_args["acr_values"] = self.behaviour.get("acr_value") + if do_biometric_auth: + self._set_args_for_biometric_auth_request(session, request_args) else: - request_args["vtr"] = json.dumps(self.behaviour.get("vtr")) + request_args["acr_values"] = self.behaviour.get("acr_value") if extra_args is not None: request_args.update(extra_args) @@ -153,6 +153,12 @@ class Client(oic.Client): return response + def _set_args_for_biometric_auth_request(self, session, request_args): + if "acr_value" in session: + session.pop("acr_value") + request_args["vtr"] = self.get_vtr_value() + request_args["vtm"] = self.get_vtm_value() + def callback(self, unparsed_response, session): """Step 3: Receive OP's response, request an access token, and user info.""" logger.debug("Processing the OpenID Connect callback response...") @@ -300,16 +306,12 @@ class Client(oic.Client): this helper function is called from djangooidc views""" return self.behaviour.get("acr_value") - def get_step_up_acr_value(self): - """returns the step_up_acr_value from settings - this helper function is called from djangooidc views""" - return self.behaviour.get("step_up_acr_value") - def get_vtm_value(self): return self.behaviour.get("vtm") - def get_vtr_value(self): - return self.behaviour.get("vtr") + def get_vtr_value(self, cleaned=True): + vtr = self.behaviour.get("vtr") + return json.dumps(vtr) if cleaned else vtr def __repr__(self): return "Client {} {} {}".format( diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index f817cc4d0..e9bb5ed09 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -93,17 +93,11 @@ def login_callback(request): userinfo = CLIENT.callback(query, request.session) # test for need for identity verification and if it is satisfied # if not satisfied, redirect user to login with stepped up acr_value - request.session["needs_biometric_validation"] = False - if _requires_step_up_auth(userinfo): - # add acr_value to request.session - if "acr_value" in request.session: - request.session.pop("acr_value") - extra_args = { - "vtm": CLIENT.get_vtm_value(), - } - request.session["needs_biometric_validation"] = True - print(f"session is: {request.session}") - return CLIENT.create_authn_request(request.session, add_acr=False, extra_args=extra_args) + needs_biometric_validation = _requires_biometric_auth(userinfo) + request.session["needs_biometric_validation"] = needs_biometric_validation + if needs_biometric_validation: + return CLIENT.create_authn_request(request.session, do_biometric_auth=True) + user = authenticate(request=request, **userinfo) if user: @@ -145,14 +139,12 @@ def login_callback(request): return error_page(request, err) -def _requires_step_up_auth(userinfo): +def _requires_biometric_auth(userinfo): """if User.needs_identity_verification and step_up_acr_value not in ial returned from callback, return True""" - step_up_acr_value = CLIENT.get_step_up_acr_value() - acr_value = userinfo.get("ial", "") uuid = userinfo.get("sub", "") email = userinfo.get("email", "") - if acr_value != step_up_acr_value and (not userinfo.get("vtm") and not userinfo.get("vtr")): + if not userinfo.get("vtm") or not userinfo.get("vtr"): # The acr of this attempt is not at the highest level # so check if the user needs the higher level return User.needs_identity_verification(email, uuid) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 781b67d5a..272eb9704 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -562,7 +562,6 @@ OIDC_PROVIDERS = { "scope": ["email", "profile:name", "phone"], "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", - "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", "vtr": ["Pb","P1"], "vtm": "https://developer.login.gov/vot-trust-framework", }, @@ -582,7 +581,6 @@ OIDC_PROVIDERS = { "scope": ["email", "profile:name", "phone"], "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", - "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", # "P1" is the current IdV option; "Pb" stands for 'biometric' "vtr": ["Pb","P1"], # Stand in replacement for the step_up_acr_value for ial2 From 9551b68b741b3de295b107127135cc28c2a90264 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 16 May 2024 15:34:17 -0400 Subject: [PATCH 24/56] more tests and linting --- src/registrar/tests/test_views.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index 793be94a6..f2c3ad4b7 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -529,12 +529,29 @@ class UserProfileTests(TestWithUser, WebTest): self.domain.delete() Contact.objects.all().delete() - # - error_500_main_nav_with_profile_feature_turned_on - # - error_403_main_nav_with_profile_feature_turned_on - # - error_401_main_nav_with_profile_feature_turned_on - # - error_500_main_nav_with_profile_feature_turned_off - # - error_403_main_nav_with_profile_feature_turned_off - # - error_401_main_nav_with_profile_feature_turned_off + @less_console_noise_decorator + def error_500_main_nav_with_profile_feature_turned_on(self): + """test that Your profile is in main nav of 500 error page when profile_feature is on. + + Our treatment of 401 and 403 error page handling with that waffle feature is similar, so we + assume that the same test results hold true for 401 and 403.""" + with override_flag("profile_feature", active=True): + with self.assertRaises(Exception): + response = self.client.get(reverse("home")) + self.assertEqual(response.status_code, 500) + self.assertContains(response, "Your profile") + + @less_console_noise_decorator + def error_500_main_nav_with_profile_feature_turned_off(self): + """test that Your profile is not in main nav of 500 error page when profile_feature is off. + + Our treatment of 401 and 403 error page handling with that waffle feature is similar, so we + assume that the same test results hold true for 401 and 403.""" + with override_flag("profile_feature", active=False): + with self.assertRaises(Exception): + response = self.client.get(reverse("home"), follow=True) + self.assertEqual(response.status_code, 500) + self.assertNotContains(response, "Your profile") @less_console_noise_decorator def test_home_page_main_nav_with_profile_feature_on(self): From 3c0facfc9dfc72c6e66ffba167dedf23584bdcb1 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 13:35:35 -0600 Subject: [PATCH 25/56] Add comments, do cleanup --- src/djangooidc/oidc.py | 23 ++++++++++++++--------- src/djangooidc/views.py | 8 +++++++- src/registrar/config/settings.py | 10 +++++++--- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 0f52c0688..f95146b11 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -14,7 +14,7 @@ from oic.oic import AuthorizationRequest, AuthorizationResponse, RegistrationRes from oic.oic.message import AccessTokenResponse from oic.utils.authn.client import CLIENT_AUTHN_METHOD from oic.utils import keyio -from urllib.parse import urlparse, urlunparse, urlencode, parse_qs + from . import exceptions as o_e @@ -145,7 +145,7 @@ class Client(oic.Client): if headers: for key, value in headers.items(): response[key] = value - print(f"create auth => response is {response}") + except Exception as err: logger.error(err) logger.error("Failed to create redirect object for %s" % state) @@ -237,11 +237,12 @@ class Client(oic.Client): raise o_e.AuthenticationFailed(locator=state) info_response_dict = info_response.to_dict() - if "needs_biometric_validation" in session and session["needs_biometric_validation"]: - if "vtm" in session: - info_response_dict["vtm"] = session.get("vtm") - if "vtr" in session: - info_response_dict["vtr"] = session.get("vtr") + # Define vtm/vtr information on the user dictionary so we can track this in one location. + # If a user has this information, then they are bumped up in terms of verification level. + if session.get("needs_biometric_validation") is True: + info_response_dict["vtm"] = session.get("vtm", "") + info_response_dict["vtr"] = session.get("vtr", "") + logger.debug("user info: %s" % info_response_dict) return info_response_dict @@ -302,14 +303,18 @@ class Client(oic.Client): super(Client, self).store_response(resp, info) def get_default_acr_value(self): - """returns the acr_value from settings - this helper function is called from djangooidc views""" + """Returns the acr_value from settings. + This helper function is called from djangooidc views.""" return self.behaviour.get("acr_value") def get_vtm_value(self): + """Returns the vtm value from settings. + This helper function is called from djangooidc views.""" return self.behaviour.get("vtm") def get_vtr_value(self, cleaned=True): + """Returns the vtr value from settings. + This helper function is called from djangooidc views.""" vtr = self.behaviour.get("vtr") return json.dumps(vtr) if cleaned else vtr diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index e9bb5ed09..69bd89afe 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -91,10 +91,16 @@ def login_callback(request): _initialize_client() query = parse_qs(request.GET.urlencode()) userinfo = CLIENT.callback(query, request.session) + # test for need for identity verification and if it is satisfied - # if not satisfied, redirect user to login with stepped up acr_value + # if not satisfied, redirect user to login requiring biometric auth + + # Tests for the presence of the vtm/vtr values in the userinfo object. + # If they are there, then we can set a flag in our session for tracking purposes. needs_biometric_validation = _requires_biometric_auth(userinfo) request.session["needs_biometric_validation"] = needs_biometric_validation + + # Return a redirect request to a new auth url that enables biometric validation if needs_biometric_validation: return CLIENT.create_authn_request(request.session, do_biometric_auth=True) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 272eb9704..12b0aad78 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -497,13 +497,13 @@ LOGGING = { # OpenID Connect logger "oic": { "handlers": ["console"], - "level": "DEBUG", + "level": "INFO", "propagate": False, }, # Django wrapper for OpenID Connect "djangooidc": { "handlers": ["console"], - "level": "DEBUG", + "level": "INFO", "propagate": False, }, # Our app! @@ -562,7 +562,10 @@ OIDC_PROVIDERS = { "scope": ["email", "profile:name", "phone"], "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", + # "P1" is the current IdV option; "Pb" stands for 'biometric' "vtr": ["Pb","P1"], + # The url that biometric authentication takes place at. + # A similar analog is the url for acr_value. "vtm": "https://developer.login.gov/vot-trust-framework", }, "client_registration": { @@ -583,7 +586,8 @@ OIDC_PROVIDERS = { "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", # "P1" is the current IdV option; "Pb" stands for 'biometric' "vtr": ["Pb","P1"], - # Stand in replacement for the step_up_acr_value for ial2 + # The url that biometric authentication takes place at. + # A similar analog is the url for acr_value. "vtm": "https://developer.login.gov/vot-trust-framework", }, "client_registration": { From 733cc53f91216ca3240fd321517c7be24763b2cd Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 13:37:23 -0600 Subject: [PATCH 26/56] Update src/djangooidc/views.py --- src/djangooidc/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index 69bd89afe..c36d4e77d 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -100,7 +100,7 @@ def login_callback(request): needs_biometric_validation = _requires_biometric_auth(userinfo) request.session["needs_biometric_validation"] = needs_biometric_validation - # Return a redirect request to a new auth url that enables biometric validation + # Return a redirect request to a new auth url that does biometric validation if needs_biometric_validation: return CLIENT.create_authn_request(request.session, do_biometric_auth=True) From 7681cc4f0ba905c136d0b5e6bbe50567e3b85b69 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 14:15:42 -0600 Subject: [PATCH 27/56] Linting and fix unit tests --- src/djangooidc/oidc.py | 52 ++++++++++++++++----------- src/djangooidc/tests/test_views.py | 56 ++++++++---------------------- src/djangooidc/views.py | 21 ++++++++--- src/registrar/config/settings.py | 4 +-- 4 files changed, 65 insertions(+), 68 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index f95146b11..80915d740 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -117,26 +117,7 @@ class Client(oic.Client): logger.debug("request args: %s" % request_args) - try: - # prepare the request for sending - cis = self.construct_AuthorizationRequest(request_args=request_args) - logger.debug("request: %s" % cis) - - # obtain the url and headers from the prepared request - url, body, headers, cis = self.uri_and_body( - AuthorizationRequest, - cis, - method="GET", - request_args=request_args, - ) - - logger.debug("body: %s" % body) - logger.debug("URL: %s" % url) - logger.debug("headers: %s" % headers) - except Exception as err: - logger.error(err) - logger.error("Failed to prepare request for %s" % state) - raise o_e.InternalError(locator=state) + url, headers = self._prepare_authn_request(request_args, state) # C901 too complex try: # create the redirect object @@ -159,6 +140,35 @@ class Client(oic.Client): request_args["vtr"] = self.get_vtr_value() request_args["vtm"] = self.get_vtm_value() + def _prepare_authn_request(self, request_args, state): + """ + Constructs an authorization request. Then, assembles the url, body, headers, and cis. + + Returns the assembled url and associated header information: `(url, headers)` + """ + try: + # prepare the request for sending + cis = self.construct_AuthorizationRequest(request_args=request_args) + logger.debug("request: %s" % cis) + + # obtain the url and headers from the prepared request + url, body, headers, cis = self.uri_and_body( + AuthorizationRequest, + cis, + method="GET", + request_args=request_args, + ) + + logger.debug("body: %s" % body) + logger.debug("URL: %s" % url) + logger.debug("headers: %s" % headers) + except Exception as err: + logger.error(err) + logger.error("Failed to prepare request for %s" % state) + raise o_e.InternalError(locator=state) + + return (url, headers) + def callback(self, unparsed_response, session): """Step 3: Receive OP's response, request an access token, and user info.""" logger.debug("Processing the OpenID Connect callback response...") @@ -311,7 +321,7 @@ class Client(oic.Client): """Returns the vtm value from settings. This helper function is called from djangooidc views.""" return self.behaviour.get("vtm") - + def get_vtr_value(self, cleaned=True): """Returns the vtr value from settings. This helper function is called from djangooidc views.""" diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index bdd61b346..b25c4f602 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -184,7 +184,7 @@ class ViewsTest(TestCase): # patch that the request does not require step up auth # TEST # test the login callback url - with patch("djangooidc.views._requires_step_up_auth", return_value=False): + with patch("djangooidc.views._requires_biometric_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS # assert the redirect url is the same as the 'next' value set in session @@ -224,7 +224,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_step_up_auth", return_value=False): + with patch("djangooidc.views._requires_biometric_auth", return_value=False): with patch("djangooidc.views._initialize_client") as mock_init_client: with patch("djangooidc.views._client_is_none") as mock_client_is_none: # mock the client to initially be None @@ -252,7 +252,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( + with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -285,7 +285,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( + with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -319,7 +319,7 @@ class ViewsTest(TestCase): td, _ = TransitionDomain.objects.get_or_create(username="test@example.com", domain_name="test123.gov") # patch that the request does not require step up auth - with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( + with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -353,7 +353,7 @@ class ViewsTest(TestCase): vip, _ = VerifiedByStaff.objects.get_or_create(email="test@example.com") # patch that the request does not require step up auth - with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( + with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -374,7 +374,7 @@ class ViewsTest(TestCase): self.assertEqual(created_user.verification_type, User.VerificationTypeChoices.VERIFIED_BY_STAFF) def test_login_callback_no_step_up_auth(self, mock_client): - """Walk through login_callback when _requires_step_up_auth returns False + """Walk through login_callback when _requires_biometric_auth returns False and assert that we have a redirect to /""" with less_console_noise(): # SETUP @@ -386,59 +386,33 @@ class ViewsTest(TestCase): # patch that the request does not require step up auth # TEST # test the login callback url - with patch("djangooidc.views._requires_step_up_auth", return_value=False): + with patch("djangooidc.views._requires_biometric_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS # assert that redirect is to / when no 'next' is set self.assertEqual(response.status_code, 302) self.assertEqual(response.url, "/") - def test_login_callback_requires_step_up_auth(self, mock_client): - """Invoke login_callback passing it a request when _requires_step_up_auth returns True - and assert that session is updated and create_authn_request (mock) is called.""" - with less_console_noise(): - # MOCK - # Configure the mock to return an expected value for get_step_up_acr_value - mock_client.return_value.get_step_up_acr_value.return_value = "step_up_acr_value" - # Create a mock request - request = self.factory.get("/some-url") - request.session = {"acr_value": ""} - # Ensure that the CLIENT instance used in login_callback is the mock - # patch _requires_step_up_auth to return True - with patch("djangooidc.views._requires_step_up_auth", return_value=True), patch( - "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() - ) as mock_create_authn_request: - # TEST - # test the login callback - login_callback(request) - # ASSERTIONS - # create_authn_request only gets called when _requires_step_up_auth is True - # and it changes this acr_value in request.session - # Assert that acr_value is no longer empty string - self.assertNotEqual(request.session["acr_value"], "") - # And create_authn_request was called again - mock_create_authn_request.assert_called_once() - - def test_login_callback_does_not_requires_step_up_auth(self, mock_client): - """Invoke login_callback passing it a request when _requires_step_up_auth returns False + def test_login_callback_does_not_requires_biometric_auth(self, mock_client): + """Invoke login_callback passing it a request when _requires_biometric_auth returns False and assert that session is not updated and create_authn_request (mock) is not called. - Possibly redundant with test_login_callback_requires_step_up_auth""" + Possibly redundant with test_login_callback_requires_biometric_auth""" with less_console_noise(): # MOCK # Create a mock request request = self.factory.get("/some-url") request.session = {"acr_value": ""} # Ensure that the CLIENT instance used in login_callback is the mock - # patch _requires_step_up_auth to return False - with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( + # patch _requires_biometric_auth to return False + with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() ) as mock_create_authn_request: # TEST # test the login callback login_callback(request) # ASSERTIONS - # create_authn_request only gets called when _requires_step_up_auth is True + # create_authn_request only gets called when _requires_biometric_auth is True # and it changes this acr_value in request.session # Assert that acr_value is NOT updated by testing that it is still an empty string self.assertEqual(request.session["acr_value"], "") @@ -454,7 +428,7 @@ class ViewsTest(TestCase): mock_client.callback.side_effect = self.user_info mock_auth.return_value = None # TEST - with patch("djangooidc.views._requires_step_up_auth", return_value=False): + with patch("djangooidc.views._requires_biometric_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS self.assertEqual(response.status_code, 401) diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index c36d4e77d..deca09565 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -96,7 +96,7 @@ def login_callback(request): # if not satisfied, redirect user to login requiring biometric auth # Tests for the presence of the vtm/vtr values in the userinfo object. - # If they are there, then we can set a flag in our session for tracking purposes. + # If they are there, then we can set a flag in our session for tracking purposes. needs_biometric_validation = _requires_biometric_auth(userinfo) request.session["needs_biometric_validation"] = needs_biometric_validation @@ -145,9 +145,22 @@ def login_callback(request): return error_page(request, err) -def _requires_biometric_auth(userinfo): - """if User.needs_identity_verification and step_up_acr_value not in - ial returned from callback, return True""" +def _requires_biometric_auth(userinfo) -> bool: + """ + Checks for the presence of the key 'vtm' and 'vtr' in the provided `userinfo` object. + + If they are not found, then we call `User.needs_identity_verification()`. + + Args: + userinfo (dict): A dictionary of data from the returned user object. + + Return Conditions: + If the provided user does not exist in any tables which would preclude them from doing + biometric authentication, then we return True. Otherwise, we return False. + + Alternatively, if 'vtm' and 'vtr' already exist on `userinfo`, then we return False. + + """ uuid = userinfo.get("sub", "") email = userinfo.get("email", "") if not userinfo.get("vtm") or not userinfo.get("vtr"): diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index 12b0aad78..a0b35a6ca 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -563,7 +563,7 @@ OIDC_PROVIDERS = { "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", # "P1" is the current IdV option; "Pb" stands for 'biometric' - "vtr": ["Pb","P1"], + "vtr": ["Pb", "P1"], # The url that biometric authentication takes place at. # A similar analog is the url for acr_value. "vtm": "https://developer.login.gov/vot-trust-framework", @@ -585,7 +585,7 @@ OIDC_PROVIDERS = { "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", # "P1" is the current IdV option; "Pb" stands for 'biometric' - "vtr": ["Pb","P1"], + "vtr": ["Pb", "P1"], # The url that biometric authentication takes place at. # A similar analog is the url for acr_value. "vtm": "https://developer.login.gov/vot-trust-framework", From ab9d1af8b12f9000588dd48b36f1ad643c3b2d41 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 14:46:45 -0600 Subject: [PATCH 28/56] Add readonly fields --- src/registrar/admin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 9905cf340..61f814c91 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1171,7 +1171,7 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin): ] # Readonly fields for analysts and superusers - readonly_fields = ("other_contacts", "generic_org_type", "is_election_board") + readonly_fields = ("other_contacts", "generic_org_type", "is_election_board", "federal_agency") # Read only that we'll leverage for CISA Analysts analyst_readonly_fields = [ @@ -1438,6 +1438,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "alternative_domains", "generic_org_type", "is_election_board", + "federal_agency", ) # Read only that we'll leverage for CISA Analysts @@ -1879,7 +1880,7 @@ class DomainAdmin(ListHeaderAdmin, ImportExportModelAdmin): search_fields = ["name"] search_help_text = "Search by domain name." change_form_template = "django/admin/domain_change_form.html" - readonly_fields = ["state", "expiration_date", "first_ready", "deleted"] + readonly_fields = ("state", "expiration_date", "first_ready", "deleted", "federal_agency") # Table ordering ordering = ["name"] From 921a804cab5c2dfb643717d29618916ce8c2f88b Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 14:54:07 -0600 Subject: [PATCH 29/56] Change user group settings --- .../migrations/0095_create_groups_v13.py | 37 +++++++++++++++++++ src/registrar/models/user_group.py | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/registrar/migrations/0095_create_groups_v13.py diff --git a/src/registrar/migrations/0095_create_groups_v13.py b/src/registrar/migrations/0095_create_groups_v13.py new file mode 100644 index 000000000..dc8cf4a57 --- /dev/null +++ b/src/registrar/migrations/0095_create_groups_v13.py @@ -0,0 +1,37 @@ +# This migration creates the create_full_access_group and create_cisa_analyst_group groups +# It is dependent on 0079 (which populates federal agencies) +# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS +# in the user_group model then: +# [NOT RECOMMENDED] +# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions +# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups +# step 3: fake run the latest migration in the migrations list +# [RECOMMENDED] +# Alternatively: +# step 1: duplicate the migration that loads data +# step 2: docker-compose exec app ./manage.py migrate + +from django.db import migrations +from registrar.models import UserGroup +from typing import Any + + +# For linting: RunPython expects a function reference, +# so let's give it one +def create_groups(apps, schema_editor) -> Any: + UserGroup.create_cisa_analyst_group(apps, schema_editor) + UserGroup.create_full_access_group(apps, schema_editor) + + +class Migration(migrations.Migration): + dependencies = [ + ("registrar", "0094_create_groups_v12"), + ] + + operations = [ + migrations.RunPython( + create_groups, + reverse_code=migrations.RunPython.noop, + atomic=True, + ), + ] diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py index 76657fe29..23cc59c69 100644 --- a/src/registrar/models/user_group.py +++ b/src/registrar/models/user_group.py @@ -64,7 +64,7 @@ class UserGroup(Group): { "app_label": "registrar", "model": "federalagency", - "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"], + "permissions": ["change_federalagency"], }, ] From 401309ac5dfe20f476e68df75dc38f0f3bf59444 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 15:15:43 -0600 Subject: [PATCH 30/56] Fix tests --- src/registrar/tests/test_admin.py | 4 ++++ src/registrar/tests/test_migrations.py | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 4a6e76e3d..8c771a73b 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -2232,6 +2232,7 @@ class TestDomainRequestAdmin(MockEppLib): "alternative_domains", "generic_org_type", "is_election_board", + "federal_agency", "id", "created_at", "updated_at", @@ -2286,6 +2287,7 @@ class TestDomainRequestAdmin(MockEppLib): "alternative_domains", "generic_org_type", "is_election_board", + "federal_agency", "creator", "about_your_organization", "requested_domain", @@ -2314,6 +2316,7 @@ class TestDomainRequestAdmin(MockEppLib): "alternative_domains", "generic_org_type", "is_election_board", + "federal_agency", ] self.assertEqual(readonly_fields, expected_fields) @@ -3172,6 +3175,7 @@ class TestDomainInformationAdmin(TestCase): "other_contacts", "generic_org_type", "is_election_board", + "federal_agency", "creator", "type_of_work", "more_organization_information", diff --git a/src/registrar/tests/test_migrations.py b/src/registrar/tests/test_migrations.py index 6d8ff7151..415644200 100644 --- a/src/registrar/tests/test_migrations.py +++ b/src/registrar/tests/test_migrations.py @@ -37,9 +37,7 @@ class TestGroups(TestCase): "add_domaininvitation", "view_domaininvitation", "change_domainrequest", - "add_federalagency", "change_federalagency", - "delete_federalagency", "analyst_access_permission", "change_user", "delete_userdomainrole", From 784d5728ae939b8a3f01b211f3aeeed80cbfab69 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 16 May 2024 15:25:10 -0600 Subject: [PATCH 31/56] Remove usergroup change --- .../migrations/0095_create_groups_v13.py | 37 ------------------- src/registrar/models/user_group.py | 2 +- src/registrar/tests/test_migrations.py | 2 + 3 files changed, 3 insertions(+), 38 deletions(-) delete mode 100644 src/registrar/migrations/0095_create_groups_v13.py diff --git a/src/registrar/migrations/0095_create_groups_v13.py b/src/registrar/migrations/0095_create_groups_v13.py deleted file mode 100644 index dc8cf4a57..000000000 --- a/src/registrar/migrations/0095_create_groups_v13.py +++ /dev/null @@ -1,37 +0,0 @@ -# This migration creates the create_full_access_group and create_cisa_analyst_group groups -# It is dependent on 0079 (which populates federal agencies) -# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS -# in the user_group model then: -# [NOT RECOMMENDED] -# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions -# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups -# step 3: fake run the latest migration in the migrations list -# [RECOMMENDED] -# Alternatively: -# step 1: duplicate the migration that loads data -# step 2: docker-compose exec app ./manage.py migrate - -from django.db import migrations -from registrar.models import UserGroup -from typing import Any - - -# For linting: RunPython expects a function reference, -# so let's give it one -def create_groups(apps, schema_editor) -> Any: - UserGroup.create_cisa_analyst_group(apps, schema_editor) - UserGroup.create_full_access_group(apps, schema_editor) - - -class Migration(migrations.Migration): - dependencies = [ - ("registrar", "0094_create_groups_v12"), - ] - - operations = [ - migrations.RunPython( - create_groups, - reverse_code=migrations.RunPython.noop, - atomic=True, - ), - ] diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py index 23cc59c69..76657fe29 100644 --- a/src/registrar/models/user_group.py +++ b/src/registrar/models/user_group.py @@ -64,7 +64,7 @@ class UserGroup(Group): { "app_label": "registrar", "model": "federalagency", - "permissions": ["change_federalagency"], + "permissions": ["add_federalagency", "change_federalagency", "delete_federalagency"], }, ] diff --git a/src/registrar/tests/test_migrations.py b/src/registrar/tests/test_migrations.py index 415644200..6d8ff7151 100644 --- a/src/registrar/tests/test_migrations.py +++ b/src/registrar/tests/test_migrations.py @@ -37,7 +37,9 @@ class TestGroups(TestCase): "add_domaininvitation", "view_domaininvitation", "change_domainrequest", + "add_federalagency", "change_federalagency", + "delete_federalagency", "analyst_access_permission", "change_user", "delete_userdomainrole", From b03c34b68c4e554b06b00cd62939819be4279527 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Thu, 16 May 2024 17:58:39 -0400 Subject: [PATCH 32/56] Update uswds --- src/gulpfile.js | 3 +- src/package-lock.json | 6612 ++---------------- src/package.json | 2 +- src/registrar/templates/base.html | 2 +- src/registrar/templates/includes/footer.html | 2 +- 5 files changed, 563 insertions(+), 6058 deletions(-) diff --git a/src/gulpfile.js b/src/gulpfile.js index 2996a5dab..c8d5ca261 100644 --- a/src/gulpfile.js +++ b/src/gulpfile.js @@ -33,4 +33,5 @@ exports.init = uswds.init; exports.compile = uswds.compile; exports.watch = uswds.watch; exports.copyAssets = uswds.copyAssets - +exports.updateUswds = uswds.updateUswds + \ No newline at end of file diff --git a/src/package-lock.json b/src/package-lock.json index 9df99a739..ee2dada01 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -1,7 +1,7 @@ { "name": "getgov", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@uswds/uswds": "^3.3.0", + "@uswds/uswds": "^3.8.0", "pa11y-ci": "^3.0.1", "sass": "^1.54.8" }, @@ -21,6 +21,12 @@ "npm": "10.5.0" } }, + "node_modules/@bufbuild/protobuf": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.9.0.tgz", + "integrity": "sha512-W7gp8Q/v1NlCZLsv8pQ3Y0uCu/SHgXOVFK+eUluUKWXmsb6VHkpNx0apdOWWcDbB9sJoKeP8uPrjmehJz6xETQ==", + "dev": true + }, "node_modules/@gulp-sourcemaps/identity-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", @@ -137,15 +143,18 @@ "dev": true }, "node_modules/@types/node": { - "version": "14.18.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", - "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", - "devOptional": true + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "devOptional": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/vinyl": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.7.tgz", - "integrity": "sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", "dev": true, "dependencies": { "@types/expect": "^1.20.4", @@ -153,40 +162,40 @@ } }, "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "optional": true, "dependencies": { "@types/node": "*" } }, "node_modules/@uswds/compile": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@uswds/compile/-/compile-1.0.0.tgz", - "integrity": "sha512-dIAL2cr6K+QnSNr/fe7Y2Db06rkxMla5VtockxHF+CYcBl3DbJ8qbMn/kxouYDX5rgN0So2PbMAouzpM7uhyMA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@uswds/compile/-/compile-1.1.0.tgz", + "integrity": "sha512-kKlszBhO13v/qa1jaNqaOWiAJjuKtASHCxjmu+OXw/wMGVdaJcNjkM8hWL9/sx4AUe07PBwlJoGPtkKRWqSxWw==", "dev": true, "dependencies": { - "autoprefixer": "10.4.13", - "del": "6.0.0", + "autoprefixer": "10.4.16", + "del": "6.1.1", "gulp": "4.0.2", "gulp-postcss": "9.0.1", "gulp-rename": "2.0.0", - "gulp-replace": "1.1.3", + "gulp-replace": "1.1.4", "gulp-sass": "5.1.0", "gulp-sourcemaps": "3.0.0", "gulp-svgstore": "9.0.0", - "postcss": "8.4.19", + "postcss": "8.4.31", "postcss-csso": "6.0.1", - "sass-embedded": "1.56.1" + "sass-embedded": "1.69.5" } }, "node_modules/@uswds/uswds": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.3.0.tgz", - "integrity": "sha512-qiugkbwrO+eIIwi4lbEdH15LCHuAjfUMDRQNBBujakR99Ka3iqmrLpPllffdKaJJnnYkt75v0lltnJ5Nnd/obQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.8.0.tgz", + "integrity": "sha512-rMwCXe/u4HGkfskvS1Iuabapi/EXku3ChaIFW7y/dUhc7R1TXQhbbfp8YXEjmXPF0yqJnv9T08WPgS0fQqWZ8w==", "dependencies": { - "classlist-polyfill": "1.0.3", + "classlist-polyfill": "1.2.0", "object-assign": "4.1.1", "receptor": "1.0.0", "resolve-id-refs": "0.1.0" @@ -195,11 +204,6 @@ "node": ">= 4" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "node_modules/acorn": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", @@ -335,42 +339,17 @@ "node": ">=0.10.0" } }, - "node_modules/anymatch/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/anymatch/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/anymatch/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/anymatch/node_modules/is-extendable": { @@ -645,9 +624,9 @@ } }, "node_modules/async-each": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.5.tgz", - "integrity": "sha512-5QzqtU3BlagehwmdoqwaS2FBQF2P5eL6vFqXwNsb5jwoEsmtfAXg1ocFvW7I6/gGLFhBMKwcMwZuy7uv/Bo9jA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", "dev": true, "funding": [ { @@ -681,9 +660,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", "dev": true, "funding": [ { @@ -693,12 +672,16 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", "postcss-value-parser": "^4.2.0" @@ -714,9 +697,9 @@ } }, "node_modules/axe-core": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", - "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.4.tgz", + "integrity": "sha512-9AiDKFKUCWEQm1Kj4lcq7KFavLqSXdf2m/zJo+NVh4VXlW5iwXRJ6alkKmipCyYorsRnqsICH9XLubP1jBF+Og==", "engines": { "node": ">=4" } @@ -776,51 +759,17 @@ "node": ">=0.10.0" } }, - "node_modules/base/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/base/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/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": ">= 0.4" } }, "node_modules/base64-js": { @@ -898,9 +847,9 @@ } }, "node_modules/bl/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==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -951,9 +900,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -963,13 +912,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -1054,13 +1007,19 @@ } }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1076,9 +1035,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", + "version": "1.0.30001620", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", + "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", "dev": true, "funding": [ { @@ -1088,13 +1047,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, "node_modules/check-types": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", - "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" }, "node_modules/cheerio": { "version": "1.0.0-rc.12", @@ -1198,9 +1161,9 @@ } }, "node_modules/classlist-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.0.3.tgz", - "integrity": "sha512-bDLDUsSg5LYFWsc2hphtG6ulyaCFSupdEBU3wxNECKWHnyPVvY8EB9Wbt9DzWkstWclFZhDaZK/VnEK/DmqE/Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", + "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==" }, "node_modules/clean-stack": { "version": "2.2.0", @@ -1332,10 +1295,13 @@ } }, "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -1453,13 +1419,16 @@ } }, "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dev": true, "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" } }, "node_modules/debug": { @@ -1521,12 +1490,30 @@ "node": ">= 0.10" } }, - "node_modules/define-properties": { + "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -1550,9 +1537,9 @@ } }, "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", "dev": true, "dependencies": { "globby": "^11.0.1", @@ -1645,13 +1632,13 @@ } }, "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" + "domhandler": "^5.0.3" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" @@ -1692,9 +1679,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.773", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.773.tgz", + "integrity": "sha512-87eHF+h3PlCRwbxVEAw9KtK3v7lWfc/sUDr0W76955AdYTG4bV/k0zrl585Qnj/skRMH2qOSiE+kqMeOQ+LOpw==", "dev": true }, "node_modules/element-closest": { @@ -1714,9 +1701,9 @@ } }, "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -1744,15 +1731,37 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" }, "engines": { @@ -1771,13 +1780,16 @@ } }, "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", "dev": true, "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" } }, "node_modules/es6-weak-map": { @@ -1793,9 +1805,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -1810,6 +1822,21 @@ "node": ">=0.8.0" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", @@ -1874,12 +1901,6 @@ "type": "^2.7.2" } }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1929,51 +1950,17 @@ "node": ">=0.10.0" } }, - "node_modules/extglob/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extglob/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/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": ">= 0.4" } }, "node_modules/extract-zip": { @@ -2032,9 +2019,9 @@ } }, "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==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2054,9 +2041,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -2153,42 +2140,17 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/findup-sync/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/findup-sync/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/findup-sync/node_modules/is-extendable": { @@ -2317,16 +2279,16 @@ } }, "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "engines": { "node": "*" }, "funding": { "type": "patreon", - "url": "https://www.patreon.com/infusion" + "url": "https://github.com/sponsors/rawify" } }, "node_modules/fragment-cache": { @@ -2368,7 +2330,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2", "dev": true, "hasInstallScript": true, "optional": true, @@ -2384,9 +2346,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-caller-file": { "version": "1.0.3", @@ -2395,14 +2360,19 @@ "dev": true }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2584,16 +2554,22 @@ "node": ">= 0.10" } }, - "node_modules/google-protobuf": { - "version": "3.21.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", - "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==", - "dev": true + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/gulp": { @@ -2674,12 +2650,12 @@ } }, "node_modules/gulp-replace": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", - "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.4.tgz", + "integrity": "sha512-SVSF7ikuWKhpAW4l4wapAqPPSToJoiNKsbDoUnRrSgwZHH7lH8pbPeQj1aOVYQrbZKhfSVBxVW+Py7vtulRktw==", "dev": true, "dependencies": { - "@types/node": "^14.14.41", + "@types/node": "*", "@types/vinyl": "^2.0.4", "istextorbinary": "^3.0.0", "replacestream": "^4.0.3", @@ -2755,17 +2731,6 @@ "node": ">= 0.10" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2776,12 +2741,24 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2838,16 +2815,15 @@ "node": ">=0.10.0" } }, - "node_modules/hogan.js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { - "mkdirp": "0.3.0", - "nopt": "1.0.10" + "function-bind": "^1.1.2" }, - "bin": { - "hulk": "bin/hulk" + "engines": { + "node": ">= 0.4" } }, "node_modules/homedir-polyfill": { @@ -2885,9 +2861,9 @@ } }, "node_modules/htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -2897,9 +2873,9 @@ ], "dependencies": { "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", + "domhandler": "^5.0.3", "domutils": "^3.0.1", - "entities": "^4.3.0" + "entities": "^4.4.0" } }, "node_modules/https-proxy-agent": { @@ -2955,18 +2931,18 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/immutable": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", - "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==" + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==" }, "node_modules/indent-string": { "version": "4.0.0", @@ -3037,27 +3013,15 @@ } }, "node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, "node_modules/is-arrayish": { @@ -3085,53 +3049,40 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/is-extendable": { @@ -3440,9 +3391,9 @@ } }, "node_modules/lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, "engines": { "node": ">=10" @@ -3604,42 +3555,17 @@ "node": ">= 0.10" } }, - "node_modules/matchdep/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/matchdep/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/matchdep/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/matchdep/node_modules/is-extendable": { @@ -3853,15 +3779,6 @@ "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "engines": { - "node": "*" - } - }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -3873,6 +3790,14 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mute-stdout": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", @@ -3883,17 +3808,23 @@ } }, "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", + "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==", "dev": true, "optional": 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==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3949,42 +3880,17 @@ "node": ">=0.10.0" } }, - "node_modules/nanomatch/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/nanomatch/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/nanomatch/node_modules/is-extendable": { @@ -4027,9 +3933,9 @@ "dev": true }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -4046,37 +3952,23 @@ } }, "node_modules/node-releases": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", - "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/node.extend": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", - "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.3.tgz", + "integrity": "sha512-xwADg/okH48PvBmRZyoX8i8GJaKuJ1CqlqotlZOhUio8egD1P5trJupHKBzcPjSF9ifK2gPcEICRBnkfPqQXZw==", "dependencies": { - "has": "^1.0.3", - "is": "^3.2.1" + "hasown": "^2.0.0", + "is": "^3.3.0" }, "engines": { "node": ">=0.4.0" } }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -4203,13 +4095,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -4359,17 +4251,17 @@ } }, "node_modules/pa11y": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-6.1.1.tgz", - "integrity": "sha512-2NzqA3D9CUlDWj8WuOI4fM2P0qM1d/IUxsRRpzCOfDT5eMR1oEgmUwW2TAk+f90ff/GVck0BewdYT4et4BANew==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-6.2.3.tgz", + "integrity": "sha512-69JoUlfW2QVmrgQAm+17XBxIvmd1u0ImFBYIHPyjC61CzAkmxO3kkbqDVxIcl0OKLvAMYSMbvfCH8kMFE9xsbg==", "dependencies": { - "axe-core": "^4.0.2", + "axe-core": "~4.2.1", "bfj": "~7.0.2", "commander": "~8.0.0", "envinfo": "~7.8.1", - "hogan.js": "^3.0.2", - "html_codesniffer": "^2.5.1", + "html_codesniffer": "~2.5.1", "kleur": "~4.1.4", + "mustache": "~4.2.0", "node.extend": "~2.0.2", "p-timeout": "~4.1.0", "puppeteer": "~9.1.1", @@ -4383,18 +4275,18 @@ } }, "node_modules/pa11y-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-3.0.1.tgz", - "integrity": "sha512-DUtEIhEG3Ofds7qRuplq0DdCb9doILRlzcRctFNzo4QUNmVy4iZfM3u51A9cqoPo2irCJZoo5BzfiFrcriY2IQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-3.1.0.tgz", + "integrity": "sha512-1WBGBMq0dYtZ+N/SH/AcnFSsT6sZ2w27d8Z/5XHJWSELeX8Qhh4yX5f0drb7crwjt7ugKSo4A7eEF9RbMB0LYg==", "dependencies": { - "async": "~2.6.3", + "async": "~2.6.4", "cheerio": "~1.0.0-rc.10", "commander": "~6.2.1", "globby": "~6.1.0", "kleur": "~4.1.4", "lodash": "~4.17.21", "node-fetch": "~2.6.1", - "pa11y": "~6.1.0", + "pa11y": "^6.2.3", "protocolify": "~3.0.0", "puppeteer": "~9.1.1", "wordwrap": "~1.0.0" @@ -4403,7 +4295,7 @@ "pa11y-ci": "bin/pa11y-ci.js" }, "engines": { - "node": ">=12" + "node": ">= 12" } }, "node_modules/pa11y-ci/node_modules/array-union": { @@ -4580,9 +4472,9 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -4696,9 +4588,9 @@ } }, "node_modules/postcss": { - "version": "8.4.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", - "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -4708,10 +4600,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -4852,7 +4748,7 @@ "version": "9.1.1", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", - "deprecated": "< 18.1.0 is no longer supported", + "deprecated": "< 22.5.0 is no longer supported", "hasInstallScript": true, "dependencies": { "debug": "^4.1.0", @@ -4980,9 +4876,9 @@ } }, "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==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -5034,42 +4930,17 @@ "node": ">=0.10.0" } }, - "node_modules/readdirp/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readdirp/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/readdirp/node_modules/is-extendable": { @@ -5303,12 +5174,12 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -5413,9 +5284,9 @@ } }, "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { "tslib": "^2.1.0" @@ -5436,9 +5307,9 @@ } }, "node_modules/sass": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", - "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", + "version": "1.77.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.1.tgz", + "integrity": "sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -5448,39 +5319,40 @@ "sass": "sass.js" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, "node_modules/sass-embedded": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.56.1.tgz", - "integrity": "sha512-8VuohdRoGfqVWgBNeC+iqek1KXIVWYcG6AOQ6rJvRUe08HbdPQgp0+fseDQX7E5UxaoM8wvU5VBwCbZvPwFZQw==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.69.5.tgz", + "integrity": "sha512-0YNcRcbSpgGd4AnE+mm3a3g4S97puFLIZ0cYJgbwdD4iGz/hiOzE+yh72XS+u1LMhE+pQfNeC9MNnRsc8n1yRg==", "dev": true, "dependencies": { + "@bufbuild/protobuf": "^1.0.0", "buffer-builder": "^0.2.0", - "google-protobuf": "^3.11.4", "immutable": "^4.0.0", "rxjs": "^7.4.0", - "supports-color": "^8.1.1" + "supports-color": "^8.1.1", + "varint": "^6.0.0" }, "engines": { "node": ">=14.0.0" }, "optionalDependencies": { - "sass-embedded-darwin-arm64": "1.56.1", - "sass-embedded-darwin-x64": "1.56.1", - "sass-embedded-linux-arm": "1.56.1", - "sass-embedded-linux-arm64": "1.56.1", - "sass-embedded-linux-ia32": "1.56.1", - "sass-embedded-linux-x64": "1.56.1", - "sass-embedded-win32-ia32": "1.56.1", - "sass-embedded-win32-x64": "1.56.1" + "sass-embedded-darwin-arm64": "1.69.5", + "sass-embedded-darwin-x64": "1.69.5", + "sass-embedded-linux-arm": "1.69.5", + "sass-embedded-linux-arm64": "1.69.5", + "sass-embedded-linux-ia32": "1.69.5", + "sass-embedded-linux-x64": "1.69.5", + "sass-embedded-win32-ia32": "1.69.5", + "sass-embedded-win32-x64": "1.69.5" } }, "node_modules/sass-embedded-darwin-arm64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.56.1.tgz", - "integrity": "sha512-Y6us8rg7uwLtAzGiKDebAhFn98RLpW3u5Jnfbsvetlm/rDJ1fZg/roVXFttepLdVbYBjimVFTUaNuGxU3bWbBA==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.69.5.tgz", + "integrity": "sha512-zVuXJzgT54t24E4QPP/iteHsw/cawZE8gAXGEm20cP2DKsIQBF7bvSTk0zzY0bS01YFtJviYM13HcGUe4q7/7w==", "cpu": [ "arm64" ], @@ -5489,14 +5361,17 @@ "os": [ "darwin" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-darwin-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.56.1.tgz", - "integrity": "sha512-UypB3IREbreNNc+dG+L6hG5yoeTujKDCdmu38SSSS/zl9XBFTc8McX58SWapTJOUFK8G43CCimfB3r8FOcyNfA==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.69.5.tgz", + "integrity": "sha512-HcA9YER3Ax7lMnHouxnIY462gnst5lNL56QXkZaTQmg9nH7oqR2bMfWbckEQL+mHIXGSM/QfX0aD59VOm5iKZw==", "cpu": [ "x64" ], @@ -5505,14 +5380,17 @@ "os": [ "darwin" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-arm": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.56.1.tgz", - "integrity": "sha512-pXv+2HlMsjlk0g3dzuVhofuUNJZWUfWVe5xbbWHv+wrdH9kuui6WOyHDhSdUolPrRXOrdsG6Z4/Balr9wa1JWQ==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.69.5.tgz", + "integrity": "sha512-m0NxVkrfcS3UsF33q0FgItMWIz/F1FZdfVZpjp+dP6qd0KLeTuoPUCh2GSize0DAU5T0Zj24b2mXeowDKv463g==", "cpu": [ "arm" ], @@ -5521,14 +5399,17 @@ "os": [ "linux" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-arm64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.56.1.tgz", - "integrity": "sha512-Ly2wk8EmhjXkBpNPM+yAygSxTVIBjQlf4cDAHYgsaDUIIvRSAKAe2CUmxJjik069Qmv54g+Ac7WF6k63c2CTNw==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.69.5.tgz", + "integrity": "sha512-HWCjdFSLGh0dMUNLNh+slc2j9koSZnfTEO9qQR6WEIuC+We6vYKJugGPo1V9pFbBeoW6VAJGYdlqsRPquteCZw==", "cpu": [ "arm64" ], @@ -5537,14 +5418,17 @@ "os": [ "linux" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-ia32": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.56.1.tgz", - "integrity": "sha512-cGmhnHdCbwJsQgsogwmlALzS/j8g+qQTiBuKBcXIWyFn4hLWo2BAr4Gm9vY5p+8aapcYrRQF9b0nwpFQcUScOg==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.69.5.tgz", + "integrity": "sha512-0taR6AJDb+eLOBTEMc1nfX2fI1hgRF9M+Hmv+wwGrxfBu/MkASk6fmR9B8MDw9hPHIqGVUkTVizjOh50O7nIKg==", "cpu": [ "ia32" ], @@ -5553,14 +5437,17 @@ "os": [ "linux" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-linux-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.56.1.tgz", - "integrity": "sha512-yMXS37lP3abTI5ThuydOrLacSNz4Oo9+xlfQDR0pntrugdKzH7vHWK7T7Ynd+vGjVqFajUhI+VihP7vZlhhndw==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.69.5.tgz", + "integrity": "sha512-gN9yLTbKC0hUHukx4mdRs4V39WD719PM2GhWQBUA+3Z8qr9ywywi7LiU2atWrKESRF34V+eqF9lYiYVQxtTHZw==", "cpu": [ "x64" ], @@ -5569,14 +5456,17 @@ "os": [ "linux" ], + "bin": { + "sass": "dart-sass/sass" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-win32-ia32": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.56.1.tgz", - "integrity": "sha512-cjtuKc1O0F+yQZ8hLLYhalulEkBZ6HPdR/ys0l6hn7KTlrYooMyvZXbdU5KaB2lfK1WD29I0HefT8Em7d9cpfA==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.69.5.tgz", + "integrity": "sha512-9OgSaufHP53b33gaH1Y5NZ/Im3druCHIQvLUEqJBCFuOzly47g/hZGrO+dBDiWgYGYKbSYI7Z4/PBtQoK5Vkxg==", "cpu": [ "ia32" ], @@ -5585,14 +5475,17 @@ "os": [ "win32" ], + "bin": { + "sass": "dart-sass/sass.bat" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/sass-embedded-win32-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.56.1.tgz", - "integrity": "sha512-VxqwSluQdNBdBEx0p6N2dOrGPIEL3AcG62KuDJ4KD/rHPQgoCPiJvLa5MXKdVHC24tHgE2AYlirILS/iE/N1NQ==", + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.69.5.tgz", + "integrity": "sha512-p1PsOJnpwXdPfiRbX6QdRa4PnL2QXPpIRy8fkeAZpQFYZ278ZIlwemC2MukKMVLcE3iQ5lBulbC8IYm91rod6Q==", "cpu": [ "x64" ], @@ -5601,6 +5494,9 @@ "os": [ "win32" ], + "bin": { + "sass": "dart-sass/sass.bat" + }, "engines": { "node": ">=14.0.0" } @@ -5618,11 +5514,14 @@ } }, "node_modules/sass/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==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sass/node_modules/braces": { @@ -5637,15 +5536,9 @@ } }, "node_modules/sass/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -5658,6 +5551,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -5674,9 +5570,9 @@ } }, "node_modules/sass/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -5759,6 +5655,23 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -5840,51 +5753,17 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/snapdragon-node/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/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": ">= 0.4" } }, "node_modules/snapdragon-util": { @@ -5959,9 +5838,9 @@ } }, "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==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -5994,9 +5873,9 @@ } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -6004,9 +5883,9 @@ } }, "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==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -6020,9 +5899,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "node_modules/split-string": { @@ -6103,9 +5982,9 @@ "dev": true }, "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "dev": true }, "node_modules/string_decoder": { @@ -6248,9 +6127,9 @@ } }, "node_modules/tar-stream/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==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6407,42 +6286,17 @@ "node": ">=0.10.0" } }, - "node_modules/to-regex/node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-regex/node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/to-regex/node_modules/is-extendable": { @@ -6469,15 +6323,6 @@ "node": ">=0.10.0" } }, - "node_modules/to-regex/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/to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", @@ -6501,15 +6346,15 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", "dev": true }, "node_modules/typedarray": { @@ -6566,6 +6411,12 @@ "node": ">= 0.10" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -6650,9 +6501,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -6662,14 +6513,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -6727,6 +6582,12 @@ "node": ">= 0.10" } }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true + }, "node_modules/vinyl": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", @@ -7003,5362 +6864,5 @@ "fd-slicer": "~1.1.0" } } - }, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", - "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", - "dev": true, - "requires": { - "acorn": "^6.4.1", - "normalize-path": "^3.0.0", - "postcss": "^7.0.16", - "source-map": "^0.6.0", - "through2": "^3.0.1" - }, - "dependencies": { - "picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha512-o/EatdaGt8+x2qpb0vFLC/2Gug/xYPRXb6a+ET1wGYKozKN3krDWC/zZFZAtrzxJHuDL12mwdfEFKcKMNvc55A==", - "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.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" - } - }, - "@types/expect": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", - "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", - "dev": true - }, - "@types/node": { - "version": "14.18.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", - "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==", - "devOptional": true - }, - "@types/vinyl": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.7.tgz", - "integrity": "sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==", - "dev": true, - "requires": { - "@types/expect": "^1.20.4", - "@types/node": "*" - } - }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "@uswds/compile": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@uswds/compile/-/compile-1.0.0.tgz", - "integrity": "sha512-dIAL2cr6K+QnSNr/fe7Y2Db06rkxMla5VtockxHF+CYcBl3DbJ8qbMn/kxouYDX5rgN0So2PbMAouzpM7uhyMA==", - "dev": true, - "requires": { - "autoprefixer": "10.4.13", - "del": "6.0.0", - "gulp": "4.0.2", - "gulp-postcss": "9.0.1", - "gulp-rename": "2.0.0", - "gulp-replace": "1.1.3", - "gulp-sass": "5.1.0", - "gulp-sourcemaps": "3.0.0", - "gulp-svgstore": "9.0.0", - "postcss": "8.4.19", - "postcss-csso": "6.0.1", - "sass-embedded": "1.56.1" - } - }, - "@uswds/uswds": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.3.0.tgz", - "integrity": "sha512-qiugkbwrO+eIIwi4lbEdH15LCHuAjfUMDRQNBBujakR99Ka3iqmrLpPllffdKaJJnnYkt75v0lltnJ5Nnd/obQ==", - "requires": { - "classlist-polyfill": "1.0.3", - "object-assign": "4.1.1", - "receptor": "1.0.0", - "resolve-id-refs": "0.1.0" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "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==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "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, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "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 - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", - "dev": true - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - } - }, - "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-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "requires": { - "lodash": "^4.17.14" - } - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.5.tgz", - "integrity": "sha512-5QzqtU3BlagehwmdoqwaS2FBQF2P5eL6vFqXwNsb5jwoEsmtfAXg1ocFvW7I6/gGLFhBMKwcMwZuy7uv/Bo9jA==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.13", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", - "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001426", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "axe-core": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", - "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==" - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "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 - } - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bfj": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", - "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", - "requires": { - "bluebird": "^3.5.5", - "check-types": "^11.1.1", - "hoopy": "^0.1.4", - "tryer": "^1.0.1" - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "binaryextensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", - "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "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==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-builder": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", - "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" - }, - "buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true - }, - "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 - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "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, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", - "dev": true - }, - "check-types": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", - "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" - }, - "cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", - "requires": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - } - }, - "cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "requires": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - } - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - } - }, - "classlist-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.0.3.tgz", - "integrity": "sha512-bDLDUsSg5LYFWsc2hphtG6ulyaCFSupdEBU3wxNECKWHnyPVvY8EB9Wbt9DzWkstWclFZhDaZK/VnEK/DmqE/Q==" - }, - "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 - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "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 - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true - }, - "copy-props": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", - "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", - "dev": true, - "requires": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" - } - }, - "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 - }, - "css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - } - }, - "css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "requires": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" - }, - "csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "requires": { - "css-tree": "~2.2.0" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dev": true, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", - "dev": true - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", - "dev": true - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==", - "dev": true - }, - "devtools-protocol": { - "version": "0.0.869402", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz", - "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==" - }, - "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" - } - }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - }, - "dependencies": { - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "element-closest": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/element-closest/-/element-closest-2.0.2.tgz", - "integrity": "sha512-QCqAWP3kwj8Gz9UXncVXQGdrhnWxD8SQBSeZp5pOsyCcQ6RpL738L1/tfuwBiMi6F1fYkxqPnBrFBR4L+f49Cg==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==" - }, - "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, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "dev": true, - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "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 - } - } - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "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-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "requires": { - "pend": "~1.2.0" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "file-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==" - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "dependencies": { - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "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" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "google-protobuf": { - "version": "3.21.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", - "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - }, - "gulp-postcss": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-9.0.1.tgz", - "integrity": "sha512-9QUHam5JyXwGUxaaMvoFQVT44tohpEFpM8xBdPfdwTYGM0AItS1iTQz0MpsF8Jroh7GF5Jt2GVPaYgvy8qD2Fw==", - "dev": true, - "requires": { - "fancy-log": "^1.3.3", - "plugin-error": "^1.0.1", - "postcss-load-config": "^3.0.0", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "gulp-rename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", - "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", - "dev": true - }, - "gulp-replace": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", - "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", - "dev": true, - "requires": { - "@types/node": "^14.14.41", - "@types/vinyl": "^2.0.4", - "istextorbinary": "^3.0.0", - "replacestream": "^4.0.3", - "yargs-parser": ">=5.0.0-security.0" - } - }, - "gulp-sass": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-5.1.0.tgz", - "integrity": "sha512-7VT0uaF+VZCmkNBglfe1b34bxn/AfcssquLKVDYnCDJ3xNBaW7cUuI3p3BQmoKcoKFrs9jdzUxyb+u+NGfL4OQ==", - "dev": true, - "requires": { - "lodash.clonedeep": "^4.5.0", - "picocolors": "^1.0.0", - "plugin-error": "^1.0.1", - "replace-ext": "^2.0.0", - "strip-ansi": "^6.0.1", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "gulp-sourcemaps": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", - "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "^2.0.1", - "@gulp-sourcemaps/map-sources": "^1.0.0", - "acorn": "^6.4.1", - "convert-source-map": "^1.0.0", - "css": "^3.0.0", - "debug-fabulous": "^1.0.0", - "detect-newline": "^2.0.0", - "graceful-fs": "^4.0.0", - "source-map": "^0.6.0", - "strip-bom-string": "^1.0.0", - "through2": "^2.0.0" - } - }, - "gulp-svgstore": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/gulp-svgstore/-/gulp-svgstore-9.0.0.tgz", - "integrity": "sha512-+Dz+2Pycw9ayb7JY7U0yz7tX0iRMPJ0ORg3yIIHYLHu5tYku34mPjR4DCt1IGpVOe2Nk3ZMoOJwX1xrqpwqBEQ==", - "dev": true, - "requires": { - "cheerio": "^1.0.0-rc.10", - "fancy-log": "^1.3.3", - "plugin-error": "^1.0.1", - "vinyl": "^2.2.1" - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "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 - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hogan.js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", - "requires": { - "mkdirp": "0.3.0", - "nopt": "1.0.10" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hoopy": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" - }, - "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 - }, - "html_codesniffer": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.5.1.tgz", - "integrity": "sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==" - }, - "htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "entities": "^4.3.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "immutable": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", - "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==" - }, - "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 - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", - "dev": true - }, - "is": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", - "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "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": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-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 - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", - "dev": true - }, - "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 - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "istextorbinary": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz", - "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", - "dev": true, - "requires": { - "binaryextensions": "^2.2.0", - "textextensions": "^3.2.0" - } - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "just-debounce": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", - "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", - "dev": true - }, - "keyboardevent-key-polyfill": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keyboardevent-key-polyfill/-/keyboardevent-key-polyfill-1.1.0.tgz", - "integrity": "sha512-NTDqo7XhzL1fqmUzYroiyK2qGua7sOMzLav35BfNA/mPUSCtw8pZghHFMTYR9JdnJ23IQz695FcaM6EE6bpbFQ==" - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - }, - "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true - }, - "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==", - "requires": { - "yallist": "^4.0.0" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "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 - } - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "matches-selector": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/matches-selector/-/matches-selector-1.2.0.tgz", - "integrity": "sha512-c4vLwYWyl+Ji+U43eU/G5FwxWd4ZH0ePUsFs5y0uwD9HUEFBXUQ1zUUan+78IpRD+y4pUfG0nAzNM292K7ItvA==" - }, - "mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "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" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "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, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "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 - }, - "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, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==" - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - } - } - }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, - "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-releases": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", - "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", - "dev": true - }, - "node.extend": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", - "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", - "requires": { - "has": "^1.0.3", - "is": "^3.2.1" - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "requires": { - "abbrev": "1" - } - }, - "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, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "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 - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "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==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-timeout": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz", - "integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==" - }, - "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==" - }, - "pa11y": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-6.1.1.tgz", - "integrity": "sha512-2NzqA3D9CUlDWj8WuOI4fM2P0qM1d/IUxsRRpzCOfDT5eMR1oEgmUwW2TAk+f90ff/GVck0BewdYT4et4BANew==", - "requires": { - "axe-core": "^4.0.2", - "bfj": "~7.0.2", - "commander": "~8.0.0", - "envinfo": "~7.8.1", - "hogan.js": "^3.0.2", - "html_codesniffer": "^2.5.1", - "kleur": "~4.1.4", - "node.extend": "~2.0.2", - "p-timeout": "~4.1.0", - "puppeteer": "~9.1.1", - "semver": "~7.3.5" - }, - "dependencies": { - "commander": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.0.0.tgz", - "integrity": "sha512-Xvf85aAtu6v22+E5hfVoLHqyul/jyxh91zvqk/ioJTQuJR7Z78n7H558vMPKanPSRgIEeZemT92I2g9Y8LPbSQ==" - } - } - }, - "pa11y-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-3.0.1.tgz", - "integrity": "sha512-DUtEIhEG3Ofds7qRuplq0DdCb9doILRlzcRctFNzo4QUNmVy4iZfM3u51A9cqoPo2irCJZoo5BzfiFrcriY2IQ==", - "requires": { - "async": "~2.6.3", - "cheerio": "~1.0.0-rc.10", - "commander": "~6.2.1", - "globby": "~6.1.0", - "kleur": "~4.1.4", - "lodash": "~4.17.21", - "node-fetch": "~2.6.1", - "pa11y": "~6.1.0", - "protocolify": "~3.0.0", - "puppeteer": "~9.1.1", - "wordwrap": "~1.0.0" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true - }, - "parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "requires": { - "entities": "^4.4.0" - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", - "requires": { - "domhandler": "^5.0.2", - "parse5": "^7.0.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "dev": true - }, - "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==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "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 - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "dev": true - }, - "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 - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", - "requires": { - "pinkie": "^2.0.0" - } - }, - "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==", - "requires": { - "find-up": "^4.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true - }, - "postcss": { - "version": "8.4.19", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz", - "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==", - "dev": true, - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-csso": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-csso/-/postcss-csso-6.0.1.tgz", - "integrity": "sha512-ZV4yEziMrx6CEiqabGLrDva0pMD7Fbw7yP+LzJvaynM4OJgTssGN6dHiMsJMJdpmNaLJltXVLsrb/5sxbFa8sA==", - "dev": true, - "requires": { - "csso": "^5.0.5" - } - }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } - }, - "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 - }, - "prepend-http": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-3.0.1.tgz", - "integrity": "sha512-BLxfZh+m6UiAiCPZFJ4+vYoL7NrRs5XgCTRrjseATAggXhdZKKxn+JUNmuVYWY23bDHgaEHodxw8mnmtVEDtHw==" - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "dev": true - }, - "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 - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "protocolify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/protocolify/-/protocolify-3.0.0.tgz", - "integrity": "sha512-PuvDJOkKJMVQx8jSNf8E5g0bJw/UTKm30mTjFHg4N30c8sefgA5Qr/f8INKqYBKfvP/MUSJrj+z1Smjbq4/3rQ==", - "requires": { - "file-url": "^3.0.0", - "prepend-http": "^3.0.0" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "puppeteer": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", - "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", - "requires": { - "debug": "^4.1.0", - "devtools-protocol": "0.0.869402", - "extract-zip": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.1", - "pkg-dir": "^4.2.0", - "progress": "^2.0.1", - "proxy-from-env": "^1.1.0", - "rimraf": "^3.0.2", - "tar-fs": "^2.0.0", - "unbzip2-stream": "^1.3.3", - "ws": "^7.2.3" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "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 - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "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, - "requires": { - "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" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "receptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/receptor/-/receptor-1.0.0.tgz", - "integrity": "sha512-yvVEqVQDNzEmGkluCkEdbKSXqZb3WGxotI/VukXIQ+4/BXEeXVjWtmC6jWaR1BIsmEAGYQy3OTaNgDj2Svr01w==", - "requires": { - "element-closest": "^2.0.1", - "keyboardevent-key-polyfill": "^1.0.2", - "matches-selector": "^1.0.0", - "object-assign": "^4.1.0" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true - }, - "replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "replacestream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", - "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.3", - "object-assign": "^4.0.1", - "readable-stream": "^2.0.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-id-refs": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/resolve-id-refs/-/resolve-id-refs-0.1.0.tgz", - "integrity": "sha512-hNS03NEmVpJheF7yfyagNh57XuKc0z+NkSO0oBbeO67o6IJKoqlDfnNIxhjp7aTWwjmSWZQhtiGrOgZXVyM90w==" - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "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", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "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" - } - }, - "rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "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==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "sass": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", - "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", - "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.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" - } - }, - "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==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "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==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "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==", - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "sass-embedded": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.56.1.tgz", - "integrity": "sha512-8VuohdRoGfqVWgBNeC+iqek1KXIVWYcG6AOQ6rJvRUe08HbdPQgp0+fseDQX7E5UxaoM8wvU5VBwCbZvPwFZQw==", - "dev": true, - "requires": { - "buffer-builder": "^0.2.0", - "google-protobuf": "^3.11.4", - "immutable": "^4.0.0", - "rxjs": "^7.4.0", - "sass-embedded-darwin-arm64": "1.56.1", - "sass-embedded-darwin-x64": "1.56.1", - "sass-embedded-linux-arm": "1.56.1", - "sass-embedded-linux-arm64": "1.56.1", - "sass-embedded-linux-ia32": "1.56.1", - "sass-embedded-linux-x64": "1.56.1", - "sass-embedded-win32-ia32": "1.56.1", - "sass-embedded-win32-x64": "1.56.1", - "supports-color": "^8.1.1" - } - }, - "sass-embedded-darwin-arm64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.56.1.tgz", - "integrity": "sha512-Y6us8rg7uwLtAzGiKDebAhFn98RLpW3u5Jnfbsvetlm/rDJ1fZg/roVXFttepLdVbYBjimVFTUaNuGxU3bWbBA==", - "dev": true, - "optional": true - }, - "sass-embedded-darwin-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.56.1.tgz", - "integrity": "sha512-UypB3IREbreNNc+dG+L6hG5yoeTujKDCdmu38SSSS/zl9XBFTc8McX58SWapTJOUFK8G43CCimfB3r8FOcyNfA==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-arm": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.56.1.tgz", - "integrity": "sha512-pXv+2HlMsjlk0g3dzuVhofuUNJZWUfWVe5xbbWHv+wrdH9kuui6WOyHDhSdUolPrRXOrdsG6Z4/Balr9wa1JWQ==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-arm64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.56.1.tgz", - "integrity": "sha512-Ly2wk8EmhjXkBpNPM+yAygSxTVIBjQlf4cDAHYgsaDUIIvRSAKAe2CUmxJjik069Qmv54g+Ac7WF6k63c2CTNw==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-ia32": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.56.1.tgz", - "integrity": "sha512-cGmhnHdCbwJsQgsogwmlALzS/j8g+qQTiBuKBcXIWyFn4hLWo2BAr4Gm9vY5p+8aapcYrRQF9b0nwpFQcUScOg==", - "dev": true, - "optional": true - }, - "sass-embedded-linux-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.56.1.tgz", - "integrity": "sha512-yMXS37lP3abTI5ThuydOrLacSNz4Oo9+xlfQDR0pntrugdKzH7vHWK7T7Ynd+vGjVqFajUhI+VihP7vZlhhndw==", - "dev": true, - "optional": true - }, - "sass-embedded-win32-ia32": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.56.1.tgz", - "integrity": "sha512-cjtuKc1O0F+yQZ8hLLYhalulEkBZ6HPdR/ys0l6hn7KTlrYooMyvZXbdU5KaB2lfK1WD29I0HefT8Em7d9cpfA==", - "dev": true, - "optional": true - }, - "sass-embedded-win32-x64": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.56.1.tgz", - "integrity": "sha512-VxqwSluQdNBdBEx0p6N2dOrGPIEL3AcG62KuDJ4KD/rHPQgoCPiJvLa5MXKdVHC24tHgE2AYlirILS/iE/N1NQ==", - "dev": true, - "optional": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "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 - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "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 - }, - "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==" - }, - "source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" - } - }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "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 - }, - "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, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - } - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "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==", - "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", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "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, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "dev": true - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg==", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "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==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "textextensions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", - "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", - "dev": true - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "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, - "requires": { - "isobject": "^3.0.1" - } - }, - "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 - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true - }, - "undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "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, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", - "dev": true - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, - "dependencies": { - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - } - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", - "dev": true, - "requires": { - "source-map": "^0.5.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true - } - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "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" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "requires": {} - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", - "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" - }, - "dependencies": { - "yargs-parser": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", - "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } } } diff --git a/src/package.json b/src/package.json index 3afce297f..487d0dad6 100644 --- a/src/package.json +++ b/src/package.json @@ -15,7 +15,7 @@ "author": "", "license": "ISC", "dependencies": { - "@uswds/uswds": "^3.3.0", + "@uswds/uswds": "^3.8.0", "pa11y-ci": "^3.0.1", "sass": "^1.54.8" }, diff --git a/src/registrar/templates/base.html b/src/registrar/templates/base.html index c0702e78f..4f2025cc7 100644 --- a/src/registrar/templates/base.html +++ b/src/registrar/templates/base.html @@ -81,7 +81,7 @@
        U.S. flag
        -
        +
      • {% if not has_profile_feature_flag %} - {% comment %}Conditionally display profile link in main nav{% endcomment %} + {# Conditionally display profile link in main nav #}
      • {% url 'domain-your-contact-information' pk=domain.id as url %} - {% comment %} If the link_text appears more than once, the first instance will be a link and the other instances will be ignored {% endcomment %} + {# If the link_text appears more than once, the first instance will be a link and the other instances will be ignored #} {% if link_text and link_text in sublabel_text %} {% with link_index=sublabel_text|find_index:link_text %} {{ sublabel_text|slice:link_index }} - {% comment %} HTML will convert a new line into a space, resulting with a space before the fullstop in case link_text is at the end of sublabel_text, hence the unfortunate line below {% endcomment %} - {{ link_text }}{% with sublabel_part_after=sublabel_text|slice_after:link_text %}{{ sublabel_part_after }}{% endwith %} + {# HTML will convert a new line into a space, resulting with a space before the fullstop in case link_text is at the end of sublabel_text, hence the unfortunate line below #} + {{ link_text }}{% with sublabel_part_after=sublabel_text|slice_after:link_text %}{{ sublabel_part_after }}{% endwith %} {% endwith %} {% else %} {{ sublabel_text }} @@ -76,7 +76,7 @@ error messages, if necessary. {% endif %} -{% if widget.attrs.maxlength and do_not_show_max_chars == "false" %} +{% if widget.attrs.maxlength and not do_not_show_max_chars %} Date: Tue, 21 May 2024 11:35:34 -0600 Subject: [PATCH 36/56] Fix unit test --- src/djangooidc/tests/test_views.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index b25c4f602..0ebd0ed0b 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -393,6 +393,32 @@ class ViewsTest(TestCase): self.assertEqual(response.status_code, 302) self.assertEqual(response.url, "/") + def test_login_callback_requires_step_up_auth(self, mock_client): + """Invoke login_callback passing it a request when _requires_step_up_auth returns True + and assert that session is updated and create_authn_request (mock) is called.""" + with less_console_noise(): + # Create a mock request + request = self.factory.get("/some-url") + request.session = {"acr_value": ""} + + # Ensure that the CLIENT instance used in login_callback is the mock + # patch _requires_step_up_auth to return True + with patch("djangooidc.views._requires_biometric_auth", return_value=True), patch( + "djangooidc.views.CLIENT.create_authn_request" + ) as mock_create_authn_request: + # TEST + # test the login callback + login_callback(request) + + # ASSERTIONS + # create_authn_request only gets called when _requires_biometric_auth is True. + # The acr_value should be blank here + self.assertEqual(request.session["acr_value"], "") + self.assertEqual(request.session["needs_biometric_validation"], True) + + # And create_authn_request was called again + mock_create_authn_request.assert_called_once() + def test_login_callback_does_not_requires_biometric_auth(self, mock_client): """Invoke login_callback passing it a request when _requires_biometric_auth returns False and assert that session is not updated and create_authn_request (mock) is not called. From c779255b283cf748194aa592962952e3821d1317 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Tue, 21 May 2024 11:44:26 -0600 Subject: [PATCH 37/56] Rename requires_biometric to requires step up --- src/djangooidc/oidc.py | 4 ++-- src/djangooidc/tests/test_views.py | 34 +++++++++++++++--------------- src/djangooidc/views.py | 6 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 80915d740..6c942d6eb 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -85,7 +85,7 @@ class Client(oic.Client): def create_authn_request( self, session, - do_biometric_auth=False, + do_step_up_auth=False, extra_args=None, ): """Step 2: Construct a login URL at OP's domain and send the user to it.""" @@ -103,7 +103,7 @@ class Client(oic.Client): "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0], } - if do_biometric_auth: + if do_step_up_auth: self._set_args_for_biometric_auth_request(session, request_args) else: request_args["acr_values"] = self.behaviour.get("acr_value") diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index 0ebd0ed0b..d002c71f6 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -184,7 +184,7 @@ class ViewsTest(TestCase): # patch that the request does not require step up auth # TEST # test the login callback url - with patch("djangooidc.views._requires_biometric_auth", return_value=False): + with patch("djangooidc.views._requires_step_up_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS # assert the redirect url is the same as the 'next' value set in session @@ -224,7 +224,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_biometric_auth", return_value=False): + with patch("djangooidc.views._requires_step_up_auth", return_value=False): with patch("djangooidc.views._initialize_client") as mock_init_client: with patch("djangooidc.views._client_is_none") as mock_client_is_none: # mock the client to initially be None @@ -252,7 +252,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( + with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -285,7 +285,7 @@ class ViewsTest(TestCase): # mock that callback returns user_info; this is the expected behavior mock_client.callback.side_effect = self.user_info # patch that the request does not require step up auth - with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( + with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -319,7 +319,7 @@ class ViewsTest(TestCase): td, _ = TransitionDomain.objects.get_or_create(username="test@example.com", domain_name="test123.gov") # patch that the request does not require step up auth - with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( + with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -353,7 +353,7 @@ class ViewsTest(TestCase): vip, _ = VerifiedByStaff.objects.get_or_create(email="test@example.com") # patch that the request does not require step up auth - with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( + with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( "djangooidc.views._initialize_client" ) as mock_init_client: with patch("djangooidc.views._client_is_none", return_value=True): @@ -374,7 +374,7 @@ class ViewsTest(TestCase): self.assertEqual(created_user.verification_type, User.VerificationTypeChoices.VERIFIED_BY_STAFF) def test_login_callback_no_step_up_auth(self, mock_client): - """Walk through login_callback when _requires_biometric_auth returns False + """Walk through login_callback when _requires_step_up_auth returns False and assert that we have a redirect to /""" with less_console_noise(): # SETUP @@ -386,7 +386,7 @@ class ViewsTest(TestCase): # patch that the request does not require step up auth # TEST # test the login callback url - with patch("djangooidc.views._requires_biometric_auth", return_value=False): + with patch("djangooidc.views._requires_step_up_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS # assert that redirect is to / when no 'next' is set @@ -403,7 +403,7 @@ class ViewsTest(TestCase): # Ensure that the CLIENT instance used in login_callback is the mock # patch _requires_step_up_auth to return True - with patch("djangooidc.views._requires_biometric_auth", return_value=True), patch( + with patch("djangooidc.views._requires_step_up_auth", return_value=True), patch( "djangooidc.views.CLIENT.create_authn_request" ) as mock_create_authn_request: # TEST @@ -411,7 +411,7 @@ class ViewsTest(TestCase): login_callback(request) # ASSERTIONS - # create_authn_request only gets called when _requires_biometric_auth is True. + # create_authn_request only gets called when _requires_step_up_auth is True. # The acr_value should be blank here self.assertEqual(request.session["acr_value"], "") self.assertEqual(request.session["needs_biometric_validation"], True) @@ -419,26 +419,26 @@ class ViewsTest(TestCase): # And create_authn_request was called again mock_create_authn_request.assert_called_once() - def test_login_callback_does_not_requires_biometric_auth(self, mock_client): - """Invoke login_callback passing it a request when _requires_biometric_auth returns False + def test_login_callback_does_not_requires_step_up_auth(self, mock_client): + """Invoke login_callback passing it a request when _requires_step_up_auth returns False and assert that session is not updated and create_authn_request (mock) is not called. - Possibly redundant with test_login_callback_requires_biometric_auth""" + Possibly redundant with test_login_callback_requires_step_up_auth""" with less_console_noise(): # MOCK # Create a mock request request = self.factory.get("/some-url") request.session = {"acr_value": ""} # Ensure that the CLIENT instance used in login_callback is the mock - # patch _requires_biometric_auth to return False - with patch("djangooidc.views._requires_biometric_auth", return_value=False), patch( + # patch _requires_step_up_auth to return False + with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() ) as mock_create_authn_request: # TEST # test the login callback login_callback(request) # ASSERTIONS - # create_authn_request only gets called when _requires_biometric_auth is True + # create_authn_request only gets called when _requires_step_up_auth is True # and it changes this acr_value in request.session # Assert that acr_value is NOT updated by testing that it is still an empty string self.assertEqual(request.session["acr_value"], "") @@ -454,7 +454,7 @@ class ViewsTest(TestCase): mock_client.callback.side_effect = self.user_info mock_auth.return_value = None # TEST - with patch("djangooidc.views._requires_biometric_auth", return_value=False): + with patch("djangooidc.views._requires_step_up_auth", return_value=False): response = self.client.get(reverse("openid_login_callback")) # ASSERTIONS self.assertEqual(response.status_code, 401) diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index deca09565..3eff7b9dc 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -97,12 +97,12 @@ def login_callback(request): # Tests for the presence of the vtm/vtr values in the userinfo object. # If they are there, then we can set a flag in our session for tracking purposes. - needs_biometric_validation = _requires_biometric_auth(userinfo) + needs_biometric_validation = _requires_step_up_auth(userinfo) request.session["needs_biometric_validation"] = needs_biometric_validation # Return a redirect request to a new auth url that does biometric validation if needs_biometric_validation: - return CLIENT.create_authn_request(request.session, do_biometric_auth=True) + return CLIENT.create_authn_request(request.session, do_step_up_auth=True) user = authenticate(request=request, **userinfo) if user: @@ -145,7 +145,7 @@ def login_callback(request): return error_page(request, err) -def _requires_biometric_auth(userinfo) -> bool: +def _requires_step_up_auth(userinfo) -> bool: """ Checks for the presence of the key 'vtm' and 'vtr' in the provided `userinfo` object. From c0a0e075303e114ba16333a1ab382e94285ae45f Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Tue, 21 May 2024 12:17:25 -0600 Subject: [PATCH 38/56] Fix unit test --- src/djangooidc/oidc.py | 10 ++-------- src/djangooidc/tests/test_views.py | 14 ++++++++++---- src/djangooidc/views.py | 7 ++++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 6c942d6eb..10fb2ec9f 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -137,8 +137,8 @@ class Client(oic.Client): def _set_args_for_biometric_auth_request(self, session, request_args): if "acr_value" in session: session.pop("acr_value") - request_args["vtr"] = self.get_vtr_value() - request_args["vtm"] = self.get_vtm_value() + request_args["vtr"] = session.get("vtr") + request_args["vtm"] = session.get("vtm") def _prepare_authn_request(self, request_args, state): """ @@ -247,12 +247,6 @@ class Client(oic.Client): raise o_e.AuthenticationFailed(locator=state) info_response_dict = info_response.to_dict() - # Define vtm/vtr information on the user dictionary so we can track this in one location. - # If a user has this information, then they are bumped up in terms of verification level. - if session.get("needs_biometric_validation") is True: - info_response_dict["vtm"] = session.get("vtm", "") - info_response_dict["vtr"] = session.get("vtr", "") - logger.debug("user info: %s" % info_response_dict) return info_response_dict diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index d002c71f6..4ca2fda40 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -406,15 +406,21 @@ class ViewsTest(TestCase): with patch("djangooidc.views._requires_step_up_auth", return_value=True), patch( "djangooidc.views.CLIENT.create_authn_request" ) as mock_create_authn_request: - # TEST - # test the login callback - login_callback(request) + with patch("djangooidc.views.CLIENT.get_vtm_value") as mock_get_vtm_value, patch( + "djangooidc.views.CLIENT.get_vtr_value" + ) as mock_get_vtr_value: + mock_get_vtm_value.return_value = "test_vtm" + mock_get_vtr_value.return_value = "test_vtr" + # TEST + # test the login callback + login_callback(request) # ASSERTIONS # create_authn_request only gets called when _requires_step_up_auth is True. # The acr_value should be blank here self.assertEqual(request.session["acr_value"], "") - self.assertEqual(request.session["needs_biometric_validation"], True) + self.assertEqual(request.session["vtm"], "test_vtm") + self.assertEqual(request.session["vtr"], "test_vtr") # And create_authn_request was called again mock_create_authn_request.assert_called_once() diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index 3eff7b9dc..9d5bbe360 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -97,11 +97,12 @@ def login_callback(request): # Tests for the presence of the vtm/vtr values in the userinfo object. # If they are there, then we can set a flag in our session for tracking purposes. - needs_biometric_validation = _requires_step_up_auth(userinfo) - request.session["needs_biometric_validation"] = needs_biometric_validation + needs_step_up_auth = _requires_step_up_auth(userinfo) # Return a redirect request to a new auth url that does biometric validation - if needs_biometric_validation: + if needs_step_up_auth: + request.session["vtm"] = CLIENT.get_vtm_value() + request.session["vtr"] = CLIENT.get_vtr_value() return CLIENT.create_authn_request(request.session, do_step_up_auth=True) user = authenticate(request=request, **userinfo) From 5e9db8f1dbde81c59e882383d0c5e6fcf7a82baf Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Tue, 21 May 2024 12:25:55 -0600 Subject: [PATCH 39/56] Fix reintroduced login loop --- src/djangooidc/oidc.py | 6 ++++++ src/djangooidc/views.py | 1 + 2 files changed, 7 insertions(+) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 10fb2ec9f..a720006ed 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -247,6 +247,12 @@ class Client(oic.Client): raise o_e.AuthenticationFailed(locator=state) info_response_dict = info_response.to_dict() + # Define vtm/vtr information on the user dictionary so we can track this in one location. + # If a user has this information, then they are bumped up in terms of verification level. + if session.get("needs_step_up_auth") is True: + info_response_dict["vtm"] = session.get("vtm", "") + info_response_dict["vtr"] = session.get("vtr", "") + logger.debug("user info: %s" % info_response_dict) return info_response_dict diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index 9d5bbe360..d94e173c2 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -98,6 +98,7 @@ def login_callback(request): # Tests for the presence of the vtm/vtr values in the userinfo object. # If they are there, then we can set a flag in our session for tracking purposes. needs_step_up_auth = _requires_step_up_auth(userinfo) + request.session["needs_step_up_auth"] = needs_step_up_auth # Return a redirect request to a new auth url that does biometric validation if needs_step_up_auth: From 4d7417c0332654a2186202d296e7701e064fbdb9 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 21 May 2024 16:06:06 -0400 Subject: [PATCH 40/56] Try adding profile to pa11y --- src/.pa11yci | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/.pa11yci b/src/.pa11yci index 12b76cd90..56ea40416 100644 --- a/src/.pa11yci +++ b/src/.pa11yci @@ -19,6 +19,7 @@ "http://localhost:8080/request/other_contacts/", "http://localhost:8080/request/anything_else/", "http://localhost:8080/request/requirements/", - "http://localhost:8080/request/finished/" + "http://localhost:8080/request/finished/", + "http://localhost:8080/user-profile/" ] } From ac545ef5aaa119a62a81cb4f3d553966f4cc12ad Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Wed, 22 May 2024 08:59:40 -0600 Subject: [PATCH 41/56] Add middle name and title --- src/registrar/admin.py | 6 +++-- .../0095_user_middle_name_user_title.py | 23 +++++++++++++++++++ src/registrar/models/user.py | 11 +++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/registrar/migrations/0095_user_middle_name_user_title.py diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 9905cf340..667648a3c 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -594,7 +594,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): None, {"fields": ("username", "password", "status", "verification_type")}, ), - ("Personal Info", {"fields": ("first_name", "last_name", "email")}), + ("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}), ( "Permissions", { @@ -625,7 +625,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): ) }, ), - ("Personal Info", {"fields": ("first_name", "last_name", "email")}), + ("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}), ( "Permissions", { @@ -651,7 +651,9 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): analyst_readonly_fields = [ "Personal Info", "first_name", + "middle_name", "last_name", + "title", "email", "Permissions", "is_active", diff --git a/src/registrar/migrations/0095_user_middle_name_user_title.py b/src/registrar/migrations/0095_user_middle_name_user_title.py new file mode 100644 index 000000000..b946ea238 --- /dev/null +++ b/src/registrar/migrations/0095_user_middle_name_user_title.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.10 on 2024-05-22 14:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("registrar", "0094_create_groups_v12"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="middle_name", + field=models.CharField(blank=True, null=True), + ), + migrations.AddField( + model_name="user", + name="title", + field=models.CharField(blank=True, null=True, verbose_name="title / role"), + ), + ] diff --git a/src/registrar/models/user.py b/src/registrar/models/user.py index 8a9fe425f..ce14c0a69 100644 --- a/src/registrar/models/user.py +++ b/src/registrar/models/user.py @@ -80,6 +80,17 @@ class User(AbstractUser): db_index=True, ) + middle_name = models.CharField( + null=True, + blank=True, + ) + + title = models.CharField( + null=True, + blank=True, + verbose_name="title / role", + ) + verification_type = models.CharField( choices=VerificationTypeChoices.choices, null=True, From 05540e66f50f63b9042868793fa7b4c1a208a0ec Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Wed, 22 May 2024 09:34:32 -0600 Subject: [PATCH 42/56] Fix unit test --- src/registrar/tests/test_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 4a6e76e3d..0a1bd1361 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -3534,7 +3534,7 @@ class TestMyUserAdmin(TestCase): ) }, ), - ("Personal Info", {"fields": ("first_name", "last_name", "email")}), + ("Personal Info", {"fields": ("first_name", "middle_name", "last_name", "email", "title")}), ("Permissions", {"fields": ("is_active", "groups")}), ("Important dates", {"fields": ("last_login", "date_joined")}), ) From 54623354165b6f5d7cc82225a495fa82ed5a42e5 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Wed, 22 May 2024 12:37:25 -0600 Subject: [PATCH 43/56] Updated exception handling and function comments --- src/registrar/views/domain.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index b9ade278b..cf1b24e0c 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -795,7 +795,8 @@ class DomainAddUserView(DomainFormBaseView): return redirect(self.get_success_url()) def form_valid(self, form): - """Add the specified user on this domain.""" + """Add the specified user on this domain. + Throws EmailSendingError.""" requested_email = form.cleaned_data["email"] requestor = self.request.user # look up a user with that email @@ -808,7 +809,19 @@ class DomainAddUserView(DomainFormBaseView): # if user already exists then just send an email try: self._send_domain_invitation_email(requested_email, requestor, add_success=False) + except EmailSendingError: + logger.warn( + "Could not send email invitation (EmailSendingError)", + self.object, + exc_info=True, + ) + messages.warning(self.request, "Could not send email invitation.") except Exception: + logger.warn( + "Could not send email invitation (Other Exception)", + self.object, + exc_info=True, + ) messages.warning(self.request, "Could not send email invitation.") try: From 2733a9045cf79f4ab8046ea2dc0409b2201cd658 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Wed, 22 May 2024 15:10:40 -0600 Subject: [PATCH 44/56] restored if statement (not sure why it dissappeared) --- src/registrar/utility/email.py | 5 ++++- src/registrar/views/domain.py | 10 ++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/registrar/utility/email.py b/src/registrar/utility/email.py index 5f61181c7..10a4acc52 100644 --- a/src/registrar/utility/email.py +++ b/src/registrar/utility/email.py @@ -32,8 +32,9 @@ def send_templated_email( template_name and subject_template_name are relative to the same template context as Django's HTML templates. context gives additional information that the template may use. + + Raises EmailSendingError if SES client could not be accessed """ - logger.info(f"An email was sent! Template name: {template_name} to {to_address}") template = get_template(template_name) email_body = template.render(context=context) @@ -48,7 +49,9 @@ def send_templated_email( aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY, config=settings.BOTO_CONFIG, ) + logger.info(f"An email was sent! Template name: {template_name} to {to_address}") except Exception as exc: + logger.debug(f"E-mail unable to send! Could not access the SES client.") raise EmailSendingError("Could not access the SES client.") from exc destination = {"ToAddresses": [to_address]} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index cf1b24e0c..03a0849eb 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -778,11 +778,13 @@ class DomainAddUserView(DomainFormBaseView): """Make a Domain invitation for this email and redirect with a message.""" # Check to see if an invite has already been sent (NOTE: we do not want to create an invite just yet.) try: + invite = DomainInvitation.objects.get(email=email_address, domain=self.object) # that invitation already existed - messages.warning( - self.request, - f"{email_address} has already been invited to this domain.", - ) + if invite is not None: + messages.warning( + self.request, + f"{email_address} has already been invited to this domain.", + ) except DomainInvitation.DoesNotExist: # Try to send the invitation. If it succeeds, add it to the DomainInvitation table. try: From 0c863119829ea8b62cae0f307409e2ce5bdb90d1 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 23 May 2024 10:02:59 -0600 Subject: [PATCH 45/56] Fix refresh bug There was a bug where the session would not retain data correctly after a hard refresh. This fixes that --- src/djangooidc/oidc.py | 2 ++ src/djangooidc/views.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index a720006ed..6e6c209f0 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -250,6 +250,8 @@ class Client(oic.Client): # Define vtm/vtr information on the user dictionary so we can track this in one location. # If a user has this information, then they are bumped up in terms of verification level. if session.get("needs_step_up_auth") is True: + if "ial" in info_response_dict: + info_response_dict.pop("ial") info_response_dict["vtm"] = session.get("vtm", "") info_response_dict["vtr"] = session.get("vtr", "") diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index d94e173c2..bb2cebd38 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -165,7 +165,9 @@ def _requires_step_up_auth(userinfo) -> bool: """ uuid = userinfo.get("sub", "") email = userinfo.get("email", "") - if not userinfo.get("vtm") or not userinfo.get("vtr"): + # This value is returned after successful auth + user_verified = userinfo.get("vot", "") + if not userinfo.get("vtm") or not userinfo.get("vtr") or not user_verified: # The acr of this attempt is not at the highest level # so check if the user needs the higher level return User.needs_identity_verification(email, uuid) From 15bf1a04902a8feae60a551292560d9fb8a34e70 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 23 May 2024 10:07:41 -0600 Subject: [PATCH 46/56] Remove generic org type from fields --- src/registrar/admin.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 9905cf340..70a4c520b 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1124,7 +1124,6 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin): "Type of organization", { "fields": [ - "generic_org_type", "is_election_board", "organization_type", ] @@ -1171,7 +1170,7 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin): ] # Readonly fields for analysts and superusers - readonly_fields = ("other_contacts", "generic_org_type", "is_election_board") + readonly_fields = ("other_contacts", "is_election_board") # Read only that we'll leverage for CISA Analysts analyst_readonly_fields = [ @@ -1385,7 +1384,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "Type of organization", { "fields": [ - "generic_org_type", "is_election_board", "organization_type", ] @@ -1436,7 +1434,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "other_contacts", "current_websites", "alternative_domains", - "generic_org_type", "is_election_board", ) From 8845e0ff754fb51f472256e9b5489866eccb1e8e Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Thu, 23 May 2024 12:21:32 -0400 Subject: [PATCH 47/56] updated labels in user profile form --- src/registrar/forms/user_profile.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/registrar/forms/user_profile.py b/src/registrar/forms/user_profile.py index 31e26a5a6..11b5cc069 100644 --- a/src/registrar/forms/user_profile.py +++ b/src/registrar/forms/user_profile.py @@ -43,7 +43,11 @@ class UserProfileForm(forms.ModelForm): self.fields[field_name].required = True # Set custom form label + self.fields["first_name"].label = "First name / given name" self.fields["middle_name"].label = "Middle name (optional)" + self.fields["last_name"].label = "Last name / family name" + self.fields["title"].label = "Title or role in your organization" + self.fields["email"].label = "Organizational email" # Set custom error messages self.fields["first_name"].error_messages = {"required": "Enter your first name / given name."} From 0220fcb6646b88b9f96ec2adcb0764dd496633e3 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 23 May 2024 10:31:41 -0600 Subject: [PATCH 48/56] Fix unit tests --- src/registrar/tests/test_admin.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 4a6e76e3d..845cf2693 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -2230,7 +2230,6 @@ class TestDomainRequestAdmin(MockEppLib): "other_contacts", "current_websites", "alternative_domains", - "generic_org_type", "is_election_board", "id", "created_at", @@ -2284,7 +2283,6 @@ class TestDomainRequestAdmin(MockEppLib): "other_contacts", "current_websites", "alternative_domains", - "generic_org_type", "is_election_board", "creator", "about_your_organization", @@ -2312,7 +2310,6 @@ class TestDomainRequestAdmin(MockEppLib): "other_contacts", "current_websites", "alternative_domains", - "generic_org_type", "is_election_board", ] @@ -3170,7 +3167,6 @@ class TestDomainInformationAdmin(TestCase): expected_fields = [ "other_contacts", - "generic_org_type", "is_election_board", "creator", "type_of_work", From 2d39561d2b8e8c299a9772aef54418182cc20904 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Thu, 23 May 2024 10:53:46 -0600 Subject: [PATCH 49/56] linted --- src/registrar/utility/email.py | 2 +- src/registrar/views/domain.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/registrar/utility/email.py b/src/registrar/utility/email.py index 10a4acc52..51d61355a 100644 --- a/src/registrar/utility/email.py +++ b/src/registrar/utility/email.py @@ -51,7 +51,7 @@ def send_templated_email( ) logger.info(f"An email was sent! Template name: {template_name} to {to_address}") except Exception as exc: - logger.debug(f"E-mail unable to send! Could not access the SES client.") + logger.debug("E-mail unable to send! Could not access the SES client.") raise EmailSendingError("Could not access the SES client.") from exc destination = {"ToAddresses": [to_address]} diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 03a0849eb..66fd148f0 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -797,7 +797,7 @@ class DomainAddUserView(DomainFormBaseView): return redirect(self.get_success_url()) def form_valid(self, form): - """Add the specified user on this domain. + """Add the specified user on this domain. Throws EmailSendingError.""" requested_email = form.cleaned_data["email"] requestor = self.request.user From 7ebf5b2df1a3871ad9479a2606a138d7a468f841 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Thu, 23 May 2024 15:17:54 -0600 Subject: [PATCH 50/56] Revert changes --- .github/workflows/deploy-development.yaml | 13 +++---------- .github/workflows/deploy-sandbox.yaml | 13 +++---------- .github/workflows/deploy-stable.yaml | 13 +++---------- .github/workflows/deploy-staging.yaml | 13 +++---------- src/node.Dockerfile | 3 --- src/package-lock.json | 4 ---- src/package.json | 5 ----- 7 files changed, 12 insertions(+), 52 deletions(-) diff --git a/.github/workflows/deploy-development.yaml b/.github/workflows/deploy-development.yaml index e62607d95..03994e1de 100644 --- a/.github/workflows/deploy-development.yaml +++ b/.github/workflows/deploy-development.yaml @@ -22,16 +22,9 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node bash -c "\ - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash && \ - export NVM_DIR=\"\$HOME/.nvm\" && \ - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" && \ - [ -s \"\$NVM_DIR/bash_completion\" ] && \. \"\$NVM_DIR/bash_completion\" && \ - nvm install 21.7.3 && \ - nvm use 21.7.3 && \ - npm install && \ - npx gulp copyAssets && \ - npx gulp compile" + docker compose run node npm install && + docker compose run node npx gulp copyAssets && + docker compose run node npx gulp compile - name: Collect static assets working-directory: ./src run: docker compose run app python manage.py collectstatic --no-input diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml index 1c486bdf7..214cf6076 100644 --- a/.github/workflows/deploy-sandbox.yaml +++ b/.github/workflows/deploy-sandbox.yaml @@ -43,16 +43,9 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node bash -c "\ - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash && \ - export NVM_DIR=\"\$HOME/.nvm\" && \ - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" && \ - [ -s \"\$NVM_DIR/bash_completion\" ] && \. \"\$NVM_DIR/bash_completion\" && \ - nvm install 21.7.3 && \ - nvm use 21.7.3 && \ - npm install && \ - npx gulp copyAssets && \ - npx gulp compile" + docker compose run node npm install && + docker compose run node npx gulp copyAssets && + docker compose run node npx gulp compile - name: Collect static assets working-directory: ./src run: docker compose run app python manage.py collectstatic --no-input diff --git a/.github/workflows/deploy-stable.yaml b/.github/workflows/deploy-stable.yaml index 9d0573e01..a1b947ca5 100644 --- a/.github/workflows/deploy-stable.yaml +++ b/.github/workflows/deploy-stable.yaml @@ -23,16 +23,9 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node bash -c "\ - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash && \ - export NVM_DIR=\"\$HOME/.nvm\" && \ - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" && \ - [ -s \"\$NVM_DIR/bash_completion\" ] && \. \"\$NVM_DIR/bash_completion\" && \ - nvm install 21.7.3 && \ - nvm use 21.7.3 && \ - npm install && \ - npx gulp copyAssets && \ - npx gulp compile" + docker compose run node npm install && + docker compose run node npx gulp copyAssets && + docker compose run node npx gulp compile - name: Collect static assets working-directory: ./src run: docker compose run app python manage.py collectstatic --no-input diff --git a/.github/workflows/deploy-staging.yaml b/.github/workflows/deploy-staging.yaml index 9584985f0..3cf5ad5a1 100644 --- a/.github/workflows/deploy-staging.yaml +++ b/.github/workflows/deploy-staging.yaml @@ -23,16 +23,9 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node bash -c "\ - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash && \ - export NVM_DIR=\"\$HOME/.nvm\" && \ - [ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\" && \ - [ -s \"\$NVM_DIR/bash_completion\" ] && \. \"\$NVM_DIR/bash_completion\" && \ - nvm install 21.7.3 && \ - nvm use 21.7.3 && \ - npm install && \ - npx gulp copyAssets && \ - npx gulp compile" + docker compose run node npm install && + docker compose run node npx gulp copyAssets && + docker compose run node npx gulp compile - name: Collect static assets working-directory: ./src run: docker compose run app python manage.py collectstatic --no-input diff --git a/src/node.Dockerfile b/src/node.Dockerfile index cf0b6acc6..0fcab7d92 100644 --- a/src/node.Dockerfile +++ b/src/node.Dockerfile @@ -1,5 +1,4 @@ FROM docker.io/cimg/node:current-browsers -FROM node:21.7.3 WORKDIR /app # Install app dependencies @@ -7,6 +6,4 @@ WORKDIR /app # where available (npm@5+) COPY --chown=circleci:circleci package*.json ./ - -RUN npm install -g npm@10.5.0 RUN npm install \ No newline at end of file diff --git a/src/package-lock.json b/src/package-lock.json index ee2dada01..2ff464d5e 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -15,10 +15,6 @@ }, "devDependencies": { "@uswds/compile": "^1.0.0-beta.3" - }, - "engines": { - "node": "21.7.3", - "npm": "10.5.0" } }, "node_modules/@bufbuild/protobuf": { diff --git a/src/package.json b/src/package.json index 487d0dad6..58ae3a4ed 100644 --- a/src/package.json +++ b/src/package.json @@ -3,11 +3,6 @@ "version": "1.0.0", "description": "========================", "main": "index.js", - "engines": { - "node": "21.7.3", - "npm": "10.5.0" - }, - "engineStrict": true, "scripts": { "pa11y-ci": "pa11y-ci", "test": "echo \"Error: no test specified\" && exit 1" From 84e136120826c2b64c08711178aa604be6ea3370 Mon Sep 17 00:00:00 2001 From: zandercymatics <141044360+zandercymatics@users.noreply.github.com> Date: Fri, 24 May 2024 12:21:20 -0600 Subject: [PATCH 51/56] Revert "Ticket #2158: Use biometric auth instead of IAL2" --- src/djangooidc/oidc.py | 84 +++++++++--------------------- src/djangooidc/tests/test_views.py | 28 ++++------ src/djangooidc/views.py | 44 ++++------------ src/registrar/config/settings.py | 12 +---- 4 files changed, 48 insertions(+), 120 deletions(-) diff --git a/src/djangooidc/oidc.py b/src/djangooidc/oidc.py index 6e6c209f0..95ed322f5 100644 --- a/src/djangooidc/oidc.py +++ b/src/djangooidc/oidc.py @@ -15,7 +15,6 @@ from oic.oic.message import AccessTokenResponse from oic.utils.authn.client import CLIENT_AUTHN_METHOD from oic.utils import keyio - from . import exceptions as o_e __author__ = "roland" @@ -85,7 +84,6 @@ class Client(oic.Client): def create_authn_request( self, session, - do_step_up_auth=False, extra_args=None, ): """Step 2: Construct a login URL at OP's domain and send the user to it.""" @@ -102,11 +100,10 @@ class Client(oic.Client): "state": session["state"], "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0], + # acr_value may be passed in session if overriding, as in the case + # of step up auth, otherwise get from settings.py + "acr_values": session.get("acr_value") or self.behaviour.get("acr_value"), } - if do_step_up_auth: - self._set_args_for_biometric_auth_request(session, request_args) - else: - request_args["acr_values"] = self.behaviour.get("acr_value") if extra_args is not None: request_args.update(extra_args) @@ -117,35 +114,6 @@ class Client(oic.Client): logger.debug("request args: %s" % request_args) - url, headers = self._prepare_authn_request(request_args, state) # C901 too complex - - try: - # create the redirect object - response = HttpResponseRedirect(str(url)) - # add headers to the object, if any - if headers: - for key, value in headers.items(): - response[key] = value - - except Exception as err: - logger.error(err) - logger.error("Failed to create redirect object for %s" % state) - raise o_e.InternalError(locator=state) - - return response - - def _set_args_for_biometric_auth_request(self, session, request_args): - if "acr_value" in session: - session.pop("acr_value") - request_args["vtr"] = session.get("vtr") - request_args["vtm"] = session.get("vtm") - - def _prepare_authn_request(self, request_args, state): - """ - Constructs an authorization request. Then, assembles the url, body, headers, and cis. - - Returns the assembled url and associated header information: `(url, headers)` - """ try: # prepare the request for sending cis = self.construct_AuthorizationRequest(request_args=request_args) @@ -158,7 +126,6 @@ class Client(oic.Client): method="GET", request_args=request_args, ) - logger.debug("body: %s" % body) logger.debug("URL: %s" % url) logger.debug("headers: %s" % headers) @@ -167,7 +134,19 @@ class Client(oic.Client): logger.error("Failed to prepare request for %s" % state) raise o_e.InternalError(locator=state) - return (url, headers) + try: + # create the redirect object + response = HttpResponseRedirect(str(url)) + # add headers to the object, if any + if headers: + for key, value in headers.items(): + response[key] = value + except Exception as err: + logger.error(err) + logger.error("Failed to create redirect object for %s" % state) + raise o_e.InternalError(locator=state) + + return response def callback(self, unparsed_response, session): """Step 3: Receive OP's response, request an access token, and user info.""" @@ -245,18 +224,9 @@ class Client(oic.Client): if isinstance(info_response, ErrorResponse): logger.error("Unable to get user info (%s) for %s" % (info_response.get("error", ""), state)) raise o_e.AuthenticationFailed(locator=state) - info_response_dict = info_response.to_dict() - # Define vtm/vtr information on the user dictionary so we can track this in one location. - # If a user has this information, then they are bumped up in terms of verification level. - if session.get("needs_step_up_auth") is True: - if "ial" in info_response_dict: - info_response_dict.pop("ial") - info_response_dict["vtm"] = session.get("vtm", "") - info_response_dict["vtr"] = session.get("vtr", "") - - logger.debug("user info: %s" % info_response_dict) - return info_response_dict + logger.debug("user info: %s" % info_response) + return info_response.to_dict() def _request_token(self, state, code, session): """Request a token from OP to allow us to then request user info.""" @@ -315,20 +285,14 @@ class Client(oic.Client): super(Client, self).store_response(resp, info) def get_default_acr_value(self): - """Returns the acr_value from settings. - This helper function is called from djangooidc views.""" + """returns the acr_value from settings + this helper function is called from djangooidc views""" return self.behaviour.get("acr_value") - def get_vtm_value(self): - """Returns the vtm value from settings. - This helper function is called from djangooidc views.""" - return self.behaviour.get("vtm") - - def get_vtr_value(self, cleaned=True): - """Returns the vtr value from settings. - This helper function is called from djangooidc views.""" - vtr = self.behaviour.get("vtr") - return json.dumps(vtr) if cleaned else vtr + def get_step_up_acr_value(self): + """returns the step_up_acr_value from settings + this helper function is called from djangooidc views""" + return self.behaviour.get("step_up_acr_value") def __repr__(self): return "Client {} {} {}".format( diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index 4ca2fda40..bdd61b346 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -397,31 +397,25 @@ class ViewsTest(TestCase): """Invoke login_callback passing it a request when _requires_step_up_auth returns True and assert that session is updated and create_authn_request (mock) is called.""" with less_console_noise(): + # MOCK + # Configure the mock to return an expected value for get_step_up_acr_value + mock_client.return_value.get_step_up_acr_value.return_value = "step_up_acr_value" # Create a mock request request = self.factory.get("/some-url") request.session = {"acr_value": ""} - # Ensure that the CLIENT instance used in login_callback is the mock # patch _requires_step_up_auth to return True with patch("djangooidc.views._requires_step_up_auth", return_value=True), patch( - "djangooidc.views.CLIENT.create_authn_request" + "djangooidc.views.CLIENT.create_authn_request", return_value=MagicMock() ) as mock_create_authn_request: - with patch("djangooidc.views.CLIENT.get_vtm_value") as mock_get_vtm_value, patch( - "djangooidc.views.CLIENT.get_vtr_value" - ) as mock_get_vtr_value: - mock_get_vtm_value.return_value = "test_vtm" - mock_get_vtr_value.return_value = "test_vtr" - # TEST - # test the login callback - login_callback(request) - + # TEST + # test the login callback + login_callback(request) # ASSERTIONS - # create_authn_request only gets called when _requires_step_up_auth is True. - # The acr_value should be blank here - self.assertEqual(request.session["acr_value"], "") - self.assertEqual(request.session["vtm"], "test_vtm") - self.assertEqual(request.session["vtr"], "test_vtr") - + # create_authn_request only gets called when _requires_step_up_auth is True + # and it changes this acr_value in request.session + # Assert that acr_value is no longer empty string + self.assertNotEqual(request.session["acr_value"], "") # And create_authn_request was called again mock_create_authn_request.assert_called_once() diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py index bb2cebd38..815df4ecf 100644 --- a/src/djangooidc/views.py +++ b/src/djangooidc/views.py @@ -91,21 +91,12 @@ def login_callback(request): _initialize_client() query = parse_qs(request.GET.urlencode()) userinfo = CLIENT.callback(query, request.session) - # test for need for identity verification and if it is satisfied - # if not satisfied, redirect user to login requiring biometric auth - - # Tests for the presence of the vtm/vtr values in the userinfo object. - # If they are there, then we can set a flag in our session for tracking purposes. - needs_step_up_auth = _requires_step_up_auth(userinfo) - request.session["needs_step_up_auth"] = needs_step_up_auth - - # Return a redirect request to a new auth url that does biometric validation - if needs_step_up_auth: - request.session["vtm"] = CLIENT.get_vtm_value() - request.session["vtr"] = CLIENT.get_vtr_value() - return CLIENT.create_authn_request(request.session, do_step_up_auth=True) - + # if not satisfied, redirect user to login with stepped up acr_value + if _requires_step_up_auth(userinfo): + # add acr_value to request.session + request.session["acr_value"] = CLIENT.get_step_up_acr_value() + return CLIENT.create_authn_request(request.session) user = authenticate(request=request, **userinfo) if user: @@ -147,27 +138,14 @@ def login_callback(request): return error_page(request, err) -def _requires_step_up_auth(userinfo) -> bool: - """ - Checks for the presence of the key 'vtm' and 'vtr' in the provided `userinfo` object. - - If they are not found, then we call `User.needs_identity_verification()`. - - Args: - userinfo (dict): A dictionary of data from the returned user object. - - Return Conditions: - If the provided user does not exist in any tables which would preclude them from doing - biometric authentication, then we return True. Otherwise, we return False. - - Alternatively, if 'vtm' and 'vtr' already exist on `userinfo`, then we return False. - - """ +def _requires_step_up_auth(userinfo): + """if User.needs_identity_verification and step_up_acr_value not in + ial returned from callback, return True""" + step_up_acr_value = CLIENT.get_step_up_acr_value() + acr_value = userinfo.get("ial", "") uuid = userinfo.get("sub", "") email = userinfo.get("email", "") - # This value is returned after successful auth - user_verified = userinfo.get("vot", "") - if not userinfo.get("vtm") or not userinfo.get("vtr") or not user_verified: + if acr_value != step_up_acr_value: # The acr of this attempt is not at the highest level # so check if the user needs the higher level return User.needs_identity_verification(email, uuid) diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py index a0b35a6ca..9f31ffc2c 100644 --- a/src/registrar/config/settings.py +++ b/src/registrar/config/settings.py @@ -562,11 +562,7 @@ OIDC_PROVIDERS = { "scope": ["email", "profile:name", "phone"], "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", - # "P1" is the current IdV option; "Pb" stands for 'biometric' - "vtr": ["Pb", "P1"], - # The url that biometric authentication takes place at. - # A similar analog is the url for acr_value. - "vtm": "https://developer.login.gov/vot-trust-framework", + "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", }, "client_registration": { "client_id": "cisa_dotgov_registrar", @@ -584,11 +580,7 @@ OIDC_PROVIDERS = { "scope": ["email", "profile:name", "phone"], "user_info_request": ["email", "first_name", "last_name", "phone"], "acr_value": "http://idmanagement.gov/ns/assurance/ial/1", - # "P1" is the current IdV option; "Pb" stands for 'biometric' - "vtr": ["Pb", "P1"], - # The url that biometric authentication takes place at. - # A similar analog is the url for acr_value. - "vtm": "https://developer.login.gov/vot-trust-framework", + "step_up_acr_value": "http://idmanagement.gov/ns/assurance/ial/2", }, "client_registration": { "client_id": ("urn:gov:cisa:openidconnect.profiles:sp:sso:cisa:dotgov_registrar"), From b72037a073d6d42257965572400a6aa04efd3a72 Mon Sep 17 00:00:00 2001 From: CocoByte Date: Fri, 24 May 2024 13:13:24 -0600 Subject: [PATCH 52/56] Added emailSendingError exception to comment --- src/registrar/views/domain.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 66fd148f0..08affba6e 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -734,7 +734,10 @@ class DomainAddUserView(DomainFormBaseView): does not make a domain information object email: string- email to send to add_success: bool- default True indicates: - adding a success message to the view if the email sending succeeds""" + adding a success message to the view if the email sending succeeds + + raises EmailSendingError + """ # Set a default email address to send to for staff requestor_email = settings.DEFAULT_FROM_EMAIL From b2891fe2d27c2079234dac48ff3e50bd3116b70e Mon Sep 17 00:00:00 2001 From: CocoByte Date: Fri, 24 May 2024 13:16:42 -0600 Subject: [PATCH 53/56] linted --- src/registrar/views/domain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py index 08affba6e..be484f06a 100644 --- a/src/registrar/views/domain.py +++ b/src/registrar/views/domain.py @@ -735,7 +735,7 @@ class DomainAddUserView(DomainFormBaseView): email: string- email to send to add_success: bool- default True indicates: adding a success message to the view if the email sending succeeds - + raises EmailSendingError """ From c78024c0982750ca13c76fc40532ab2039000d2a Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 28 May 2024 12:30:55 -0400 Subject: [PATCH 54/56] remove fieldset markup --- src/registrar/templates/profile.html | 38 +++++++++++++--------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index 70081698c..a672005f7 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -41,35 +41,33 @@ Edit your User Profile |
        {% csrf_token %} -
        - {% input_with_errors form.first_name %} + {% input_with_errors form.first_name %} - {% input_with_errors form.middle_name %} - - {% input_with_errors form.last_name %} - - {% input_with_errors form.title %} + {% input_with_errors form.middle_name %} + + {% input_with_errors form.last_name %} + + {% input_with_errors form.title %} - {% public_site_url "help/account-management/#get-help-with-login.gov" as login_help_url %} + {% public_site_url "help/account-management/#get-help-with-login.gov" as login_help_url %} - {% with link_href=login_help_url %} - {% with sublabel_text="We recommend using your work email for your .gov account. If the wrong email is displayed below, you’ll need to update your Login.gov account and log back in. Get help with your Login.gov account." %} - {% with link_text="Get help with your Login.gov account" %} - {% with target_blank=True %} - {% with do_not_show_max_chars=True %} - {% input_with_errors form.email %} - {% endwith %} + {% with link_href=login_help_url %} + {% with sublabel_text="We recommend using your work email for your .gov account. If the wrong email is displayed below, you’ll need to update your Login.gov account and log back in. Get help with your Login.gov account." %} + {% with link_text="Get help with your Login.gov account" %} + {% with target_blank=True %} + {% with do_not_show_max_chars=True %} + {% input_with_errors form.email %} {% endwith %} {% endwith %} {% endwith %} {% endwith %} - - {% with add_class="usa-input--medium" %} - {% input_with_errors form.phone %} - {% endwith %} + {% endwith %} + + {% with add_class="usa-input--medium" %} + {% input_with_errors form.phone %} + {% endwith %} -
        From e048a73e82b93d80e62537020ee1fb1db014391d Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 28 May 2024 12:47:49 -0400 Subject: [PATCH 55/56] test teardown cleanup --- src/registrar/tests/test_views.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py index f2c3ad4b7..8c8a0fda0 100644 --- a/src/registrar/tests/test_views.py +++ b/src/registrar/tests/test_views.py @@ -528,6 +528,8 @@ class UserProfileTests(TestWithUser, WebTest): self.role.delete() self.domain.delete() Contact.objects.all().delete() + DraftDomain.objects.all().delete() + DomainRequest.objects.all().delete() @less_console_noise_decorator def error_500_main_nav_with_profile_feature_turned_on(self): @@ -635,9 +637,6 @@ class UserProfileTests(TestWithUser, WebTest): self.assertContains(response, "Your profile") response = self.client.get(f"/domain-request/{domain_request.id}/withdraw") self.assertContains(response, "Your profile") - # cleanup - domain_request.delete() - site.delete() @less_console_noise_decorator def test_request_when_profile_feature_off(self): From b8781da51ade7dff457c6d004d843a607cf7b9d4 Mon Sep 17 00:00:00 2001 From: Rachid Mrad Date: Tue, 28 May 2024 12:53:52 -0400 Subject: [PATCH 56/56] edit the getgov href to use the right var instead of hardcoded value --- src/registrar/templates/profile.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/registrar/templates/profile.html b/src/registrar/templates/profile.html index a672005f7..13179e4ac 100644 --- a/src/registrar/templates/profile.html +++ b/src/registrar/templates/profile.html @@ -32,7 +32,7 @@ Edit your User Profile | {% include "includes/form_errors.html" with form=form %}

        Your profile

        -

        We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

        +

        We require that you maintain accurate contact information. The details you provide will only be used to support the administration of .gov and won’t be made public.

        Contact information

        Review the details below and update any required information. Note that editing this information won’t affect your Login.gov account information.