From 71a0aaf2bb741eea02a583b091ce3410a2414cc5 Mon Sep 17 00:00:00 2001 From: Kirill Sizov Date: Thu, 12 Jan 2023 14:00:24 +0200 Subject: [PATCH] Improve error messages when limits reached (#5556) --- cvat-core/package.json | 2 +- cvat-core/src/server-proxy.ts | 5 +- cvat-ui/package.json | 3 +- cvat-ui/src/components/cvat-app.tsx | 17 +- cvat-ui/src/reducers/notifications-reducer.ts | 56 +- cvat-ui/src/styles.scss | 6 + cvat/apps/iam/exceptions.py | 36 ++ cvat/apps/iam/permissions.py | 9 +- cvat/apps/iam/rules/limits.rego | 22 +- cvat/settings/base.py | 2 + tests/python/rest_api/test_limits.py | 72 ++- yarn.lock | 512 +++++++++++++++++- 12 files changed, 625 insertions(+), 117 deletions(-) create mode 100644 cvat/apps/iam/exceptions.py diff --git a/cvat-core/package.json b/cvat-core/package.json index 878542a9..5405acbc 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "7.4.0", + "version": "7.4.1", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "src/api.ts", "scripts": { diff --git a/cvat-core/src/server-proxy.ts b/cvat-core/src/server-proxy.ts index b84898f9..4cd12163 100644 --- a/cvat-core/src/server-proxy.ts +++ b/cvat-core/src/server-proxy.ts @@ -121,7 +121,10 @@ async function chunkUpload(file, uploadConfig) { function generateError(errorData) { if (errorData.response) { - const message = `${errorData.message}. ${JSON.stringify(errorData.response.data) || ''}.`; + if (errorData.response.data?.message) { + return new ServerError(errorData.response.data?.message, errorData.response.status); + } + const message = `${errorData.message}. ${JSON.stringify(errorData.response.data || '')}.`; return new ServerError(message, errorData.response.status); } diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 054d4344..a681c0fc 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.46.0", + "version": "1.46.1", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { @@ -50,6 +50,7 @@ "react-color": "^2.19.3", "react-cookie": "^4.0.3", "react-dom": "^16.14.0", + "react-markdown": "^8.0.4", "react-moment": "^1.1.1", "react-redux": "^8.0.2", "react-resizable": "^3.0.4", diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx index 8a92bbc7..13fa7bf8 100644 --- a/cvat-ui/src/components/cvat-app.tsx +++ b/cvat-ui/src/components/cvat-app.tsx @@ -14,6 +14,7 @@ import Spin from 'antd/lib/spin'; import { DisconnectOutlined } from '@ant-design/icons'; import Space from 'antd/lib/space'; import Text from 'antd/lib/typography/Text'; +import ReactMarkdown from 'react-markdown'; import 'antd/dist/antd.css'; import LogoutComponent from 'components/logout-component'; @@ -306,12 +307,7 @@ class CVATApplication extends React.PureComponent + {title} ), duration: null, }); @@ -342,15 +338,10 @@ class CVATApplication extends React.PureComponent + {title} ), duration: null, - description: error.length > 200 ? 'Open the Browser Console to get details' : error, + description: error.length > 200 ? 'Open the Browser Console to get details' : {error}, }); // eslint-disable-next-line no-console diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index c81778b0..80134793 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2022 CVAT.ai Corporation +// Copyright (C) 2022-2023 CVAT.ai Corporation // // SPDX-License-Identifier: MIT @@ -380,8 +380,7 @@ export default function (state = defaultState, action: AnyAction): Notifications dataset: { message: 'Could not export dataset for the ' + - `` + - `${instanceType} ${instance.id}`, + `[${instanceType} ${instance.id}](/${instanceType}s/${instance.id})`, reason: action.payload.error.toString(), }, }, @@ -444,10 +443,8 @@ export default function (state = defaultState, action: AnyAction): Notifications const { instance, resource } = action.payload; const message = resource === 'annotation' ? 'Annotations have been loaded to the ' + - `` + - `task ${instance.taskId || instance.id}` : - 'Dataset has been imported to the ' + - `project ${instance.id}`; + `[task ${instance.taskId || instance.id}](/tasks/${instance.taskId || instance.id}) ` : + `Dataset was imported to the [project ${instance.id}](/projects/${instance.id})`; return { ...state, messages: { @@ -461,11 +458,10 @@ export default function (state = defaultState, action: AnyAction): Notifications } case ImportActionTypes.IMPORT_DATASET_FAILED: { const { instance, resource } = action.payload; - const message = resource === 'annotation' ? 'Could not upload annotation for the ' + - `` : - 'Could not import dataset to the ' + - `` + - `project ${instance.id}`; + const message = resource === 'annotation' ? + 'Could not upload annotation for the ' + + `[task ${instance.taskId || instance.id}](/tasks/${instance.taskId || instance.id})` : + `Could not import dataset to the [project ${instance.id}](/projects/${instance.id})`; return { ...state, errors: { @@ -492,7 +488,7 @@ export default function (state = defaultState, action: AnyAction): Notifications ...state.messages.importing, backup: `The ${instanceType} has been restored succesfully. - Click here to open`, + Click [here](/${instanceType}s/${instanceId}) to open`, }, }, }; @@ -538,7 +534,7 @@ export default function (state = defaultState, action: AnyAction): Notifications tasks: { ...state.errors.tasks, updating: { - message: `Could not update task ${taskID}`, + message: `Could not update [task ${taskID}](/tasks/${taskID})`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-update-task-failed', }, @@ -555,9 +551,7 @@ export default function (state = defaultState, action: AnyAction): Notifications tasks: { ...state.errors.tasks, deleting: { - message: - 'Could not delete the ' + - `task ${taskID}`, + message: `Could not delete the [task ${taskID}](/tasks/${taskID})`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-delete-task-failed', }, @@ -638,9 +632,7 @@ export default function (state = defaultState, action: AnyAction): Notifications projects: { ...state.errors.projects, updating: { - message: - 'Could not update ' + - `project ${projectId}`, + message: `Could not update [project ${projectId}](/project/${projectId})`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-update-project-failed', }, @@ -657,9 +649,7 @@ export default function (state = defaultState, action: AnyAction): Notifications projects: { ...state.errors.projects, updating: { - message: - 'Could not delete ' + - `project ${projectId}`, + message: `Could not delete [project ${projectId}](/project/${projectId})`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-delete-project-failed', }, @@ -721,9 +711,8 @@ export default function (state = defaultState, action: AnyAction): Notifications ...state.messages, models: { ...state.messages.models, - inferenceDone: - 'Automatic annotation finished for the ' + - `task ${taskID}`, + inferenceDone: 'Automatic annotation accomplished for the ' + + `[task ${taskID}](/tasks/${taskID})`, }, }, }; @@ -761,9 +750,7 @@ export default function (state = defaultState, action: AnyAction): Notifications models: { ...state.errors.models, inferenceStatusFetching: { - message: - 'Fetching inference status for the ' + - `task ${taskID}`, + message: `Fetching inference status for the [task ${taskID}](/tasks/${taskID})`, reason: action.payload.error.toString(), }, }, @@ -794,9 +781,7 @@ export default function (state = defaultState, action: AnyAction): Notifications models: { ...state.errors.models, starting: { - message: - 'Could not infer model for the ' + - `task ${taskID}`, + message: `Could not infer model for the [task ${taskID}](/tasks/${taskID})`, reason: action.payload.error.toString(), }, }, @@ -812,9 +797,7 @@ export default function (state = defaultState, action: AnyAction): Notifications models: { ...state.errors.models, canceling: { - message: - 'Could not cancel model inference for the ' + - `task ${taskID}`, + message: `Could not cancel model inference for the [task ${taskID}](/tasks/${taskID})`, reason: action.payload.error.toString(), }, }, @@ -1021,8 +1004,7 @@ export default function (state = defaultState, action: AnyAction): Notifications ...state.errors.annotation, uploadAnnotations: { message: - 'Could not upload annotations for the ' + - `job ${taskID}`, + `Could not upload annotations for the [job ${jobID}](/tasks/${taskID}/jobs/${jobID})`, reason: error.toString(), className: 'cvat-notification-notice-upload-annotations-fail', }, diff --git a/cvat-ui/src/styles.scss b/cvat-ui/src/styles.scss index cafc0b9f..5ff6e92a 100644 --- a/cvat-ui/src/styles.scss +++ b/cvat-ui/src/styles.scss @@ -110,3 +110,9 @@ hr { padding-top: 0; } } + +.ant-notification-notice { + p { + margin-bottom: 0; + } +} diff --git a/cvat/apps/iam/exceptions.py b/cvat/apps/iam/exceptions.py new file mode 100644 index 00000000..12a62711 --- /dev/null +++ b/cvat/apps/iam/exceptions.py @@ -0,0 +1,36 @@ +# Copyright (C) 2023 CVAT.ai Corporation +# +# SPDX-License-Identifier: MIT + +from django.conf import settings +from django.utils.module_loading import import_string +from rest_framework.exceptions import PermissionDenied + +class DefaultLimitsReachedException(PermissionDenied): + default_personal_detail = "You've reached the maximum number of {}. Contact the administrator to extend the limits." + default_org_detail = "You've reached the maximum number of {}. Contact the administrator to extend the limits for `{}` organization." + + def __init__(self, reasons, iam_context): + if not reasons or not isinstance(reasons, list): + super().__init__(reasons) + + msg = self.default_personal_detail + if iam_context["organization"] is not None: + msg = self.default_org_detail + msg = msg.format(', '.join(reasons), iam_context["organization"].slug) + else: + msg = msg.format(', '.join(reasons)) + + super().__init__({"message": msg}) + +class ExceptionFactory: + def __call__(self, *args, **kwargs): + dotted_path = getattr(settings, "IAM_BASE_EXCEPTION", None) + print(dotted_path) + + if dotted_path is None: + return DefaultLimitsReachedException(*args, **kwargs) + + return import_string(dotted_path)(*args, **kwargs) + +LimitsReachedException = ExceptionFactory() diff --git a/cvat/apps/iam/permissions.py b/cvat/apps/iam/permissions.py index 6836cf0a..ea5ac9dc 100644 --- a/cvat/apps/iam/permissions.py +++ b/cvat/apps/iam/permissions.py @@ -20,6 +20,7 @@ from rest_framework.permissions import BasePermission from cvat.apps.organizations.models import Membership, Organization from cvat.apps.engine.models import Project, Task, Job, Issue +from cvat.apps.iam.exceptions import LimitsReachedException from cvat.apps.limit_manager.core.limits import (CapabilityContext, LimitManager, Limits, OrgCloudStoragesContext, OrgTasksContext, ProjectWebhooksContext, OrgCommonWebhooksContext, @@ -32,8 +33,6 @@ class StrEnum(str, Enum): def __str__(self) -> str: return self.value -class RequestNotAllowedError(PermissionDenied): - pass @define class PermissionResult: @@ -1590,6 +1589,8 @@ class PolicyEnforcer(BasePermission): request, view, obj, basic_permissions )) + self._iam_context = request.iam_context + allow = self._check_permissions(basic_permissions) if allow and conditional_permissions: allow = self._check_permissions(conditional_permissions) @@ -1605,8 +1606,10 @@ class PolicyEnforcer(BasePermission): if allow: return True + elif reasons: + raise LimitsReachedException(reasons, self._iam_context) else: - raise RequestNotAllowedError(reasons or "not authorized") + raise PermissionDenied("not authorized") def has_permission(self, request, view): if not view.detail: diff --git a/cvat/apps/iam/rules/limits.rego b/cvat/apps/iam/rules/limits.rego index b6040384..a097088b 100644 --- a/cvat/apps/iam/rules/limits.rego +++ b/cvat/apps/iam/rules/limits.rego @@ -27,77 +27,77 @@ check_limit_exceeded(current, max) { -problems contains "user tasks limit reached" if { +problems contains "tasks per user" if { check_limit_exceeded( input.resource.limits[CAP_USER_SANDBOX_TASKS].used, input.resource.limits[CAP_USER_SANDBOX_TASKS].max ) } -problems contains "user projects limit reached" if { +problems contains "projects per user" if { check_limit_exceeded( input.resource.limits[CAP_USER_SANDBOX_PROJECTS].used, input.resource.limits[CAP_USER_SANDBOX_PROJECTS].max ) } -problems contains "user project tasks limit reached" if { +problems contains "tasks per project for the user" if { check_limit_exceeded( input.resource.limits[CAP_TASKS_IN_USER_SANDBOX_PROJECT].used, input.resource.limits[CAP_TASKS_IN_USER_SANDBOX_PROJECT].max ) } -problems contains "org tasks limit reached" if { +problems contains "tasks per organization" if { check_limit_exceeded( input.resource.limits[CAP_ORG_TASKS].used, input.resource.limits[CAP_ORG_TASKS].max ) } -problems contains "org projects limit reached" if { +problems contains "projects per organization" if { check_limit_exceeded( input.resource.limits[CAP_ORG_PROJECTS].used, input.resource.limits[CAP_ORG_PROJECTS].max ) } -problems contains "org project tasks limit reached" if { +problems contains "tasks per project for the organization" if { check_limit_exceeded( input.resource.limits[CAP_TASKS_IN_ORG_PROJECT].used, input.resource.limits[CAP_TASKS_IN_ORG_PROJECT].max ) } -problems contains "project webhooks limit reached" if { +problems contains "webhooks per project" if { check_limit_exceeded( input.resource.limits[CAP_PROJECT_WEBHOOKS].used, input.resource.limits[CAP_PROJECT_WEBHOOKS].max ) } -problems contains "org webhooks limit reached" if { +problems contains "webhooks per organization" if { check_limit_exceeded( input.resource.limits[CAP_ORG_COMMON_WEBHOOKS].used, input.resource.limits[CAP_ORG_COMMON_WEBHOOKS].max ) } -problems contains "user orgs limit reached" if { +problems contains "organizations per user" if { check_limit_exceeded( input.resource.limits[CAP_USER_OWNED_ORGS].used, input.resource.limits[CAP_USER_OWNED_ORGS].max ) } -problems contains "user cloud storages limit reached" if { +problems contains "cloud storages per user" if { check_limit_exceeded( input.resource.limits[CAP_USER_SANDBOX_CLOUD_STORAGES].used, input.resource.limits[CAP_USER_SANDBOX_CLOUD_STORAGES].max ) } -problems contains "org cloud storages limit reached" if { +problems contains "cloud storages per organization" if { check_limit_exceeded( input.resource.limits[CAP_ORG_CLOUD_STORAGES].used, input.resource.limits[CAP_ORG_CLOUD_STORAGES].max diff --git a/cvat/settings/base.py b/cvat/settings/base.py index 4b0439d8..8d2c5d60 100644 --- a/cvat/settings/base.py +++ b/cvat/settings/base.py @@ -192,6 +192,7 @@ REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'cvat.apps.iam.schema.CustomAutoSchema', } + REST_AUTH_REGISTER_SERIALIZERS = { 'REGISTER_SERIALIZER': 'cvat.apps.iam.serializers.RegisterSerializerEx', } @@ -249,6 +250,7 @@ WSGI_APPLICATION = 'cvat.wsgi.application' # IAM settings IAM_TYPE = 'BASIC' +IAM_BASE_EXCEPTION = None # a class which will be used by IAM to report errors IAM_DEFAULT_ROLES = ['user'] IAM_ADMIN_ROLE = 'admin' # Index in the list below corresponds to the priority (0 has highest priority) diff --git a/tests/python/rest_api/test_limits.py b/tests/python/rest_api/test_limits.py index 61fed5dd..cea57510 100644 --- a/tests/python/rest_api/test_limits.py +++ b/tests/python/rest_api/test_limits.py @@ -102,11 +102,11 @@ class TestUserLimits: _DEFAULT_ORGS_LIMIT = 1 _DEFAULT_CLOUD_STORAGES_LIMIT = 10 - _TASK_LIMIT_MESSAGE = "user tasks limit reached" - _PROJECT_TASK_LIMIT_MESSAGE = "user project tasks limit reached" - _PROJECTS_LIMIT_MESSAGE = "user projects limit reached" - _ORGS_LIMIT_MESSAGE = "user orgs limit reached" - _CLOUD_STORAGES_LIMIT_MESSAGE = "user cloud storages limit reached" + _TASK_LIMIT_MESSAGE = "tasks per user" + _PROJECT_TASK_LIMIT_MESSAGE = "tasks per project for the user" + _PROJECTS_LIMIT_MESSAGE = "projects per user" + _ORGS_LIMIT_MESSAGE = "organizations per user" + _CLOUD_STORAGES_LIMIT_MESSAGE = "cloud storages per user" def _create_task( self, *, project: Optional[int] = None, client: Optional[Client] = None @@ -138,7 +138,7 @@ class TestUserLimits: self._create_task() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_importing_backup(self): for _ in range(self._DEFAULT_TASKS_LIMIT): @@ -151,7 +151,7 @@ class TestUserLimits: self.client.tasks.create_from_backup(backup_filename) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_project(self): project = self._create_project().id @@ -163,7 +163,7 @@ class TestUserLimits: self._create_task(project=project) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECT_TASK_LIMIT_MESSAGE} + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_different_projects(self): project1 = self._create_project().id @@ -178,7 +178,7 @@ class TestUserLimits: self._create_task() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_filled_project(self): project = self._create_project().id @@ -192,10 +192,8 @@ class TestUserLimits: self._create_task(project=project) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == { - self._TASK_LIMIT_MESSAGE, - self._PROJECT_TASK_LIMIT_MESSAGE, - } + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_project_tasks_limit_when_moving_into_filled_project(self): project = self._create_project().id @@ -208,7 +206,7 @@ class TestUserLimits: task.update(models.PatchedTaskWriteRequest(project_id=project)) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECT_TASK_LIMIT_MESSAGE} + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) @pytest.mark.xfail( raises=AssertionError, reason="only admins can change ownership, but they ignore limits" @@ -229,7 +227,7 @@ class TestUserLimits: ) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECT_TASK_LIMIT_MESSAGE} + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) @pytest.mark.xfail( raises=AssertionError, reason="only admins can change ownership, but they ignore limits" @@ -254,10 +252,8 @@ class TestUserLimits: ) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == { - self._DEFAULT_TASKS_LIMIT, - self._PROJECT_TASK_LIMIT_MESSAGE, - } + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) @pytest.mark.xfail( raises=AssertionError, reason="only admins can change ownership, but they ignore limits" @@ -278,7 +274,7 @@ class TestUserLimits: ) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECT_TASK_LIMIT_MESSAGE} + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_projects_limit(self): for _ in range(self._DEFAULT_PROJECTS_LIMIT): @@ -288,7 +284,7 @@ class TestUserLimits: self._create_project() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECTS_LIMIT_MESSAGE} + assert self._PROJECTS_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_projects_limit_when_importing_backup(self): for _ in range(self._DEFAULT_PROJECTS_LIMIT): @@ -301,7 +297,7 @@ class TestUserLimits: self.client.projects.create_from_backup(backup_filename) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECTS_LIMIT_MESSAGE} + assert self._PROJECTS_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_orgs_limit(self): for i in range(self._DEFAULT_ORGS_LIMIT): @@ -316,7 +312,7 @@ class TestUserLimits: ) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._ORGS_LIMIT_MESSAGE} + assert self._ORGS_LIMIT_MESSAGE in str(capture.value.body) @pytest.mark.with_external_services def test_can_reach_cloud_storages_limit(self, request: pytest.FixtureRequest): @@ -350,7 +346,7 @@ class TestUserLimits: response = _add_storage(i) assert response.status_code == HTTPStatus.FORBIDDEN - assert set(response.json()) == {self._CLOUD_STORAGES_LIMIT_MESSAGE} + assert self._CLOUD_STORAGES_LIMIT_MESSAGE in str(response.content) class TestOrgLimits: @@ -391,10 +387,10 @@ class TestOrgLimits: _DEFAULT_PROJECTS_LIMIT = 3 _DEFAULT_CLOUD_STORAGES_LIMIT = 10 - _TASK_LIMIT_MESSAGE = "org tasks limit reached" - _PROJECT_TASK_LIMIT_MESSAGE = "org project tasks limit reached" - _PROJECTS_LIMIT_MESSAGE = "org projects limit reached" - _CLOUD_STORAGES_LIMIT_MESSAGE = "org cloud storages limit reached" + _TASK_LIMIT_MESSAGE = "tasks per organization" + _PROJECT_TASK_LIMIT_MESSAGE = "tasks per project for the organization" + _PROJECTS_LIMIT_MESSAGE = "projects per organization" + _CLOUD_STORAGES_LIMIT_MESSAGE = "cloud storages per organization" @contextmanager def _patch_client_with_org(self, client: Optional[Client] = None): @@ -442,7 +438,7 @@ class TestOrgLimits: self._create_task() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_importing_backup(self): for _ in range(self._DEFAULT_TASKS_LIMIT): @@ -455,7 +451,7 @@ class TestOrgLimits: self.client.tasks.create_from_backup(backup_filename) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_project(self): project = self._create_project().id @@ -467,7 +463,7 @@ class TestOrgLimits: self._create_task(project=project) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECT_TASK_LIMIT_MESSAGE} + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_different_projects(self): project1 = self._create_project().id @@ -482,7 +478,7 @@ class TestOrgLimits: self._create_task() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._TASK_LIMIT_MESSAGE} + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_tasks_limit_when_creating_in_filled_project(self): project = self._create_project().id @@ -496,10 +492,8 @@ class TestOrgLimits: self._create_task(project=project) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == { - self._TASK_LIMIT_MESSAGE, - self._PROJECT_TASK_LIMIT_MESSAGE, - } + assert self._TASK_LIMIT_MESSAGE in str(capture.value.body) + assert self._PROJECT_TASK_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_projects_limit(self): for _ in range(self._DEFAULT_PROJECTS_LIMIT): @@ -509,7 +503,7 @@ class TestOrgLimits: self._create_project() assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECTS_LIMIT_MESSAGE} + assert self._PROJECTS_LIMIT_MESSAGE in str(capture.value.body) def test_can_reach_projects_limit_when_importing_backup(self): for _ in range(self._DEFAULT_PROJECTS_LIMIT): @@ -522,7 +516,7 @@ class TestOrgLimits: self.client.projects.create_from_backup(str(backup_filename)) assert capture.value.status == HTTPStatus.FORBIDDEN - assert set(json.loads(capture.value.body)) == {self._PROJECTS_LIMIT_MESSAGE} + assert self._PROJECTS_LIMIT_MESSAGE in str(capture.value.body) @pytest.mark.with_external_services def test_can_reach_cloud_storages_limit(self, request: pytest.FixtureRequest): @@ -557,4 +551,4 @@ class TestOrgLimits: response = _add_storage(i) assert response.status_code == HTTPStatus.FORBIDDEN - assert set(response.json()) == {self._CLOUD_STORAGES_LIMIT_MESSAGE} + assert self._CLOUD_STORAGES_LIMIT_MESSAGE in str(response.content) diff --git a/yarn.lock b/yarn.lock index 70c3b556..e0ce0e21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1694,6 +1694,13 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== +"@types/debug@^4.0.0": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -1751,6 +1758,13 @@ dependencies: "@types/node" "*" +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + "@types/history@^4.7.11": version "4.7.11" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" @@ -1840,6 +1854,11 @@ resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.9.tgz#f1ef9adbd1eac3466f21b6988b1c82c633a45340" integrity sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg== +"@types/ms@*": + version "0.7.31" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + "@types/node@*", "@types/node@^18.0.3": version "18.7.11" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.11.tgz#486e72cfccde88da24e1f23ff1b7d8bfb64e6250" @@ -1865,12 +1884,12 @@ resolved "https://registry.yarnpkg.com/@types/polylabel/-/polylabel-1.0.5.tgz#9262f269de36f1e9248aeb9dee0ee9d10065e043" integrity sha512-gnaNmo1OJiYNBFAZMZdqLZ3hKx2ee4ksAzqhKWBxuQ61PmhINHMcvIqsGmyCD1WFKCkwRt9NFhMSmKE6AgYY+w== -"@types/prettier@2.4.1", "@types/prettier@^2.0.0", "@types/prettier@^2.1.5": +"@types/prettier@^2.0.0", "@types/prettier@^2.1.5": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== -"@types/prop-types@*": +"@types/prop-types@*", "@types/prop-types@^15.0.0": version "15.7.5" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== @@ -1898,14 +1917,14 @@ "@types/react" "*" "@types/reactcss" "*" -"@types/react-dom@^16.9.14", "@types/react-dom@^18.0.5": - version "18.0.6" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1" - integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA== +"@types/react-dom@^16.9.14": + version "16.9.17" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.17.tgz#29100cbcc422d7b7dba7de24bb906de56680dd34" + integrity sha512-qSRyxEsrm5btPXnowDOs5jSkgT8ldAA0j6Qp+otHUh+xHzy3sXmgNfyhucZjAjkgpdAUw9rJe0QRtX/l+yaS4g== dependencies: - "@types/react" "*" + "@types/react" "^16" -"@types/react-redux@^7.1.18", "@types/react-redux@^7.1.24": +"@types/react-redux@^7.1.18": version "7.1.24" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0" integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ== @@ -1922,7 +1941,7 @@ dependencies: "@types/react" "*" -"@types/react-router-dom@^5.1.9", "@types/react-router-dom@^5.3.3": +"@types/react-router-dom@^5.1.9": version "5.3.3" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== @@ -1946,7 +1965,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.14.15", "@types/react@^17.0.30": +"@types/react@*": version "17.0.48" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.48.tgz#a4532a8b91d7b27b8768b6fc0c3bccb760d15a6c" integrity sha512-zJ6IYlJ8cYYxiJfUaZOQee4lh99mFihBoqkOSEGV+dFi9leROW6+PgstzQ+w3gWTnUfskALtQPGHK6dYmPj+2A== @@ -1955,6 +1974,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^16", "@types/react@^16.14.15": + version "16.14.34" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.34.tgz#d129324ffda312044e1c47aab18696e4ed493282" + integrity sha512-b99nWeGGReLh6aKBppghVqp93dFJtgtDOzc8NXM6hewD8PQ2zZG5kBLgbx+VJr7Q7WBMjHxaIl3dwpwwPIUgyA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/reactcss@*": version "1.2.6" resolved "https://registry.yarnpkg.com/@types/reactcss/-/reactcss-1.2.6.tgz#133c1e7e896f2726370d1d5a26bf06a30a038bcc" @@ -3087,6 +3115,11 @@ bail@^1.0.0: resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== +bail@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3436,6 +3469,11 @@ character-entities@^1.0.0: resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + character-reference-invalid@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" @@ -3683,6 +3721,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +comma-separated-tokens@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -4186,6 +4229,13 @@ decimal.js@^10.2.1, decimal.js@^10.3.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.0.tgz#97a7448873b01e92e5ff9117d89a7bca8e63e0fe" integrity sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg== +decode-named-character-reference@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + dependencies: + character-entities "^2.0.0" + decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" @@ -4299,6 +4349,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -4341,6 +4396,11 @@ diff-sequences@^29.3.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== +diff@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -5781,6 +5841,11 @@ hasha@^5.0.0: is-stream "^2.0.0" type-fest "^0.8.0" +hast-util-whitespace@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz#0ec64e257e6fc216c7d14c8a1b74d27d650b4557" + integrity sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng== + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -6153,6 +6218,11 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -6441,6 +6511,11 @@ is-plain-obj@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -7616,6 +7691,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kleur@^4.0.3: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + klona@^2.0.4: version "2.0.5" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" @@ -8001,6 +8081,15 @@ mdast-comment-marker@^1.0.0: resolved "https://registry.yarnpkg.com/mdast-comment-marker/-/mdast-comment-marker-1.1.2.tgz#5ad2e42cfcc41b92a10c1421a98c288d7b447a6d" integrity sha512-vTFXtmbbF3rgnTh3Zl3irso4LtvwUq/jaDvT2D1JqTGAwaipcS7RpTxzi6KjoRqI9n2yuAhzLDAC8xVTF3XYVQ== +mdast-util-definitions@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" + integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + mdast-util-find-and-replace@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" @@ -8021,6 +8110,24 @@ mdast-util-from-markdown@^0.8.0: parse-entities "^2.0.0" unist-util-stringify-position "^2.0.0" +mdast-util-from-markdown@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" + integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + mdast-util-frontmatter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz#8bd5cd55e236c03e204a036f7372ebe9e6748240" @@ -8075,6 +8182,21 @@ mdast-util-heading-style@^1.0.2: resolved "https://registry.yarnpkg.com/mdast-util-heading-style/-/mdast-util-heading-style-1.0.6.tgz#6410418926fd5673d40f519406b35d17da10e3c5" integrity sha512-8ZuuegRqS0KESgjAGW8zTx4tJ3VNIiIaGFNEzFpRSAQBavVc7AvOo9I4g3crcZBfYisHs4seYh0rAVimO6HyOw== +mdast-util-to-hast@^12.1.0: + version "12.2.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.5.tgz#91532ebd929a7def21585034f7901eb367d2d272" + integrity sha512-EFNhT35ZR/VZ85/EedDdCNTq0oFM+NM/+qBomVGQ0+Lcg0nhI8xIwmdCzNMlVlCJNXRprpobtKP/IUh8cfz6zQ== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-definitions "^5.0.0" + micromark-util-sanitize-uri "^1.1.0" + trim-lines "^3.0.0" + unist-builder "^3.0.0" + unist-util-generated "^2.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: version "0.6.5" resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" @@ -8097,6 +8219,11 @@ mdast-util-to-string@^2.0.0: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== +mdast-util-to-string@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" + integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -8171,6 +8298,28 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromark-core-commonmark@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" + integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromark-extension-frontmatter@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz#61b8e92e9213e1d3c13f5a59e7862f5ca98dfa53" @@ -8223,6 +8372,156 @@ micromark-extension-gfm@^0.3.0: micromark-extension-gfm-tagfilter "~0.3.0" micromark-extension-gfm-task-list-item "~0.3.0" +micromark-factory-destination@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" + integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" + integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-space@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" + integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" + integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" + integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" + integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" + integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" + integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" + integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" + integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" + integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-encode@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" + integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== + +micromark-util-html-tag-name@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" + integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== + +micromark-util-normalize-identifier@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" + integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" + integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0, micromark-util-sanitize-uri@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz#f12e07a85106b902645e0364feb07cf253a85aee" + integrity sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" + integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-util-symbol@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" + integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" + integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== + micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: version "2.11.4" resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" @@ -8231,6 +8530,29 @@ micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: debug "^4.0.0" parse-entities "^2.0.0" +micromark@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.1.0.tgz#eeba0fe0ac1c9aaef675157b52c166f125e89f62" + integrity sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -8389,6 +8711,11 @@ mousetrap@^1.6.5: resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9" integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA== +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9657,7 +9984,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -9675,6 +10002,11 @@ proper-lockfile@^4.1.2: retry "^0.12.0" signal-exit "^3.0.2" +property-information@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" + integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -10224,6 +10556,27 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-markdown@^8.0.4: + version "8.0.4" + resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.4.tgz#b5ff1f0f29ead71a7a6f98815eb1a70bcc2a036e" + integrity sha512-2oxHa6oDxc1apg/Gnc1Goh06t3B617xeywqI/92wmDV9FELI6ayRkwge7w7DoEqM0gRpZGTNU6xQG+YpJISnVg== + dependencies: + "@types/hast" "^2.0.0" + "@types/prop-types" "^15.0.0" + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^2.0.0" + prop-types "^15.0.0" + property-information "^6.0.0" + react-is "^18.0.0" + remark-parse "^10.0.0" + remark-rehype "^10.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unified "^10.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + react-moment@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/react-moment/-/react-moment-1.1.2.tgz#a9b157c58ddd226a2f746e5ca43415b24a17b6af" @@ -11083,6 +11436,15 @@ remark-message-control@^6.0.0: mdast-comment-marker "^1.0.0" unified-message-control "^3.0.0" +remark-parse@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" + integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.0.0" + remark-parse@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" @@ -11182,6 +11544,16 @@ remark-preset-lint-recommended@^5.0.0: remark-lint-no-unused-definitions "^2.0.0" remark-lint-ordered-list-marker-style "^2.0.0" +remark-rehype@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" + integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^12.1.0" + unified "^10.0.0" + remark-stringify@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-9.0.1.tgz#576d06e910548b0a7191a71f27b33f1218862894" @@ -11403,6 +11775,13 @@ rxjs@^7.5.5: dependencies: tslib "^2.1.0" +sade@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -11874,6 +12253,11 @@ source-map@^0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== +space-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== + spawn-wrap@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" @@ -12172,6 +12556,13 @@ style-search@^0.1.0: resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" integrity sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg== +style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + stylelint-config-recommended@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz#e0e547434016c5539fe2650afd58049a2fd1d657" @@ -12586,6 +12977,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -12601,6 +12997,11 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +trough@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" + integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + ts-jest@26: version "26.5.6" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.6.tgz#c32e0746425274e1dfe333f43cd3c800e014ec35" @@ -12847,6 +13248,19 @@ unified-message-control@^3.0.0: unist-util-visit "^2.0.0" vfile-location "^3.0.0" +unified@^10.0.0: + version "10.1.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== + dependencies: + "@types/unist" "^2.0.0" + bail "^2.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^4.0.0" + trough "^2.0.0" + vfile "^5.0.0" + unified@^9.1.0: version "9.2.2" resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" @@ -12874,6 +13288,13 @@ uniq@^1.0.1: resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== +unist-builder@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" + integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-find-all-after@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz#fdfecd14c5b7aea5e9ef38d5e0d5f774eeb561f6" @@ -12886,6 +13307,11 @@ unist-util-generated@^1.0.0, unist-util-generated@^1.1.0: resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== +unist-util-generated@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" + integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== + unist-util-inspect@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/unist-util-inspect/-/unist-util-inspect-5.0.1.tgz#168c8770a99902318ca268f8c391e294bcf44540" @@ -12898,11 +13324,23 @@ unist-util-is@^4.0.0: resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== +unist-util-is@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" + integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + unist-util-position@^3.0.0, unist-util-position@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== +unist-util-position@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" + integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" @@ -12910,6 +13348,13 @@ unist-util-stringify-position@^2.0.0: dependencies: "@types/unist" "^2.0.2" +unist-util-stringify-position@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit-parents@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" @@ -12918,6 +13363,14 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" +unist-util-visit-parents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" + integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit@^2.0.0, unist-util-visit@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" @@ -12927,6 +13380,15 @@ unist-util-visit@^2.0.0, unist-util-visit@^2.0.1: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" +unist-util-visit@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" + integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + universal-cookie@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-4.0.4.tgz#06e8b3625bf9af049569ef97109b4bb226ad798d" @@ -13038,6 +13500,16 @@ uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -13092,6 +13564,14 @@ vfile-message@^2.0.0: "@types/unist" "^2.0.0" unist-util-stringify-position "^2.0.0" +vfile-message@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.3.tgz#1360c27a99234bebf7bddbbbca67807115e6b0dd" + integrity sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-reporter-json@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vfile-reporter-json/-/vfile-reporter-json-2.0.2.tgz#c2e4e5b92bcb70f65c5a93f1ad3a08ef60b94606" @@ -13129,6 +13609,16 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +vfile@^5.0.0: + version "5.3.6" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.6.tgz#61b2e70690cc835a5d0d0fd135beae74e5a39546" + integrity sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"