From fa06168375885a3e579acf4e6638c28fe9c3efe8 Mon Sep 17 00:00:00 2001 From: Aron Buzogany <108480125+AronBuzogany@users.noreply.github.com> Date: Thu, 23 May 2024 21:51:42 +0200 Subject: [PATCH] release version 1 (#426) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #15 - Using environment variable UPLOAD_FOLDER * #15 - Add static typing to the submissions model * #15 - Fixing linter * docker-compose added * #15 - Will fix this later * #15 - Linter has cyclic imports * change port * #15 - Small URL change * fixed extracting of zip and uploading in project upload directory * fix 400 when non zip is uploaded * fixed tests * added test zip file * linter fixes * removed some test files * linter and test fixes * import depedency fix * fix import order * removed import getenv * removed valid_project function * fix fstring * fix: upload_directory * removed exist_ok=True * use path.join * added url field * fixed not checking for tuple type anymore * fixed env var for tests * fixed env var for tests * fixed with statements * using os.path.split instead of regular split * added exist_ok * i forgot :skull: fix lmao yeet * i forgot :skull: fix lmao yeet * goofy augh fstring * another small fix * fixed the 'not fixed eh' problem * linting * fix handling fail * added try block * linter * nginx.conf added * rm conf * fixed archieved to archived typo (#84) * fixed archieved to archived typo * fixed typo descriptions to description * last change * tests passed! * #15 - Spelling * #15 - Fixing tests the merge broke * Feature/share link (#72) * create subfolder for course tests * added table for share codes * loading env variables * added default value to function parameters * added endpoint for join_codes * added tests for join_codes * fixed: linting * fixed typo: * fixed import conftest * fixed merge with singular model naming * unused file * added functionlity for downloading files * reformatting * linter * niets veranderd? linter flipt * small newline change * removed f-string formatting * added 404 and 500 cases * fixed tests * fixed os.curcwd * linter * removed print * check if file exist and commented code removed * fixed code duplication * used basename insteal of .split * linter fix * Backend/tests/review models (#83) * #81 - Updated user model tests, TODO delete * #81 - Removing an unnecessary file * #81 - Updated course model tests, TODO delete * #81 - Updated course_relation model tests * #81 - Cleanup * #81 - Project model tests * #81 - Submission model tests * #81 - Cleanup * #81 - Adding a test and also testing GH tests out * #81 - Adding rollbacks after every error raised * #81 - Maybe fix * #81 - Another try * #81 - This should fix it * #81 Adding the delete method tests and updating the db_construct * Tests/cleanup (#104) * command useless and takes time * cleaned up courses tests * cleaned up project tests * moved testzip to resources folder * cleaned up users tests * small cleanup submission tests * resolved linting * corrected function docs * re-using existing fixtures to reduce code duplication * resolved linter * removed useless fstring * removed unused import * fix badge for workflow in readme.md (#108) * test example workflow * check if push argument works * does the value update test * Create ci-test-backend.yaml created a seperate file for the backend test * added backend badge to readme * changed yml to yaml * changed tests to test * added seperate files for linter and tests for both front and backend * gave correct names to workflows * correct names to run name * removed code dupe and pray for test run * added both badges for linter and tests from backend * file changes detected? * removed unused code parts * fix: eslint not found error * added frontend badges * frontend developper instructions (#110) * frontend developper instructions * only 1 backtick fix * Merge backend authentication into development (#73) * start authentication * authentication start decorators * login_required should work with access token * backend authentication for most endpoints (very rough draft of functions in authentication.py) * clean_up_function * authentication cleanup * give error when access_token fails * documentation auth functions * fixed imports * actual import fix * added requests * authorize submissions * removed double checks * start testing setup backend authentication * poging testen * github tests check * user tests with authentication * auth url accessible hopefully * change authorization to be easier to deal with since it doesn't matter for tests * fixed jobCategory -> jobTitle * fix authentication * user tests zouden moeten slagen * fix authentication arguments * project tests with authentication * changed auth server id of teacher * maybe correct primary keys * second try on primary key of course relations * further test authentication * authentication on project assignment files * auth on course_join_codes and extra tests * teacher_id in function when necessary * user tests with authentication * extra testing * fixed comments * lots of testing changes * should be 1 error test now * fix tests * Fix #114 (#115) * Fix #114 * test 1 * Fix #114 try 2 * fixed misnamed runner * removed trailing new line * Merge cleanup of authentication and tests into development (#111) * start authentication * authentication start decorators * login_required should work with access token * backend authentication for most endpoints (very rough draft of functions in authentication.py) * clean_up_function * authentication cleanup * give error when access_token fails * documentation auth functions * fixed imports * actual import fix * added requests * authorize submissions * removed double checks * start testing setup backend authentication * poging testen * github tests check * user tests with authentication * auth url accessible hopefully * change authorization to be easier to deal with since it doesn't matter for tests * fixed jobCategory -> jobTitle * fix authentication * user tests zouden moeten slagen * fix authentication arguments * project tests with authentication * changed auth server id of teacher * maybe correct primary keys * second try on primary key of course relations * further test authentication * authentication on project assignment files * auth on course_join_codes and extra tests * teacher_id in function when necessary * user tests with authentication * extra testing * fixed comments * lots of testing changes * should be 1 error test now * fix tests * small linter fix * should fix the linter * actually fixed this time * linter all return statements * allow admins to patch users * should pass all tests * mergeable * grouped imports * made requested changes * requested changes * line too long * unused imports * added models folder to utils * Enhancement/debug env variable (#128) * added waitress te requirements to serve in production * added debug as an env variable and serving with waitress when not in debug mode * fixed backend to frontend typo and added workflow branch argument (#119) * fixed backend to frontend typo and added workflow branch argument * added back 2. back to readme of backend * changed submission status to enum (#133) * changed submission status to enum * resolved linting * Fix #77 changed grading to float (#134) * Fixed #112 (#113) * Fixed #112 * removed new line * Fix for uploading project files (#120) * files are now patchable uncluding the files * fix for uploading a file that is not a zip that it doesn't get saved * unsaved changes * buzoghany requested changes * linter * added rollbacks * extra rollback * Add get courses tests * Add post courses tests * Add get course tests * Add patch course tests * Add delete course tests * Removes all usage of str(e) in courses endpoint (#126) * Removed all usage of str(e) in courses endpoint * common parts of error put into const var --------- Co-authored-by: Siebe Vlietinck <71773032+Vucis@users.noreply.github.com> * changed port to 5001 (#142) * Removed is_teacher and is_admin, changed to role enum (#127) * Removed is_teacher and is_admin, changed to role enum * sql enum type * usage of enum and fixed sql * made role serializable * clean * docs * fixed user patch * args vs json * test * check if course name is blank (#100) * check if course name is blank * generalized blank string check * fixed yo request * fixed conflicts * cleaned code * fix * started initial readme for repo (#122) * started initial readme for repo * added workflow badges * readme edits * spelling mistakes * grammar fix * fixed route /docs and edited projects endpoint (#123) * fixed route /docs and edited projects endpoint * linter+test succeed * fix: remove duplicate json file * edited env variable for failing tests * linter * Base setup for easy translations in frontend (#145) * i18n setup * added dependencies * Fix for issue 102. Submissions get now returns summary information instead of only url (#147) * Fix #102 * linting * Correctly uploading submission files (#136) * 116 - Correctly uploading submission files * #116 - Spelling * Remove break * Remove unused variable * Specify which files are required * Remove unnecessary stringify of UPLOAD_FOLDER * Update the submission_path path.join * Catching OSErrors when making directories and saving files * Update the run_tests script * This should allow frontend to communicate with our backend (#144) * allow cors * moved CORS to create_app_with_db * Test invalid user form (#137) * added test for invalid user form * traling whitespace * post to /users is not allowed * removed double invalid fixture * Test for course with invalid field (#125) * added test for course with invalid field * authorization header! * fix * Merge with backend/tests/auth * courses get finished * Feature/backend/documentation (#94) * cooken on the projects documentation * #92 - Fixing missing /submissions * #92 - Fixing apilinter * requested changes * openapi object * changed to yaml file * small fix * grammar * json->yaml * pyyaml installed in dev.txt * linter --------- Co-authored-by: Jarne Clauw <67628242+JarneClauw@users.noreply.github.com> * Base test class to handle auth (#153) * Adding auth tokens * Setup for auth tests * Fixing tests * Cleanup * Spelling * Remove unnecessary commit * navbar (#80) * navbar * changes * oops * close bar on redirect * linter conflicts for component function * scalability matters * useEffect to check login state and adjust link item list * a little more readable * No longer authenticating teachers/students through url params (#165) * Fix #105 * adjusted tests to not use url query as authentication * nested translation files (#163) * return deadline aswel on projects (#168) * Bump vite from 5.1.3 to 5.1.7 in /frontend (#166) Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.1.3 to 5.1.7. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v5.1.7/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v5.1.7/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Using i18n browser detector and route detection to assign languages aswell as menu for users (#156) * added tag to locales * added menu to switch between languages * updated i18n detector dependency * configured detector to detect language in path * configured language routes * added outlet that detects languague and adds it to i18n * added menu to select language * resolved linting * unused statement removed * Frontend/feature/submission post (#150) * added dependencies for treeview and code viewer * created drag and drop upload, treeview and code viewer * Fix #10 * removed unused dependencies * created files utils with zip regex checker * moved function to utils * removed unused eslint rule * corrected message on missing required files * consistent frontend text * fixed grammar * resolved package diff * Fixed inconsistently added auth tokens * Whoops added it again * Adding commented out tests * Adding all the other auth tests * Tests for students * Admin tests * Forgot part of merge * Fix #179 (#180) * Fix #179 * adjusted test to new endpoint * fixed test * fixed linting * Whoops * Hope this fixes it * Typing and comments * updating tests * Set title of header using Portal (#177) * Set title using Portal * cleanup * Removed paths from db for projects and allowing multiple deadlines (#185) * Fix #181 * resolved syntax errors * Fix #181 * removed unused statement * resolved linting issues * removed print statement * Created dynamic deadline calender view/input (#190) * Fix #188 * added mui date time components to dependencies * fixed editable not being passed as prop * Backend/feature/submission evaluation (#67) * added docker to requirements * added: functionality to run a dockerized tester on a given submission * added tests for submission evaluators * moved file handling functions to seperate file * added interpretor path * updated dependencies * fixed: linting * added init file for module recognition * CMD isn't used anymore as it is provided by the compose * not running utils in docker as it uses docker internally and we don't yet have support for dind * switched to LF * changed: running tests not linting * subfolders for submissions are nog longer made by the evaluator * removed unused import statement * linting: added blank line * added ussage of requirements manifest which allows teachers to manifest which requirements are allowed to be used * added: helper functions to prepare test cases * added test case for working with requirements * disabled pylinter for evaluator test resources * fixed: linter ignoring all files * using pylint recursive argument instead * resolved merging issues * using docker in docker image instead * no longer binding socket to image * passing path instead of project * hotfix * binding docker daemon * starting dind docker daemon in entrypoint script * removed unused env variable * running all tests * fixed linting --------- Co-authored-by: Aron Buzogany Co-authored-by: abuzogan * Generalizing data field typing tests * Cleanup + renaming * Moving format to functions to make it clearer * cleanup * Fix test_post_admins * Fix test_get_courses_wrong_parameter * Creates project display for students and solves issue 186 (#187) * init project display * Fix #175 * added dependencies for #178 * Fix #186 * fixed test * resolved linting * fixed download url of submissions * added title to header * fixed typos * merge fail * Fixing all tests * cleanup * Generalizing some query parameter tests * Fixing linter * Whoops * Making authorization tests more explicit * registering composite types (#197) * Added the runner used to test submissions as an optional field of project table (#199) * Fix #198 * added possibility for custom runner * fixed enum type name * Running evaluator in synchron when runner is set (#203) * Fix #200 * created executor * fixed tests * resolved linting * linting * fix wrong evaluator in test * adjusted runner to support test * Check if submission is LATE (#196) * checking for if deadline is on time * Fix #82 * removed redundant print statement * authenticate endpoint * setting submission status when no runner * fixed inverted boolean * router fix (#205) * Added functionality to download submissions (#206) * Fix #189 * fixed linter * fixed linting * fix the no status on workflow badges (#211) * dev changes? * removed branch argument * removed random changes * The submissions form for project page (#124) * fixed beginning of project submission form * changed * changes * changed * removed print * form works * project form is working * backend fixes * backend linter * linter * fixed language support * frontend linter * packagelock * linter * letsgoo * unused import :nerd: * augh * siebe review * aron pr review * merge conf * pr fixed * veel * :) * idk how it works but it does * changes, a lot of them * does this fix * conftest * dev changes? * tests are working * working regexes * veel hihi * removed unused React * working form * linter and tests * small changes * pr review jeej * tag and route * removed CORS * removed unused imports * hopefully aron is happy nowgit pushgit pushgit push! * comment changed * re added decorator (#214) * Backend/project submission authorization issue (#210) * Fixing authorization for project * Fixing submission authorization issues * cleanup * Remove print and fix comments * Fixing submissions * Fixing projects * Cleanup * Fix filter placement * error pages (#93) * initial draft for error pages * indentation fixed * docs * error pages v1 * indentation fixed * layout adjusted, using RouterProvider instead of BrowserRouter to render errors correctly, tests added * linter * documentation * linter error parameters * Added i18n, changed general structure of App component and got rid of fade animation for the image * linting, package-lock.json fix * package file * changes to paramters in ErrorPage.tsx * use of keyPrefix * keyPrefix * fix * Added endpoint to add a user using a join code (#218) * Fix #71 * added course join endpoint * internal server error is 500 * fixed code docs * Addding a displayname to a user object (#221) * Homepage student + landing page (#194) Homepages added * Full authentication (#216) * backend-authentication * fix projects * remove extra requirements * fix test-auth_server * added: frontend redirect link * fix backend auth * fix error + code_challenge in frontend link * line too long + frontend linter errors * actual linter fix * removed code_verifier until milestone 3 * added ability to log out and added everything to init * redis added later * added login button to header * linter fix unused import * add display_name to user creation * test tests * linter fix * cookies test * flask test cookies? * added logout button * with client * Project overview (#219) * goeie styling yallah * pls werk * werkt hopelijk * linter --------- Co-authored-by: Siebe Vlietinck <71773032+Vucis@users.noreply.github.com> * Project overview page (#222) * start homepage * added calender functions and titlecard * homepage changes * homepage changes * Added: Homepage and Student Homepage * homepage changes * project projects parser * test passed * linter * pr review * Project card refactor * homepage change fix * Revert "Merge remote-tracking branch 'origin/backend/projectendpoint-fix' into frontend/feature/homepage" This reverts commit 645443a0aca84b31465aee99e59eda91cf8dadc4, reversing changes made to e5451b6cdd166f1c4632edddff9b4d9385f137cd. * homepage changes * rm comment * pr changes * project overview * project overview * project overview done * pr changes * project page changes * added support for no deadline projects * link changed * link changed * pr changes * merged with HomeStudent.tsx * projects overview page * wording change * homepage change * homepage change * API URL to API_HOST * end point with /me * project pages * home * create button * create button * opt * deadline fix * deadline fix * deadline fix * deadline fix * creds --------- Co-authored-by: gerwoud * Course views for teacher (#161) * teacher detailed course base project list * basic * scrollers * doc * backtick strings * base all courses page * changed height * first finished version of teacher course views * teacher all course page reviewed * display time until deadline * more searchbars and translations * changed file structure for maintainability * titles and absolute create button * searchbars update url and remain on reload * user and admin listing * reworked form and gave unique ids to all list items * whoops linter ssst * added .env to gitignore * placeholder for loading courses * debounce seachbars * better debouncing more hooks * setup for loader but doesnt work yet bc bad router * loaders * course detail teacher course join codes menu * join code link points to app host now * accident * fixed empty filters, placeholders and teacher in admin list * delete * removed wannabe popup errorer * unuserud * package * fix * uhh * u * Fix authentication bugs (#226) * fixed invalid_token_loader and added function to get csrf_cookie * changed name of file to be correct * small fixes * added csrf to all fetches * forgot an import * formatting * formatting * added custom fetch function * removed e * Frontend/enhancement/join code endpoint (#248) * Fix #247 * fixed linting * using authenticated fetch * unused import * Fixes several buggs in join code endpoint (#251) * Fix #249 * linting * fix home/header login button (#228) fix home/header login button #227 #241 * add label (#258) * fix logout on server (#264) * Fix #277 (#278) * Fix #276 (#281) * Changed AUTHENTICATION_URL .env variable (#268) * changed authentication_url to test_authentication_url * line too long * Creates a general code evaluator (#256) * Fix #255 * using apt to install node instead * fixed using join instead of dirname Co-authored-by: Jarne Clauw <67628242+JarneClauw@users.noreply.github.com> --------- Co-authored-by: Jarne Clauw <67628242+JarneClauw@users.noreply.github.com> * Authentication fix for backend tests (#280) * fixed invalid_token_loader and added function to get csrf_cookie * changed name of file to be correct * small fixes * added csrf to all fetches * forgot an import * formatting * formatting * added custom fetch function * removed e * some backend tests fixed hopefully * added display names to test auth server * set propagate exceptions to TRUE * added checks in test auth * csrf test * get csrf token from response * using cookie_jar * return 401 on test auth when necessary * get csrf token out of set-cookie headers * fixed all user tests * correct import this time * actual correct import * added default empty string so login does not crash * fixed courses test * fixed share link test * fix project tests * fixed submission tests * change docker command * removed authentication in no_auth test and correct authentication for project tests * trying parameterized tests * extra fixes * actually correct fixes this time * errors fixed * fixed csrf error when wrong authentication * Fix fill in the course selector (#261) * fixed the issue * make let const * refactor api url * refactor api url * use effect * use effect * renamed for clarity * use date not hours (#289) * Cleanup of authentication tests (#285) * Cleanup of authentication tests * Adding tests where no csrf token is given * Submissions download authorization (#293) * Fixing * Removing a test * Courses now converts deadlines from string to Date right after fetch (#295) * adjusted courses frontend to use deadlines Date instantiated right after fetch instead of str str 2d * lintr * removed TODO * deadlines now have their own datatype! * Submission authorization issues (#301) * fix * Fixing linter * Submission issues (#304) * Change the returned data from submission patch * Updating the filtering on /submissions * Return bad request on invalid keys in data * Little fix * Little fix * fixing the f linter * change path (#305) * course path (#308) * Navbar link to homepage added (#262) * navbar link added * rm i18 * Fix status on ProjectCards (#307) * status fix * rm space * Fix #253 (#254) * Seeder for easier demo and frontend testing (#291) * basic seeder provider, course titles, usernames and random uid * seeder creates and populates a few courses with random students where given uid is teacher * ffix * relocate, weird project deadline bug tho * seeder go bvv * fun with linter * lint * removed leading spaces * batch operations and documentation cleanup * bad env name * more batch and better try except finally * specific error * close * projects have 0-2 deadlines now, also randomized numprojects from fixed 2 to random 1-3 * 1-3 * import not good * toml test * toml * faker is dev * linter mad * titles now in txt file * completed toml info * fixed parsing error --------- Co-authored-by: Aron Buzogany * Redirecting when creation of project is succesful or showing error message on failure (#313) * Fix #275 * removed unused import * enhanced project submission error message in dutch * When doing GET on courses, only returning courses you are authorized to see (#282) * Fix #242 * fixed linting * Added functionality for url queries * fixed tests maybe * changed error code on wrong parameter in tests to 500 * actually changed the assert this time * courses currently ignores wrong filters * ignore filter tests on courses for now --------- Co-authored-by: Siebe Vlietinck * Fix #239 (#316) * Fix #238 (#317) * Fix #323 (#324) * added paper islands, made project cards of equal size, displaying username instead of uid (#311) * Added header on error pages and moved env import outside fetchme function (#319) * added header to error pages * moved env import outside function * added check on posting project (#321) * project form upload in user documentation (#250) * project form upload * added dutch translation * PR review and styling * siebe pr * aron pr * aron pr * When no run_tests.sh is given when creating a project, cannot submit. (#326) * trnanslation changes * runner check * changed everything to have 1 env var name (#332) * Fix #274 (#314) * added clipboard to copy the join code and redirecting to course when … (#325) * added clipboard to copy the join code and redirecting to course when user already in course * styling * added dutch translation of python evaluator (#333) * added dutch translation of python evaluator * siebe pr * Added readme for user guide (#330) * added readme * siebe pr * Textfield performance issue (#334) * added useTransition to wrap useState * linter * changed documentation location (#337) * redirect lang fix (#339) * add lang path (#341) * uses display name instead of uid (#328) * uses display name instead of uid * re added authentication * fix failing test * changed APP var * removed console log * replaced path and merge conflicts * removed 404 for submissions * fixed page spamming backend with requests * type error --------- Co-authored-by: Aron Buzogany * Using react mui tabs in project view instead of implementing it again (#343) * Fix #279 * linting * Fix flickering with data loader (#348) * added loader * added loader * linter * fix name * Seeder should generate unique submission times now (#354) * unique deadlines * unique submiss times * max 10 days into past * Project form/drag drop translations (#359) * added some translations * consistency! * fixed axios.post to use authentication (#363) * del (#365) * outdated code (#358) Co-authored-by: Warre Provoost <133233646+warreprovoost@users.noreply.github.com> * teacher added as student to course for real this time (#368) * Submission tests (#362) * Cleanup of authentication tests * Adding tests where no csrf token is given * Adding authentication tests * Adding authorization tests * Fixing most of the issues rn, but waiting on completion of other issue * fix * Fixing linter * Fixing auth tests * All tests written, but fixes needed * Fixing most tests * Fixing all tests except for the evaluator * Trying to fix tests * Fixing * linter * fix * Ignore bad filters on fetches to endpoints (#360) * test * submissions now ignore bad filters * small oopsies * getatribute(Model, key, None), i forgot the None * table__columns * Teacher is now listed as admin on course page (#349) * teacher is also listed, useMemo instead of useEffect to prevent listing twice * useMemo bad, reworked the student and admin fetchers * all fetches straight to loader fetches Me objects after fetching admins and students, no need for useffect * fixed loader and seeder * fix join codes bug (#374) * Fix en-us bug (#366) * fix en-us bug on homepage * should be fixed everywhere now * actually fixed hopefully * fix bug req. change * Fix the filter tests (#376) * changed 200 to 400 * changed != to == * added filter functionlity to submissions * removed prints * linter * linter again * filters that aren't fields are now ignored in the code, tests for this are fixed * yeet * idk tbh * Documentation/fix/GitHub link (#378) * added table to frontend readme * added .env vars to the README * updated readme * changed URL of api part * changed github url * changes not for this pr reverted * newline goofy augh * patch score in backend when edited in the frontend and i18n for page (#355) * score patch is working * changes * added error message and i18n support * added tooltip instead of alert :) * linter * update frontend readme variables (#356) * added table to frontend readme * added .env vars to the README * updated readme * changed URL of api part * removed code verfier * Frontend testing setup (#290) * testing setup * changed from jest to vitest and changed npm scripts to be easier to work with * hopefully final version of config files * fixed double import react bug * setup finished * linter fix * forgot to push this * any type * requested changes * vitest coverage generates coverage files * fix JWT refresh to use database (#383) * Update backend README (#357) * added table to frontend readme * added .env vars to the README * added readme vars * changes * added explanation * removed changes to frontend readme to exclude it from this pr * remove code verifier * added JWT application * POST_HOST name * added rfc link * added microsoft admin link * updated link * fix requirements/docker dependency bug (#392) * Fix #265 (#353) * removed edit link (#396) * added user guide links (#397) * added user guide links * added specific runner link * small styling issue * Add overview button to admin page of projects (#384) * changes bekijken * beaucoup * edit title and description functionality * linter :nerd: * frontend linter --------- Co-authored-by: Siebe Vlietinck <71773032+Vucis@users.noreply.github.com> * Fixed join code copy to clipboard (#404) * fixed join code copy * removed : * Only return projects where u are student if visible for students is true (#403) * projects visible for students * lint * added conditional rendering for edit funtionality (#402) * added translation for homepage of user guide (#400) * added translation * fix * Groups backend (#338) * temp bad * db_constr, model and first attempt at endpoint for group * group prim key (group_id,project_id) added delete endpoint to leave groups, next up is test * allow students in max 1 group * model tests * lint * group menu frontend * hm * working endpoint for create and delete group * translations * begone front * front removal * lintr * fixed changes, untested tho * groups locked var should not mess up all older code * only student or teacher can get groups ; unlock groups * linter mad * Very mad lintr * vscode linter errors should be more obvi * removed some teacher_id = None * removed unused import * bad prints * unzipping submissions on submission (#406) * unzipping submissions * run_test -> run_tests * run_test -> run_tests * Fixed deadline time left (#407) * fixed deadline time left * > to >= * Fix #408 (#409) Co-authored-by: Warre Provoost <133233646+warreprovoost@users.noreply.github.com> * Filter on conditions the students projects (#411) * projects visible for students * lint * filter on conditions * lint * fixed bad merge * show red dots on home page (#412) * Project issues (#410) * Fixing the legacy warning * Adding auth decorators to the project submission download enpoints * Fixing query parameter tests * remove bad param filter * Project tests (#416) * Auth tests * Fixing the legacy warning * Adding auth decorators to the project submission download enpoints * Fixing auth tests * Broken data field and query parameter tests * Fixing query parameter tests * More tests but first fixing some issues * working tests * remove bad param filter * stuff * added 403 for overview page (#414) * added 403 for overview page * linter * added good response.ok placement and status code for 404 * linter * Student course overview (#417) * student overview * linter * linter * linter * check if teacher * fixed authorizations in projectview (#418) * fixed authorizations in projectview * linting * added locales * redirecting to homepage when user not logged in (#421) * redirecting to homepage when user not logged in * linting * only fetching admins when needed (#420) * Fixed url flickering (#423) * redirecting to homepage when user not logged in * linting * fixed url flickering * fix seeder path (#422) * added explanation (#425) * added general evaluator documentation (#424) * added general evaluator documentation * fix 1 * fix 2 * fix yallah * final fix i believe * Header tests frontend (#391) * file structure * added hompage not logged in tests and header login functionality test * linting + pass current tests hopefully * more linting * extra header tests * other way of testing center button * third option * language test * ignore screenshots * logged in test * formatting * extra formatting * deleted unused files * intercept doesn't work on runner * removed comments --------- Signed-off-by: dependabot[bot] Co-authored-by: Jarne Clauw <67628242+JarneClauw@users.noreply.github.com> Co-authored-by: warre Co-authored-by: gerwoud Co-authored-by: Siebe Vlietinck <71773032+Vucis@users.noreply.github.com> Co-authored-by: Warre Provoost <133233646+warreprovoost@users.noreply.github.com> Co-authored-by: Gerwoud Van den Eynden <62761483+Gerwoud@users.noreply.github.com> Co-authored-by: Cedric Mekeirle <143823820+JibrilExe@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matisse Sulzer <160239816+Matisse-Sulzer@users.noreply.github.com> Co-authored-by: Siebe Vlietinck --- .github/workflows/ci-linter-backend.yaml | 22 + .github/workflows/ci-linter-frontend.yaml | 30 + .github/workflows/ci-test-backend.yaml | 27 + .github/workflows/ci-test-frontend.yaml | 38 + .github/workflows/ci-tests.yml | 62 - README.md | 22 +- backend/.gitignore | 4 +- backend/Dockerfile | 18 +- backend/Dockerfile.test | 24 + backend/Dockerfile_auth_test | 9 + backend/README.md | 79 + backend/auth_server_requirements.txt | 4 + backend/db_construct.sql | 103 + backend/dev-requirements.txt | 2 + backend/entry-point.sh | 12 + backend/flake.lock | 27 + backend/flake.nix | 26 + backend/project/__init__.py | 69 +- backend/project/__main__.py | 19 +- backend/project/db_in.py | 22 + .../project/endpoints/authentication/auth.py | 115 + .../endpoints/authentication/logout.py | 28 + .../project/endpoints/authentication/me.py | 33 + .../courses/course_admin_relation.py | 112 + .../endpoints/courses/course_details.py | 120 + .../courses/course_student_relation.py | 124 + backend/project/endpoints/courses/courses.py | 111 + .../endpoints/courses/courses_config.py | 35 + .../endpoints/courses/courses_utils.py | 245 + backend/project/endpoints/courses/join.py | 92 + .../courses/join_codes/course_join_code.py | 48 + .../courses/join_codes/course_join_codes.py | 58 + .../courses/join_codes/join_codes_config.py | 24 + .../project/endpoints/docs/docs_endpoint.py | 17 + backend/project/endpoints/index.py | 10 - backend/project/endpoints/index/index.py | 22 + .../endpoints/projects/endpoint_parser.py | 69 + .../projects/groups/group_student.py | 128 + .../endpoints/projects/groups/groups.py | 127 + .../projects/project_assignment_file.py | 57 + .../endpoints/projects/project_detail.py | 115 + .../endpoints/projects/project_endpoint.py | 45 + .../projects/project_last_submission.py | 26 + .../projects/project_submissions_download.py | 108 + .../project/endpoints/projects/projects.py | 146 + .../submissions/submission_config.py | 22 + .../submissions/submission_detail.py | 119 + .../submissions/submission_download.py | 62 + .../endpoints/submissions/submissions.py | 206 + backend/project/endpoints/users.py | 161 + backend/project/executor.py | 9 + backend/project/init_auth.py | 60 + backend/project/models/__init__.py | 0 backend/project/models/course.py | 16 + backend/project/models/course_relation.py | 27 + backend/project/models/course_share_code.py | 22 + backend/project/models/group.py | 17 + backend/project/models/group_student.py | 13 + backend/project/models/project.py | 62 + backend/project/models/submission.py | 44 + backend/project/models/user.py | 35 + backend/project/sessionmaker.py | 15 + backend/project/static/OpenAPI_Object.yaml | 1333 ++ backend/project/utils/__init__.py | 0 backend/project/utils/authentication.py | 326 + backend/project/utils/files.py | 63 + backend/project/utils/misc.py | 95 + backend/project/utils/models/course_utils.py | 67 + backend/project/utils/models/project_utils.py | 41 + .../project/utils/models/submission_utils.py | 44 + backend/project/utils/models/user_utils.py | 36 + backend/project/utils/project.py | 27 + backend/project/utils/query_agent.py | 236 + backend/project/utils/submissions/__init__.py | 0 .../project/utils/submissions/evaluator.py | 139 + .../submissions/evaluators/general/Dockerfile | 32 + .../evaluators/general/entry_point.sh | 3 + .../submissions/evaluators/python/Dockerfile | 3 + .../evaluators/python/entry_point.sh | 40 + .../utils/submissions/file_handling.py | 47 + backend/project/utils/user.py | 69 + backend/pylintrc | 19 + backend/pyproject.toml | 13 + backend/requirements.txt | 15 +- backend/run_tests.sh | 20 + backend/seeder/__init__.py | 0 backend/seeder/seeder.py | 264 + backend/seeder/titles.txt | 208 + backend/test_auth_server/__main__.py | 121 + backend/tests.yaml | 53 + backend/tests/__init__.py | 26 + backend/tests/conftest.py | 226 +- backend/tests/endpoints/__init__.py | 0 backend/tests/endpoints/conftest.py | 385 + .../tests/endpoints/course/courses_test.py | 361 + .../tests/endpoints/course/share_link_test.py | 58 + backend/tests/endpoints/endpoint.py | 124 + backend/tests/endpoints/index_test.py | 19 + backend/tests/endpoints/project_test.py | 260 + backend/tests/endpoints/submissions_test.py | 218 + backend/tests/endpoints/user_test.py | 201 + backend/tests/models/course_relation_test.py | 83 + backend/tests/models/course_test.py | 59 + backend/tests/models/group_test.py | 52 + backend/tests/models/project_test.py | 76 + backend/tests/models/submission_test.py | 92 + backend/tests/models/user_test.py | 57 + backend/tests/resources/testzip.zip | Bin 0 -> 175 bytes backend/tests/test_base.py | 6 - backend/tests/utils/__init__.py | 0 backend/tests/utils/auth_login.py | 13 + .../utils/submission_evaluators/__init__.py | 0 .../base_evaluators_test.py | 19 + .../utils/submission_evaluators/conftest.py | 44 + .../submission_evaluators/python_test.py | 76 + .../resources/python/__init__.py | 0 .../python/tc_1/assignment/run_test.zip | Bin 0 -> 184 bytes .../python/tc_1/assignment/run_tests.sh | 3 + .../python/tc_2/assignment/run_tests.sh | 3 + .../tc_2/submission/submission/hello_world.py | 4 + .../submission/submission/requirements.txt | 1 + .../python/tc_3/assignment/req-manifest.txt | 0 .../python/tc_3/assignment/run_tests.sh | 3 + .../tc_3/submission/submission/hello_world.py | 4 + .../submission/submission/requirements.txt | 1 + docker-compose.yml | 19 + documentation/.gitignore | 20 + documentation/README.md | 27 + documentation/babel.config.js | 3 + documentation/docs/evaluators/_category_.json | 8 + .../docs/evaluators/custom_evaluator.md | 3 + .../docs/evaluators/general_evaluator.md | 7 + .../docs/evaluators/python_evaluator.md | 13 + documentation/docs/intro.md | 7 + .../docs/projectform/_category_.json | 8 + documentation/docs/projectform/image.png | Bin 0 -> 2313 bytes .../docs/projectform/project_upload_form.md | 34 + documentation/docusaurus.config.ts | 94 + .../current/evaluators/_category_.json | 8 + .../current/evaluators/custom_evaluator.md | 2 + .../current/evaluators/general_evaluator.md | 8 + .../current/evaluators/python_evaluator.md | 13 + .../current/intro.md | 7 + .../projectform/project_upload_form.md | 31 + documentation/package-lock.json | 14626 ++++++++++++++++ documentation/package.json | 47 + documentation/sidebars.ts | 31 + .../src/components/HomepageFeatures/index.tsx | 70 + .../HomepageFeatures/styles.module.css | 11 + documentation/src/css/custom.css | 30 + documentation/src/pages/index.module.css | 23 + documentation/src/pages/index.tsx | 43 + documentation/static/.nojekyll | 0 documentation/static/img/logo_app.png | Bin 0 -> 704 bytes .../static/img}/logo_ugent.png | Bin documentation/static/img/project_form_1.png | Bin 0 -> 10483 bytes documentation/static/img/project_form_2.png | Bin 0 -> 31455 bytes .../static/img/project_upload_form_3.png | Bin 0 -> 3966 bytes .../static/img/project_upload_form_4.png | Bin 0 -> 23502 bytes .../static/img/project_upload_form_5.png | Bin 0 -> 27294 bytes .../static/img/project_upload_form_6.png | Bin 0 -> 18312 bytes .../static/img/project_upload_form_7.png | Bin 0 -> 2313 bytes .../static/img/undraw_docusaurus_mountain.svg | 171 + .../static/img/undraw_docusaurus_react.svg | 170 + .../static/img/undraw_docusaurus_tree.svg | 40 + documentation/tsconfig.json | 7 + frontend/.eslintrc.cjs | 7 +- frontend/.gitignore | 3 + frontend/Dockerfile | 4 +- frontend/README.md | 78 +- frontend/cypress/e2e/ErrorPage.cy.tsx | 16 + frontend/cypress/e2e/Header.cy.tsx | 31 + frontend/cypress/e2e/HomePageTests.cy.tsx | 20 + frontend/cypress/tsconfig.json | 8 + frontend/index.html | 4 +- frontend/package-lock.json | 13008 ++++++++++---- frontend/package.json | 53 +- frontend/public/img/error_pigeon.png | Bin 0 -> 2358 bytes frontend/public/img/logo_app.png | Bin 0 -> 704 bytes frontend/public/img/logo_ugent.png | Bin 0 -> 6422 bytes .../locales/en/projectformTranslation.json | 27 + .../public/locales/en/submissionOverview.json | 12 + frontend/public/locales/en/translation.json | 157 + .../locales/nl/projectformTranslation.json | 27 + .../public/locales/nl/submissionOverview.json | 12 + frontend/public/locales/nl/translation.json | 148 + frontend/src/App.tsx | 96 +- .../components/Calender/DeadlineCalender.tsx | 250 + .../components/Courses/AllCoursesTeacher.tsx | 110 + .../Courses/CourseDetailStudent.tsx | 94 + .../Courses/CourseDetailTeacher.tsx | 617 + .../Courses/CourseUtilComponents.tsx | 311 + .../src/components/Courses/CourseUtils.tsx | 270 + .../src/components/Courses/CoursesDetail.tsx | 24 + frontend/src/components/Courses/courses.ts | 22 + .../components/DeadlineView/DeadlineGrid.tsx | 43 + .../components/FolderUpload/FolderUpload.tsx | 134 + frontend/src/components/Header/Header.tsx | 198 +- frontend/src/components/Header/Layout.tsx | 58 + frontend/src/components/Header/Login.tsx | 22 + frontend/src/components/Header/Logout.tsx | 14 + frontend/src/components/Header/PageTitle.tsx | 14 + frontend/src/components/Header/Title.tsx | 51 + .../src/components/Header/TitlePortal.tsx | 14 + frontend/src/components/LanguagePath.tsx | 28 + .../components/ProjectForm/AdvancedRegex.tsx | 53 + .../ProjectForm/FileStructureForm.tsx | 99 + .../components/ProjectForm/ProjectForm.tsx | 447 + .../components/ProjectForm/RunnerSelecter.tsx | 84 + .../components/ProjectForm/project-form.ts | 11 + .../ProjectSubmissionOverview.tsx | 59 + .../ProjectSubmissionOverviewDatagrid.tsx | 155 + frontend/src/i18n.js | 26 + frontend/src/loaders/join-code.ts | 35 + frontend/src/loaders/project-view-loader.ts | 84 + .../src/loaders/submission-overview-loader.ts | 67 + frontend/src/main.tsx | 1 + .../create_project/ProjectCreateHome.tsx | 29 + frontend/src/pages/error/ErrorBoundary.tsx | 69 + frontend/src/pages/error/ErrorPage.tsx | 51 + frontend/src/pages/home/Home.tsx | 46 +- frontend/src/pages/home/HomePage.tsx | 214 + frontend/src/pages/home/HomePages.tsx | 21 + .../projectDeadline/ProjectDeadline.tsx | 50 + .../projectDeadline/ProjectDeadlineCard.tsx | 79 + .../src/pages/project/projectOverview.tsx | 97 + .../pages/project/projectView/ProjectView.tsx | 313 + .../project/projectView/SubmissionCard.tsx | 160 + .../project/projectView/SubmissionsGrid.tsx | 92 + .../SubmissionsOverview.tsx | 17 + frontend/src/types/course.ts | 4 + frontend/src/types/deadline.ts | 4 + frontend/src/types/me.ts | 6 + frontend/src/types/submission.ts | 7 + frontend/src/utils/authenticated-fetch.ts | 17 + frontend/src/utils/csrf.ts | 11 + frontend/src/utils/date-utils.ts | 41 + frontend/src/utils/fetches/FetchMe.ts | 20 + frontend/src/utils/fetches/FetchProjects.tsx | 116 + frontend/src/utils/file-utils.ts | 42 + frontend/tests/unit/header.test.tsx | 6 + frontend/tests/unit/homepage.test.tsx | 3 + frontend/tests/unit/type-tests/me.test.tsx | 5 + frontend/tests/utils/data.ts | 7 + frontend/tests/utils/me-fixture.ts | 5 + frontend/tsconfig.json | 10 +- frontend/vite.config.ts | 5 + usecases/edit_links.txt | 3 + usecases/usecase_student.pdf | Bin 0 -> 17142 bytes usecases/usecase_teacher_admin.pdf | Bin 0 -> 25563 bytes 250 files changed, 39938 insertions(+), 3611 deletions(-) create mode 100644 .github/workflows/ci-linter-backend.yaml create mode 100644 .github/workflows/ci-linter-frontend.yaml create mode 100644 .github/workflows/ci-test-backend.yaml create mode 100644 .github/workflows/ci-test-frontend.yaml delete mode 100644 .github/workflows/ci-tests.yml create mode 100644 backend/Dockerfile.test create mode 100644 backend/Dockerfile_auth_test create mode 100644 backend/README.md create mode 100644 backend/auth_server_requirements.txt create mode 100644 backend/db_construct.sql create mode 100755 backend/entry-point.sh create mode 100644 backend/flake.lock create mode 100644 backend/flake.nix create mode 100644 backend/project/db_in.py create mode 100644 backend/project/endpoints/authentication/auth.py create mode 100644 backend/project/endpoints/authentication/logout.py create mode 100644 backend/project/endpoints/authentication/me.py create mode 100644 backend/project/endpoints/courses/course_admin_relation.py create mode 100644 backend/project/endpoints/courses/course_details.py create mode 100644 backend/project/endpoints/courses/course_student_relation.py create mode 100644 backend/project/endpoints/courses/courses.py create mode 100644 backend/project/endpoints/courses/courses_config.py create mode 100644 backend/project/endpoints/courses/courses_utils.py create mode 100644 backend/project/endpoints/courses/join.py create mode 100644 backend/project/endpoints/courses/join_codes/course_join_code.py create mode 100644 backend/project/endpoints/courses/join_codes/course_join_codes.py create mode 100644 backend/project/endpoints/courses/join_codes/join_codes_config.py create mode 100644 backend/project/endpoints/docs/docs_endpoint.py delete mode 100644 backend/project/endpoints/index.py create mode 100644 backend/project/endpoints/index/index.py create mode 100644 backend/project/endpoints/projects/endpoint_parser.py create mode 100644 backend/project/endpoints/projects/groups/group_student.py create mode 100644 backend/project/endpoints/projects/groups/groups.py create mode 100644 backend/project/endpoints/projects/project_assignment_file.py create mode 100644 backend/project/endpoints/projects/project_detail.py create mode 100644 backend/project/endpoints/projects/project_endpoint.py create mode 100644 backend/project/endpoints/projects/project_last_submission.py create mode 100644 backend/project/endpoints/projects/project_submissions_download.py create mode 100644 backend/project/endpoints/projects/projects.py create mode 100644 backend/project/endpoints/submissions/submission_config.py create mode 100644 backend/project/endpoints/submissions/submission_detail.py create mode 100644 backend/project/endpoints/submissions/submission_download.py create mode 100644 backend/project/endpoints/submissions/submissions.py create mode 100644 backend/project/endpoints/users.py create mode 100644 backend/project/executor.py create mode 100644 backend/project/init_auth.py create mode 100644 backend/project/models/__init__.py create mode 100644 backend/project/models/course.py create mode 100644 backend/project/models/course_relation.py create mode 100644 backend/project/models/course_share_code.py create mode 100644 backend/project/models/group.py create mode 100644 backend/project/models/group_student.py create mode 100644 backend/project/models/project.py create mode 100644 backend/project/models/submission.py create mode 100644 backend/project/models/user.py create mode 100644 backend/project/sessionmaker.py create mode 100644 backend/project/static/OpenAPI_Object.yaml create mode 100644 backend/project/utils/__init__.py create mode 100644 backend/project/utils/authentication.py create mode 100644 backend/project/utils/files.py create mode 100644 backend/project/utils/misc.py create mode 100644 backend/project/utils/models/course_utils.py create mode 100644 backend/project/utils/models/project_utils.py create mode 100644 backend/project/utils/models/submission_utils.py create mode 100644 backend/project/utils/models/user_utils.py create mode 100644 backend/project/utils/project.py create mode 100644 backend/project/utils/query_agent.py create mode 100644 backend/project/utils/submissions/__init__.py create mode 100644 backend/project/utils/submissions/evaluator.py create mode 100644 backend/project/utils/submissions/evaluators/general/Dockerfile create mode 100644 backend/project/utils/submissions/evaluators/general/entry_point.sh create mode 100644 backend/project/utils/submissions/evaluators/python/Dockerfile create mode 100644 backend/project/utils/submissions/evaluators/python/entry_point.sh create mode 100644 backend/project/utils/submissions/file_handling.py create mode 100644 backend/project/utils/user.py create mode 100644 backend/pylintrc create mode 100644 backend/pyproject.toml create mode 100755 backend/run_tests.sh create mode 100644 backend/seeder/__init__.py create mode 100644 backend/seeder/seeder.py create mode 100644 backend/seeder/titles.txt create mode 100644 backend/test_auth_server/__main__.py create mode 100644 backend/tests.yaml create mode 100644 backend/tests/endpoints/__init__.py create mode 100644 backend/tests/endpoints/conftest.py create mode 100644 backend/tests/endpoints/course/courses_test.py create mode 100644 backend/tests/endpoints/course/share_link_test.py create mode 100644 backend/tests/endpoints/endpoint.py create mode 100644 backend/tests/endpoints/index_test.py create mode 100644 backend/tests/endpoints/project_test.py create mode 100644 backend/tests/endpoints/submissions_test.py create mode 100644 backend/tests/endpoints/user_test.py create mode 100644 backend/tests/models/course_relation_test.py create mode 100644 backend/tests/models/course_test.py create mode 100644 backend/tests/models/group_test.py create mode 100644 backend/tests/models/project_test.py create mode 100644 backend/tests/models/submission_test.py create mode 100644 backend/tests/models/user_test.py create mode 100644 backend/tests/resources/testzip.zip delete mode 100644 backend/tests/test_base.py create mode 100644 backend/tests/utils/__init__.py create mode 100644 backend/tests/utils/auth_login.py create mode 100644 backend/tests/utils/submission_evaluators/__init__.py create mode 100644 backend/tests/utils/submission_evaluators/base_evaluators_test.py create mode 100644 backend/tests/utils/submission_evaluators/conftest.py create mode 100644 backend/tests/utils/submission_evaluators/python_test.py create mode 100644 backend/tests/utils/submission_evaluators/resources/python/__init__.py create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_test.zip create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_tests.sh create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_2/assignment/run_tests.sh create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/hello_world.py create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/requirements.txt create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/req-manifest.txt create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/run_tests.sh create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/hello_world.py create mode 100644 backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/requirements.txt create mode 100644 docker-compose.yml create mode 100644 documentation/.gitignore create mode 100644 documentation/README.md create mode 100644 documentation/babel.config.js create mode 100644 documentation/docs/evaluators/_category_.json create mode 100644 documentation/docs/evaluators/custom_evaluator.md create mode 100644 documentation/docs/evaluators/general_evaluator.md create mode 100644 documentation/docs/evaluators/python_evaluator.md create mode 100644 documentation/docs/intro.md create mode 100644 documentation/docs/projectform/_category_.json create mode 100644 documentation/docs/projectform/image.png create mode 100644 documentation/docs/projectform/project_upload_form.md create mode 100644 documentation/docusaurus.config.ts create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/_category_.json create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/custom_evaluator.md create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/general_evaluator.md create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/python_evaluator.md create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/intro.md create mode 100644 documentation/i18n/nl/docusaurus-plugin-content-docs/current/projectform/project_upload_form.md create mode 100644 documentation/package-lock.json create mode 100644 documentation/package.json create mode 100644 documentation/sidebars.ts create mode 100644 documentation/src/components/HomepageFeatures/index.tsx create mode 100644 documentation/src/components/HomepageFeatures/styles.module.css create mode 100644 documentation/src/css/custom.css create mode 100644 documentation/src/pages/index.module.css create mode 100644 documentation/src/pages/index.tsx create mode 100644 documentation/static/.nojekyll create mode 100644 documentation/static/img/logo_app.png rename {frontend/public => documentation/static/img}/logo_ugent.png (100%) create mode 100644 documentation/static/img/project_form_1.png create mode 100644 documentation/static/img/project_form_2.png create mode 100644 documentation/static/img/project_upload_form_3.png create mode 100644 documentation/static/img/project_upload_form_4.png create mode 100644 documentation/static/img/project_upload_form_5.png create mode 100644 documentation/static/img/project_upload_form_6.png create mode 100644 documentation/static/img/project_upload_form_7.png create mode 100644 documentation/static/img/undraw_docusaurus_mountain.svg create mode 100644 documentation/static/img/undraw_docusaurus_react.svg create mode 100644 documentation/static/img/undraw_docusaurus_tree.svg create mode 100644 documentation/tsconfig.json create mode 100644 frontend/cypress/e2e/ErrorPage.cy.tsx create mode 100644 frontend/cypress/e2e/Header.cy.tsx create mode 100644 frontend/cypress/e2e/HomePageTests.cy.tsx create mode 100644 frontend/cypress/tsconfig.json create mode 100644 frontend/public/img/error_pigeon.png create mode 100644 frontend/public/img/logo_app.png create mode 100644 frontend/public/img/logo_ugent.png create mode 100644 frontend/public/locales/en/projectformTranslation.json create mode 100644 frontend/public/locales/en/submissionOverview.json create mode 100644 frontend/public/locales/en/translation.json create mode 100644 frontend/public/locales/nl/projectformTranslation.json create mode 100644 frontend/public/locales/nl/submissionOverview.json create mode 100644 frontend/public/locales/nl/translation.json create mode 100644 frontend/src/components/Calender/DeadlineCalender.tsx create mode 100644 frontend/src/components/Courses/AllCoursesTeacher.tsx create mode 100644 frontend/src/components/Courses/CourseDetailStudent.tsx create mode 100644 frontend/src/components/Courses/CourseDetailTeacher.tsx create mode 100644 frontend/src/components/Courses/CourseUtilComponents.tsx create mode 100644 frontend/src/components/Courses/CourseUtils.tsx create mode 100644 frontend/src/components/Courses/CoursesDetail.tsx create mode 100644 frontend/src/components/Courses/courses.ts create mode 100644 frontend/src/components/DeadlineView/DeadlineGrid.tsx create mode 100644 frontend/src/components/FolderUpload/FolderUpload.tsx create mode 100644 frontend/src/components/Header/Layout.tsx create mode 100644 frontend/src/components/Header/Login.tsx create mode 100644 frontend/src/components/Header/Logout.tsx create mode 100644 frontend/src/components/Header/PageTitle.tsx create mode 100644 frontend/src/components/Header/Title.tsx create mode 100644 frontend/src/components/Header/TitlePortal.tsx create mode 100644 frontend/src/components/LanguagePath.tsx create mode 100644 frontend/src/components/ProjectForm/AdvancedRegex.tsx create mode 100644 frontend/src/components/ProjectForm/FileStructureForm.tsx create mode 100644 frontend/src/components/ProjectForm/ProjectForm.tsx create mode 100644 frontend/src/components/ProjectForm/RunnerSelecter.tsx create mode 100644 frontend/src/components/ProjectForm/project-form.ts create mode 100644 frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverview.tsx create mode 100644 frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverviewDatagrid.tsx create mode 100644 frontend/src/i18n.js create mode 100644 frontend/src/loaders/join-code.ts create mode 100644 frontend/src/loaders/project-view-loader.ts create mode 100644 frontend/src/loaders/submission-overview-loader.ts create mode 100644 frontend/src/pages/create_project/ProjectCreateHome.tsx create mode 100644 frontend/src/pages/error/ErrorBoundary.tsx create mode 100644 frontend/src/pages/error/ErrorPage.tsx create mode 100644 frontend/src/pages/home/HomePage.tsx create mode 100644 frontend/src/pages/home/HomePages.tsx create mode 100644 frontend/src/pages/project/projectDeadline/ProjectDeadline.tsx create mode 100644 frontend/src/pages/project/projectDeadline/ProjectDeadlineCard.tsx create mode 100644 frontend/src/pages/project/projectOverview.tsx create mode 100644 frontend/src/pages/project/projectView/ProjectView.tsx create mode 100644 frontend/src/pages/project/projectView/SubmissionCard.tsx create mode 100644 frontend/src/pages/project/projectView/SubmissionsGrid.tsx create mode 100644 frontend/src/pages/submission_overview/SubmissionsOverview.tsx create mode 100644 frontend/src/types/course.ts create mode 100644 frontend/src/types/deadline.ts create mode 100644 frontend/src/types/me.ts create mode 100644 frontend/src/types/submission.ts create mode 100644 frontend/src/utils/authenticated-fetch.ts create mode 100644 frontend/src/utils/csrf.ts create mode 100644 frontend/src/utils/date-utils.ts create mode 100644 frontend/src/utils/fetches/FetchMe.ts create mode 100644 frontend/src/utils/fetches/FetchProjects.tsx create mode 100644 frontend/src/utils/file-utils.ts create mode 100644 frontend/tests/unit/header.test.tsx create mode 100644 frontend/tests/unit/homepage.test.tsx create mode 100644 frontend/tests/unit/type-tests/me.test.tsx create mode 100644 frontend/tests/utils/data.ts create mode 100644 frontend/tests/utils/me-fixture.ts create mode 100644 usecases/edit_links.txt create mode 100644 usecases/usecase_student.pdf create mode 100644 usecases/usecase_teacher_admin.pdf diff --git a/.github/workflows/ci-linter-backend.yaml b/.github/workflows/ci-linter-backend.yaml new file mode 100644 index 00000000..401e96fb --- /dev/null +++ b/.github/workflows/ci-linter-backend.yaml @@ -0,0 +1,22 @@ +name: UGent-3-backend-linter +run-name: ${{ github.actor }} is running backend linter 🚀 +on: + pull_request: + paths: + - 'backend/**' +jobs: + Backend-tests: + runs-on: self-hosted + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + cache: 'pip' + + - name: Run linting + working-directory: ./backend + run: find . -type f -name "*.py" | xargs pylint + \ No newline at end of file diff --git a/.github/workflows/ci-linter-frontend.yaml b/.github/workflows/ci-linter-frontend.yaml new file mode 100644 index 00000000..8efab247 --- /dev/null +++ b/.github/workflows/ci-linter-frontend.yaml @@ -0,0 +1,30 @@ +name: UGent-3-frontend-linter +run-name: ${{ github.actor }} is running frontend linter 🚀 +on: + pull_request: + paths: + - 'frontend/**' +jobs: + Frontend-tests: + runs-on: self-hosted + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + + - name: Install dependencies + working-directory: ./frontend + run: npm i eslint + + - name: Run linting + working-directory: ./frontend + run: npm run lint + \ No newline at end of file diff --git a/.github/workflows/ci-test-backend.yaml b/.github/workflows/ci-test-backend.yaml new file mode 100644 index 00000000..0b2faf75 --- /dev/null +++ b/.github/workflows/ci-test-backend.yaml @@ -0,0 +1,27 @@ +name: UGent-3-backend-test +run-name: ${{ github.actor }} is running backend tests 🚀 +on: + pull_request: + paths: + - 'backend/**' +jobs: + Backend-tests: + runs-on: self-hosted + steps: + - uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + cache: 'pip' + + - name: Install dependencies + working-directory: ./backend + run: pip3 install -r requirements.txt && pip3 install -r dev-requirements.txt + + - name: Running tests + working-directory: ./backend + run: bash ./run_tests.sh + + diff --git a/.github/workflows/ci-test-frontend.yaml b/.github/workflows/ci-test-frontend.yaml new file mode 100644 index 00000000..210ec6d0 --- /dev/null +++ b/.github/workflows/ci-test-frontend.yaml @@ -0,0 +1,38 @@ +name: UGent-3-frontend-test +run-name: ${{ github.actor }} is running frontend tests 🚀 +on: + pull_request: + paths: + - 'frontend/**' +jobs: + Frontend-tests: + runs-on: self-hosted + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/.npm + key: npm-${{ hashFiles('package-lock.json') }} + restore-keys: npm- + + - name: Install dependencies + working-directory: ./frontend + run: npm ci + + - name: Build + working-directory: ./frontend + run: npm run build + + - name: Preview Web App + working-directory: ./frontend + run: npm run preview & + + - name: Running tests + working-directory: ./frontend + run: npm test + diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml deleted file mode 100644 index c0d4cfa4..00000000 --- a/.github/workflows/ci-tests.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: UGent-3 -run-name: ${{ github.actor }} is running tests 🚀 -on: [push, pull_request] -jobs: - Frontend-tests: - runs-on: self-hosted - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v3 - - - name: Cache dependencies - uses: actions/cache@v2 - with: - path: ~/.npm - key: npm-${{ hashFiles('package-lock.json') }} - restore-keys: npm- - - - name: Install dependencies - working-directory: ./frontend - run: npm ci - - - name: Build - working-directory: ./frontend - run: npm run build - - - name: Preview Web App - working-directory: ./frontend - run: npm run preview & - - - name: Running tests - working-directory: ./frontend - run: npm test - - - name: Run linting - working-directory: ./frontend - run: npm run lint - Backend-tests: - runs-on: self-hosted - steps: - - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - cache: 'pip' - - - name: Install dependencies - working-directory: ./backend - run: pip3 install -r requirements.txt && pip3 install -r dev-requirements.txt - - - name: Running tests - working-directory: ./backend - run: pytest - - - name: Run linting - working-directory: ./backend - run: pylint ./*/*.py - - diff --git a/README.md b/README.md index c684e92f..510b4a14 100644 --- a/README.md +++ b/README.md @@ -1 +1,21 @@ -# UGent-3 \ No newline at end of file +# UGent-3 project peristerónas +![tests](https://github.com/SELab-2/UGent-3/actions/workflows/ci-test-frontend.yaml/badge.svg) +![linter](https://github.com/SELab-2/UGent-3/actions/workflows/ci-linter-frontend.yaml/badge.svg) +![tests](https://github.com/SELab-2/UGent-3/actions/workflows/ci-test-backend.yaml/badge.svg) +![linter](https://github.com/SELab-2/UGent-3/actions/workflows/ci-linter-backend.yaml/badge.svg) +## Introduction +Project peristerónas was created to aid both teachers and students in achieving a +clear overview of deadlines and projects that need to be submitted. + +There's a separate functionality depending on if you're logged in as a teacher or as a student. +For students the main functionality is to have a user-friendly interface to submit projects and check the correctness of their submissions. + +When a teacher is logged in they can get an overview of the projects he assigned and check how many students have already +handed in a correct solution for example. It's also possible to edit the project and to grade projects in peristerónas' interface. +## Usage +### Frontend +For the developer instructions of the frontend please refer to the [frontend readme](frontend/README.md) +where clear instructions can be found for usage, test cases, deployment and development. +### Backend +For the developer instructions of the backend please refer to the [backend readme](backend/README.md) +where clear instructions can be found for usage, test cases, deployment and development. diff --git a/backend/.gitignore b/backend/.gitignore index c5c0cc3f..72cc6e44 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -7,4 +7,6 @@ __pycache__/ htmlcov/ docs/_build/ dist/ -venv/ \ No newline at end of file +venv/ +.env +.run/ diff --git a/backend/Dockerfile b/backend/Dockerfile index 8e4fa18e..462d840e 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,6 +1,20 @@ +FROM docker:dind as builder + FROM python:3.9 + +COPY --from=builder /usr/local/bin/docker /usr/local/bin/docker + RUN mkdir /app -WORKDIR /app/ +WORKDIR /app + ADD ./project /app/ + +COPY requirements.txt /app/requirements.txt + RUN pip3 install -r requirements.txt -CMD ["python3", "/app"] \ No newline at end of file + +COPY . /app + +ENTRYPOINT ["python"] + +CMD ["__main__.py"] diff --git a/backend/Dockerfile.test b/backend/Dockerfile.test new file mode 100644 index 00000000..82abc168 --- /dev/null +++ b/backend/Dockerfile.test @@ -0,0 +1,24 @@ +FROM docker:dind + +RUN apk add --no-cache \ + python3 \ + py3-pip \ + tzdata + +ENV TZ=UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + + + +RUN python3 -m venv /venv +ENV PATH="/venv/bin:$PATH" + +COPY . /app + +WORKDIR /app + +RUN pip3 install --no-cache-dir -r requirements.txt -r dev-requirements.txt + +RUN chmod +x /app/entry-point.sh + +ENTRYPOINT ["/app/entry-point.sh"] diff --git a/backend/Dockerfile_auth_test b/backend/Dockerfile_auth_test new file mode 100644 index 00000000..3653f2b8 --- /dev/null +++ b/backend/Dockerfile_auth_test @@ -0,0 +1,9 @@ +FROM python:3.9 +RUN mkdir /auth-app +WORKDIR /auth-app +ADD ./test_auth_server /auth-app/ +COPY auth_server_requirements.txt /auth-app/requirements.txt +RUN pip3 install -r requirements.txt +COPY . /auth-app +ENTRYPOINT ["python"] +CMD ["__main__.py"] \ No newline at end of file diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 00000000..d9f0dc48 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,79 @@ +# Project pigeonhole backend +![tests](https://github.com/SELab-2/UGent-3/actions/workflows/ci-test-backend.yaml/badge.svg) +![linter](https://github.com/SELab-2/UGent-3/actions/workflows/ci-linter-backend.yaml/badge.svg) +## Prerequisites +**1. Clone the repo** + ```sh + git clone git@github.com:SELab-2/UGent-3.git + ``` +**2. Installing required packages** + + If you want the development environment: run both commands. If you only need to deploy, run the deployment command. + + The [dev-requirements.txt](dev-requirements.txt) contains everything for writing tests and linters for maintaining quality code. +On the other hand the regular [requirements.txt](requirements.txt) installs the packages needed for +the regular base application. + + - Deployment + ```sh + pip install -r requirements.txt + ``` + - Development + ```sh + pip install -r dev-requirements.txt + ``` + +## Setting up the environment variables +The project requires a couple of environment variables to run, if you want to develop on this codebase. +Setting values for these variables can be done with a method to your own liking. + +| Variable | Description | +|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| POSTGRES_USER | Name of the user, needed to login to the postgres database | +| POSTGRES_PASSWORD | Password of the user, needed to login to the postgres database | +| POSTGRES_HOST | Location of the postgres database | +| POSTGRES_DB | Name of the postgres database | +| API_HOST | Location of the API root | +| CLIENT_ID | [Client id](https://learn.microsoft.com/nl-nl/entra/identity-platform/v2-protocols) | +| CLIENT_SECRET | Client's secret is your personal secret key for authentication, this can be found at the [Entra ID admin center](https://learn.microsoft.com/en-us/purview/sit-defn-azure-ad-client-secret) | +| JWT_SECRET_KEY | JWT secret key is the key used to encode the JWT's and should be kept secret, because otherwise everyone can create "valid" JWT's for our application. Variable should be a random 32 characters long string, if you need more information please refer to the [RDF documentation](https://www.rfc-editor.org/rfc/rfc4868#page-3) | +| TENANT_ID | [Tenant id](https://learn.microsoft.com/nl-nl/entra/fundamentals/whatis), an ID that is used to identify yourself to the microsoft servic | +| HOMEPAGE_URL | URL of where the website's homepage is located | + +All the variables except the last one are for the database setup, +these are needed to make a connection with the database. +The last one is for keeping the API restful since the location of the resource should be located. + +## Running the project +Once all the setup is done you can start the development server by +navigating to the backend directory and running: +```sh +python project +``` +The server should now be located at `localhost:5000` and you can +start developing. + +## Maintaining the codebase +### Writing tests +When writing new code it is important to maintain the right functionality so +writing tests is mandatory for this, the test library used in this codebase is [pytest](https://docs.pytest.org/en/8.0.x/). + +If you want to write tests we highly advise to read the pytest documentation on how +to write tests, so they are kept conventional. + +For executing the tests and testing your newly added functionality +you can run: +```sh +sudo ./run_tests.sh +``` + +Located in the backend directory. +### Running the linter +This codebase is kept clean by the [pylint](https://pypi.org/project/pylint/) linter. + +If you want to execute the linter on all .py files in the project it can simply be done +with the command: +```sh +find . -type f -name "*.py" | xargs pylint +``` +The code needs to get a 10/10 score to get pushed to the repository. diff --git a/backend/auth_server_requirements.txt b/backend/auth_server_requirements.txt new file mode 100644 index 00000000..2a0efdf3 --- /dev/null +++ b/backend/auth_server_requirements.txt @@ -0,0 +1,4 @@ +flask~=3.0.2 +flask-restful +python-dotenv~=1.0.1 +psycopg2-binary \ No newline at end of file diff --git a/backend/db_construct.sql b/backend/db_construct.sql new file mode 100644 index 00000000..5b209431 --- /dev/null +++ b/backend/db_construct.sql @@ -0,0 +1,103 @@ +CREATE TYPE role AS ENUM ('STUDENT', 'TEACHER', 'ADMIN'); + +CREATE TYPE submission_status AS ENUM ('SUCCESS', 'LATE', 'FAIL', 'RUNNING'); +CREATE TYPE runner AS ENUM ('PYTHON', 'GENERAL', 'CUSTOM'); + +CREATE TABLE users ( + uid VARCHAR(255), + display_name VARCHAR(255), + role role NOT NULL, + PRIMARY KEY(uid) +); + +CREATE TABLE courses ( + course_id INT GENERATED ALWAYS AS IDENTITY, + name VARCHAR(50) NOT NULL, + ufora_id VARCHAR(50), + teacher VARCHAR(255) NOT NULL, + CONSTRAINT fk_teacher FOREIGN KEY(teacher) REFERENCES users(uid) ON DELETE CASCADE, + PRIMARY KEY(course_id) +); + +CREATE TABLE course_join_codes ( + join_code UUID DEFAULT gen_random_uuid() NOT NULL, + course_id INT NOT NULL, + expiry_time DATE, + for_admins BOOLEAN NOT NULL, + CONSTRAINT fk_course_join_link FOREIGN KEY(course_id) REFERENCES courses(course_id) ON DELETE CASCADE, + PRIMARY KEY(join_code) +); + +CREATE TABLE course_admins ( + course_id INT NOT NULL REFERENCES courses(course_id) ON DELETE CASCADE, + uid VARCHAR(255) NOT NULL REFERENCES users(uid) ON DELETE CASCADE, + PRIMARY KEY(course_id, uid) +); + +CREATE TABLE course_students ( + course_id INT NOT NULL REFERENCES courses(course_id) ON DELETE CASCADE, + uid VARCHAR(255) NOT NULL REFERENCES users(uid) ON DELETE CASCADE, + PRIMARY KEY(course_id, uid) +); + +CREATE TYPE deadline AS( + description TEXT, + deadline TIMESTAMP WITH TIME ZONE +); + +CREATE TABLE projects ( + project_id INT GENERATED ALWAYS AS IDENTITY, + title VARCHAR(100) NOT NULL, + description TEXT NOT NULL, + deadlines deadline[], + course_id INT NOT NULL, + visible_for_students BOOLEAN NOT NULL, + archived BOOLEAN NOT NULL, + groups_locked BOOLEAN DEFAULT FALSE, + regex_expressions VARCHAR(50)[], + runner runner, + PRIMARY KEY(project_id), + CONSTRAINT fk_course FOREIGN KEY(course_id) REFERENCES courses(course_id) ON DELETE CASCADE +); + +CREATE TABLE groups ( + group_id INT GENERATED ALWAYS AS IDENTITY, + project_id INT NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE, + group_size INT NOT NULL, + PRIMARY KEY(project_id, group_id) +); + +CREATE TABLE group_students ( + uid VARCHAR(255) NOT NULL REFERENCES users(uid) ON DELETE CASCADE, + group_id INT NOT NULL, + project_id INT NOT NULL, + PRIMARY KEY(uid, group_id, project_id), + CONSTRAINT fk_group_reference FOREIGN KEY (group_id, project_id) REFERENCES groups(group_id, project_id) ON DELETE CASCADE +); + +CREATE TABLE submissions ( + submission_id INT GENERATED ALWAYS AS IDENTITY, + uid VARCHAR(255) NOT NULL, + project_id INT NOT NULL, + grading FLOAT CHECK (grading >= 0 AND grading <= 20), + submission_time TIMESTAMP WITH TIME ZONE NOT NULL, + submission_path VARCHAR(255) NOT NULL, + submission_status submission_status NOT NULL, + PRIMARY KEY(submission_id), + CONSTRAINT fk_project FOREIGN KEY(project_id) REFERENCES projects(project_id) ON DELETE CASCADE, + CONSTRAINT fk_user FOREIGN KEY(uid) REFERENCES users(uid) ON DELETE CASCADE +); + +CREATE OR REPLACE FUNCTION remove_expired_codes() +RETURNS TRIGGER AS $$ +BEGIN + DELETE FROM course_join_codes + WHERE expiry_time < CURRENT_DATE; + + RETURN NULL; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER remove_expired_codes_trigger +AFTER INSERT OR UPDATE ON course_join_codes +FOR EACH ROW EXECUTE FUNCTION remove_expired_codes(); diff --git a/backend/dev-requirements.txt b/backend/dev-requirements.txt index dd9b3470..0263c7e7 100644 --- a/backend/dev-requirements.txt +++ b/backend/dev-requirements.txt @@ -1,3 +1,5 @@ pytest pylint pylint-flask +pyyaml +faker \ No newline at end of file diff --git a/backend/entry-point.sh b/backend/entry-point.sh new file mode 100755 index 00000000..daeb6329 --- /dev/null +++ b/backend/entry-point.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Start the Docker daemon in the background +dockerd-entrypoint.sh & + +# Wait for the Docker daemon to start +until docker info; do + echo "Waiting for Docker daemon to start..." + sleep 1 +done + +# Execute the command passed to the docker run command +exec "$@" diff --git a/backend/flake.lock b/backend/flake.lock new file mode 100644 index 00000000..f4191007 --- /dev/null +++ b/backend/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1708723535, + "narHash": "sha256-1z+3BHE9o1TfMpp7QAGAfu4+znaQv/47hIaV3n6HAuA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "27c12cd057b9dcd903a0ffb6a0712199cf4a66e1", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/backend/flake.nix b/backend/flake.nix new file mode 100644 index 00000000..3d88fde4 --- /dev/null +++ b/backend/flake.nix @@ -0,0 +1,26 @@ +{ + description = "Python pip DevShell"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + + outputs = { self, nixpkgs }: let + systems = [ "x86_64-linux" ]; + forAllSystems = function: nixpkgs.lib.genAttrs systems (system: function { + pkgs = import nixpkgs { inherit system; config.allowUnfree = true; }; + }); + in { + devShells = forAllSystems ({ pkgs }: { + default = (pkgs.buildFHSUserEnv { + name = "pip-zone"; + targetPkgs = pkgs: with pkgs; [ + python311Full + python311Packages.pip + + postgresql + dbeaver + ]; + runScript = "zsh || bash"; + }).env; + }); + }; +} diff --git a/backend/project/__init__.py b/backend/project/__init__.py index 98017b80..3c971e08 100644 --- a/backend/project/__init__.py +++ b/backend/project/__init__.py @@ -1,9 +1,31 @@ """ Flask API base file This file is the base of the Flask API. It contains the basic structure of the API. """ +from os import getenv +from datetime import timedelta -from flask import Flask, jsonify -from .endpoints.index import index_bp +from dotenv import load_dotenv + +from flask import Flask +from flask_jwt_extended import JWTManager +from flask_cors import CORS +from sqlalchemy_utils import register_composites +from .executor import executor +from .db_in import db +from .endpoints.index.index import index_bp +from .endpoints.users import users_bp +from .endpoints.courses.courses_config import courses_bp +from .endpoints.projects.project_endpoint import project_bp +from .endpoints.submissions.submission_config import submissions_bp +from .endpoints.courses.join_codes.join_codes_config import join_codes_bp +from .endpoints.docs.docs_endpoint import swagger_ui_blueprint +from .endpoints.authentication.auth import auth_bp +from .endpoints.authentication.me import me_bp +from .endpoints.authentication.logout import logout_bp +from .init_auth import auth_init + +load_dotenv() +JWT_SECRET_KEY = getenv("JWT_SECRET_KEY") def create_app(): """ @@ -11,8 +33,49 @@ def create_app(): Returns: Flask -- A Flask application instance """ - app = Flask(__name__) + app = Flask(__name__) + app.config['PROPAGATE_EXCEPTIONS'] = True + app.config["JWT_COOKIE_SECURE"] = True + app.config["JWT_COOKIE_CSRF_PROTECT"] = True + app.config["JWT_TOKEN_LOCATION"] = ["cookies"] + app.config["JWT_SECRET_KEY"] = JWT_SECRET_KEY + app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=3) + app.config["JWT_ACCESS_COOKIE_NAME"] = "peristeronas_access_token" + app.config["JWT_SESSION_COOKIE"] = False + executor.init_app(app) app.register_blueprint(index_bp) + app.register_blueprint(users_bp) + app.register_blueprint(courses_bp) + app.register_blueprint(project_bp) + app.register_blueprint(submissions_bp) + app.register_blueprint(join_codes_bp) + app.register_blueprint(swagger_ui_blueprint) + app.register_blueprint(auth_bp) + app.register_blueprint(me_bp) + app.register_blueprint(logout_bp) + + jwt = JWTManager(app) + auth_init(jwt, app) + return app + +def create_app_with_db(db_uri: str): + """ + Initialize the database with the given uri + and connect it to the app made with create_app. + Parameters: + db_uri (str): The URI of the database to initialize. + Returns: + Flask -- A Flask application instance + """ + app = create_app() + app.config["SQLALCHEMY_DATABASE_URI"] = db_uri + app.config["UPLOAD_FOLDER"] = "/" + db.init_app(app) + with app.app_context(): + # Getting a connection from the scoped session + connection = db.session.connection() + register_composites(connection) + CORS(app, supports_credentials=True) return app diff --git a/backend/project/__main__.py b/backend/project/__main__.py index 0e79612a..8a965261 100644 --- a/backend/project/__main__.py +++ b/backend/project/__main__.py @@ -1,9 +1,18 @@ """Main entry point for the application.""" -from sys import path -path.append(".") +from os import getenv +from dotenv import load_dotenv +from project import create_app_with_db +from project.db_in import url + +load_dotenv() +DEBUG=getenv("DEBUG") if __name__ == "__main__": - from project import create_app - app = create_app() - app.run(debug=True) + app = create_app_with_db(url) + + if DEBUG and DEBUG.lower() == "true": + app.run(debug=True, host='0.0.0.0') + else: + from waitress import serve + serve(app, host='0.0.0.0', port=5000) diff --git a/backend/project/db_in.py b/backend/project/db_in.py new file mode 100644 index 00000000..76534360 --- /dev/null +++ b/backend/project/db_in.py @@ -0,0 +1,22 @@ +"""db initialization""" + +import os +from dotenv import load_dotenv +from flask_sqlalchemy import SQLAlchemy +from sqlalchemy import URL + +db = SQLAlchemy() +load_dotenv() + +DATABSE_NAME = os.getenv("POSTGRES_DB") +DATABASE_USER = os.getenv("POSTGRES_USER") +DATABASE_PASSWORD = os.getenv("POSTGRES_PASSWORD") +DATABASE_HOST = os.getenv("POSTGRES_HOST") + +url = URL.create( + drivername="postgresql", + username=DATABASE_USER, + host=DATABASE_HOST, + database=DATABSE_NAME, + password=DATABASE_PASSWORD, +) diff --git a/backend/project/endpoints/authentication/auth.py b/backend/project/endpoints/authentication/auth.py new file mode 100644 index 00000000..1a496c8c --- /dev/null +++ b/backend/project/endpoints/authentication/auth.py @@ -0,0 +1,115 @@ +"""Auth api endpoint""" +from os import getenv + +from dotenv import load_dotenv +import requests +from flask import Blueprint, request, redirect, abort, make_response +from flask_jwt_extended import create_access_token, set_access_cookies +from flask_restful import Resource, Api + +from project.models.user import Role +from project.utils.user import get_or_make_user + +auth_bp = Blueprint("auth", __name__) +auth_api = Api(auth_bp) + +load_dotenv() +API_URL = getenv("API_HOST") +AUTH_METHOD = getenv("AUTH_METHOD") +TEST_AUTHENTICATION_URL = getenv("TEST_AUTHENTICATION_URL") +CLIENT_ID = getenv("CLIENT_ID") +CLIENT_SECRET = getenv("CLIENT_SECRET") +HOMEPAGE_URL = getenv("HOMEPAGE_URL") +TENANT_ID = getenv("TENANT_ID") + +def microsoft_authentication(): + """ + This function will handle a microsoft based login, + creating a new user profile in the process and + return a valid access token as a cookie. + Redirects to the homepage of the website + """ + code = request.args.get("code") + if code is None: + return {"message":"This endpoint is only used for authentication."}, 400 + # got code from microsoft + data = {"client_id":CLIENT_ID, + "scope":".default", + "code":code, + "redirect_uri":f"{API_URL}/auth", + "grant_type":"authorization_code", + "client_secret":CLIENT_SECRET} + try: + res = requests.post(f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token", + data=data, + timeout=5) + if res.status_code != 200: + abort(make_response(( + {"message": + "An error occured while trying to authenticate your access token"}, + 500))) + # hier wel nog if om error zelf op te vangen + token = res.json()["access_token"] + profile_res = requests.get("https://graph.microsoft.com/v1.0/me", + headers={"Authorization":f"Bearer {token}"}, + timeout=5) + except TimeoutError: + return {"message":"Request to Microsoft timed out"}, 500 + if profile_res is None or profile_res.status_code != 200: + abort(make_response(({"message": + "An error occured while trying to authenticate your access token"}, + 500))) + user = get_or_make_user(profile_res) + resp = redirect(HOMEPAGE_URL, code=303) + additional_claims = {"is_teacher":user.role == Role.TEACHER, + "is_admin":user.role == Role.ADMIN} + set_access_cookies(resp, + create_access_token(identity=profile_res.json()["id"], + additional_claims=additional_claims)) + return resp + + +def test_authentication(): + """ + This function will handle the logins done using our + own authentication server for testing purposes + """ + code = request.args.get("code") + if code is None: + abort(make_response(({"message": + "No code"}, + 400))) + profile_res = requests.get(TEST_AUTHENTICATION_URL, + headers={"Authorization":f"{code}"}, + timeout=5) + if profile_res is None: + abort(make_response(({"message": + "An error occured while trying to authenticate your access token"}, + 500))) + if profile_res.status_code != 200: + abort(make_response(({"message": + "Something was wrong with your code"}, + 401))) + user = get_or_make_user(profile_res) + resp = redirect(HOMEPAGE_URL, code=303) + additional_claims = {"is_teacher":user.role == Role.TEACHER, + "is_admin":user.role == Role.ADMIN} + set_access_cookies(resp, + create_access_token(identity=profile_res.json()["id"], + additional_claims=additional_claims)) + return resp + + +class Auth(Resource): + """Api endpoint for the /auth route""" + + def get(self): + """ + Will handle the request according to the method defined in the .env variables. + Currently only Microsoft and our test authentication are supported + """ + if AUTH_METHOD == "Microsoft": + return microsoft_authentication() + return test_authentication() + +auth_api.add_resource(Auth, "/auth") diff --git a/backend/project/endpoints/authentication/logout.py b/backend/project/endpoints/authentication/logout.py new file mode 100644 index 00000000..e629bbe3 --- /dev/null +++ b/backend/project/endpoints/authentication/logout.py @@ -0,0 +1,28 @@ +"""Api endpoint to handle logout requests""" +from os import getenv + +from dotenv import load_dotenv +from flask import Blueprint, redirect +from flask_jwt_extended import unset_jwt_cookies, jwt_required +from flask_restful import Resource, Api + +logout_bp = Blueprint("logout", __name__) +logout_api = Api(logout_bp) + +load_dotenv() +HOMEPAGE_URL = getenv("HOMEPAGE_URL") + +class Logout(Resource): + """Api endpoint for the /auth route""" + + @jwt_required() + def get(self): + """ + Will handle the request according to the method defined in the .env variables. + Currently only Microsoft and our test authentication are supported + """ + resp = redirect(HOMEPAGE_URL, 303) + unset_jwt_cookies(resp) + return resp + +logout_api.add_resource(Logout, "/logout") diff --git a/backend/project/endpoints/authentication/me.py b/backend/project/endpoints/authentication/me.py new file mode 100644 index 00000000..bd43d8aa --- /dev/null +++ b/backend/project/endpoints/authentication/me.py @@ -0,0 +1,33 @@ +"""User info api endpoint""" +from os import getenv + +from dotenv import load_dotenv +from flask import Blueprint +from flask_jwt_extended import get_jwt_identity, jwt_required +from flask_restful import Resource, Api + +from project.models.user import User +from project.utils.query_agent import query_by_id_from_model + +load_dotenv() +API_URL = getenv("API_HOST") + +me_bp = Blueprint("me", __name__) +me_api = Api(me_bp) + +class Me(Resource): + """Api endpoint for the /user_info route""" + + @jwt_required() + def get(self): + """ + Will return all user data associated with the access token in the request + """ + uid = get_jwt_identity() + + return query_by_id_from_model(User, + "uid", + uid, + "Could not find you in the database, please log in again") + +me_api.add_resource(Me, "/me") diff --git a/backend/project/endpoints/courses/course_admin_relation.py b/backend/project/endpoints/courses/course_admin_relation.py new file mode 100644 index 00000000..a208d6b9 --- /dev/null +++ b/backend/project/endpoints/courses/course_admin_relation.py @@ -0,0 +1,112 @@ +""" +This module will handle the /courses//admins endpoint +It will allow the teacher of a course to add and remove admins from a course +""" + +from os import getenv +from urllib.parse import urljoin +from dotenv import load_dotenv + +from flask import request +from flask_restful import Resource + +from project.models.course_relation import CourseAdmin +from project.models.user import User +from project.endpoints.courses.courses_utils import ( + execute_query_abort_if_db_error, + commit_abort_if_error, + delete_abort_if_error, + get_course_abort_if_not_found, + abort_if_not_teacher_or_none_assistant, + json_message +) +from project.utils.query_agent import query_selected_from_model, insert_into_model +from project.utils.authentication import authorize_teacher_of_course, \ + authorize_teacher_or_course_admin + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseForAdmins(Resource): + """ + This class will handle post and delete queries to + the /courses/course_id/admins url, only the teacher of a course can do this + """ + + @authorize_teacher_or_course_admin + def get(self, course_id): + """ + This function will return all the admins of a course + """ + abort_url = urljoin(f"{RESPONSE_URL}/" , f"{str(course_id)}/", "admins") + get_course_abort_if_not_found(course_id) + + return query_selected_from_model( + CourseAdmin, + abort_url, + select_values=["uid"], + url_mapper={"uid": urljoin(f"{API_URL}/", "users")}, + filters={"course_id": course_id}, + ) + + @authorize_teacher_of_course + def post(self, course_id): + """ + Api endpoint for adding new admins to a course, can only be done by the teacher + """ + abort_url = urljoin(f"{RESPONSE_URL}/" , f"{str(course_id)}/", "admins") + data = request.get_json() + if any(key != "admin_uid" for key in data.keys()): + return json_message("Incorrect data field given"), 400 + assistant = data.get("admin_uid") + abort_if_not_teacher_or_none_assistant(course_id, assistant) + + query = User.query.filter_by(uid=assistant) + new_admin = execute_query_abort_if_db_error(query, abort_url) + if not new_admin: + message = ( + "User to make admin was not found, please request with a valid uid" + ) + return json_message(message), 400 + + query = CourseAdmin.query.filter_by(uid=assistant) + new_admin = execute_query_abort_if_db_error(query, abort_url) + if new_admin: + return json_message("Admin already added to the course"), 400 + + return insert_into_model( + CourseAdmin, + {"uid": assistant, "course_id": course_id}, + abort_url, + "uid" + ) + + @authorize_teacher_of_course + def delete(self, course_id): + """ + Api endpoint for removing admins of a course, can only be done by the teacher + """ + abort_url = urljoin(f"{RESPONSE_URL}/" , f"{str(course_id)}/", "admins") + data = request.get_json() + if any(key != "admin_uid" for key in data.keys()): + return json_message("Incorrect data field given"), 400 + assistant = data.get("admin_uid") + abort_if_not_teacher_or_none_assistant(course_id, assistant) + + query = CourseAdmin.query.filter_by(uid=assistant, course_id=course_id) + admin_relation = execute_query_abort_if_db_error(query, abort_url) + if not admin_relation: + message = "Course with given admin not found" + return json_message(message), 400 + + delete_abort_if_error(admin_relation, abort_url) + commit_abort_if_error(abort_url) + + message = ( + f"Admin {assistant}" + f" was succesfully removed from course {course_id}" + ) + response = json_message(message) + response["url"] = abort_url + return response, 204 diff --git a/backend/project/endpoints/courses/course_details.py b/backend/project/endpoints/courses/course_details.py new file mode 100644 index 00000000..2fad705c --- /dev/null +++ b/backend/project/endpoints/courses/course_details.py @@ -0,0 +1,120 @@ +""" +This file contains the api endpoint for the /courses/course_id url +This file is responsible for handling the requests made to the /courses/course_id url +and returning the appropriate response as well as handling the requests made to the +/courses/course_id/admins and /courses/course_id/students urls +""" + +from os import getenv +from urllib.parse import urljoin + +from dotenv import load_dotenv + +from flask import request +from flask_restful import Resource +from sqlalchemy.exc import SQLAlchemyError + +from project.models.course import Course +from project.models.course_relation import CourseAdmin, CourseStudent + +from project.db_in import db +from project.endpoints.courses.courses_utils import check_data +from project.utils.query_agent import delete_by_id_from_model, patch_by_id_from_model +from project.utils.authentication import login_required, authorize_teacher_of_course + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseByCourseId(Resource): + """Api endpoint for the /courses/course_id link""" + + @login_required + def get(self, course_id): + """ + This get function will return all the related projects of the course + in the following form: + { + course: course with course_id + projects: [ + list of all projects that have course_id + where projects are jsons containing the title, deadline and project_id + ] + } + """ + try: + course_details = db.session.query( + Course.course_id, + Course.name, + Course.ufora_id, + Course.teacher + ).filter( + Course.course_id == course_id).first() + + if not course_details: + return { + "message": "Course not found", + "url": RESPONSE_URL + }, 404 + + admins = db.session.query(CourseAdmin.uid).filter( + CourseAdmin.course_id == course_id + ).all() + + students = db.session.query(CourseStudent.uid).filter( + CourseStudent.course_id == course_id + ).all() + + user_url = urljoin(API_URL + "/", "users") + + admin_ids = [ urljoin(f"{user_url}/" , admin[0]) for admin in admins] + student_ids = [ urljoin(f"{user_url}/", student[0]) for student in students] + + result = { + 'course_id': course_details.course_id, + 'name': course_details.name, + 'ufora_id': course_details.ufora_id, + 'teacher': course_details.teacher, + 'admins': admin_ids, + 'students': student_ids + } + + return { + "message": f"Succesfully retrieved course with course_id: {str(course_id)}", + "data": result, + "url": urljoin(f"{RESPONSE_URL}/", str(course_id)) + } + except SQLAlchemyError: + return { + "error": "Something went wrong while querying the database.", + "url": RESPONSE_URL}, 500 + + @authorize_teacher_of_course + def delete(self, course_id): + """ + This function will delete the course with course_id + """ + return delete_by_id_from_model( + Course, + "course_id", + course_id, + RESPONSE_URL + ) + + @authorize_teacher_of_course + def patch(self, course_id): + """ + This function will update the course with course_id + """ + + message, status = check_data(request.json, True) + if status != 200: + return message, status + + return patch_by_id_from_model( + Course, + "course_id", + course_id, + RESPONSE_URL, + request.json + ) diff --git a/backend/project/endpoints/courses/course_student_relation.py b/backend/project/endpoints/courses/course_student_relation.py new file mode 100644 index 00000000..20d0a3cc --- /dev/null +++ b/backend/project/endpoints/courses/course_student_relation.py @@ -0,0 +1,124 @@ +""" +This file contains the class CourseToAddStudents which is a +resource for the /courses/course_id/students link. +This class will allow admins of a course to assign and remove students from courses, +and everyone should be able to list all students assigned to a course. +""" + +from os import getenv +from urllib.parse import urljoin + +from dotenv import load_dotenv + +from flask import request +from flask_restful import Resource + +from project.db_in import db +from project.models.user import User +from project.models.course_relation import CourseStudent +from project.endpoints.courses.courses_utils import ( + execute_query_abort_if_db_error, + add_abort_if_error, + commit_abort_if_error, + delete_abort_if_error, + get_course_abort_if_not_found, + abort_if_none_uid_student_uids_or_non_existant_course_id, + json_message, +) + +from project.utils.query_agent import query_selected_from_model +from project.utils.authentication import login_required, authorize_teacher_or_course_admin + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseToAddStudents(Resource): + """ + Class that will respond to the /courses/course_id/students link + teachers should be able to assign and remove students from courses, + and everyone should be able to list all students assigned to a course + """ + + @login_required + def get(self, course_id): + """ + Get function at /courses/course_id/students + to get all the users assigned to a course + everyone can get this data so no need to have uid query in the link + """ + abort_url = f"{API_URL}/courses/{course_id}/students" + get_course_abort_if_not_found(course_id) + + return query_selected_from_model( + CourseStudent, + abort_url, + select_values=["uid"], + url_mapper={"uid": urljoin(f"{API_URL}/", "users")}, + filters={"course_id": course_id} + ) + + @authorize_teacher_or_course_admin + def post(self, course_id): + """ + Allows admins of a course to assign new students by posting to: + /courses/course_id/students with a list of uid in the request body under key "students" + """ + abort_url = f"{API_URL}/courses/{course_id}/students" + data = request.get_json() + if any(key != "students" for key in data.keys()): + return json_message("Incorrect data field given"), 400 + student_uids = data.get("students") + abort_if_none_uid_student_uids_or_non_existant_course_id( + course_id, student_uids + ) + + for uid in student_uids: + query = User.query.filter_by(uid=uid) + user = execute_query_abort_if_db_error(query, abort_url) + if not user: + return json_message("User does not exist"), 400 + query = CourseStudent.query.filter_by(uid=uid, course_id=course_id) + student_relation = execute_query_abort_if_db_error(query, abort_url) + if student_relation: + db.session.rollback() + message = ( + f"Student with uid {uid} is already assigned to the course" + ) + return json_message(message), 400 + add_abort_if_error(CourseStudent(uid=uid, course_id=course_id), abort_url) + commit_abort_if_error(abort_url) + response = json_message("Users were succesfully added to the course") + response["url"] = abort_url + data = {"students": [f"{API_URL}/users/{uid}" for uid in student_uids]} + response["data"] = data + return response, 201 + + @authorize_teacher_or_course_admin + def delete(self, course_id): + """ + This function allows admins of a course to remove students by sending a delete request to + /courses/course_id/students with inside the request body + a field "students" = [list of uids to unassign] + """ + abort_url = f"{API_URL}/courses/{str(course_id)}/students" + data = request.get_json() + if len([key for key in data.keys() if key != "students"]) != 0: + return json_message("Incorrect data field given"), 400 + student_uids = data.get("students") + abort_if_none_uid_student_uids_or_non_existant_course_id( + course_id, student_uids + ) + + for uid in student_uids: + query = CourseStudent.query.filter_by(uid=uid, course_id=course_id) + student_relation = execute_query_abort_if_db_error(query, abort_url) + if student_relation: + delete_abort_if_error(student_relation, abort_url) + else: + return json_message(f"'{uid}' is not a student of the course"), 400 + commit_abort_if_error(abort_url) + + response = json_message("Users were succesfully removed from the course") + response["url"] = f"{API_URL}/courses/{str(course_id)}/students" + return response diff --git a/backend/project/endpoints/courses/courses.py b/backend/project/endpoints/courses/courses.py new file mode 100644 index 00000000..306df744 --- /dev/null +++ b/backend/project/endpoints/courses/courses.py @@ -0,0 +1,111 @@ +""" +This file contains the main endpoint for the /courses url. +This endpoint is used to get all courses and filter by given +query parameter like /courses?parameter=... +parameters can be either one of the following: teacher,ufora_id,name. +""" + +from os import getenv +from urllib.parse import urljoin +from dataclasses import fields +from dotenv import load_dotenv + +from flask import request +from flask_restful import Resource + +from sqlalchemy import union, select +from sqlalchemy.exc import SQLAlchemyError + +from project.models.course import Course +from project.models.course_relation import CourseAdmin, CourseStudent +from project.utils.query_agent import insert_into_model +from project.utils.authentication import login_required_return_uid, authorize_teacher +from project.endpoints.courses.courses_utils import check_data +from project.db_in import db + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseForUser(Resource): + """Api endpoint for the /courses link""" + + @login_required_return_uid + def get(self, uid=None): + """ " + Get function for /courses this will be the main endpoint + to get all courses and filter by given query parameter like /courses?parameter=... + parameters can be either one of the following: teacher,ufora_id,name. + """ + + try: + filter_params = { + key: value for key, value + in request.args.to_dict().items() + if key in {f.name for f in fields(Course)} + } + + # Start with a base query + base_query = select(Course) + + # Apply filters dynamically if they are provided + for param, value in filter_params.items(): + if value: + if param in Course.__table__.columns: + attribute = getattr(Course, param) + base_query = base_query.filter(attribute == value) + + # Define the role-specific queries + student_courses = base_query.join( + CourseStudent, + Course.course_id == CourseStudent.course_id).filter( + CourseStudent.uid == uid) + admin_courses = base_query.join( + CourseAdmin, + Course.course_id == CourseAdmin.course_id).filter( + CourseAdmin.uid == uid) + teacher_courses = base_query.filter(Course.teacher == uid) + + # Combine the select statements using union to remove duplicates + all_courses_query = union(student_courses, admin_courses, teacher_courses) + + # Execute the union query and fetch all results as Course instances + courses = db.session.execute(all_courses_query).mappings().all() + courses_data = [dict(course) for course in courses] + + for course in courses_data: + course["course_id"] = urljoin(f"{RESPONSE_URL}/", str(course['course_id'])) + + return { + "data": courses_data, + "url": RESPONSE_URL, + "message": "Courses fetched successfully" + } + + except SQLAlchemyError: + db.session.rollback() + return { + "message": "An error occurred while fetching the courses", + "url": RESPONSE_URL + }, 500 + + @authorize_teacher + def post(self, teacher_id=None): + """ + This function will create a new course + if the body of the post contains a name and uid is an admin or teacher + """ + + message, status = check_data(request.json, False) + if status != 200: + return message, status + + req = request.json + req["teacher"] = teacher_id + return insert_into_model( + Course, + req, + RESPONSE_URL, + "course_id", + required_fields=["name", "teacher"] + ) diff --git a/backend/project/endpoints/courses/courses_config.py b/backend/project/endpoints/courses/courses_config.py new file mode 100644 index 00000000..03f1abca --- /dev/null +++ b/backend/project/endpoints/courses/courses_config.py @@ -0,0 +1,35 @@ +""" +This file is used to configure the courses blueprint and the courses api. +It is used to define the routes for the courses blueprint and the +corresponding api endpoints. + +The courses blueprint is used to define the routes for the courses api +endpoints and the courses api is used to define the routes for the courses +api endpoints. +""" + +from flask import Blueprint +from flask_restful import Api + +from project.endpoints.courses.courses import CourseForUser +from project.endpoints.courses.course_details import CourseByCourseId +from project.endpoints.courses.course_admin_relation import CourseForAdmins +from project.endpoints.courses.course_student_relation import CourseToAddStudents +from project.endpoints.courses.join import CourseJoin + +courses_bp = Blueprint("courses", __name__) +courses_api = Api(courses_bp) + +courses_bp.add_url_rule("/courses", + view_func=CourseForUser.as_view('course_endpoint')) + +courses_bp.add_url_rule("/courses/", + view_func=CourseByCourseId.as_view('course_by_course_id')) + +courses_bp.add_url_rule("/courses//admins", + view_func=CourseForAdmins.as_view('course_admins')) + +courses_bp.add_url_rule("/courses//students", + view_func=CourseToAddStudents.as_view('course_students')) + +courses_bp.add_url_rule("/courses/join", view_func=CourseJoin.as_view('course_join')) diff --git a/backend/project/endpoints/courses/courses_utils.py b/backend/project/endpoints/courses/courses_utils.py new file mode 100644 index 00000000..a6ea3fc8 --- /dev/null +++ b/backend/project/endpoints/courses/courses_utils.py @@ -0,0 +1,245 @@ +""" +This module contains utility functions for the courses endpoints. +The functions are used to interact with the database and handle errors. +""" + +from os import getenv +from urllib.parse import urljoin + +from dotenv import load_dotenv +from flask import abort +from sqlalchemy.exc import SQLAlchemyError + +from project.db_in import db +from project.models.course_relation import CourseAdmin +from project.models.user import User, Role +from project.models.course import Course + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(API_URL + "/", "courses") +BASE_DB_ERROR = "Database error occurred while" + +def execute_query_abort_if_db_error(query, url, query_all=False): + """ + Execute the given SQLAlchemy query and handle any SQLAlchemyError that might occur. + If query_all == True, the query will be executed with the all() method, + otherwise with the first() method. + Args: + query (Query): The SQLAlchemy query to execute. + + Returns: + ResultProxy: The result of the query if successful, otherwise aborts with error 500. + """ + try: + if query_all: + result = query.all() + else: + result = query.first() + except SQLAlchemyError: + response = json_message(f"{BASE_DB_ERROR} executing query") + response["url"] = url + abort(500, description=response) + return result + + +def add_abort_if_error(to_add, url): + """ + Add a new object to the database + and handle any SQLAlchemyError that might occur. + + Args: + to_add (object): The object to add to the database. + """ + try: + db.session.add(to_add) + except SQLAlchemyError: + db.session.rollback() + response = json_message(f"{BASE_DB_ERROR} adding object") + response["url"] = url + abort(500, description=response) + + +def delete_abort_if_error(to_delete, url): + """ + Deletes the given object from the database + and aborts the request with a 500 error if a SQLAlchemyError occurs. + + Args: + - to_delete: The object to be deleted from the database. + """ + try: + db.session.delete(to_delete) + except SQLAlchemyError: + db.session.rollback() + response = json_message(f"{BASE_DB_ERROR} deleting object") + response["url"] = url + abort(500, description=response) + + +def commit_abort_if_error(url): + """ + Commit the current session and handle any SQLAlchemyError that might occur. + """ + try: + db.session.commit() + except SQLAlchemyError: + db.session.rollback() + response = json_message(f"{BASE_DB_ERROR} committing changes") + response["url"] = url + abort(500, description=response) + + +def abort_if_not_teacher_or_none_assistant(course_id, assistant): + """ + Check if the current user is authorized to appoint new admins to a course. + + Args: + course_id (int): The ID of the course. + assistant (int): The UID of the person to be made an admin. + + Raises: + HTTPException: If the current user is not authorized or + if the UID of the person to be made an admin is missing in the request body. + """ + url = f"{API_URL}/courses/{str(course_id)}/admins" + + if not assistant: + response = json_message( + "uid of person to make admin is required in the request body" + ) + response["url"] = url + abort(400, description=response) + + +def abort_if_none_uid_student_uids_or_non_existant_course_id( + course_id, student_uids +): + """ + Check the request to assign new students to a course. + + Args: + course_id (int): The ID of the course. + + Raises: + 403: If the user is not authorized to assign new students to the course. + 400: If the request body does not contain the required 'students' field. + """ + url = f"{API_URL}/courses/{str(course_id)}/students" + get_course_abort_if_not_found(course_id) + + if not student_uids: + message = """To assign new students to a course, + you should have a students field with a list of uids in the request body""" + response = json_message(message) + response["url"] = url + abort(400, description=response) + + +def abort_if_uid_is_none(uid, url): + """ + Check whether the uid is None if so + abort with error 400 + """ + if uid is None: + response = json_message("There should be a uid in the request query") + response["url"] = url + abort(400, description=response) + + +def abort_if_no_user_found_for_uid(uid, url): + """ + Check if a user exists based on the provided uid. + + Args: + uid (int): The unique identifier of the user. + + Raises: + NotFound: If the user with the given uid is not found. + """ + query = User.query.filter_by(uid=uid) + user = execute_query_abort_if_db_error(query, url) + + if not user: + response = json_message(f"User with uid {uid} was not found") + response["url"] = url + abort(404, description=response) + return user + + +def get_admin_relation(uid, course_id): + """ + Retrieve the CourseAdmin object for the given uid and course. + + Args: + uid (int): The user ID. + course_id (int): The course ID. + + Returns: + CourseAdmin: The CourseAdmin object if the user is an admin, otherwise None. + """ + return execute_query_abort_if_db_error( + CourseAdmin.query.filter_by(uid=uid, course_id=course_id), + url=f"{API_URL}/courses/{str(course_id)}/admins", + ) + + +def json_message(message): + """ + Create a json message with the given message. + + Args: + message (str): The message to include in the json. + + Returns: + dict: The message in a json format. + """ + return {"message": message} + + +def get_course_abort_if_not_found(course_id, url=f"{API_URL}/courses"): + """ + Get a course by its ID. + + Args: + course_id (int): The course ID. + + Returns: + Course: The course with the given ID. + """ + query = Course.query.filter_by(course_id=course_id) + course = execute_query_abort_if_db_error(query, url) + + if not course: + response = json_message("Course not found") + response["url"] = url + abort(404, description=response) + + return course + +def check_data(data: dict[str, str], check_teacher: bool): + """Check the data""" + if not all(hasattr(Course, key) for key in data.keys()): + return json_message("The data contains an incorrect field"), 400 + + if "name" in data.keys(): + name = data.get("name") + if name is None or not isinstance(name, str): + return json_message("The name field does not have the correct type"), 400 + + if "ufora_id" in data.keys(): + ufora_id = data.get("ufora_id") + if not isinstance(ufora_id, str): + return json_message("The ufora_id field does not have the correct type"), 400 + + if check_teacher and "teacher" in data.keys(): + teacher = data.get("teacher") + if teacher is None or not isinstance(teacher, str): + return json_message("The teacher field does not have the correct type"), 400 + user = execute_query_abort_if_db_error(User.query.filter_by(uid=teacher), RESPONSE_URL) + if user.role != Role.TEACHER: + return json_message( + "The user given in the teacher field does not have the correct role" + ), 400 + + return json_message("ok"), 200 diff --git a/backend/project/endpoints/courses/join.py b/backend/project/endpoints/courses/join.py new file mode 100644 index 00000000..31f57608 --- /dev/null +++ b/backend/project/endpoints/courses/join.py @@ -0,0 +1,92 @@ +""" +This file contains the endpoint to join a course using a join code +""" + + +from os import getenv +from datetime import datetime + +from flask import request +from flask_restful import Resource + +from sqlalchemy.exc import SQLAlchemyError + +from project.models.course_share_code import CourseShareCode +from project.models.course_relation import CourseStudent, CourseAdmin +from project.utils.misc import is_valid_uuid +from project.db_in import db +from project.utils.authentication import login_required_return_uid + +API_URL = getenv("API_HOST") + +class CourseJoin(Resource): + """ + Class that will respond to the /courses/join link + students or admins with a join code can join a course + """ + + @login_required_return_uid + def post(self, uid=None): # pylint: disable=too-many-return-statements + """ + Post function for /courses/join + students or admins with a join code can join a course + """ + + response = { + "url": f"{API_URL}/courses/join" + } + + data = request.get_json() + if not "join_code" in data: + return {"message": "join_code is required"}, 400 + + join_code = data["join_code"] + + if not is_valid_uuid(join_code): + response["message"] = "Invalid join code" + return response, 400 + + share_code = CourseShareCode.query.filter_by(join_code=join_code).first() + + if not share_code: + response["message"] = "Invalid join code" + return response, 400 + + if share_code.expiry_time and share_code.expiry_time < datetime.now().date(): + response["message"] = "Join code has expired" + return response, 400 + + + course_id = share_code.course_id + is_for_admins = share_code.for_admins + + course_relation = CourseStudent + if is_for_admins: + course_relation = CourseAdmin + + try: + relation = course_relation.query.filter_by(course_id=course_id, uid=uid).first() + if relation: + response["message"] = "User already in course" + response["data"] = { + "course_id": course_id + } + return response, 409 + except SQLAlchemyError: + response["message"] = "Internal server error" + return response, 500 + + course_relation = course_relation(course_id=course_id, uid=uid) + + try: + db.session.add(course_relation) + db.session.commit() + response["data"] = { + "course_id": course_id + } + response["message"] = "User added to course" + return response, 201 + except SQLAlchemyError: + db.session.rollback() + response["message"] = "Internal server error" + return response, 500 diff --git a/backend/project/endpoints/courses/join_codes/course_join_code.py b/backend/project/endpoints/courses/join_codes/course_join_code.py new file mode 100644 index 00000000..c5cbfb17 --- /dev/null +++ b/backend/project/endpoints/courses/join_codes/course_join_code.py @@ -0,0 +1,48 @@ +""" +This file will contain the api endpoints for the /courses//join_codes url +""" + +from os import getenv +from urllib.parse import urljoin +from dotenv import load_dotenv + +from flask_restful import Resource +from project.utils.query_agent import query_by_id_from_model, delete_by_id_from_model +from project.models.course_share_code import CourseShareCode +from project.utils.authentication import authorize_teacher_of_course + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseJoinCode(Resource): + """ + This class will handle post and delete queries to + the /courses/course_id/join_codes/ url, only an admin of a course can do this + """ + + @authorize_teacher_of_course + def get(self, course_id, join_code): + """ + This function will return all the join codes of a course + """ + + return query_by_id_from_model( + CourseShareCode, + "join_code", + join_code, + urljoin(f"{RESPONSE_URL}/", f"{str(course_id)}/", "join_codes") + ) + + @authorize_teacher_of_course + def delete(self, course_id, join_code): + """ + Api endpoint for deleting join codes from a course, can only be done by the teacher + """ + + return delete_by_id_from_model( + CourseShareCode, + "join_code", + join_code, + urljoin(f"{RESPONSE_URL}/", f"{str(course_id)}/", "join_codes") + ) diff --git a/backend/project/endpoints/courses/join_codes/course_join_codes.py b/backend/project/endpoints/courses/join_codes/course_join_codes.py new file mode 100644 index 00000000..1eb7e00c --- /dev/null +++ b/backend/project/endpoints/courses/join_codes/course_join_codes.py @@ -0,0 +1,58 @@ +""" +This file will contain the api endpoints for the /courses//join_codes url +""" + +from os import getenv +from urllib.parse import urljoin +from dotenv import load_dotenv + +from flask_restful import Resource +from flask import request +from project.utils.query_agent import query_selected_from_model, insert_into_model +from project.models.course_share_code import CourseShareCode +from project.endpoints.courses.courses_utils import get_course_abort_if_not_found +from project.utils.authentication import authorize_teacher_of_course + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "courses") + +class CourseJoinCodes(Resource): + """ + This class will handle get and post queries to + the /courses/course_id/join_codes url, only an admin of a course can do this + """ + + @authorize_teacher_of_course + def get(self, course_id): + """ + This function will return all the join codes of a course + """ + + get_course_abort_if_not_found(course_id) + + return query_selected_from_model( + CourseShareCode, + urljoin(f"{RESPONSE_URL}/", f"{str(course_id)}/", "join_codes"), + select_values=["join_code", "expiry_time", "for_admins"], + filters={"course_id": course_id} + ) + + @authorize_teacher_of_course + def post(self, course_id): + """ + Api endpoint for adding new join codes to a course, can only be done by the teacher + """ + + get_course_abort_if_not_found(course_id) + + data = request.get_json() + data["course_id"] = course_id + + return insert_into_model( + CourseShareCode, + data, + urljoin(f"{RESPONSE_URL}/", f"{str(course_id)}/", "join_codes"), + "join_code", + required_fields=["for_admins"] + ) diff --git a/backend/project/endpoints/courses/join_codes/join_codes_config.py b/backend/project/endpoints/courses/join_codes/join_codes_config.py new file mode 100644 index 00000000..a2ae0bce --- /dev/null +++ b/backend/project/endpoints/courses/join_codes/join_codes_config.py @@ -0,0 +1,24 @@ +""" +This file is used to configure the join codes endpoints. +It is used to define the routes for the join codes blueprint and the +corresponding api endpoints. + +The join codes blueprint is used to define the routes for the join codes api +endpoints and the join codes api is used to define the routes for the join codes +api endpoints. +""" + +from flask import Blueprint +from flask_restful import Api + +from project.endpoints.courses.join_codes.course_join_codes import CourseJoinCodes +from project.endpoints.courses.join_codes.course_join_code import CourseJoinCode + +join_codes_bp = Blueprint("join_codes", __name__) +join_codes_api = Api(join_codes_bp) + +join_codes_bp.add_url_rule("/courses//join_codes", + view_func=CourseJoinCodes.as_view('course_join_codes')) + +join_codes_bp.add_url_rule("/courses//join_codes/", + view_func=CourseJoinCode.as_view('course_join_code')) diff --git a/backend/project/endpoints/docs/docs_endpoint.py b/backend/project/endpoints/docs/docs_endpoint.py new file mode 100644 index 00000000..197641ae --- /dev/null +++ b/backend/project/endpoints/docs/docs_endpoint.py @@ -0,0 +1,17 @@ +""" +Module for defining the swagger docs +""" + +from os import getenv +from flask_swagger_ui import get_swaggerui_blueprint + +SWAGGER_URL = getenv("DOCS_URL") +API_URL = getenv("DOCS_JSON_PATH") + +swagger_ui_blueprint = get_swaggerui_blueprint( + SWAGGER_URL, + f"/{API_URL}", + config={ + 'app_name': 'Pigeonhole API' + } +) diff --git a/backend/project/endpoints/index.py b/backend/project/endpoints/index.py deleted file mode 100644 index b5536eaf..00000000 --- a/backend/project/endpoints/index.py +++ /dev/null @@ -1,10 +0,0 @@ -from flask import Blueprint -from flask_restful import Resource - -index_bp = Blueprint("index", __name__) - -class Index(Resource): - def get(self): - return {"Message": "Hello World!"} - -index_bp.add_url_rule("/", view_func=Index.as_view("index")) \ No newline at end of file diff --git a/backend/project/endpoints/index/index.py b/backend/project/endpoints/index/index.py new file mode 100644 index 00000000..4feb3382 --- /dev/null +++ b/backend/project/endpoints/index/index.py @@ -0,0 +1,22 @@ +"""Index api point""" +import os +from flask import Blueprint, send_file +from flask_restful import Resource, Api + +index_bp = Blueprint("index", __name__) +index_endpoint = Api(index_bp) + +API_URL = os.getenv("DOCS_JSON_PATH") + +class Index(Resource): + """Api endpoint for the / route""" + + def get(self): + """ + Example of an api endpoint function that will respond to get requests made to + return a json data structure with key Message and value Hello World! + """ + return send_file(API_URL) + + +index_bp.add_url_rule("/", view_func=Index.as_view("index")) diff --git a/backend/project/endpoints/projects/endpoint_parser.py b/backend/project/endpoints/projects/endpoint_parser.py new file mode 100644 index 00000000..895658be --- /dev/null +++ b/backend/project/endpoints/projects/endpoint_parser.py @@ -0,0 +1,69 @@ +""" +Parser for the argument when posting or patching a project +""" + +import json +from flask_restful import reqparse +from werkzeug.datastructures import FileStorage + +parser = reqparse.RequestParser() +parser.add_argument('title', type=str, help='Projects title', location="form") +parser.add_argument('description', type=str, help='Projects description', location="form") +parser.add_argument( + 'assignment_file', + type=FileStorage, + help='Projects assignment file', + location="form" +) +parser.add_argument( + 'deadlines', + type=str, + help='Projects deadlines', + location="form", action="append" +) +parser.add_argument("course_id", type=str, help='Projects course_id', location="form") +parser.add_argument( + "visible_for_students", + type=bool, + help='Projects visibility for students', + location="form" +) +parser.add_argument("archived", type=str, help='Projects', location="form") +parser.add_argument( + "regex_expressions", + type=str, + help='Projects regex expressions', + location="form", + action="append" +) + +parser.add_argument("runner", type=str, help='Projects runner', location="form") + + +def parse_project_params(): + """ + Return a dict of every non None value in the param + """ + args = parser.parse_args() + + result_dict = {} + for key, value in args.items(): + if value is not None: + if "deadlines" == key: + deadlines_parsed = value + new_deadlines = [] + for deadline in deadlines_parsed: + deadline = json.loads(deadline) + new_deadlines.append( + ( + deadline["description"], + deadline["deadline"] + ) + ) + result_dict[key] = new_deadlines + elif "archived" == key: + result_dict[key] = value == "true" + else: + result_dict[key] = value + + return result_dict diff --git a/backend/project/endpoints/projects/groups/group_student.py b/backend/project/endpoints/projects/groups/group_student.py new file mode 100644 index 00000000..6a148a1f --- /dev/null +++ b/backend/project/endpoints/projects/groups/group_student.py @@ -0,0 +1,128 @@ +"""Endpoint for joining and leaving groups in a project""" + + +from os import getenv +from urllib.parse import urljoin +from dotenv import load_dotenv +from flask import request +from flask_restful import Resource +from sqlalchemy.exc import SQLAlchemyError + +from project.utils.query_agent import insert_into_model +from project.models.group import Group +from project.models.project import Project +from project.utils.authentication import authorize_student_submission + +from project import db + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "groups") + + +class GroupStudent(Resource): + """Api endpoint to allow students to join and leave project groups""" + @authorize_student_submission + def post(self, project_id, group_id, uid=None): + """ + This function will allow students to join project groups if not full + """ + try: + project = db.session.query(Project).filter_by( + project_id=project_id).first() + if project.groups_locked: + return { + "message": "Groups are locked for this project", + "url": RESPONSE_URL + }, 400 + + group = db.session.query(Group).filter_by( + project_id=project_id, group_id=group_id).first() + if group is None: + return { + "message": "Group does not exist", + "url": RESPONSE_URL + }, 404 + + joined_groups = db.session.query(GroupStudent).filter_by( + uid=uid, project_id=project_id).all() + if len(joined_groups) > 0: + return { + "message": "Student is already in a group", + "url": RESPONSE_URL + }, 400 + + joined_students = db.session.query(GroupStudent).filter_by( + group_id=group_id, project_id=project_id).all() + if len(joined_students) >= group.group_size: + return { + "message": "Group is full", + "url": RESPONSE_URL + }, 400 + + req = request.json + req["project_id"] = project_id + req["group_id"] = group_id + req["uid"] = uid + return insert_into_model( + GroupStudent, + req, + RESPONSE_URL, + "group_id", + required_fields=["project_id", "group_id", "uid"] + ) + except SQLAlchemyError: + data = { + "url": urljoin(f"{API_URL}/", "projects") + } + data["message"] = "An error occurred while fetching the projects" + return data, 500 + + + @authorize_student_submission + def delete(self, project_id, group_id, uid=None): + """ + This function will allow students to leave project groups + """ + data = { + "url": urljoin(f"{API_URL}/", "projects") + } + try: + project = db.session.query(Project).filter_by( + project_id=project_id).first() + if project.groups_locked: + return { + "message": "Groups are locked for this project", + "url": RESPONSE_URL + }, 400 + + group = db.session.query(Group).filter_by( + project_id=project_id, group_id=group_id).first() + if group is None: + return { + "message": "Group does not exist", + "url": RESPONSE_URL + }, 404 + + if uid is None: + return { + "message": "Failed to verify uid of user", + "url": RESPONSE_URL + }, 400 + + student_group = db.session.query(GroupStudent).filter_by( + group_id=group_id, project_id=project_id, uid=uid).first() + if student_group is None: + return { + "message": "Student is not in the group", + "url": RESPONSE_URL + }, 404 + + db.session.delete(student_group) + db.session.commit() + data["message"] = "Student has succesfully left the group" + return data, 200 + + except SQLAlchemyError: + data["message"] = "An error occurred while fetching the projects" + return data, 500 diff --git a/backend/project/endpoints/projects/groups/groups.py b/backend/project/endpoints/projects/groups/groups.py new file mode 100644 index 00000000..a6b070e0 --- /dev/null +++ b/backend/project/endpoints/projects/groups/groups.py @@ -0,0 +1,127 @@ +"""Endpoint for creating/deleting groups in a project""" +from os import getenv +from urllib.parse import urljoin +from dotenv import load_dotenv +from flask import request +from flask_restful import Resource +from sqlalchemy.exc import SQLAlchemyError + +from project.models.project import Project +from project.models.group import Group +from project.utils.query_agent import query_selected_from_model, insert_into_model +from project.utils.authentication import ( + authorize_teacher_or_student_of_project, + authorize_teacher_of_project +) +from project import db + +load_dotenv() +API_URL = getenv("API_HOST") +RESPONSE_URL = urljoin(f"{API_URL}/", "groups") + + +class Groups(Resource): + """Api endpoint for the /project/project_id/groups link""" + + @authorize_teacher_of_project + def patch(self, project_id): + """ + This function will set locked state of project groups, + need to pass locked field in the body + """ + req = request.json + locked = req.get("locked") + if locked is None: + return { + "message": "Bad request: locked field is required", + "url": RESPONSE_URL + }, 400 + + try: + project = db.session.query(Project).filter_by( + project_id=project_id).first() + if project is None: + return { + "message": "Project does not exist", + "url": RESPONSE_URL + }, 404 + project.groups_locked = locked + db.session.commit() + + return { + "message": "Groups are locked", + "url": RESPONSE_URL + }, 200 + except SQLAlchemyError: + return { + "message": "Database error", + "url": RESPONSE_URL + }, 500 + + @authorize_teacher_or_student_of_project + def get(self, project_id): + """ + Get function for /project/project_id/groups this will be the main endpoint + to get all groups for a project + """ + return query_selected_from_model( + Group, + RESPONSE_URL, + url_mapper={"group_id": RESPONSE_URL}, + filters={"project_id": project_id} + ) + + @authorize_teacher_of_project + def post(self, project_id): + """ + This function will create a new group for a project + if the body of the post contains a group_size and project_id exists + """ + + req = request.json + req["project_id"] = project_id + return insert_into_model( + Group, + req, + RESPONSE_URL, + "group_id", + required_fields=["project_id", "group_size"] + ) + + @authorize_teacher_of_project + def delete(self, project_id): + """ + This function will delete a group + if group_id is provided and request is from teacher + """ + + req = request.json + group_id = req.get("group_id") + if group_id is None: + return { + "message": "Bad request: group_id is required", + "url": RESPONSE_URL + }, 400 + + try: + project = db.session.query(Project).filter_by( + project_id=project_id).first() + if project is None: + return { + "message": "Project associated with group does not exist", + "url": RESPONSE_URL + }, 404 + + group = db.session.query(Group).filter_by( + project_id=project_id, group_id=group_id).first() + db.session.delete(group) + db.session.commit() + return { + "message": "Group deleted", + "url": RESPONSE_URL + }, 204 + except SQLAlchemyError: + return { + "message": "Database error", + "url": RESPONSE_URL + }, 500 diff --git a/backend/project/endpoints/projects/project_assignment_file.py b/backend/project/endpoints/projects/project_assignment_file.py new file mode 100644 index 00000000..977950f5 --- /dev/null +++ b/backend/project/endpoints/projects/project_assignment_file.py @@ -0,0 +1,57 @@ +""" +Module for getting the assignment files +of a project +""" +import os +from urllib.parse import urljoin + +from flask import send_from_directory, request + +from flask_restful import Resource + +from project.utils.authentication import authorize_project_visible + +API_URL = os.getenv('API_HOST') +RESPONSE_URL = urljoin(API_URL, "projects") +UPLOAD_FOLDER = os.getenv('UPLOAD_FOLDER') + +ASSIGNMENT_FILE_NAME = "assignment.md" + +class ProjectAssignmentFiles(Resource): + """ + Class for getting the assignment files of a project + """ + + @authorize_project_visible + def get(self, project_id): + """ + Get the assignment files of a project + """ + + language = request.args.get('lang') + directory_path = os.path.abspath(os.path.join(UPLOAD_FOLDER, str(project_id))) + file_name = ASSIGNMENT_FILE_NAME + if language: + potential_file = f"assignment_{language}.md" + if os.path.isfile(os.path.join(directory_path, potential_file)): + file_name = potential_file + else: + # Find any .md file that starts with "assignment" + for filename in os.listdir(directory_path): + if filename.startswith("assignment") and filename.endswith(".md"): + file_name = filename + break + + + assignment_file = os.path.join(directory_path, file_name) + + if not os.path.isfile(assignment_file): + # no file is found so return 404 + return { + "message": "No assignment file found for this project", + "url": f"{API_URL}/projects/{project_id}/assignment" + }, 404 + + + + return send_from_directory(directory_path, ASSIGNMENT_FILE_NAME) diff --git a/backend/project/endpoints/projects/project_detail.py b/backend/project/endpoints/projects/project_detail.py new file mode 100644 index 00000000..eb7724df --- /dev/null +++ b/backend/project/endpoints/projects/project_detail.py @@ -0,0 +1,115 @@ +""" +Module for project details page +for example /projects/1 if the project id of +the corresponding project is 1 +""" +import os +import zipfile +from urllib.parse import urljoin + +from flask import request +from flask_restful import Resource + +from project.db_in import db + +from project.models.project import Project +from project.utils.query_agent import query_by_id_from_model, delete_by_id_from_model, \ + patch_by_id_from_model +from project.utils.authentication import authorize_teacher_or_project_admin, \ + authorize_teacher_of_project, authorize_project_visible + +from project.endpoints.projects.endpoint_parser import parse_project_params + +API_URL = os.getenv('API_HOST') +RESPONSE_URL = urljoin(API_URL, "projects") +UPLOAD_FOLDER = os.getenv('UPLOAD_FOLDER') + + +class ProjectDetail(Resource): + """ + Class for projects/id endpoints + Inherits from flask_restful.Resource class + for implementing get, delete and put methods + """ + + @authorize_project_visible + def get(self, project_id): + """ + Get method for listing a specific project + filtered by id of that specific project + the id fetched from the url with the reaparse + """ + + return query_by_id_from_model( + Project, + "project_id", + project_id, + RESPONSE_URL) + + @authorize_teacher_or_project_admin + def patch(self, project_id): + """ + Update method for updating a specific project + filtered by id of that specific project + """ + project_json = parse_project_params() + + output, status_code = patch_by_id_from_model( + Project, + "project_id", + project_id, + RESPONSE_URL, + project_json + ) + if status_code != 200: + return output, status_code + + if "assignment_file" in request.files: + file = request.files["assignment_file"] + filename = os.path.basename(file.filename) + project_upload_directory = os.path.join(f"{UPLOAD_FOLDER}", f"{project_id}") + os.makedirs(project_upload_directory, exist_ok=True) + try: + # remove the old file + try: + to_rem_files = os.listdir(project_upload_directory) + for to_rem_file in to_rem_files: + to_rem_file_path = os.path.join(project_upload_directory, to_rem_file) + if os.path.isfile(to_rem_file_path): + os.remove(to_rem_file_path) + except FileNotFoundError: + db.session.rollback() + return ({ + "message": "Something went wrong deleting the old project files", + "url": f"{API_URL}/projects/{project_id}" + }) + + # removed all files now upload the new files + file.save(os.path.join(project_upload_directory, filename)) + zip_location = os.path.join(project_upload_directory, filename) + with zipfile.ZipFile(zip_location) as upload_zip: + upload_zip.extractall(project_upload_directory) + + except zipfile.BadZipfile: + db.session.rollback() + return ({ + "message": + "Please provide a valid .zip file for updating the instructions", + "url": f"{API_URL}/projects/{project_id}" + }, + 400) + + return output, status_code + + @authorize_teacher_of_project + def delete(self, project_id): + """ + Delete a project and all of its submissions in cascade + done by project id + """ + + return delete_by_id_from_model( + Project, + "project_id", + project_id, + RESPONSE_URL) diff --git a/backend/project/endpoints/projects/project_endpoint.py b/backend/project/endpoints/projects/project_endpoint.py new file mode 100644 index 00000000..2c9a09b9 --- /dev/null +++ b/backend/project/endpoints/projects/project_endpoint.py @@ -0,0 +1,45 @@ +""" +Module for providing the blueprint to the api +of both routes +""" + +from flask import Blueprint + +from project.endpoints.projects.projects import ProjectsEndpoint +from project.endpoints.projects.project_detail import ProjectDetail +from project.endpoints.projects.project_assignment_file import ProjectAssignmentFiles +from project.endpoints.projects.project_submissions_download import SubmissionDownload +from project.endpoints.projects.project_last_submission import SubmissionPerUser +from project.endpoints.projects.groups.groups import Groups + +project_bp = Blueprint('project_endpoint', __name__) + +project_bp.add_url_rule( + '/projects', + view_func=ProjectsEndpoint.as_view('project_endpoint') +) + +project_bp.add_url_rule( + '/projects/', + view_func=ProjectDetail.as_view('project_detail') +) + +project_bp.add_url_rule( + '/projects//assignment', + view_func=ProjectAssignmentFiles.as_view('project_assignment') +) + +project_bp.add_url_rule( + '/projects//submissions-download', + view_func=SubmissionDownload.as_view('project_submissions') +) + +project_bp.add_url_rule( + '/projects//latest-per-user', + view_func=SubmissionPerUser.as_view('latest_per_user') +) + +project_bp.add_url_rule( + '/projects//groups', + view_func=Groups.as_view('groups') +) diff --git a/backend/project/endpoints/projects/project_last_submission.py b/backend/project/endpoints/projects/project_last_submission.py new file mode 100644 index 00000000..6cd4e719 --- /dev/null +++ b/backend/project/endpoints/projects/project_last_submission.py @@ -0,0 +1,26 @@ +""" +This module gives the last submission for a project for every user +""" + +from os import getenv +from urllib.parse import urljoin +from flask_restful import Resource +from project.endpoints.projects.project_submissions_download import get_last_submissions_per_user +from project.utils.authentication import authorize_teacher_or_project_admin + +API_HOST = getenv("API_HOST") +UPLOAD_FOLDER = getenv("UPLOAD_FOLDER") +BASE_URL = urljoin(f"{API_HOST}/", "/projects") + +class SubmissionPerUser(Resource): + """ + Recourse to get all the submissions for users + """ + + @authorize_teacher_or_project_admin + def get(self, project_id: int): + """ + Download all submissions for a project as a zip file. + """ + + return get_last_submissions_per_user(project_id) diff --git a/backend/project/endpoints/projects/project_submissions_download.py b/backend/project/endpoints/projects/project_submissions_download.py new file mode 100644 index 00000000..31d8e80a --- /dev/null +++ b/backend/project/endpoints/projects/project_submissions_download.py @@ -0,0 +1,108 @@ +""" +This module contains the implementation of the endpoint that +allows teachers to download all relevant submissions for a project. +""" + +from os import getenv, path, walk +from urllib.parse import urljoin +import zipfile +import io +from flask_restful import Resource +from flask import Response, stream_with_context +from sqlalchemy import func +from sqlalchemy.exc import SQLAlchemyError +from project.models.project import Project +from project.models.submission import Submission +from project.db_in import db +from project.utils.authentication import authorize_teacher_or_project_admin + +API_HOST = getenv("API_HOST") +UPLOAD_FOLDER = getenv("UPLOAD_FOLDER") +BASE_URL = urljoin(f"{API_HOST}/", "/projects") + +def get_last_submissions_per_user(project_id): + """ + Get the last submissions per user for a given project + """ + try: + project = db.session.get(Project, project_id) + except SQLAlchemyError: + return {"message": "Internal server error"}, 500 + + if project is None: + return { + "message": f"Project (project_id={project_id}) not found", + "url": BASE_URL}, 404 + + # Define a subquery to find the latest submission times for each user + latest_submissions = db.session.query( + Submission.uid, + func.max(Submission.submission_time).label('max_time') + ).filter( + Submission.project_id == project_id, + Submission.submission_status != 'LATE' + ).group_by( + Submission.uid + ).subquery() + + # Use the subquery to fetch the actual submissions + submissions = db.session.query(Submission).join( + latest_submissions, + (Submission.uid == latest_submissions.c.uid) & + (Submission.submission_time == latest_submissions.c.max_time) + ).all() + + return {"message": "Resource fetched succesfully", "data": submissions}, 200 + +class SubmissionDownload(Resource): + """ + Resource to download all submissions for a project. + """ + + @authorize_teacher_or_project_admin + def get(self, project_id: int): + """ + Download all submissions for a project as a zip file. + """ + data, status_code = get_last_submissions_per_user(project_id) + + if status_code != 200: + return data, status_code + submissions = data["data"] + + def zip_directory_stream(): + with io.BytesIO() as memory_file: + with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zf: + for submission in submissions: + submission_path = path.join( + UPLOAD_FOLDER, + str(submission.project_id), + "submissions", + str(submission.submission_id)) + + # Directory in the zip should use uid instead of submission_id + zip_dir_path = path.join( + "submissions", + str(submission.uid)) + + # Walk through each directory and file, maintaining the structure + if path.exists(submission_path) and path.isdir(submission_path): + for dirname, _, files in walk(submission_path): + arcname_dir = dirname.replace(submission_path, zip_dir_path) + zf.write(dirname, arcname=arcname_dir) + for filename in files: + file_path = path.join(dirname, filename) + arcname_file = file_path.replace(submission_path, zip_dir_path) + zf.write(file_path, arcname=arcname_file) + + memory_file.seek(0) + + while True: + data = memory_file.read(4096) + if not data: + break + yield data + + response = Response(stream_with_context(zip_directory_stream()), mimetype='application/zip') + response.headers['Content-Disposition'] = 'attachment; filename="submissions.zip"' + return response diff --git a/backend/project/endpoints/projects/projects.py b/backend/project/endpoints/projects/projects.py new file mode 100644 index 00000000..03d46112 --- /dev/null +++ b/backend/project/endpoints/projects/projects.py @@ -0,0 +1,146 @@ +""" +Module that implements the /projects endpoint of the API +""" + +import os +from urllib.parse import urljoin +import zipfile + +from sqlalchemy import and_ +from sqlalchemy.exc import SQLAlchemyError +from flask import request, jsonify +from flask_restful import Resource + +from project.db_in import db +from project.models.project import Project, Runner +from project.models.course import Course +from project.models.course_relation import CourseStudent, CourseAdmin +from project.utils.query_agent import create_model_instance +from project.utils.authentication import login_required_return_uid, authorize_teacher +from project.endpoints.projects.endpoint_parser import parse_project_params +from project.utils.models.course_utils import is_teacher_of_course +from project.utils.models.project_utils import get_course_of_project + +API_URL = os.getenv('API_HOST') +UPLOAD_FOLDER = os.getenv("UPLOAD_FOLDER") + +class ProjectsEndpoint(Resource): + """ + Class for projects endpoints + Inherits from flask_restful.Resource class + for implementing get method + """ + + @login_required_return_uid + def get(self, uid=None): + """ + Get method for listing all available projects + that are currently in the API + """ + + data = { + "url": urljoin(f"{API_URL}/", "projects") + } + try: + # Get all the courses a user is part of + courses_student = CourseStudent.query.filter_by(uid=uid).\ + with_entities(CourseStudent.course_id).all() + courses = CourseAdmin.query.filter_by(uid=uid).\ + with_entities(CourseAdmin.course_id).all() + courses += Course.query.filter_by(teacher=uid).with_entities(Course.course_id).all() + courses = [c[0] for c in courses] # Remove the tuple wrapping the course_id + courses_student = [c[0] for c in courses_student] + # Filter the projects based on the query parameters + filters = dict(request.args) + conditions = [] + for key, value in filters.items(): + if key in Project.__table__.columns: + conditions.append(getattr(Project, key) == value) + + # Get the projects + projects = Project.query + projects = projects.filter(and_(*conditions)) if conditions else projects + projects = projects.all() + projects = [p for p in projects if get_course_of_project(p.project_id) in courses] + projects_student = Project.query.filter(Project.course_id.in_(courses_student)) + projects_student = projects_student.filter(and_(*conditions)) \ + if conditions else projects_student + projects_student = projects_student.all() + projects_student = [p for p in projects_student if p.visible_for_students] + projects += projects_student + + # Return the projects + data["message"] = "Successfully fetched the projects" + data["data"] = [{ + "project_id": urljoin(f"{API_URL}/", f"projects/{p.project_id}"), + "title": p.title, + "course_id": urljoin(f"{API_URL}/", f"courses/{p.course_id}") + } for p in projects] + return data + + except SQLAlchemyError: + data["message"] = "An error occurred while fetching the projects" + return data, 500 + + @authorize_teacher + def post(self, teacher_id=None): + """ + Post functionality for project + using flask_restfull parse lib + """ + project_json = parse_project_params() + + if not is_teacher_of_course(teacher_id, project_json["course_id"]): + return {"message":"You are not the teacher of this course"}, 403 + + filename = None + if "assignment_file" in request.files: + file = request.files["assignment_file"] + filename = os.path.basename(file.filename) + + # save the file that is given with the request + try: + new_project, status_code = create_model_instance( + Project, + project_json, + urljoin(f"{API_URL}/", "/projects"), + required_fields=[ + "title", + "description", + "course_id", + "visible_for_students", + "archived"] + ) + except SQLAlchemyError: + return jsonify({"error": "Something went wrong while inserting into the database.", + "url": f"{API_URL}/projects"}), 500 + + if status_code == 400: + return new_project, status_code + + project_upload_directory = os.path.join(f"{UPLOAD_FOLDER}", f"{new_project.project_id}") + os.makedirs(project_upload_directory, exist_ok=True) + if filename is not None: + try: + file_path = os.path.join(project_upload_directory, filename) + file.save(file_path) + with zipfile.ZipFile(file_path) as upload_zip: + upload_zip.extractall(project_upload_directory) + + if not new_project.runner and \ + os.path.exists(os.path.join(project_upload_directory, "Dockerfile")): + + new_project.runner = Runner.CUSTOM + except zipfile.BadZipfile: + os.remove(os.path.join(project_upload_directory, filename)) + db.session.rollback() + return ({ + "message": "Please provide a .zip file for uploading the instructions", + "url": f"{API_URL}/projects" + }, + 400) + return { + "message": "Project created succesfully", + "data": new_project, + "url": f"{API_URL}/projects/{new_project.project_id}" + }, 201 diff --git a/backend/project/endpoints/submissions/submission_config.py b/backend/project/endpoints/submissions/submission_config.py new file mode 100644 index 00000000..c17395ad --- /dev/null +++ b/backend/project/endpoints/submissions/submission_config.py @@ -0,0 +1,22 @@ +""" +This module is responsible for creating the submissions blueprint and +adding the submission endpoints to it. +""" + +from flask import Blueprint +from project.endpoints.submissions.submissions import SubmissionsEndpoint +from project.endpoints.submissions.submission_detail import SubmissionEndpoint +from project.endpoints.submissions.submission_download import SubmissionDownload + +submissions_bp = Blueprint("submissions", __name__) + + +submissions_bp.add_url_rule("/submissions", view_func=SubmissionsEndpoint.as_view("submissions")) +submissions_bp.add_url_rule( + "/submissions/", + view_func=SubmissionEndpoint.as_view("submission") +) +submissions_bp.add_url_rule( + "/submissions//download", + view_func=SubmissionDownload.as_view("submission_download") +) diff --git a/backend/project/endpoints/submissions/submission_detail.py b/backend/project/endpoints/submissions/submission_detail.py new file mode 100644 index 00000000..8574cfb3 --- /dev/null +++ b/backend/project/endpoints/submissions/submission_detail.py @@ -0,0 +1,119 @@ +""" +This module contains the API endpoint for the submission detail +""" + +from os import getenv +from urllib.parse import urljoin +from flask import request +from flask_restful import Resource +from sqlalchemy import exc +from project.db_in import db +from project.models.submission import Submission +from project.utils.models.submission_utils import submission_response +from project.utils.authentication import ( + authorize_submission_request, + authorize_grader +) + +API_HOST = getenv("API_HOST") +UPLOAD_FOLDER = getenv("UPLOAD_FOLDER") +BASE_URL = urljoin(f"{API_HOST}/", "/submissions") + +class SubmissionEndpoint(Resource): + """API endpoint for the submission""" + + @authorize_submission_request + def get(self, submission_id: int) -> dict[str, any]: + """Get the submission given an submission ID + + Args: + submission_id (int): Submission ID + + Returns: + dict[str, any]: The submission + """ + + data = { + "url": urljoin(f"{BASE_URL}/", str(submission_id)) + } + try: + with db.session() as session: + submission = session.get(Submission, submission_id) + if submission is None: + data["url"] = urljoin(f"{API_HOST}/", "/submissions") + data["message"] = f"Submission (submission_id={submission_id}) not found" + return data, 404 + + return { + "data": { + "submission_id": urljoin(f"{BASE_URL}/", str(submission.submission_id)), + "uid": urljoin(f"{API_HOST}/", f"/users/{str(submission.uid)}"), + "project_id": urljoin( + f"{API_HOST}/", + f"/projects/{str(submission.project_id)}"), + "grading": submission.grading, + "submission_time": submission.submission_time, + "submission_status": submission.submission_status + }, + "message": "Successfully fetched the submission", + "url": urljoin(f"{BASE_URL}/", str(submission.submission_id)) + }, 200 + + except exc.SQLAlchemyError: + data["message"] = \ + f"An error occurred while fetching the submission (submission_id={submission_id})" + return data, 500 + + @authorize_grader + def patch(self, submission_id:int) -> dict[str, any]: + """Update some fields of a submission given a submission ID + + Args: + submission_id (int): Submission ID + + Returns: + dict[str, any]: A message + """ + + data = { + "url": urljoin(f"{BASE_URL}/", str(submission_id)) + } + try: + with db.session() as session: + # Get the submission + submission = session.get(Submission, submission_id) + if submission is None: + data["url"] = urljoin(f"{API_HOST}/", "/submissions") + data["message"] = f"Submission (submission_id={submission_id}) not found" + return data, 404 + + # Update the grading field + if set(request.form.keys()) - {"grading"}: + data["message"] = "Invalid data field given, only 'grading' is allowed" + return data, 400 + + grading = request.form.get("grading") + if grading is not None: + try: + grading_float = float(grading) + if 0 <= grading_float <= 20: + submission.grading = grading_float + else: + data["message"] = "Invalid grading (grading=0-20)" + return data, 400 + except ValueError: + data["message"] = "Invalid grading (not a valid float)" + return data, 400 + + # Save the submission + session.commit() + data["message"] = f"Submission (submission_id={submission_id}) patched" + data["url"] = urljoin(f"{BASE_URL}/", str(submission.submission_id)) + data["data"] = submission_response(submission, API_HOST) + return data, 200 + + except exc.SQLAlchemyError: + session.rollback() + data["message"] = \ + f"An error occurred while patching submission (submission_id={submission_id})" + return data, 500 diff --git a/backend/project/endpoints/submissions/submission_download.py b/backend/project/endpoints/submissions/submission_download.py new file mode 100644 index 00000000..25186c11 --- /dev/null +++ b/backend/project/endpoints/submissions/submission_download.py @@ -0,0 +1,62 @@ +""" +This module contains the endpoint for downloading a submission. +""" + +import zipfile +import io +from os import getenv, path, walk +from urllib.parse import urljoin +from flask import Response, stream_with_context +from flask_restful import Resource +from project.models.submission import Submission +from project.utils.authentication import authorize_submission_request +from project.db_in import db + +API_HOST = getenv("API_HOST") +UPLOAD_FOLDER = getenv("UPLOAD_FOLDER") +BASE_URL = urljoin(f"{API_HOST}/", "/submissions") + +class SubmissionDownload(Resource): + """ + Resource to download a submission. + """ + @authorize_submission_request + def get(self, submission_id: int): + """ + Download a submission as a zip file. + """ + submission = db.session.get(Submission, submission_id) + if submission is None: + return { + "message": f"Submission (submission_id={submission_id}) not found", + "url": BASE_URL}, 404 + + submission_path = path.join( + UPLOAD_FOLDER, + str(submission.project_id), + "submissions", + str(submission_id)) + + if not path.exists(submission_path) or not path.isdir(submission_path): + return {"message": "Submission directory not found", "url": BASE_URL}, 404 + + def zip_directory_stream(): + with io.BytesIO() as memory_file: + with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zf: + + for dirname, _, files in walk(submission_path): + zf.write(dirname, path.relpath(dirname, start=submission_path)) + for filename in files: + file_path = path.join(dirname, filename) + zf.write(file_path, path.relpath(file_path, start=submission_path)) + + memory_file.seek(0) + data = memory_file.read(4096) + while data: + yield data + data = memory_file.read(4096) + + response = Response(stream_with_context(zip_directory_stream()), mimetype='application/zip') + response.headers['Content-Disposition'] = \ + f'attachment; filename="submission_{submission_id}.zip"' + return response diff --git a/backend/project/endpoints/submissions/submissions.py b/backend/project/endpoints/submissions/submissions.py new file mode 100644 index 00000000..b03490fe --- /dev/null +++ b/backend/project/endpoints/submissions/submissions.py @@ -0,0 +1,206 @@ +""" +This module contains the API endpoint for the submissions +""" + +from os import path, makedirs, getenv +from urllib.parse import urljoin +from datetime import datetime +from zoneinfo import ZoneInfo +from shutil import rmtree +import zipfile +from flask import request +from flask_restful import Resource +from sqlalchemy import exc, and_ +from project.executor import executor +from project.db_in import db +from project.models.submission import Submission, SubmissionStatus +from project.models.project import Project +from project.models.course import Course +from project.models.course_relation import CourseAdmin +from project.utils.files import all_files_uploaded +from project.utils.project import is_valid_project +from project.utils.authentication import authorize_student_submission, login_required_return_uid +from project.utils.submissions.evaluator import run_evaluator +from project.utils.models.project_utils import get_course_of_project +from project.utils.models.submission_utils import submission_response + +API_HOST = getenv("API_HOST") +UPLOAD_FOLDER = getenv("UPLOAD_FOLDER") +BASE_URL = urljoin(f"{API_HOST}/", "/submissions") +TIMEZONE = getenv("TIMEZONE", "GMT") + +class SubmissionsEndpoint(Resource): + """API endpoint for the submissions""" + + @login_required_return_uid + def get(self, uid=None) -> dict[str, any]: + """Get all the submissions from a user + + Returns: + dict[str, any]: The list of submission URLs + """ + + data = { + "url": BASE_URL + } + filters = dict(request.args) + + try: + # Check the uid query parameter + user_id = filters.get("uid") + if user_id and not isinstance(user_id, str): + data["message"] = f"Invalid user (uid={user_id})" + return data, 400 + + # Check the project_id query parameter + project_id = filters.get("project_id") + if project_id: + if not project_id.isdigit(): + data["message"] = f"Invalid project (project_id={project_id})" + return data, 400 + filters["project_id"] = int(project_id) + + filters = { + key: value for key, value + in filters.items() + if key in Submission.__table__.columns + } + + # Get the courses + courses = Course.query.filter_by(teacher=uid).\ + with_entities(Course.course_id).all() + courses += CourseAdmin.query.filter_by(uid=uid).\ + with_entities(CourseAdmin.course_id).all() + courses = [c[0] for c in courses] # Remove the tuple wrapping the course_id + + # Filter the courses based on the query parameters + conditions = [] + for key, value in filters.items(): + if key in Submission.__table__.columns: + conditions.append(getattr(Submission, key) == value) + + # Get the submissions + submissions = Submission.query + submissions = submissions.filter(and_(*conditions)) if conditions else submissions + submissions = submissions.all() + submissions = [ + s for s in submissions if + s.uid == uid or get_course_of_project(s.project_id) in courses + ] + + # Return the submissions + data["message"] = "Successfully fetched the submissions" + data["data"] = [{ + "submission_id": urljoin(f"{API_HOST}/", f"/submissions/{s.submission_id}"), + "uid": urljoin(f"{API_HOST}/", f"users/{s.uid}"), + "project_id": urljoin(f"{API_HOST}/", f"projects/{s.project_id}"), + "grading": s.grading, + "submission_time": s.submission_time, + "submission_status": s.submission_status + } for s in submissions] + return data + + except exc.SQLAlchemyError: + data["message"] = "An error occurred while fetching the submissions" + return data, 500 + + @authorize_student_submission + def post(self, uid=None) -> dict[str, any]: # pylint: disable=too-many-locals, too-many-branches, too-many-statements + """Post a new submission to a project + + Returns: + dict[str, any]: The URL to the submission + """ + + data = { + "url": BASE_URL + } + try: + if set(request.form.keys()) - {"project_id", "files"}: + data["message"] = "Invalid data fields, only 'project_id' and 'files' are allowed" + return data, 400 + + with db.session() as session: + submission = Submission() + + # User + submission.uid = uid + + # Project + project_id = request.form.get("project_id") + valid, message = is_valid_project(session, project_id) + if not valid: + data["message"] = message + return data, 400 + submission.project_id = int(project_id) + + # Submission time + submission.submission_time = datetime.now(ZoneInfo(TIMEZONE)) + + # Submission files + submission.submission_path = "" # Must be set on creation + files = request.files.getlist("files") + + # Check files otherwise stop + project = session.get(Project, submission.project_id) + if project.regex_expressions and \ + (not files or not all_files_uploaded(files, project.regex_expressions)): + data["message"] = "No files were uploaded" if not files else \ + "Not all required files were uploaded " \ + f"(required files={','.join(project.regex_expressions)})" + return data, 400 + + deadlines = project.deadlines + is_late = deadlines is not None + if deadlines: + for deadline in deadlines: + if submission.submission_time < deadline.deadline: + is_late = False + + if project.runner: + submission.submission_status = SubmissionStatus.RUNNING + else: + submission.submission_status = SubmissionStatus.LATE if is_late \ + else SubmissionStatus.SUCCESS + + # Submission_id needed for the file location + session.add(submission) + session.commit() + + # Save the files + submission.submission_path = path.join(UPLOAD_FOLDER, str(submission.project_id), + "submissions", str(submission.submission_id)) + try: + makedirs(submission.submission_path, exist_ok=True) + input_folder = path.join(submission.submission_path, "submission") + makedirs(input_folder, exist_ok=True) + for file in files: + file_path = path.join(input_folder, file.filename) + file.save(file_path) + if file.filename.endswith(".zip"): + with zipfile.ZipFile(file_path) as upload_zip: + upload_zip.extractall(input_folder) + + + except OSError: + rmtree(submission.submission_path) + session.rollback() + + if project.runner: + submission.submission_status = SubmissionStatus.RUNNING + executor.submit( + run_evaluator, + submission, + path.join(UPLOAD_FOLDER, str(project.project_id)), + project.runner.value, + False) + + data["message"] = "Successfully fetched the submissions" + data["url"] = urljoin(f"{API_HOST}/", f"/submissions/{submission.submission_id}") + data["data"] = submission_response(submission, API_HOST) + return data, 201 + + except exc.SQLAlchemyError: + session.rollback() + data["message"] = "An error occurred while creating a new submission" + return data, 500 diff --git a/backend/project/endpoints/users.py b/backend/project/endpoints/users.py new file mode 100644 index 00000000..cf5e054a --- /dev/null +++ b/backend/project/endpoints/users.py @@ -0,0 +1,161 @@ +"""Users api endpoint""" +from os import getenv + +from dotenv import load_dotenv +from flask import Blueprint, request, jsonify +from flask_restful import Resource, Api +from sqlalchemy.exc import SQLAlchemyError + +from project import db +from project.models.user import User as userModel, Role +from project.utils.authentication import login_required, authorize_user, \ + authorize_admin, not_allowed + +users_bp = Blueprint("users", __name__) +users_api = Api(users_bp) + +load_dotenv() +API_URL = getenv("API_HOST") + + +class Users(Resource): + """Api endpoint for the /users route""" + + @login_required + def get(self): + """ + This function will respond to get requests made to /users. + It should return all users from the database. + """ + try: + query = userModel.query + role = request.args.get("role") + if role is not None: + role = Role[role.upper()] + query = query.filter(userModel.role == role) + + uid = request.args.getlist("uid") + if len(uid) > 0: + query = query.filter(userModel.uid.in_(uid)) + + users = query.all() + users = [user.to_dict() for user in users] + + result = jsonify({"message": "Queried all users", "data": users, + "url":f"{API_URL}/users", "status_code": 200}) + return result + except SQLAlchemyError: + return {"message": "An error occurred while fetching the users", + "url": f"{API_URL}/users"}, 500 + + @not_allowed + def post(self): + """ + This function will respond to post requests made to /users. + It should create a new user and return a success message. + """ + uid = request.json.get('uid') + role = request.json.get("role") + role = Role[role.upper()] if role is not None else None + url = f"{API_URL}/users" + + if role is None or uid is None: + return { + "message": "Invalid request data!", + "correct_format": { + "uid": "User ID (string)", + "role": "User role (string)" + },"url": f"{API_URL}/users" + }, 400 + try: + user = db.session.get(userModel, uid) + if user is not None: + # Bad request, error code could be 409 but is rarely used + return {"message": f"User {uid} already exists"}, 400 + # Code to create a new user in the database using the uid and role + new_user = userModel(uid=uid, role=role) + db.session.add(new_user) + db.session.commit() + return jsonify({"message": "User created successfully!", + "data": user, "url": f"{url}/{user.uid}", "status_code": 201}) + + except SQLAlchemyError: + db.session.rollback() + return {"message": "An error occurred while creating the user", + "url": url}, 500 + + +class User(Resource): + """Api endpoint for the /users/{user_id} route""" + + @login_required + def get(self, user_id): + """ + This function will respond to GET requests made to /users/. + It should return the user with the given user_id from the database. + """ + try: + user = db.session.get(userModel, user_id) + if user is None: + return {"message": "User not found!","url": f"{API_URL}/users"}, 404 + + return jsonify({"message": "User queried","data":user.to_dict(), + "url": f"{API_URL}/users/{user.uid}", "status_code": 200}) + except SQLAlchemyError: + return {"message": "An error occurred while fetching the user", + "url": f"{API_URL}/users"}, 500 + + @authorize_admin + def patch(self, user_id): + """ + Update the user's information. + + Returns: + dict: A dictionary containing the message indicating the success + or failure of the update. + """ + role = request.json.get("role") + role = Role[role.upper()] if role is not None else None + try: + user = db.session.get(userModel, user_id) + if user is None: + return {"message": "User not found!","url": f"{API_URL}/users"}, 404 + + if role is not None: + user.role = role + + # Save the changes to the database + db.session.commit() + return jsonify({"message": "User updated successfully!", + "data": user.to_dict(), + "url": f"{API_URL}/users/{user.uid}", "status_code": 200}) + except SQLAlchemyError: + # every exception should result in a rollback + db.session.rollback() + return {"message": "An error occurred while patching the user", + "url": f"{API_URL}/users"}, 500 + + + @authorize_user + def delete(self, user_id): + """ + This function will respond to DELETE requests made to /users/. + It should delete the user with the given user_id from the database. + """ + try: + user = db.session.get(userModel, user_id) + if user is None: + return {"message": "User not found!", "url": f"{API_URL}/users"}, 404 + + db.session.delete(user) + db.session.commit() + return {"message": "User deleted successfully!", "url": f"{API_URL}/users"}, 200 + except SQLAlchemyError: + # every exception should result in a rollback + db.session.rollback() + return {"message": "An error occurred while deleting the user", + "url": f"{API_URL}/users"}, 500 + + +users_api.add_resource(Users, "/users") +users_api.add_resource(User, "/users/") diff --git a/backend/project/executor.py b/backend/project/executor.py new file mode 100644 index 00000000..12405d1e --- /dev/null +++ b/backend/project/executor.py @@ -0,0 +1,9 @@ +""" +This file is used to create an instance of the Executor class from the flask_executor package. +This instance is used to create a background task that will run the evaluator. +This is done to prevent the server from being blocked while the model is being trained. +""" + +from flask_executor import Executor + +executor = Executor() diff --git a/backend/project/init_auth.py b/backend/project/init_auth.py new file mode 100644 index 00000000..d2d6adf8 --- /dev/null +++ b/backend/project/init_auth.py @@ -0,0 +1,60 @@ +""" This file will change the JWT return messages to custom messages + and make it so the access tokens implicitly refresh +""" +from datetime import timedelta, timezone, datetime + +from flask_jwt_extended import get_jwt, get_jwt_identity,\ + create_access_token, set_access_cookies +from .utils.models.user_utils import get_user +from .models.user import Role + +def auth_init(jwt, app): + """ + This function will overwrite the default return messages from + the flask-jwt-extended package with custom messages + and make it so the access tokens implicitly refresh + """ + @jwt.expired_token_loader + def expired_token_callback(jwt_header, jwt_payload): + return ( + {"message":"Your access token cookie has expired, please log in again"}, + 401) + + @jwt.invalid_token_loader + def invalid_token_callback(jwt_header): + return ( + {"message":("The server cannot recognize this access token cookie, " + "please log in again if you think this is an error")}, + 401) + + @jwt.revoked_token_loader + def revoked_token_callback(jwt_header, jwt_payload): + return ( + {"message":("This access token cookie has been revoked, " + "possibly from logging out. Log in again to receive a new access token")}, + 401) + + @jwt.unauthorized_loader + def unauthorized_callback(jwt_header): + return {"message":"You need an access token to get this data, please log in"}, 401 + + @app.after_request + def refresh_expiring_jwts(response): + try: + exp_timestamp = get_jwt()["exp"] + now = datetime.now(timezone.utc) + target_timestamp = datetime.timestamp(now + timedelta(minutes=30)) + if target_timestamp > exp_timestamp: + uid = get_jwt_identity() + user = get_user(uid) + access_token = create_access_token( + identity=uid, + additional_claims= + {"is_admin":user.role==Role.ADMIN, + "is_teacher":user.role==Role.TEACHER} + ) + set_access_cookies(response, access_token) + return response + except (RuntimeError, KeyError): + # Case where there is not a valid JWT. Just return the original response + return response diff --git a/backend/project/models/__init__.py b/backend/project/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/project/models/course.py b/backend/project/models/course.py new file mode 100644 index 00000000..09b37e5a --- /dev/null +++ b/backend/project/models/course.py @@ -0,0 +1,16 @@ +"""The Course model""" + +from dataclasses import dataclass +from sqlalchemy import Integer, Column, ForeignKey, String +from project.db_in import db + +@dataclass +class Course(db.Model): + """This class described the courses table, + a course has an id, name, optional ufora id and the teacher that created it""" + + __tablename__ = "courses" + course_id: int = Column(Integer, primary_key=True) + name: str = Column(String(50), nullable=False) + ufora_id: str = Column(String(50), nullable=True) + teacher: str = Column(String(255), ForeignKey("users.uid"), nullable=False) diff --git a/backend/project/models/course_relation.py b/backend/project/models/course_relation.py new file mode 100644 index 00000000..e4313ab1 --- /dev/null +++ b/backend/project/models/course_relation.py @@ -0,0 +1,27 @@ +"""Course relation model""" + +from dataclasses import dataclass +from sqlalchemy import Integer, Column, ForeignKey, String +from project.db_in import db + +@dataclass +class BaseCourseRelation(db.Model): + """Base class for course relation models, + both course relation tables have a + course_id of the course to wich someone is related and + an uid of the related person""" + + __abstract__ = True + + course_id: int = Column(Integer, ForeignKey('courses.course_id'), primary_key=True) + uid: str = Column(String(255), ForeignKey("users.uid"), primary_key=True) + +class CourseAdmin(BaseCourseRelation): + """Admin to course relation model""" + + __tablename__ = "course_admins" + +class CourseStudent(BaseCourseRelation): + """Student to course relation model""" + + __tablename__ = "course_students" diff --git a/backend/project/models/course_share_code.py b/backend/project/models/course_share_code.py new file mode 100644 index 00000000..67fbad92 --- /dev/null +++ b/backend/project/models/course_share_code.py @@ -0,0 +1,22 @@ +""" +Course Share Code Model +""" + + +from dataclasses import dataclass +import uuid +from sqlalchemy import Integer, Column, ForeignKey, Date, Boolean +from sqlalchemy.dialects.postgresql import UUID +from project import db + +@dataclass +class CourseShareCode(db.Model): + """ + This class will contain the model for the course share codes + """ + __tablename__ = "course_join_codes" + + join_code: int = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + course_id: int = Column(Integer, ForeignKey("courses.course_id"), nullable=False) + expiry_time: str = Column(Date, nullable=True) + for_admins: bool = Column(Boolean, nullable=False) diff --git a/backend/project/models/group.py b/backend/project/models/group.py new file mode 100644 index 00000000..fca8060f --- /dev/null +++ b/backend/project/models/group.py @@ -0,0 +1,17 @@ +"""Group model""" +from dataclasses import dataclass +from sqlalchemy import Integer, Column, ForeignKey +from project import db + + +@dataclass +class Group(db.Model): + """ + This class will contain the model for the groups + """ + __tablename__ = "groups" + + group_id: int = Column(Integer, autoincrement=True, primary_key=True) + project_id: int = Column(Integer, ForeignKey( + "projects.project_id"), autoincrement=False, primary_key=True) + group_size: int = Column(Integer, nullable=False) diff --git a/backend/project/models/group_student.py b/backend/project/models/group_student.py new file mode 100644 index 00000000..57a337a2 --- /dev/null +++ b/backend/project/models/group_student.py @@ -0,0 +1,13 @@ +"""Model for relation between groups and students""" +from dataclasses import dataclass +from sqlalchemy import Integer, Column, ForeignKey, String +from project.db_in import db + +@dataclass +class GroupStudent(db.Model): + """Model for relation between groups and students""" + __tablename__ = "group_students" + + uid: str = Column(String(255), ForeignKey("users.uid"), primary_key=True) + group_id: int = Column(Integer, ForeignKey("groups.group_id"), primary_key=True) + project_id: int = Column(Integer, ForeignKey("groups.project_id"), primary_key=True) diff --git a/backend/project/models/project.py b/backend/project/models/project.py new file mode 100644 index 00000000..788864b0 --- /dev/null +++ b/backend/project/models/project.py @@ -0,0 +1,62 @@ +"""Project model""" + +from dataclasses import dataclass +from enum import Enum +from sqlalchemy import ( + ARRAY, + Boolean, + Column, + DateTime, + ForeignKey, + Integer, + String, + Text, + Enum as EnumField) + +from sqlalchemy_utils import CompositeType +from project.db_in import db + +class Runner(str, Enum): + """Enum for Runner""" + PYTHON = 'PYTHON' + GENERAL = 'GENERAL' + CUSTOM = 'CUSTOM' + +@dataclass +class Project(db.Model): # pylint: disable=too-many-instance-attributes + """This class describes the projects table, + a projects has an id, a title, a description, + an optional assignment file that can contain more explanation of the projects, + an optional deadline, + the course id of the course to which the project belongs, + visible for students variable so a teacher can decide if the students can see it yet, + archived var so we can implement the archiving functionality, + a test path,script name and regex expressions for automated testing + + Pylint disable too many instance attributes because we can't reduce the amount + of fields of the model + """ + + __tablename__ = "projects" + project_id: int = Column(Integer, primary_key=True) + title: str = Column(String(50), nullable=False, unique=False) + description: str = Column(Text, nullable=False) + deadlines: list = Column(ARRAY( + CompositeType( + "deadline", + [ + Column("description", Text), + Column("deadline", DateTime(timezone=True)) + ] + ), + dimensions=1 + ) + ) + course_id: int = Column(Integer, ForeignKey("courses.course_id"), nullable=False) + visible_for_students: bool = Column(Boolean, nullable=False) + archived: bool = Column(Boolean, nullable=False) + groups_locked: bool = Column(Boolean) + runner: Runner = Column( + EnumField(Runner, name="runner"), + nullable=False) + regex_expressions: list[str] = Column(ARRAY(String(50))) diff --git a/backend/project/models/submission.py b/backend/project/models/submission.py new file mode 100644 index 00000000..1587f80f --- /dev/null +++ b/backend/project/models/submission.py @@ -0,0 +1,44 @@ +"""Submission model""" + +from dataclasses import dataclass +from enum import Enum +from sqlalchemy import ( + Column, + String, + ForeignKey, + Integer, + CheckConstraint, + DateTime, + Float, + Enum as EnumField) +from project.db_in import db + +class SubmissionStatus(str, Enum): + """Enum for submission status""" + SUCCESS = 'SUCCESS' + LATE = 'LATE' + FAIL = 'FAIL' + RUNNING = 'RUNNING' + +@dataclass +class Submission(db.Model): + """This class describes the submissions table, + submissions can be made to a project, a submission has + and id, a uid from the user that uploaded it, + the project id of the related project, + an optional grading, + the submission time, + submission path, + and finally the submission status + so we can easily present in a list which submission succeeded the automated checks""" + + __tablename__ = "submissions" + submission_id: int = Column(Integer, primary_key=True) + uid: str = Column(String(255), ForeignKey("users.uid"), nullable=False) + project_id: int = Column(Integer, ForeignKey("projects.project_id"), nullable=False) + grading: float = Column(Float, CheckConstraint("grading >= 0 AND grading <= 20")) + submission_time: DateTime = Column(DateTime(timezone=True), nullable=False) + submission_path: str = Column(String(50), nullable=False) + submission_status: SubmissionStatus = Column( + EnumField(SubmissionStatus, name="submission_status"), + nullable=False) diff --git a/backend/project/models/user.py b/backend/project/models/user.py new file mode 100644 index 00000000..4f03874e --- /dev/null +++ b/backend/project/models/user.py @@ -0,0 +1,35 @@ +"""User model""" + +from enum import Enum +from dataclasses import dataclass +from sqlalchemy import Column, String, Enum as EnumField +from project.db_in import db + +class Role(Enum): + """This class defines the roles of a user""" + STUDENT = 0 + TEACHER = 1 + ADMIN = 2 + +@dataclass +class User(db.Model): + """ + This class defines the users table + a user has a uid, + a display_name and a role, + this role can be either student, admin or teacher + """ + + __tablename__ = "users" + uid: str = Column(String(255), primary_key=True) + display_name: str = Column(String(255)) + role: Role = Column(EnumField(Role), nullable=False) + def to_dict(self): + """ + Converts a User to a serializable dict + """ + return { + 'uid': self.uid, + 'display_name': self.display_name, + 'role': self.role.name # Convert the enum to a string + } diff --git a/backend/project/sessionmaker.py b/backend/project/sessionmaker.py new file mode 100644 index 00000000..0ab68f8e --- /dev/null +++ b/backend/project/sessionmaker.py @@ -0,0 +1,15 @@ +"""initialise a datab session""" +from os import getenv +from sqlalchemy import create_engine, URL +from sqlalchemy.orm import sessionmaker + +url = URL.create( + drivername="postgresql", + username=getenv("POSTGRES_USER"), + password=getenv("POSTGRES_PASSWORD"), + host=getenv("POSTGRES_HOST"), + database=getenv("POSTGRES_DB") +) + +engine = create_engine(url) +Session = sessionmaker(bind=engine) diff --git a/backend/project/static/OpenAPI_Object.yaml b/backend/project/static/OpenAPI_Object.yaml new file mode 100644 index 00000000..6b049c98 --- /dev/null +++ b/backend/project/static/OpenAPI_Object.yaml @@ -0,0 +1,1333 @@ +--- +openapi: 3.0.1 +info: + title: Pigeonhole API + summary: A project submission and grading API for University Ghent students and + professors. + description: The API built for the Pigeonhole application. It serves as an interface + for student of University Ghent. They can submit solutions to projects created + by their professors. Professors and their assistents can then review these submitions, + grade them and define custom tests that automatically run on every submition. + The API is built using the OpenAPI 3.1.0 specification. + version: 1.0.0 + contact: + name: Project discussion forum + url: https://github.com/SELab-2/UGent-opgave/discussions + email: Bart.Coppens@UGent.be + x-authors: + - name: Aron Buzogany + github: https://github.com/AronBuzogany + - name: Gerwoud Van den Eynden + github: https://github.com/Gerwoud + - name: Jarne Clauw + github: https://github.com/JarneClauw + - name: Siebe Vlietinck + github: https://github.com/Vucis + - name: Warre Provoost + github: https://github.com/warreprovoost + - name: Cedric Mekeirle + github: https://github.com/JibrilExe + - name: Matisse Sulzer + github: https://github.com/Matisse-Sulzer +paths: + "/projects": + get: + description: Returns all projects from the database that the user has access + to + responses: + '200': + description: A list of projects + content: + application/json: + schema: + type: array + items: + type: object + properties: + project_id: + type: integer + description: + type: string + title: + type: string + example: + - project_id: 1 + description: Project 1 description + title: Project 1 + - project_id: 2 + description: Project 2 description + title: Project 2 + '500': + description: Internal Server Error + post: + description: Upload a new project + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + assignment_file: + type: string + format: binary + title: + type: string + description: + type: string + course_id: + type: integer + visible_for_students: + type: boolean + archived: + type: boolean + required: + - assignment_file + - title + - description + - course_id + - visible_for_students + - archived + responses: + '201': + description: Project created successfully + content: + application/json: + schema: + type: object + properties: + message: + type: string + data: + type: object + url: + type: string + '400': + description: Bad formatted request for uploading a project + content: + application/json: + schema: + type: object + properties: + message: + type: string + url: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/projects/{project_id}": + get: + description: Return a project with corresponding id + parameters: + - name: project_id + in: path + description: ID of the project to retrieve + required: true + schema: + type: integer + responses: + '200': + description: Project details retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Project' + '404': + description: An id that doesn't correspond to an existing project + content: + application/json: + schema: + type: object + properties: + data: + type: object + message: + type: string + url: + type: string + '500': + $ref: '#/components/responses/InternalError' + patch: + description: Patch certain fields of a project + parameters: + - name: id + in: path + description: ID of the project to retrieve + required: true + schema: + type: integer + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + assignment_file: + type: string + format: binary + title: + type: string + description: + type: string + course_id: + type: integer + visible_for_students: + type: boolean + archived: + type: boolean + responses: + '200': + description: Patched a project succesfully + content: + application/json: + schema: + type: object + properties: + data: + type: object + message: + type: string + url: + type: string + '404': + description: Tried to patch a project that is not present + content: + application/json: + schema: + type: object + properties: + message: + type: string + url: + type: string + '500': + $ref: '#/components/responses/InternalError' + delete: + description: Delete a project with corresponding project id and all of its submissions in cascade + parameters: + - name: id + in: path + description: ID of the project to retrieve + required: true + schema: + type: integer + responses: + '200': + description: Project deleted successfully + content: + application/json: + schema: + type: object + properties: + message: + type: string + url: + type: string + '404': + description: Tried to remove a project that is not present + content: + application/json: + schema: + type: object + properties: + error: + type: string + url: + type: string + "/projects/{id}/assignments": + get: + description: Get the assignment files of project with given id + parameters: + - name: project_id + in: path + description: ID of the project to retrieve + required: true + schema: + type: integer + responses: + '200': + description: Successfully downloaded the assignment files of the project + content: + multipart/form-data: + schema: + type: string + format: binary + '404': + description: The project of which you wanted to get the assignment files of doesn't exist + '500': + $ref: '#/components/responses/InternalError' + "/courses": + get: + description: Get a list of all courses. + responses: + '200': + description: Successfully retrieved all courses with given parameters + content: + application/json: + schema: + type: object + properties: + message: + type: string + data: + type: array + items: + type: object + properties: + course_id: + type: integer + name: + type: string + ufora_id: + type: string + teacher: + type: string + url: + type: string + url: + type: string + '500': + $ref: '#/components/responses/InternalError' + parameters: + - name: name + in: query + description: Name of the course + schema: + type: string + - name: ufora_id + in: query + description: Ufora ID of the course + schema: + type: string + - name: teacher + in: query + description: Teacher of the course + schema: + type: string + post: + description: Create a new course. + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the course + teacher: + type: string + description: Teacher of the course + required: + - name + - teacher + parameters: + - name: uid + in: query + description: uid of the user sending the request + schema: + type: string + responses: + '201': + description: 'Course with name: {name} and course_id: {course_id} was successfully + created' + content: + application/json: + schema: + type: object + properties: + message: + type: string + data: + type: object + properties: + course_id: + type: string + name: + type: string + teacher: + type: string + ufora_id: + type: string + url: + type: string + '400': + description: There was no uid in the request query. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: The user trying to create a course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: The user trying to create a course was not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/courses/{course_id}": + get: + description: Get a course by its ID. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + responses: + '200': + $ref: '#/components/schemas/Course' + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + delete: + description: Delete a course by its ID. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + responses: + '204': + description: Course deleted. + content: + application/json: + schema: + type: object + properties: + message: + type: string + examples: + - 'Successfully deleted course with course_id: {course_id}' + url: + type: string + examples: + - "{API_URL}/courses" + '403': + description: The user trying to delete the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + patch: + description: Update the course with given ID. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: Name of the course + teacher: + type: string + description: Teacher of the course + ufora_id: + type: string + description: Ufora ID of the course + responses: + '200': + description: Course updated. + content: + application/json: + schema: + type: object + properties: + message: + type: string + url: + type: string + data: + type: object + properties: + course_id: + type: string + name: + type: string + teacher: + type: string + ufora_id: + type: string + '403': + description: The user trying to update the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/courses/{course_id}/students": + get: + description: Get a list of all students in a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + responses: + '200': + description: Successfully retrieved all students of course. + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: string + url: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + post: + description: Assign students to a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + - name: students + in: body + description: List of uids of the students to be assigned to the course + required: true + schema: + type: array + - name: uid + in: query + description: Uid of the user sending the request + schema: + type: string + responses: + '201': + description: Students assigned to course. + content: + application/json: + schema: + type: object + properties: + message: + type: string + examples: + - User was succesfully added to the course + url: + type: string + examples: + - http://api.example.com/courses/123/students + data: + type: object + properties: + students: + type: array + items: + type: string + examples: + - http://api.example.com/users/123 + '400': + description: There was no uid in the request query. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: The user trying to assign students to the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + delete: + description: Remove students from a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + - name: students + in: body + description: List of uids of the students to be removed from the course + required: true + schema: + type: array + - name: uid + in: query + description: Uid of the user sending the request + schema: + type: string + responses: + '204': + description: Students removed from course. + content: + application/json: + schema: + type: object + properties: + message: + type: string + examples: User was succesfully removed from the course + url: + type: string + examples: + - API_URL + /courses/ + str(course_id) + /students + '400': + description: There was no uid in the request query. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: The user trying to remove students from the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/courses/{course_id}/admins": + get: + description: Get a list of all admins in a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + responses: + '200': + $ref: '#/components/schemas/Course' + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + post: + description: Assign admins to a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + - name: admin_uid + in: body + description: Uid of the admin to be assigned to the course + required: true + schema: + type: string + - name: uid + in: query + description: Uid of the user sending the request + schema: + type: string + responses: + '201': + description: User were successfully added to the course. + content: + application/json: + schema: + type: object + properties: + message: + type: string + examples: + - User was successfully added to the course. + url: + type: string + examples: + - http://api.example.com/courses/123/students + data: + type: object + properties: + students: + type: array + items: + type: string + examples: + - http://api.example.com/users/1 + - http://api.example.com/users/2 + '400': + description: There was no uid in the request query. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: The user trying to assign admins to the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + delete: + description: Remove an admin from a course. + parameters: + - name: course_id + in: path + description: ID of the course + required: true + schema: + type: string + - name: admin_uid + in: body + description: Uid of the admin to be removed from the course + required: true + schema: + type: string + - name: uid + in: query + description: Uid of the user sending the request + schema: + type: string + responses: + '204': + description: User was successfully removed from the course admins. + content: + application/json: + schema: + type: object + properties: + message: + type: string + examples: + - User was successfully removed from the course admins. + url: + type: string + examples: + - API_URL + /courses/ + str(course_id) + /students + '400': + description: There was no uid in the request query. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '403': + description: The user trying to remove the admin from the course was unauthorized. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '404': + description: Course not found. + content: + application/json: + schema: + type: object + properties: + error: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/users": + get: + summary: Get all users + responses: + '200': + description: A list of users + content: + application/json: + schema: + type: array + items: + type: object + properties: + uid: + type: string + is_teacher: + type: boolean + is_admin: + type: boolean + required: + - uid + - is_teacher + - is_admin + post: + summary: Create a new user + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + uid: + type: string + is_teacher: + type: boolean + is_admin: + type: boolean + required: + - uid + - is_teacher + - is_admin + responses: + '201': + description: User created successfully + '400': + description: Invalid request data + '415': + description: Unsupported Media Type. Expected JSON. + '500': + $ref: '#/components/responses/InternalError' + "/users/{user_id}": + get: + summary: Get a user by ID + parameters: + - name: user_id + in: path + required: true + schema: + type: string + responses: + '200': + description: A user + content: + application/json: + $ref: '#/components/schemas/User' + '404': + description: User not found + patch: + summary: Update a user's information + parameters: + - name: user_id + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + is_teacher: + type: boolean + is_admin: + type: boolean + required: + - is_teacher + - is_admin + responses: + '200': + description: User updated successfully + '404': + description: User not found + '415': + description: Unsupported Media Type. Expected JSON. + '500': + $ref: '#/components/responses/InternalError' + delete: + summary: Delete a user + parameters: + - name: user_id + in: path + required: true + schema: + type: string + responses: + '200': + description: User deleted successfully + '404': + description: User not found + '500': + $ref: '#/components/responses/InternalError' + "/submissions": + get: + summary: Gets the submissions + parameters: + - name: uid + in: query + description: User ID + schema: + type: string + - name: project_id + in: query + description: Project ID + schema: + type: integer + responses: + '200': + description: Successfully retrieved a list of submission URLs + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + data: + type: object + properties: + submissions: array + items: + type: string + format: uri + '400': + description: An invalid user or project is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '500': + $ref: '#/components/responses/InternalError' + post: + summary: Posts a new submission to a project + requestBody: + description: Form data + content: + application/json: + schema: + type: object + properties: + uid: + type: string + required: true + project_id: + type: integer + required: true + files: + type: array + items: + type: file + responses: + '201': + description: Successfully posts the submission and retrieves its data + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + data: + type: object + properties: + id: + type: integer + user: + type: string + format: uri + project: + type: string + format: uri + grading: + type: integer + time: + type: string + format: date-time + path: + type: string + status: + type: boolean + '400': + description: An invalid user, project or list of files is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '500': + $ref: '#/components/responses/InternalError' + "/submissions/{submission_id}": + get: + summary: Gets the submission + responses: + '200': + description: Successfully retrieved the submission + content: + application/json: + schema: + $ref: '#/components/schemas/Submission' + '404': + description: An invalid submission id is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '500': + $ref: '#/components/responses/InternalError' + patch: + summary: Patches the submission + requestBody: + description: The submission data + content: + application/json: + schema: + type: object + properties: + grading: + type: integer + minimum: 0 + maximum: 20 + responses: + '200': + description: Successfully patches the submission and retrieves its data + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + data: + type: object + properties: + id: + type: integer + user: + type: string + format: uri + project: + type: string + format: uri + grading: + type: integer + time: + type: string + format: date-time + path: + type: string + status: + type: boolean + '400': + description: An invalid submission grading is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '404': + description: An invalid submission id is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '500': + $ref: '#/components/responses/InternalError' + delete: + summary: Deletes the submission + responses: + '200': + description: Successfully deletes the submission + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '404': + description: An invalid submission id is given + content: + application/json: + schema: + type: object + properties: + url: + type: string + format: uri + message: + type: string + '500': + $ref: '#/components/responses/InternalError' + parameters: + - name: submission_id + in: path + description: Submission ID + required: true + schema: + type: integer +components: + responses: + InternalError: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + schemas: + Error: + type: object + properties: + code: + type: string + message: + type: string + required: + - code + - message + Project: + type: object + properties: + project_id: + type: integer + title: + type: string + description: + type: string + assignment_file: + type: string + format: binary + deadline: + type: string + format: date-time + course_id: + type: integer + visible_for_students: + type: boolean + archived: + type: boolean + test_path: + type: string + script_name: + type: string + regex_expressions: + type: array + items: + type: string + Course: + type: object + properties: + message: + type: string + data: + type: object + properties: + ufora_id: + type: string + teacher: + type: string + admins: + type: array + items: + type: string + students: + type: array + items: + type: string + projects: + type: array + items: + type: string + url: + type: string + User: + type: object + properties: + uid: + type: string + is_teacher: + type: boolean + is_admin: + type: boolean + required: + - uid + - is_teacher + - is_admin + Submission: + type: object + properties: + url: + type: string + format: uri + message: + type: string + data: + type: object + properties: + submission: + type: object + properties: + submission_id: + type: integer + user: + type: string + format: uri + project: + type: string + format: uri + grading: + type: integer + nullable: true + time: + type: string + format: date-time + path: + type: string + status: + type: boolean \ No newline at end of file diff --git a/backend/project/utils/__init__.py b/backend/project/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/project/utils/authentication.py b/backend/project/utils/authentication.py new file mode 100644 index 00000000..75bbe08f --- /dev/null +++ b/backend/project/utils/authentication.py @@ -0,0 +1,326 @@ +""" +This module contains the functions to authenticate API calls. +""" +from os import getenv + +from functools import wraps + +from dotenv import load_dotenv + +from flask import abort, request, make_response +from flask_jwt_extended import get_jwt, get_jwt_identity, verify_jwt_in_request + +from project.utils.models.course_utils import is_admin_of_course, \ + is_student_of_course, is_teacher_of_course +from project.utils.models.project_utils import get_course_of_project, project_visible +from project.utils.models.submission_utils import get_submission, get_course_of_submission +from project.utils.models.user_utils import get_user + +load_dotenv() +API_URL = getenv("API_HOST") +AUTHENTICATION_URL = getenv("AUTHENTICATION_URL") + + +def not_allowed(f): + """Decorator function to immediately abort the current request and return 403: Forbidden""" + @wraps(f) + def wrap(*args, **kwargs): + return {"message": "Forbidden action"}, 403 + return wrap + + +def return_authenticated_user_id(): + """This function will authenticate the request and ensure the user was added to the database, + otherwise it will prompt them to login again + """ + verify_jwt_in_request() + uid = get_jwt_identity() + get_user(uid) + return uid + + +def login_required(f): + """ + This function will check if the person sending a request to the API is logged in + and additionally create their user entry in the database if necessary + """ + @wraps(f) + def wrap(*args, **kwargs): + return_authenticated_user_id() + return f(*args, **kwargs) + return wrap + + +def login_required_return_uid(f): + """ + This function will check if the person sending a request to the API is logged in + and additionally create their user entry in the database if necessary + """ + @wraps(f) + def wrap(*args, **kwargs): + uid = return_authenticated_user_id() + kwargs["uid"] = uid + return f(*args, **kwargs) + return wrap + + +def authorize_admin(f): + """ + This function will check if the person sending a request to the API is logged in and an admin. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + return_authenticated_user_id() + if get_jwt()["is_admin"]: + return f(*args, **kwargs) + abort(make_response(({"message": + """You are not authorized to perfom this action, + only admins are authorized"""}, 403))) + return wrap + + +def authorize_teacher(f): + """ + This function will check if the person sending a request to the API is logged in and a teacher. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + if get_jwt()["is_teacher"]: + kwargs["teacher_id"] = auth_user_id + return f(*args, **kwargs) + abort(make_response(({"message": + """You are not authorized to perfom this action, + only teachers are authorized"""}, 403))) + return wrap + + +def authorize_teacher_of_course(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher of the course in the request. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + if is_teacher_of_course(auth_user_id, kwargs["course_id"]): + return f(*args, **kwargs) + + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + + +def authorize_teacher_or_course_admin(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher of the course in the request or an admin of this course. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + course_id = kwargs["course_id"] + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + + abort(make_response(({"message": """You are not authorized to perfom this action, + only teachers and course admins are authorized"""}, 403))) + return wrap + + +def authorize_user(f): + """ + This function will check if the person sending a request to the API is logged in, + and the same user that the request is about. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + user_id = kwargs["user_id"] + if auth_user_id == user_id: + return f(*args, **kwargs) + + abort(make_response(({"message": """You are not authorized to perfom this action, + you are not this user"""}, 403))) + return wrap + + +def authorize_teacher_of_project(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher of the course which the project in the request belongs to. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + project_id = kwargs["project_id"] + course_id = get_course_of_project(project_id) + + if is_teacher_of_course(auth_user_id, course_id): + return f(*args, **kwargs) + + abort(make_response(({"message": """You are not authorized to perfom this action, + you are not the teacher of this project"""}, 403))) + return wrap + + +def authorize_teacher_or_student_of_project(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher or student of the course which the project in the request belongs to. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + project_id = kwargs["project_id"] + course_id = get_course_of_project(project_id) + + if (is_teacher_of_course(auth_user_id, course_id) or + is_student_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + + abort(make_response(({"message": """You are not authorized to perfom this action, + you are not the teacher OR student of this project"""}, 403))) + return wrap + +def authorize_teacher_or_project_admin(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher or an admin of the course which the project in the request belongs to. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + project_id = kwargs["project_id"] + course_id = get_course_of_project(project_id) + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + abort(make_response(({"message": """You are not authorized to perfom this action, + you are not the teacher or an admin of this project"""}, 403))) + return wrap + + +def authorize_project_visible(f): + """ + This function will check if the person sending a request to the API is logged in, + and the teacher of the course which the project in the request belongs to. + Or if the person is a student of this course, + it will return the project if it is visible for students. + Returns 403: Not Authorized if either condition is false + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + project_id = kwargs["project_id"] + course_id = get_course_of_project(project_id) + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + if is_student_of_course(auth_user_id, course_id) and project_visible(project_id): + return f(*args, **kwargs) + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + +def authorize_submissions_request(f): + """This function will check if the person sending a request to the API is logged in, + and either the teacher/admin of the course or the student + that the submission belongs to + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + project_id = request.args["project_id"] + course_id = get_course_of_project(project_id) + + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + + if (is_student_of_course(auth_user_id, course_id) + and project_visible(project_id) + and auth_user_id == request.args.get("uid")): + return f(*args, **kwargs) + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + + +def authorize_student_submission(f): + """This function will check if the person sending a request to the API is logged in, + and a student of the course they're trying to post a submission to + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + kwargs["uid"] = auth_user_id + project_id = request.form["project_id"] + course_id = get_course_of_project(project_id) + if (is_student_of_course(auth_user_id, course_id) and project_visible(project_id)): + return f(*args, **kwargs) + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + + +def authorize_submission_author(f): + """This function will check if the person sending a request to the API is logged in, + and the original author of the submission + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + submission_id = kwargs["submission_id"] + submission = get_submission(submission_id) + if submission.uid == auth_user_id: + return f(*args, **kwargs) + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + + +def authorize_grader(f): + """This function will check if the person sending a request to the API is logged in, + and either the teacher/admin of the course. + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + course_id = get_course_of_submission(kwargs["submission_id"]) + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + abort(make_response( + ({"message": "You're not authorized to perform this action"}, 403))) + return wrap + + +def authorize_submission_request(f): + """This function will check if the person sending a request to the API is logged in, + and either the teacher/admin of the course or the student + that the submission belongs to + """ + @wraps(f) + def wrap(*args, **kwargs): + auth_user_id = return_authenticated_user_id() + submission_id = kwargs["submission_id"] + submission = get_submission(submission_id) + if submission.uid == auth_user_id: + return f(*args, **kwargs) + course_id = get_course_of_project(submission.project_id) + if (is_teacher_of_course(auth_user_id, course_id) + or is_admin_of_course(auth_user_id, course_id)): + return f(*args, **kwargs) + abort(make_response(({"message": + "You're not authorized to perform this action"}, 403))) + return wrap diff --git a/backend/project/utils/files.py b/backend/project/utils/files.py new file mode 100644 index 00000000..3b3c807c --- /dev/null +++ b/backend/project/utils/files.py @@ -0,0 +1,63 @@ +"""Utility functions for files""" + +from re import match +from typing import List, Optional +from io import BytesIO +from zipfile import ZipFile, ZIP_DEFLATED, is_zipfile +from werkzeug.utils import secure_filename +from werkzeug.datastructures import FileStorage + + +def all_files_uploaded(files: List[FileStorage], regexes: List[str]) -> bool: + """Check if all the required files are uploaded + + Args: + files (List[FileStorage]): The files uploaded + regexes (List[str]): The list of regexes to match against + + Returns: + bool: Are all required files uploaded + """ + + all_filenames = [] + for file in files: + # Zip + if is_zipfile(file): + with ZipFile(file, "r") as zip_file: + all_filenames += zip_file.namelist() + # File + else: + all_filenames.append(file.filename) + + for regex in regexes: + match_found = any(match(regex, name) is not None for name in all_filenames) + if not match_found: + return False + + return True + +def zip_files(name: str, files: List[FileStorage]) -> Optional[FileStorage]: + """Zip a dictionary of files + + Args: + files (List[FileStorage]): The files to be zipped + + Returns: + FileStorage: The zipped file + """ + + compression = ZIP_DEFLATED # Compression algorithm + zip64 = False # Extension for larger files and archives (now limited to 4GB) + level = None # Compression level, None = default + + try: + buffer = BytesIO() + with ZipFile(buffer, "w", compression, zip64, level) as zip_file: + for file in files: + filename = secure_filename(file.filename) + zip_file.writestr(filename, file.stream.read()) + zip_file = FileStorage(buffer, name) + + return zip_file + except IOError: + return None diff --git a/backend/project/utils/misc.py b/backend/project/utils/misc.py new file mode 100644 index 00000000..07c1a8d3 --- /dev/null +++ b/backend/project/utils/misc.py @@ -0,0 +1,95 @@ +""" +This module contains miscellaneous utility functions. +These functions apply to a variety of use cases and are not specific to any one module. +""" + +from typing import Dict, List +from urllib.parse import urljoin +from uuid import UUID +from sqlalchemy.ext.declarative import DeclarativeMeta + + +def map_keys_to_url(url_mapper: Dict[str, str], data: Dict[str, str]) -> Dict[str, str]: + """ + Maps keys to a url using a url mapper. + + Args: + url_mapper: Dict[str, str] - A dictionary that maps keys to urls. + data: Dict[str, str] - The data to map to urls. + + Returns: + A dictionary with the keys mapped to the urls. + """ + for key, value in data.items(): + if key in url_mapper: + data[key] = urljoin(url_mapper[key] + "/", str(value)) + return data + +def map_all_keys_to_url(url_mapper: Dict[str, str], data: List[Dict[str, str]]): + """ + Maps all keys to a url using a url mapper. + + Args: + url_mapper: Dict[str, str] - A dictionary that maps keys to urls. + data: List[Dict[str, str]] - The data to map to urls. + + Returns: + A list of dictionaries with the keys mapped to the urls. + """ + return [map_keys_to_url(url_mapper, entry) for entry in data] + +def model_to_dict(instance: DeclarativeMeta) -> Dict[str, str]: + """ + Converts an sqlalchemy model to a dictionary. + + Args: + instance: DeclarativeMeta - The instance of the model to convert to a dictionary. + + Returns: + A dictionary with the keys and values of the model. + """ + return {column.key: getattr(instance, column.key) for column in instance.__table__.columns} + +def models_to_dict(instances: List[DeclarativeMeta]) -> List[Dict[str, str]]: + """ + Converts a list of sqlalchemy models to a list of dictionaries. + + Args: + instances: List[DeclarativeMeta] - The instances of the models to convert to dictionaries. + + Returns: + A list of dictionaries with the keys and values of the models. + """ + return [model_to_dict(instance) for instance in instances] + +def filter_model_fields(model: DeclarativeMeta, data: Dict[str, str]): + """ + Filters the data to only contain the fields of the model. + + Args: + model: DeclarativeMeta - The model to filter the data with. + data: Dict[str, str] - The data to filter. + + Returns: + A dictionary with the fields of the model. + """ + return {key: value for key, value in data.items() if hasattr(model, key)} + + +def is_valid_uuid(uuid_to_test, version=4): + """ + Check if uuid_to_test is a valid UUID. + + Args: + uuid_to_test: str - The UUID to test. + version: int - The version of the UUID. + + Returns: + bool: True if the UUID is valid, False otherwise. + """ + + try: + uuid_obj = UUID(uuid_to_test, version=version) + except ValueError: + return False + return str(uuid_obj) == uuid_to_test diff --git a/backend/project/utils/models/course_utils.py b/backend/project/utils/models/course_utils.py new file mode 100644 index 00000000..6ea09afd --- /dev/null +++ b/backend/project/utils/models/course_utils.py @@ -0,0 +1,67 @@ +"""This module contains helper functions related to courses for accessing the database""" + +from os import getenv + +from dotenv import load_dotenv + +from flask import abort, make_response +from sqlalchemy.exc import SQLAlchemyError + +from project import db +from project.models.course import Course +from project.models.course_relation import CourseAdmin, CourseStudent + +load_dotenv() +API_URL = getenv("API_HOST") + +def get_course(course_id): + """Returns the course associated with course_id or the appropriate error""" + try: + course = db.session.get(Course, course_id) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": "An error occurred while fetching the user", + "url": f"{API_URL}/users"}, 500))) + + if not course: + abort(make_response(({"message":f"Course with id: {course_id} not found"}, 404))) + return course + +def is_teacher_of_course(auth_user_id, course_id): + """This function checks whether the user + with auth_user_id is the teacher of the course: course_id + """ + course = get_course(course_id) + if auth_user_id == course.teacher: + return True + return False + + +def is_admin_of_course(auth_user_id, course_id): + """This function checks whether the user + with auth_user_id is an admin of the course: course_id + """ + try: + course_admin = db.session.get(CourseAdmin, (course_id, auth_user_id)) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": "An error occurred while fetching the user", + "url": f"{API_URL}/users"}, 500))) + + if course_admin: + return True + return False + +def is_student_of_course(auth_user_id, course_id): + """This function checks whether the user + with auth_user_id is a student of the course: course_id + """ + try: + course_student = db.session.get(CourseStudent, (course_id, auth_user_id)) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": "An error occurred while fetching the user", + "url": f"{API_URL}/users"}, 500))) + if course_student: + return True + return False diff --git a/backend/project/utils/models/project_utils.py b/backend/project/utils/models/project_utils.py new file mode 100644 index 00000000..2e2b9f17 --- /dev/null +++ b/backend/project/utils/models/project_utils.py @@ -0,0 +1,41 @@ +"""This module contains helper functions related to projects for accessing the database""" + +from os import getenv + +from dotenv import load_dotenv + +from flask import abort, make_response +from sqlalchemy.exc import SQLAlchemyError + +from project import db +from project.models.project import Project + +load_dotenv() +API_URL = getenv("API_HOST") + +def get_project(project_id): + """Returns the project associated with project_id or the appropriate error""" + if isinstance(project_id, str) and not project_id.isnumeric(): + abort(make_response(({"message": f"{project_id} is not a valid project id"} + , 400))) + try: + project = db.session.get(Project, project_id) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": "An error occurred while fetching the project"} + , 500))) + + if not project: + abort(make_response(({"message":f"Project with id: {project_id} not found"}, 404))) + + return project + +def get_course_of_project(project_id): + """This function returns the course_id of the course associated with the project: project_id""" + project = get_project(project_id) + return project.course_id + +def project_visible(project_id): + """Determine whether a project is visible for students""" + project = get_project(project_id) + return project.visible_for_students diff --git a/backend/project/utils/models/submission_utils.py b/backend/project/utils/models/submission_utils.py new file mode 100644 index 00000000..8f5f7014 --- /dev/null +++ b/backend/project/utils/models/submission_utils.py @@ -0,0 +1,44 @@ +"""This module contains helper functions related to submissions for accessing the database""" + +from os import getenv + +from dotenv import load_dotenv + +from flask import abort, make_response +from sqlalchemy.exc import SQLAlchemyError + +from project import db +from project.models.submission import Submission +from project.utils.models.project_utils import get_course_of_project + +load_dotenv() +API_URL = getenv("API_HOST") + +def get_submission(submission_id): + """Returns the submission associated with submission_id or the appropriate error""" + try: + submission = db.session.get(Submission, submission_id) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message":"An error occurred while fetching the submission"}, 500))) + + if not submission: + abort(make_response(({"message":f"Submission with id: {submission_id} not found"}, 404))) + + return submission + +def get_course_of_submission(submission_id): + """Get the course linked to a given submission""" + submission = get_submission(submission_id) + return get_course_of_project(submission.project_id) + +def submission_response(submission, api_host): + """Return the response data for a submission""" + return { + "submission_id": f"{api_host}/submissions/{submission.submission_id}", + "uid": f"{api_host}/users/{submission.uid}", + "project_id": f"{api_host}/projects/{submission.project_id}", + "grading": submission.grading, + "submission_time": submission.submission_time, + "submission_status": submission.submission_status + } diff --git a/backend/project/utils/models/user_utils.py b/backend/project/utils/models/user_utils.py new file mode 100644 index 00000000..21568c6d --- /dev/null +++ b/backend/project/utils/models/user_utils.py @@ -0,0 +1,36 @@ +"""This module contains helper functions related to users for accessing the database""" + +from os import getenv + +from dotenv import load_dotenv + +from flask import abort, make_response +from sqlalchemy.exc import SQLAlchemyError + +from project import db +from project.models.user import User, Role + +load_dotenv() +API_URL = getenv("API_HOST") + +def get_user(user_id): + """Returns the user associated with user_id or the appropriate error""" + try: + user = db.session.get(User, user_id) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": "An error occurred while fetching the user"} + , 500))) + if user is None: + abort(make_response(({"message":f"User with id: {user_id} not found"}, 404))) + return user + +def is_teacher(auth_user_id): + """This function checks whether the user with auth_user_id is a teacher""" + user = get_user(auth_user_id) + return user.role == Role.TEACHER + +def is_admin(auth_user_id): + """This function checks whether the user with auth_user_id is a teacher""" + user = get_user(auth_user_id) + return user.role == Role.ADMIN diff --git a/backend/project/utils/project.py b/backend/project/utils/project.py new file mode 100644 index 00000000..f056fa2b --- /dev/null +++ b/backend/project/utils/project.py @@ -0,0 +1,27 @@ +"""Utility functions for the project model""" + +from typing import Tuple +from sqlalchemy.orm import Session +from project.models.project import Project + +def is_valid_project(session: Session, project_id: any) -> Tuple[bool, str]: + """Check if a project_id is valid + + Args: + project_id (any): The project_id + + Returns: + bool: Is valid + """ + if project_id is None: + return False, "The project_id is missing" + + if isinstance(project_id, str) and project_id.isdigit(): + project_id = int(project_id) + elif not isinstance(project_id, int): + return False, f"Invalid project_id typing (project_id={project_id})" + + project = session.get(Project, project_id) + if project is None: + return False, f"Invalid project (project_id={project_id})" + return True, "Valid project" diff --git a/backend/project/utils/query_agent.py b/backend/project/utils/query_agent.py new file mode 100644 index 00000000..94ace471 --- /dev/null +++ b/backend/project/utils/query_agent.py @@ -0,0 +1,236 @@ +""" +This module contains the functions to interact with the database. It contains functions to +delete, insert and query entries from the database. The functions are used by the routes +to interact with the database. +""" +from typing import Dict, List, Union +from urllib.parse import urljoin +from flask import jsonify +from sqlalchemy import and_ +from sqlalchemy.ext.declarative import DeclarativeMeta +from sqlalchemy.orm.query import Query +from sqlalchemy.exc import SQLAlchemyError +from project.utils.misc import map_all_keys_to_url, models_to_dict, filter_model_fields +from project.db_in import db + +def delete_by_id_from_model( + model: DeclarativeMeta, + column_name: str, + column_id: int, + base_url: str): + """ + Deletes an entry from the database giving the model corresponding to a certain table, + a column name and its value. + + Args: + model: DeclarativeMeta - The model corresponding to the table to delete from. + column_name: str - The name of the column to delete from. + id: int - The id of the entry to delete. + + Returns: + A message indicating that the resource was deleted successfully if the operation was + successful, otherwise a message indicating that something went wrong while deleting from + the database. + """ + try: + result: DeclarativeMeta = model.query.filter( + getattr(model, column_name) == column_id + ).first() + + if not result: + return { + "message": "Resource not found", + "url": base_url}, 404 + db.session.delete(result) + db.session.commit() + return {"message": "Resource deleted successfully", + "url": base_url}, 200 + except SQLAlchemyError: + return {"error": "Something went wrong while deleting from the database.", + "url": base_url}, 500 + + +def create_model_instance(model: DeclarativeMeta, + data: Dict[str, Union[str, int]], + response_url_base: str, + required_fields: List[str] = None): + """ + Create an instance of a model + """ + if required_fields is None: + required_fields = [] + + # Check if all non-nullable fields are present in the data + missing_fields = [field for field in required_fields if field not in data or data[field] == ''] + + if missing_fields: + return {"error": f"Missing required fields: {', '.join(missing_fields)}", + "url": response_url_base}, 400 + filtered_data = filter_model_fields(model, data) + new_instance: DeclarativeMeta = model(**filtered_data) + db.session.add(new_instance) + db.session.commit() + + return new_instance, 201 + + +def insert_into_model(model: DeclarativeMeta, + data: Dict[str, Union[str, int]], + response_url_base: str, + url_id_field: str, + required_fields: List[str] = None): + """ + Inserts a new entry into the database giving the model corresponding to a certain table + and the data to insert. + + Args: + model: DeclarativeMeta - The model corresponding to the table to insert into. + data: Dict[str, Union[str, int]] - The data to insert into the table. + response_url_base: str - The base url to use in the response. + + Returns: + The new entry inserted into the database if the operation was successful, otherwise + a message indicating that something went wrong while inserting into the database. + """ + try: + model_instance, status_code = create_model_instance( + model, + data, + response_url_base, + required_fields) + + # if its a tuple the model instance couldn't be created so it already + # is the right format of error message and we just need to return + if status_code == 400: + return model_instance, status_code + + return (jsonify({ + "data": model_instance, + "message": "Object created succesfully.", + "url": + urljoin(f"{response_url_base}/", + str(getattr(model_instance, url_id_field)))}), + status_code) + except SQLAlchemyError: + db.session.rollback() + return jsonify({"error": "Something went wrong while inserting into the database.", + "url": response_url_base}), 500 + +def query_selected_from_model(model: DeclarativeMeta, + response_url: str, + url_mapper: Dict[str, str] = None, + select_values: List[str] = None, + filters: Dict[str, Union[str, int]]=None + ): + """ + Query entries from the database giving the model corresponding to a certain table and + the filters to apply to the query. + + + Args: + model: DeclarativeMeta - The model corresponding to the table to query from. + response_url: str - The base url to use in the response. + url_mapper: Dict[str, str] - A dictionary to map the keys of the response to urls. + select_values: List[str] - The columns to select from the table. + filters: Dict[str, Union[str, int]] - The filters to apply to the query. + + Returns: + The entries queried from the database if they exist, otherwise a message indicating + that the resource was not found. + """ + try: + query: Query = model.query + if filters: + if not all(hasattr(model, key) for key in filters.keys()): + return {"message": "Unknown parameter", "url": response_url}, 400 + conditions: List[bool] = [] + for key, value in filters.items(): + conditions.append(getattr(model, key) == value) + query = query.filter(and_(*conditions)) + + if select_values: + query = query.with_entities(*[getattr(model, value) for value in select_values]) + query_result = query.all() + results = [] + for instance in query_result: + selected_instance = {} + for value in select_values: + selected_instance[value] = getattr(instance, value) + results.append(selected_instance) + else: + results = models_to_dict(query.all()) + if url_mapper: + results = map_all_keys_to_url(url_mapper, results) + response = {"data": results, + "message": "Resources fetched successfully", + "url": response_url} + return jsonify(response), 200 + except SQLAlchemyError: + return {"error": "Something went wrong while querying the database.", + "url": response_url}, 500 + +def query_by_id_from_model(model: DeclarativeMeta, + column_name: str, + column_id: int, + base_url: str): + """ + Query an entry from the database giving the model corresponding to a certain table, + a column name and its value. + + Args: + model: DeclarativeMeta - The model corresponding to the table to query from. + column_name: str - The name of the column to query from. + id: int - The id of the entry to query. + not_found_message: str - The message to return if the entry is not found. + + Returns: + The entry queried from the database if it exists, otherwise a message indicating + that the resource was not found. + + """ + try: + result: Query = model.query.filter(getattr(model, column_name) == column_id).first() + if not result: + return {"message": "Resource not found", "url": base_url}, 404 + return { + "data": result.to_dict() if hasattr(result, "to_dict") else result, + "message": "Resource fetched correctly", + "url": urljoin(f"{base_url}/", str(column_id))}, 200 + except SQLAlchemyError: + return { + "error": "Something went wrong while querying the database.", + "url": base_url}, 500 + +def patch_by_id_from_model(model: DeclarativeMeta, + column_name: str, + column_id: int, + base_url: str, + data: Dict[str, Union[str, int]]): + """ + Update an entry from the database giving the model corresponding to a certain table, + a column name and its value. + + Args: + model: DeclarativeMeta - The model corresponding to the table to update. + column_name: str - The name of the column to update. + id: int - The id of the entry to update. + data: Dict[str, Union[str, int]] - The data to update the entry with. + + Returns: + The entry updated from the database if the operation was successful, otherwise + a message indicating that something went wrong while updating the entry. + """ + try: + result: Query = model.query.filter(getattr(model, column_name) == column_id).first() + if not result: + return {"message": "Resource not found", "url": base_url}, 404 + for key, value in data.items(): + setattr(result, key, value) + db.session.commit() + return jsonify({ + "data": result, + "message": "Resource updated successfully", + "url": urljoin(f"{base_url}/", str(column_id))}), 200 + except SQLAlchemyError: + return {"error": "Something went wrong while updating the database.", + "url": base_url}, 500 diff --git a/backend/project/utils/submissions/__init__.py b/backend/project/utils/submissions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/project/utils/submissions/evaluator.py b/backend/project/utils/submissions/evaluator.py new file mode 100644 index 00000000..50e75dc0 --- /dev/null +++ b/backend/project/utils/submissions/evaluator.py @@ -0,0 +1,139 @@ +""" +This module is responsible for evaluating the submission. +It uses docker to run the evaluator in a container. +The image used for the container is determined by the evaluator argument. +If the evaluator is not found in the +DOCKER_IMAGE_MAPPER, the project test path is used as the image. +The evaluator is run in the container and the +exit code is returned. The output of the evaluator is written to a log file +in the submission output folder. +""" +from os import path, makedirs +import docker +from sqlalchemy.exc import SQLAlchemyError +from project.db_in import db +from project.models.submission import Submission + + +EVALUATORS_FOLDER = path.join(path.dirname(__file__), "evaluators") + +DOCKER_IMAGE_MAPPER = { + "PYTHON": path.join(EVALUATORS_FOLDER, "python"), + "GENERAL": path.join(EVALUATORS_FOLDER, "general") +} + + +def evaluate(submission: Submission, project_path: str, evaluator: str, is_late: bool) -> int: + """ + Evaluate a submission using the evaluator. + + Args: + submission (Submissions): The submission to evaluate. + project_path (str): The path to the project. + evaluator (str): The evaluator to use. + + Returns: + int: The exit code of the evaluator. + + Raises: + ValueError: If the evaluator is not found in the DOCKER_IMAGE_MAPPER + and the project test path does not exist. + """ + + docker_image = DOCKER_IMAGE_MAPPER.get(evaluator, None) + if docker_image is None: + docker_image = project_path + if not path.exists(docker_image): + raise ValueError(f"Test path: {docker_image},\ + not found and the provided evaluator:\ + {evaluator} is not associated with any image.") + + submission_path = submission.submission_path + submission_solution_path = path.join(submission_path, "submission") + + container = create_and_run_evaluator(docker_image, + submission.submission_id, + project_path, + submission_solution_path) + + submission_output_path = path.join(submission_path, "output") + makedirs(submission_output_path, exist_ok=True) + test_output_path = path.join(submission_output_path, "test_output.log") + + exit_code = container.wait() + + with open(path.join(test_output_path), "w", encoding='utf-8') as output_file: + output_file.write(container.logs().decode('utf-8')) + + container.remove() + + return exit_code['StatusCode'] + +def run_evaluator(submission: Submission, project_path: str, evaluator: str, is_late: bool) -> int: + """ + Run the evaluator for the submission. + + Args: + submission (Submission): The submission to evaluate. + project_path (str): The path to the project. + evaluator (str): The evaluator to use. + is_late (bool): Whether the submission is late. + + Returns: + int: The exit code of the evaluator. + """ + try: + status_code = evaluate(submission, project_path, evaluator, is_late) + if not is_late: + if status_code == 0: + submission.submission_status = 'SUCCESS' + else: + submission.submission_status = 'FAIL' + else: + submission.submission_status = 'LATE' + except: # pylint: disable=bare-except + submission.submission_status = 'FAIL' + + + try: + db.session.merge(submission) + db.session.commit() + except SQLAlchemyError: + pass + + return status_code + + +def create_and_run_evaluator(docker_image: str, + submission_id: int, + project_path: str, + submission_solution_path: str): + """ + Create and run the evaluator container. + + Args: + docker_image (str): The path to the docker image. + submission_id (int): The id of the submission. + project_path (str): The path to the project. + submission_solution_path (str): The path to the submission solution. + + Returns: + docker.models.containers.Container: The container that is running the evaluator. + """ + client = docker.from_env() + image, _ = client.images.build(path=docker_image, tag=f"submission_{submission_id}") + + + container = client.containers.run( + image.id, + detach=True, + command="bash entry_point.sh", + volumes={ + path.abspath(project_path): {'bind': "/tests", 'mode': 'rw'}, + path.abspath(submission_solution_path): {'bind': "/submission", 'mode': 'rw'} + }, + stderr=True, + stdout=True, + pids_limit=256 + ) + return container diff --git a/backend/project/utils/submissions/evaluators/general/Dockerfile b/backend/project/utils/submissions/evaluators/general/Dockerfile new file mode 100644 index 00000000..202d15c0 --- /dev/null +++ b/backend/project/utils/submissions/evaluators/general/Dockerfile @@ -0,0 +1,32 @@ +# Use Ubuntu as the base image +FROM ubuntu:latest + +# Avoiding user interaction with tzdata, etc. +ENV DEBIAN_FRONTEND=noninteractive + +# Update and install basic dependencies +RUN apt-get update && apt-get install -y \ + software-properties-common \ + build-essential \ + curl \ + wget \ + git \ + cmake # Adding CMake for C/C++ project management + +# Install Python +RUN apt-get install -y python3 python3-pip + +# Install Node.js +RUN apt-get install -y nodejs +RUN apt-get install -y npm + +# Install Java +RUN apt-get install -y openjdk-11-jdk + +# Install Ruby +RUN apt-get install -y ruby-full + +# Clean up to reduce the image size +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY . . \ No newline at end of file diff --git a/backend/project/utils/submissions/evaluators/general/entry_point.sh b/backend/project/utils/submissions/evaluators/general/entry_point.sh new file mode 100644 index 00000000..51758446 --- /dev/null +++ b/backend/project/utils/submissions/evaluators/general/entry_point.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +bash /tests/run_tests.sh diff --git a/backend/project/utils/submissions/evaluators/python/Dockerfile b/backend/project/utils/submissions/evaluators/python/Dockerfile new file mode 100644 index 00000000..f8e09927 --- /dev/null +++ b/backend/project/utils/submissions/evaluators/python/Dockerfile @@ -0,0 +1,3 @@ +FROM python:3.9-slim + +COPY . . \ No newline at end of file diff --git a/backend/project/utils/submissions/evaluators/python/entry_point.sh b/backend/project/utils/submissions/evaluators/python/entry_point.sh new file mode 100644 index 00000000..4518c789 --- /dev/null +++ b/backend/project/utils/submissions/evaluators/python/entry_point.sh @@ -0,0 +1,40 @@ +#!/bin/bash + + +tests_manifest_file="/tests/req-manifest.txt" + +if [ -f "$tests_manifest_file" ]; then + echo "Tests manifest file found. Installing tests requirements..." + pip3 install -r $tests_manifest_file &> /dev/null +else + echo "No tests manifest file found." + submission_requirements_file="/submission/requirements.txt" + if [ -f "$submission_requirements_file" ]; then + echo "Requirements file found. Installing requirements..." + pip3 install -r $submission_requirements_file &> /dev/null + else + echo "No requirements file found." + fi + + submission_dev_requirements_file="/submission/dev-requirements.txt" + + if [ -f "$submission_dev_requirements_file" ]; then + echo "Dev requirements file found. Installing dev requirements..." + pip3 install -r $submission_dev_requirements_file &> /dev/null + else + echo "No dev requirements file found." + fi + + tests_requirements_file="/tests/requirements.txt" + + if [ -f "$tests_requirements_file" ]; then + echo "Tests requirements file found. Installing tests requirements..." + pip3 install -r $tests_requirements_file &> /dev/null + else + echo "No tests requirements file found." + fi +fi + +echo "Running tests..." +ls /submission +bash /tests/run_tests.sh \ No newline at end of file diff --git a/backend/project/utils/submissions/file_handling.py b/backend/project/utils/submissions/file_handling.py new file mode 100644 index 00000000..39a018e8 --- /dev/null +++ b/backend/project/utils/submissions/file_handling.py @@ -0,0 +1,47 @@ +""" +This module contains functions for handling files and folders for submissions. +""" + +from os import path, makedirs, getenv + +def create_submission_subfolders(submission_path: str): + """ + Create the output and artifacts folder for a submission. + """ + submission_output_path = path.join(submission_path, "output") + artifacts_path = path.join(submission_output_path, "artifacts") + submission_solution_path = path.join(submission_path, "submission") + + if not path.exists(submission_solution_path): + makedirs(submission_solution_path) + + if not path.exists(submission_output_path): + makedirs(submission_output_path) + + if not path.exists(artifacts_path): + makedirs(artifacts_path) + + return submission_output_path + +def create_submission_folder(submission_id: int, project_id: int): + """ + Create the submission folder and the submission + solution folder that will contain a students solution. + + Args: + submission_id (int): The id of the submission. + project_id (int): The id of the project. + + Returns: + str: The path to the submission folder. + """ + submission_path = path.join(getenv("SUBMISSIONS_ROOT_PATH"), + str(project_id), + str(submission_id)) + + if not path.exists(submission_path): + makedirs(submission_path) + + create_submission_subfolders(submission_path) + + return submission_path diff --git a/backend/project/utils/user.py b/backend/project/utils/user.py new file mode 100644 index 00000000..c8b6438b --- /dev/null +++ b/backend/project/utils/user.py @@ -0,0 +1,69 @@ +"""Utility functions for the user model""" + +from typing import Tuple +from requests import Response + +from flask import abort, make_response + +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session + +from project import db +from project.models.user import User, Role + +def get_or_make_user(profile_res: Response) -> User: + """ + Function to create a new User in the database or return + the user associated with the profile_res received from authentication + + Returns either a database error or the User data. + """ + auth_user_id = profile_res.json()["id"] + try: + user = db.session.get(User, auth_user_id) + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": + "An unexpected database error occured while fetching the user"}, + 500))) + + if not user: + role = Role.STUDENT + if profile_res.json()["jobTitle"] is not None: + role = Role.TEACHER + + # add user if not yet in database + try: + new_user = User(uid=auth_user_id, + role=role, + display_name=profile_res.json()["displayName"]) + db.session.add(new_user) + db.session.commit() + user = new_user + except SQLAlchemyError: + db.session.rollback() + abort(make_response(({"message": + """An unexpected database error occured + while creating the user during authentication"""}, 500))) + return user + +def is_valid_user(session: Session, uid: any) -> Tuple[bool, str]: + """Check if a uid is valid + + Args: + session (Session): A database session + uid (any): The uid + + Returns: + Tuple[bool, str]: Is valid + """ + if uid is None: + return False, "The uid is missing" + + if not isinstance(uid, str): + return False, f"Invalid uid typing (uid={uid})" + + user = session.get(User, uid) + if user is None: + return False, f"Invalid user (uid={uid})" + return True, "Valid user" diff --git a/backend/pylintrc b/backend/pylintrc new file mode 100644 index 00000000..ea890a85 --- /dev/null +++ b/backend/pylintrc @@ -0,0 +1,19 @@ +[MASTER] +init-hook='import sys; sys.path.append(".")' +ignore-paths=tests/utils/submission_evaluators/resources/.* + +[MESSAGES CONTROL] +disable=W0621, # Redefining name %r from outer scope (line %s) + W0613 # unused-argument + + +[test-files:*_test.py] +disable= + W0613, # Unused argument (pytest uses it) + W0621, # Redefining name %r from outer scope (line %s) + R0904, # Too many public methods (too many unit tests essentially) + R0913, # Too many arguments (too many fixtures essentially) + +[modules:project/modules/*] +disable= + R0903 # Too few public methods (modules don't require us to have public methods) diff --git a/backend/pyproject.toml b/backend/pyproject.toml new file mode 100644 index 00000000..c1c45b42 --- /dev/null +++ b/backend/pyproject.toml @@ -0,0 +1,13 @@ +[tool.poetry] +name = "Peristeronas" +version = "1.0" +description = "Project submission platform" +authors = ["Aron","Gerwoud","Siebe","Matisse","Warre","Cedric"] +packages = [ + { include = "project/models" }, + { include = "seeder" }, +] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index 9687a048..b9d38d15 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,2 +1,15 @@ -flask +flask~=3.0.2 +flask-cors +flask-jwt-extended flask-restful +flask-sqlalchemy +sqlalchemy_utils +python-dotenv~=1.0.1 +psycopg2-binary +docker +pytest~=8.0.1 +SQLAlchemy~=2.0.27 +requests<=2.31.0 +waitress +flask_swagger_ui +flask_executor diff --git a/backend/run_tests.sh b/backend/run_tests.sh new file mode 100755 index 00000000..bc971ebb --- /dev/null +++ b/backend/run_tests.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Run Docker Compose to build and start the services, and capture the exit code from the test runner service +docker compose -f tests.yaml up --build --exit-code-from test-runner + +# Store the exit code in a variable +exit_code=$? + +# After the tests are finished, stop and remove the containers +docker compose -f tests.yaml down + +# Check the exit code to determine whether the tests passed or failed +if [ $exit_code -eq 0 ]; then + echo "Tests passed!" +else + echo "Tests failed!" +fi + +# Exit with the same exit code as the test runner service +exit $exit_code diff --git a/backend/seeder/__init__.py b/backend/seeder/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/seeder/seeder.py b/backend/seeder/seeder.py new file mode 100644 index 00000000..2e90341f --- /dev/null +++ b/backend/seeder/seeder.py @@ -0,0 +1,264 @@ +"""Seeder file does the actual seeding of the db""" +import argparse +import os +import random +import string +from datetime import datetime, timedelta + +from dotenv import load_dotenv +from faker import Faker +from faker.providers import DynamicProvider +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy_utils import register_composites + +from project.models.course import Course +from project.models.course_relation import CourseAdmin, CourseStudent +from project.models.project import Project +from project.models.submission import Submission, SubmissionStatus +from project.models.user import User +from project.sessionmaker import Session as session_maker + +load_dotenv() + +UPLOAD_URL = os.getenv("UPLOAD_FOLDER") + +fake = Faker() + +# Get the directory of the current script +script_dir = os.path.dirname(os.path.realpath(__file__)) + +# Construct the path to titles.txt relative to the script directory +titles_path = os.path.join(script_dir, 'titles.txt') + +with open(titles_path, 'r', encoding='utf-8') as file: + # Read the lines of the file and strip newline characters + titles = [line.strip() for line in file] + +course_title_provider = DynamicProvider( # Custom course titles. + provider_name="course_titles", + elements=titles, +) +fake.add_provider(course_title_provider) + + +def generate_course_name(): + """Generates a course name chosen from the predefined provider""" + return fake.course_titles() + + +def generate_random_uid(length=8): + """Generates a random uid of given length""" + characters = string.ascii_letters + string.digits + return ''.join(random.choice(characters) for _ in range(length)) + + +def teacher_generator(): + """Generates a teacher user object""" + return user_generator('TEACHER') + + +def student_generator(): + """Generates a student user object""" + return user_generator('STUDENT') + + +def admin_generator(): + """Generates an admin user object""" + return user_generator('ADMIN') + + +def user_generator(role): + """Generates a user object with the given role""" + user = User(uid=generate_random_uid(), + role=role, + display_name=fake.name()) + return user + + +def course_student_generator(course_id, uid): + """Generates a course student relation object""" + return CourseStudent(course_id=course_id, uid=uid) + + +def course_admin_generator(course_id, uid): + """Generates a course admin relation object""" + return CourseAdmin(course_id=course_id, uid=uid) + + +def generate_course(teacher_uid): + """Generates a course object with a random name and the given teacher uid""" + course = Course(name=generate_course_name(), + teacher=teacher_uid) + return course + + +def generate_projects(course_id, num_projects): + """Generates a list of project objects with random future deadlines""" + projects = [] + for _ in range(num_projects): + deadlines = [] + # Generate a random number of deadlines (0-2) + num_deadlines = random.randint(0, 2) + + for _ in range(num_deadlines): + if random.random() < 1/3: + past_datetime = datetime.now() - timedelta(days=random.randint(1, 30)) + deadline = (fake.catch_phrase(), past_datetime) + else: + future_datetime = datetime.now() + timedelta(days=random.randint(1, 30)) + deadline = (fake.catch_phrase(), future_datetime) + deadlines.append(deadline) + project = Project( + title=fake.catch_phrase(), + description=fake.catch_phrase(), + deadlines=deadlines, + course_id=course_id, + visible_for_students=random.choice([True, False]), + archived=random.choice([True, False]), + regex_expressions=[] + ) + projects.append(project) + return projects + + +def generate_submissions(project_id, student_uid): + """Generates a list of submissions with random status""" + submissions = [] + statusses = [SubmissionStatus.SUCCESS, SubmissionStatus.FAIL, + SubmissionStatus.LATE, SubmissionStatus.RUNNING] + num_submissions = random.randint(0, 2) + submission_times = [] + for _ in range(num_submissions): + past_datetime = datetime.now() - timedelta(days=random.randint(0, 10)) + while past_datetime in submission_times: + past_datetime = datetime.now() - timedelta(days=random.randint(0, 10)) + submission_times.append(past_datetime) + submission = Submission(project_id=project_id, + uid=student_uid, + submission_time=past_datetime, + submission_path="", + submission_status=random.choice(statusses)) + graded = random.choice([True, False]) + if graded and submission.submission_status == "SUCCESS": + submission.grading = random.randint(0, 20) + submissions.append(submission) + return submissions + + +def into_the_db(my_uid): + """Populates the db with 5 courses where my_uid is teacher and 5 where he is student""" + try: + session = session_maker() # setup the db session + connection = session.connection() + register_composites(connection) + + students = [] + # make a random amount of 100-200 students which we can use later to populate courses + num_students = random.randint(100, 200) + students = [student_generator() for _ in range(num_students)] + session.add_all(students) + session.commit() + + num_teachers = random.randint(5, 10) + teachers = [teacher_generator() for _ in range(num_teachers)] + session.add_all(teachers) + session.commit() # only after commit uid becomes available + + for _ in range(5): # 5 courses where my_uid is teacher + course_id = insert_course_into_db_get_id(session, my_uid) + # Add students to the course + subscribed_students = populate_course_students( + session, course_id, students) + populate_course_projects( + session, course_id, subscribed_students) + + for _ in range(5): # 5 courses where my_uid is a student + teacher_uid = teachers[random.randint(0, len(teachers)-1)].uid + course_id = insert_course_into_db_get_id(session, teacher_uid) + subscribed_students = populate_course_students( + session, course_id, students) + session.add(CourseStudent(course_id=course_id, uid=my_uid)) + session.commit() + subscribed_students.append(my_uid) # my_uid is also a student + populate_course_projects( + session, course_id, subscribed_students) + except SQLAlchemyError as e: + if session: # possibly error resulted in session being null + session.rollback() + raise e + finally: + session.close() + + +def insert_course_into_db_get_id(session, teacher_uid): + """Inserts a course with teacher_uid as teacher into the db and returns the course_id""" + course = generate_course(teacher_uid) + session.add(course) + session.commit() + return course.course_id + + +def populate_course_students(session, course_id, students): + """Populates the course with students and returns their uids as a list""" + num_students_in_course = random.randint(5, 30) + subscribed_students = random.sample(students, num_students_in_course) + student_relations = [course_student_generator(course_id, student.uid) + for student in subscribed_students] + + session.add_all(student_relations) + session.commit() + + return [student.uid for student in subscribed_students] + + +def populate_course_projects(session, course_id, students): + """Populates the course with projects and submissions, also creates the files""" + num_projects = random.randint(1, 3) + projects = generate_projects(course_id, num_projects) + session.add_all(projects) + session.commit() + for project in projects: + project_id = project.project_id + # Write assignment.md file + assignment_content = fake.text() + assignment_file_path = os.path.join( + UPLOAD_URL, str(project_id), "assignment.md") + os.makedirs(os.path.dirname(assignment_file_path), exist_ok=True) + with open(assignment_file_path, "w", encoding="utf-8") as assignment_file: + assignment_file.write(assignment_content) + populate_project_submissions(session, students, project_id) + + +def populate_project_submissions(session, students, project_id): + """Make submissions, 0 1 or 2 for each project per student""" + for student in students: + submissions = generate_submissions(project_id, student) + session.add_all(submissions) + session.commit() + for submission in submissions: + submission_directory = os.path.join(UPLOAD_URL, str( + project_id), "submissions", str(submission.submission_id), "submission") + os.makedirs(submission_directory, exist_ok=True) + submission_file_path = os.path.join( + submission_directory, "submission.md") + with open(submission_file_path, "w", encoding="utf-8") as submission_file: + submission_file.write(fake.text()) + + submission.submission_path = submission_directory + session.commit() # update submission path + +# Create a function to parse command line arguments +def parse_args(): + """Parse the given uid from the command line""" + parser = argparse.ArgumentParser(description='Populate the database') + parser.add_argument('my_uid', type=str, help='Your UID') + return parser.parse_args() + +# Main function to run when script is executed +def main(): + """Parse arguments, pass them to into_the_db function""" + args = parse_args() + into_the_db(args.my_uid) + +if __name__ == '__main__': + main() diff --git a/backend/seeder/titles.txt b/backend/seeder/titles.txt new file mode 100644 index 00000000..cd5a42ca --- /dev/null +++ b/backend/seeder/titles.txt @@ -0,0 +1,208 @@ +Computer Science +Principles of Economics +Modern Literature +Organic Chemistry +World History +Calculus and Analytic Geometry +Psychology +Microbiology Fundamentals +Principles of Marketing +Environmental Science +Sociology +Financial Accounting +Political Science and Government +Human Anatomy +Business Ethics +Philosophy +Statistics for Social Sciences +Cell Biology +Anthropology +Principles of Management +Macroeconomics +General Physics +English Composition +Human Physiology +Developmental Psychology +Linguistics +Genetics and Genomics +Principles of Finance +Art History +Microeconomics +Anatomy and Physiology +Marketing +Astronomy +Political Science +Microeconomics +Business +Cultural Anthropology +American History +World Religions +Chemistry +Environmental Science +Communication +General Chemistry +Cultural Anthropology +Human Biology +Theatre +Public Speaking +International Relations +Sociology +Criminal Justice +Statistics +Human Anatomy +Western Civilization +Literature +Biochemistry +Physical Anthropology +Human Physiology +Creative Writing +Film Studies +Music +Ethics +Philosophy of Science +Philosophy of Mind +Philosophy of Language +Political Philosophy +Philosophy of Religion +Epistemology +Metaphysics +Logic +Symbolic Logic +Modal Logic +Mathematical Logic +Computer Science +Programming +Algorithms +Data Structures +Software Engineering +Computer Networks +Operating Systems +Database Systems +Artificial Intelligence +Machine Learning +Computer Vision +Natural Language Processing +Robotics +Human-Computer Interaction +Virtual Reality +Augmented Reality +Web Development +Mobile Development +Development +Cybersecurity +Cryptography +Digital Forensics +Cloud Computing +Big Data +Data Science +Data Analytics +Data Visualization +Business Intelligence +Information Systems +E-commerce +Web Design +User Experience Design +User Interface Design +Graphic Design +Multimedia Design +Animation +Digital Art +Photography +Videography +Audio Production +Sound Design +Music Production +Film Production +Screenwriting +Directing +Cinematography +Film Editing +Visual Effects +Motion Graphics +3D Modeling +3D Animation +Design +Programming +Art +Sound +Narrative +Testing +Marketing +Publishing +Monetization +Analytics +Localization +Development Tools +Engines +AI +Networking +Servers +Security +Design Patterns +Theory +History +Culture +Studies +Journalism +Criticism +Law +Ethics +Philosophy +Psychology +Sociology +Anthropology +Archaeology +Economics +Marketing +Management +Development Methodologies +Production +Design Documents +Prototyping +Testing +Quality Assurance +Localization +Voice Acting +Music Composition +Sound Design +Art Direction +Animation +Character Design +Environment Design +Level Design +Storytelling +Writing +Dialogue +Cutscenes +Worldbuilding +Concept Art +Production Design +User Interface Design +User Experience Design +Interaction Design +Control Design +Camera Design +Interface Design +HUD Design +Menu Design +Navigation Design +Inventory Design +Map Design +Mini-map Design +Tutorial Design +Help System Design +Accessibility Design +Reward System Design +Progression System Design +Achievement System Design +Leaderboard Design +Social System Design +Community System Design +Feedback System Design +Chat System Design +Messaging System Design +Notification System Design +Ranking System Design +Matchmaking System Design +Voting System Design +Auction System Design \ No newline at end of file diff --git a/backend/test_auth_server/__main__.py b/backend/test_auth_server/__main__.py new file mode 100644 index 00000000..9cd7ae55 --- /dev/null +++ b/backend/test_auth_server/__main__.py @@ -0,0 +1,121 @@ +"""Main entry point for the application.""" +from dotenv import load_dotenv +from flask import Flask, Blueprint, request +from flask_restful import Resource, Api + + +index_bp = Blueprint("index", __name__) +index_endpoint = Api(index_bp) + +# Take the key the same as the id, uid can then be used in backend +token_dict = { + "teacher1":{ + "id":"Gunnar", + "jobTitle":"teacher", + "displayName":"Gunnar Brinckmann" + }, + "teacher2":{ + "id":"Bart", + "jobTitle":"teacher", + "displayName":"Bart Bart" + }, + "student1":{ + "id":"w_student", + "jobTitle":None, + "displayName":"William Student" + }, + "student01":{ + "id":"student01", + "jobTitle":None, + "displayName":"Student Nul Een" + }, + "course_admin1":{ + "id":"Rien", + "jobTitle":None, + "displayName":"Rien Admien" + }, + "del_user":{ + "id":"del", + "jobTitle":None, + "displayName":"Peter Deleter" + }, + "ad3_teacher":{ + "id":"brinkmann", + "jobTitle0":"teacher", + "displayName":"Gunnar Brinckmann" + }, + "student02":{ + "id":"student02", + "jobTitle":None, + "displayName":"Student Nul Twee" + }, + "admin1":{ + "id":"admin_person", + "jobTitle":"admin", + "displayName":"Admin Man" + }, + # Lowest authorized user to test login requirement + "login": { + "id": "login", + "jobTitle": None, + "displayName":"Lotte Login" + }, + # Student authorization access, associated with valid_... + "student": { + "id": "student", + "jobTitle": None, + "displayName":"Student" + }, + # Student authorization access, other + "student_other": { + "id": "student_other", + "jobTitle": None, + "displayName":"Student Other" + }, + # Teacher authorization access, associated with valid_... + "teacher": { + "id": "teacher", + "jobTitle": "teacher", + "displayName":"Gieter Teacher" + }, + # Teacher authorization access, other + "teacher_other": { + "id": "teacher_other", + "jobTitle": "teacher", + "displayName":"Teacher Other" + }, + # Admin authorization access, associated with valid_... + "admin": { + "id": "admin", + "jobTitle": "admin", + "displayName":"Admin Man" + }, + # Admin authorization access, other + "admin_other": { + "id": "admin_other", + "jobTitle": "admin", + "displayName":"Admin Woman" + } +} + +class Index(Resource): + """Api endpoint for the / route""" + + def get(self): + "Returns the data associated with the authorization bearer token" + auth = request.headers.get("Authorization") + if not auth: + return {"error":"Please give authorization"}, 401 + if token_dict.get(auth, None): + return token_dict[auth], 200 + return {"error":"Wrong address"}, 401 + + +index_bp.add_url_rule("/", view_func=Index.as_view("index")) + +load_dotenv() + +app = Flask(__name__) +app.register_blueprint(index_bp) + +app.run(debug=True, host='0.0.0.0', port=5001) diff --git a/backend/tests.yaml b/backend/tests.yaml new file mode 100644 index 00000000..fcba7cf4 --- /dev/null +++ b/backend/tests.yaml @@ -0,0 +1,53 @@ +version: '3.8' + +services: + postgres: + image: postgres:latest + environment: + POSTGRES_USER: test_user + POSTGRES_PASSWORD: test_password + POSTGRES_DB: test_database + healthcheck: + test: ["CMD-SHELL", "pg_isready -U test_user -d test_database"] + interval: 5s + timeout: 3s + retries: 3 + start_period: 5s + volumes: + - ./db_construct.sql:/docker-entrypoint-initdb.d/init.sql + auth-server: + build: + context: . + dockerfile: Dockerfile_auth_test + environment: + API_HOST: http://auth-server + volumes: + - .:/auth-app + command: ["test_auth_server"] + + + test-runner: + build: + context: . + dockerfile: Dockerfile.test + depends_on: + postgres: + condition: service_healthy + auth-server: + condition: service_started + privileged: true + environment: + POSTGRES_HOST: postgres # Use the service name defined in Docker Compose + POSTGRES_USER: test_user + POSTGRES_PASSWORD: test_password + POSTGRES_DB: test_database + API_HOST: http://api_is_here + TEST_AUTHENTICATION_URL: http://auth-server:5001 # Use the service name defined in Docker Compose + AUTH_METHOD: test + JWT_SECRET_KEY: Test123 + UPLOAD_FOLDER: /data/assignments + DOCS_JSON_PATH: static/OpenAPI_Object.yaml + DOCS_URL: /docs + volumes: + - .:/app + command: ["pytest"] \ No newline at end of file diff --git a/backend/tests/__init__.py b/backend/tests/__init__.py index e69de29b..ec43b874 100644 --- a/backend/tests/__init__.py +++ b/backend/tests/__init__.py @@ -0,0 +1,26 @@ +""" +This module is used to create a SQLAlchemy URL object for a PostgreSQL database. + +It uses environment variables to get the necessary database configuration details: +- 'POSTGRES_DB': The name of the database. +- 'POSTGRES_USER': The username to connect to the database. +- 'POSTGRES_PASSWORD': The password to connect to the database. +- 'POSTGRES_HOST': The host where the database is located. + +""" +import os +from sqlalchemy.engine.url import URL +from dotenv import load_dotenv +load_dotenv() + +DATABSE_NAME = os.getenv('POSTGRES_DB') +DATABASE_USER = os.getenv('POSTGRES_USER') +DATABASE_PASSWORD = os.getenv('POSTGRES_PASSWORD') +DATABASE_HOST = os.getenv('POSTGRES_HOST') +db_url = URL.create( + drivername="postgresql", + username=DATABASE_USER, + host=DATABASE_HOST, + database=DATABSE_NAME, + password=DATABASE_PASSWORD +) diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 582991ed..8a3f8ff0 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -1,22 +1,208 @@ -""" Configuration for pytest, Flask, and the test client.""" -import pytest -from project import create_app - -@pytest.fixture -def app(): - """A fixture that creates and configure a new app instance for each test. - Returns: - Flask -- A Flask application instance - """ - app = create_app() # pylint: disable=redefined-outer-name ; fixture testing requires the same name to be used +"""Root level fixtures""" + +from datetime import datetime +from zoneinfo import ZoneInfo +from os import getenv +from typing import Generator + +from pytest import fixture +from flask import Flask +from sqlalchemy.orm import Session + +from project import create_app_with_db +from project.sessionmaker import engine, Session as session_maker +from project.db_in import db, url +from project.models.course import Course +from project.models.user import User,Role +from project.models.project import Project +from project.models.course_relation import CourseStudent,CourseAdmin +from project.models.submission import Submission, SubmissionStatus +from project.models.group import Group + + +### CLIENT & SESSION ### +@fixture +def app() -> Generator[Flask, any, None]: + """Yield a Flask application instance with database""" + app = create_app_with_db(url) yield app -@pytest.fixture -def client(app): # pylint: disable=redefined-outer-name ; fixture testing requires the same name to be used - """A fixture that creates a test client for the app. - Arguments: - app {Flask} -- A Flask application instance - Returns: - Flask -- A Flask test client instance - """ - return app.test_client() +@fixture +def client(app: Flask) -> Generator[any, any, None]: + """Yield a test client""" + with app.test_client() as client: + with app.app_context(): + yield client + +@fixture +def session() -> Generator[Session, any, None]: + """Yield a database session for other fixtures to use""" + session = session_maker() + try: + # Create all tables + db.metadata.create_all(engine) + + # (OLD) Populate the database + session.add_all(users()) + session.commit() + session.add_all(courses()) + session.commit() + session.add_all(course_relations(session)) + session.commit() + session.add_all(projects(session)) + session.commit() + session.add_all(submissions(session)) + session.commit() + session.add(group(session)) + session.commit() + + yield session + finally: + # Rollback + session.rollback() + + # Drop all tables + for table in reversed(db.metadata.sorted_tables): + session.execute(table.delete()) + session.commit() + session.close() + + + +### AUTHENTICATION & AUTHORIZATION ### +@fixture(autouse=True) # Always run this before a test +def auth_tokens(session: Session) -> None: + """Add the authenticated users to the database""" + + session.add_all([ + User(uid="login", role=Role.STUDENT, display_name="Login User"), + User(uid="student", role=Role.STUDENT, display_name="Student Person"), + User(uid="student_other", role=Role.STUDENT, display_name="Student Other Person"), + User(uid="teacher", role=Role.TEACHER, display_name="Teacher Person"), + User(uid="teacher_other", role=Role.TEACHER, display_name="Teacher Other"), + User(uid="admin", role=Role.ADMIN, display_name="Admin Man"), + User(uid="admin_other", role=Role.ADMIN, display_name="Admin Woman") + ]) + session.commit() + + + +### OTHER ### +@fixture +def api_host() -> str: + """Get the API URL from the environment""" + return getenv("API_HOST") or "" + + + +### OLD ### +@fixture +def db_session(): + """Create a new database session for a test. + After the test, all changes are rolled back and the session is closed.""" + + db.metadata.create_all(engine) + session = Session() + + try: + yield session + finally: + # Rollback + session.rollback() + session.close() + + # Truncate all tables + for table in reversed(db.metadata.sorted_tables): + session.execute(table.delete()) + session.commit() + +def users(): + """Return a list of users to populate the database""" + return [ + User(uid="brinkmann", role=Role.ADMIN, display_name="Gunnar Brinkmann"), + User(uid="laermans", role=Role.ADMIN, display_name="Eric Laermans"), + User(uid="student01", role=Role.STUDENT, display_name="Student Zero One"), + User(uid="student02", role=Role.STUDENT, display_name="Student Zero Two") + ] + +def courses(): + """Return a list of courses to populate the database""" + return [ + Course(name="AD3", teacher="brinkmann"), + Course(name="RAF", teacher="laermans"), + ] + +def course_relations(session): + """Returns a list of course relations to populate the database""" + course_id_ad3 = session.query(Course).filter_by(name="AD3").first().course_id + course_id_raf = session.query(Course).filter_by(name="RAF").first().course_id + + return [ + CourseAdmin(course_id=course_id_ad3, uid="brinkmann"), + CourseStudent(course_id=course_id_ad3, uid="student01"), + CourseStudent(course_id=course_id_ad3, uid="student02"), + CourseAdmin(course_id=course_id_raf, uid="laermans"), + CourseStudent(course_id=course_id_raf, uid="student02") + ] + +def projects(session): + """Return a list of projects to populate the database""" + course_id_ad3 = session.query(Course).filter_by(name="AD3").first().course_id + course_id_raf = session.query(Course).filter_by(name="RAF").first().course_id + + return [ + Project( + title="B+ Trees", + description="Implement B+ trees", + deadlines=[("Deadline 1",datetime(2024,3,15,13,0,0))], + course_id=course_id_ad3, + visible_for_students=True, + archived=False, + regex_expressions=["solution"] + ), + Project( + title="Predicaten", + description="Predicaten project", + deadlines=[("Deadline 1", datetime(2023,3,15,13,0,0))], + course_id=course_id_raf, + visible_for_students=False, + archived=True, + regex_expressions=[".*"] + ) + ] + +def submissions(session): + """Return a list of submissions to populate the database""" + project_id_ad3 = session.query(Project).filter_by(title="B+ Trees").first().project_id + project_id_raf = session.query(Project).filter_by(title="Predicaten").first().project_id + + return [ + Submission( + uid="student01", + project_id=project_id_ad3, + grading=16, + submission_time=datetime(2024,3,14,12,0,0,tzinfo=ZoneInfo("GMT")), + submission_path="/submissions/1", + submission_status= SubmissionStatus.SUCCESS + ), + Submission( + uid="student02", + project_id=project_id_ad3, + submission_time=datetime(2024,3,14,23,59,59,tzinfo=ZoneInfo("GMT")), + submission_path="/submissions/2", + submission_status= SubmissionStatus.FAIL + ), + Submission( + uid="student02", + project_id=project_id_raf, + grading=15, + submission_time=datetime(2023,3,5,10,0,0,tzinfo=ZoneInfo("GMT")), + submission_path="/submissions/3", + submission_status= SubmissionStatus.SUCCESS + ) + ] + +def group(session): + """Return a group to populate the database""" + project_id = session.query(Project).filter_by(title="B+ Trees").first().project_id + return Group(project_id=project_id, group_size=4) diff --git a/backend/tests/endpoints/__init__.py b/backend/tests/endpoints/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/endpoints/conftest.py b/backend/tests/endpoints/conftest.py new file mode 100644 index 00000000..64e44f0d --- /dev/null +++ b/backend/tests/endpoints/conftest.py @@ -0,0 +1,385 @@ +"""Endpoint level fixtures""" + +import tempfile +from datetime import datetime +from zoneinfo import ZoneInfo +from typing import Any +from zipfile import ZipFile +import os + +import pytest +from pytest import fixture, FixtureRequest +from flask.testing import FlaskClient +from sqlalchemy.orm import Session + +from tests.utils.auth_login import get_csrf_from_login +from project.models.user import User,Role +from project.models.course import Course +from project.models.course_relation import CourseStudent, CourseAdmin +from project.models.course_share_code import CourseShareCode +from project.models.submission import Submission, SubmissionStatus +from project.models.project import Project, Runner + +### AUTHENTICATION & AUTHORIZATION ### +@fixture +def data_map(course: Course, project: Project, submission: Submission) -> dict[str, Any]: + """Map an id to data""" + return { + "@course_id": course.course_id, + "@project_id": project.project_id, + "@submission_id": submission.submission_id + } + +@fixture +def auth_test( + request: FixtureRequest, client: FlaskClient, data_map: dict[str, Any] + ) -> tuple[str, Any, str, bool, dict[str, Any]]: + """Add concrete test data to auth""" + endpoint, method, token, allowed = request.param + + for key, value in data_map.items(): + endpoint = endpoint.replace(key, str(value)) + csrf = get_csrf_from_login(client, token) if token else None + data = {k.strip("@"):v for k, v in data_map.items()} + + return endpoint, getattr(client, method), csrf, allowed, data + + + +### DATA FIELD TYPE ### +@fixture +def data_field_type_test( + request: FixtureRequest, client: FlaskClient, data_map: dict[str, Any] + ) -> tuple[str, Any, str, dict[str, Any]]: + """Add concrete test data to the data_field tests""" + endpoint, method, token, data = request.param + + for key, value in data_map.items(): + endpoint = endpoint.replace(key, str(value)) + for key, value in data.items(): + if isinstance(value, list): + data[key] = [data_map.get(v,v) for v in value] + elif value in data_map.keys(): + data[key] = data_map[value] + csrf = get_csrf_from_login(client, token) + return endpoint, getattr(client, method), csrf, data + + + +### QUERY PARAMETER ### +@fixture +def query_parameter_test(request: FixtureRequest, client: FlaskClient, data_map: dict[str, Any]): + """Add concrete test data to the query_parameter tests""" + endpoint, method, token, wrong_parameter = request.param + + for key, value in data_map.items(): + endpoint = endpoint.replace(key, str(value)) + csrf = get_csrf_from_login(client, token) + return endpoint, getattr(client, method), csrf, wrong_parameter + + + +### USERS ### +@fixture +def student(session: Session) -> User: + """Return a student entry""" + return session.get(User, "student") + +@fixture +def student_other(session: Session) -> User: + """Return a student entry""" + return session.get(User, "student_other") + +@fixture +def teacher(session: Session) -> User: + """Return a teacher entry""" + return session.get(User, "teacher") + +@fixture +def admin(session: Session) -> User: + """Return an admin entry""" + return session.get(User, "admin") + +@fixture +def admin_other(session: Session) -> User: + """Return an admin entry""" + return session.get(User, "admin_other") + + + +### COURSES ### +@fixture +def courses(session: Session, teacher: User) -> list[Course]: + """Return course entries""" + courses = [Course(name=f"SEL{i}", teacher=teacher.uid) for i in range(1, 3)] + session.add_all(courses) + session.commit() + return courses + +@fixture +def course(session: Session, student: User, teacher: User, admin: User) -> Course: + """Return a course entry""" + course = Course(name="SEL", ufora_id="C003784A_2023", teacher=teacher.uid) + session.add(course) + session.commit() + session.add(CourseStudent(course_id=course.course_id, uid=student.uid)) + session.add(CourseAdmin(course_id=course.course_id, uid=admin.uid)) + session.commit() + return course + + + +### PROJECTS ### +@fixture +def project(session: Session, course: Course): + """Return a project entry""" + project = Project( + title="project", + description="Test project", + deadlines=[{"deadline":"2024-05-23T21:59:59", "description":"Final deadline"}], + course_id=course.course_id, + visible_for_students=True, + archived=False, + runner=Runner.GENERAL, + regex_expressions=[".*.pdf"] + ) + session.add(project) + session.commit() + return project + +@fixture +def project_invisible(session: Session, course: Course): + """Return a project entry that is not visible for the student""" + project = Project( + title="invisible project", + description="Test project", + deadlines=[{"deadline":"2024-05-23T21:59:59", "description":"Final deadline"}], + course_id=course.course_id, + visible_for_students=False, + archived=False, + runner=Runner.GENERAL, + regex_expressions=[".*.pdf"] + ) + session.add(project) + session.commit() + return project + +@fixture +def project_archived(session: Session, course: Course): + """Return a project entry that is not visible for the student""" + project = Project( + title="archived project", + description="Test project", + deadlines=[{"deadline":"2024-05-23T21:59:59", "description":"Final deadline"}], + course_id=course.course_id, + visible_for_students=True, + archived=True, + runner=Runner.GENERAL, + regex_expressions=[".*.pdf"] + ) + session.add(project) + session.commit() + return project + +@fixture +def projects(project: Project, project_invisible: Project, project_archived: Project): + """Return a list of project entries""" + return [project, project_invisible, project_archived] + + + +### SUBMISSIONS ### +@fixture +def submission(session: Session, student: User, project: Project): + """Return a submission entry""" + submission = Submission( + uid=student.uid, + project_id=project.project_id, + submission_time=datetime(2024,5,23,22,00,00,tzinfo=ZoneInfo("GMT")), + submission_path="/1", + submission_status= SubmissionStatus.SUCCESS + ) + session.add(submission) + session.commit() + return submission + +### FILES ### +@fixture +def file_no_name(): + """Return a file with no name""" + descriptor, name = tempfile.mkstemp() + with open(descriptor, "w", encoding="UTF-8") as temp: + temp.write("This is a test file.") + with open(name, "rb") as temp: + yield temp, "" + os.remove(name) + +@fixture +def files(): + """Return a temporary file""" + name = "test.pdf" + with open(name, "w", encoding="UTF-8") as file: + file.write("This is a test file.") + with open(name, "rb") as file: + yield [(file, name)] + os.remove(name) + +@fixture +def file_assignment(): + """Return an assignment file for a project""" + assignment_file = "assignment.md" + assignment_content = "# Assignment" + with open(assignment_file, "w", encoding="UTF-8") as file: + file.write(assignment_content) + + zip_file = "project.zip" + with ZipFile(zip_file, "w") as zipf: + zipf.write(assignment_file) + + yield (zipf, zip_file) + + os.remove(assignment_file) + os.remove(zip_file) + + + +### OTHER ### +@pytest.fixture +def valid_submission(valid_user_entry, valid_project_entry): + """ + Returns a valid submission form + """ + return { + "uid": valid_user_entry.uid, + "project_id": valid_project_entry.project_id, + "grading": 16, + "submission_time": datetime(2024,3,14,12,0,0,tzinfo=ZoneInfo("GMT")), + "submission_path": "/submission/1", + "submission_status": SubmissionStatus.SUCCESS + } + +@pytest.fixture +def valid_submission_entry(session, valid_submission): + """ + Returns a submission that is in the database + """ + submission = Submission(**valid_submission) + session.add(submission) + session.commit() + return submission + +@pytest.fixture +def valid_user(): + """ + Returns a valid user form + """ + return { + "uid": "w_student", + "role": Role.STUDENT.name, + "display_name": "Valid User" + } + +@pytest.fixture +def valid_user_entry(session, valid_user): + """ + Returns a user that is in the database + """ + user = User(**valid_user) + session.add(user) + session.commit() + return user + +@pytest.fixture +def user_invalid_field(valid_user): + """ + Returns a user form with an invalid field + """ + valid_user["is_student"] = True + return valid_user + +@pytest.fixture +def valid_user_entries(session): + """ + Returns a list of users that are in the database + """ + users = [ + User(uid="del", role=Role.TEACHER, display_name="Peter Deleter"), + User(uid="pat", role=Role.TEACHER, display_name="Patrick Patcher"), + User(uid="u_get", role=Role.TEACHER, display_name="User Getter"), + User(uid="query_user", role=Role.ADMIN, display_name="Quentin Query")] + + session.add_all(users) + session.commit() + + return users + +@pytest.fixture +def course_teacher_ad(): + """A user that's a teacher for testing""" + ad_teacher = User(uid="Gunnar", role=Role.TEACHER, display_name="Gunnar Brinckmann") + return ad_teacher + +@pytest.fixture +def course_ad(course_teacher_ad: User): + """A course for testing, with the course teacher as the teacher.""" + ad2 = Course(name="Ad2", teacher=course_teacher_ad.uid) + return ad2 + +@pytest.fixture +def valid_project_entry(session, valid_project): + """A project for testing, with the course as the course it belongs to""" + valid_project["deadlines"] = [valid_project["deadlines"]] + project = Project(**valid_project) + + session.add(project) + session.commit() + return project + +@pytest.fixture +def valid_project(course): + """A function that return the json form data of a project""" + + data = { + "title": "Project", + "description": "Test project", + "deadlines": {"deadline": "2024-02-25T12:00:00", "description": "Deadline 1"}, + "course_id": course.course_id, + "visible_for_students": True, + "archived": False, + "regex_expressions": "*.pdf" + } + return data + +@pytest.fixture +def course_no_name(teacher): + """A course with no name""" + return {"name": "", "teacher": teacher.uid} + +@pytest.fixture +def course_empty_name(): + """A course with an empty name""" + return {"name": "", "teacher": "Bart"} + +@pytest.fixture +def invalid_course(): + """An invalid course for testing.""" + return {"invalid": "error"} + +@pytest.fixture +def valid_students_entries(session): + """Valid students for testing that are already in the db""" + students = [ + User(uid=f"student_sel2_{i}", role=Role.STUDENT) + for i in range(3) + ] + session.add_all(students) + session.commit() + return students + +@pytest.fixture +def share_code_admin(session, course): + """A course with share codes for testing.""" + share_code = CourseShareCode(course_id=course.course_id, for_admins=True) + session.add(share_code) + session.commit() + return share_code diff --git a/backend/tests/endpoints/course/courses_test.py b/backend/tests/endpoints/course/courses_test.py new file mode 100644 index 00000000..f2e20012 --- /dev/null +++ b/backend/tests/endpoints/course/courses_test.py @@ -0,0 +1,361 @@ +"""Tests the courses API endpoint""" + +from typing import Any +from dataclasses import fields +from pytest import mark +from flask.testing import FlaskClient +from tests.utils.auth_login import get_csrf_from_login +from tests.endpoints.endpoint import ( + TestEndpoint, + authentication_tests, + authorization_tests, + data_field_type_tests, + query_parameter_tests +) +from project.models.user import User +from project.models.course import Course + +class TestCourseEndpoint(TestEndpoint): + """Class to test the courses API endpoint""" + + ### AUTHENTICATION ### + # Where is login required + authentication_tests = \ + authentication_tests("/courses", ["get", "post"]) + \ + authentication_tests("/courses/@course_id", ["get", "patch", "delete"]) + \ + authentication_tests("/courses/@course_id/students", ["get", "post", "delete"]) + \ + authentication_tests("/courses/@course_id/admins", ["get", "post", "delete"]) + + @mark.parametrize("auth_test", authentication_tests, indirect=True) + def test_authentication(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test the authentication""" + super().authentication(auth_test) + + + + ### AUTHORIZATION ### + # Who can access what + authorization_tests = \ + authorization_tests("/courses", "get", + ["student", "student_other", "teacher", "teacher_other", "admin", "admin_other"], + []) + \ + authorization_tests("/courses", "post", + ["teacher", "teacher_other"], + ["student", "student_other", "admin", "admin_other"]) + \ + authorization_tests("/courses/@course_id", "patch", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/courses/@course_id", "delete", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/courses/@course_id/students", "get", + ["student", "student_other", "teacher", "teacher_other", "admin", "admin_other"], + []) + \ + authorization_tests("/courses/@course_id/students", "post", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/courses/@course_id/students", "delete", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/courses/@course_id/admins", "get", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/courses/@course_id/admins", "post", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/courses/@course_id/admins", "delete", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + + @mark.parametrize("auth_test", authorization_tests, indirect=True) + def test_authorization(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test the authorization""" + super().authorization(auth_test) + + + + ### DATA FIELD TYPE ### + # Test a data field by passing a list of values for which it should return bad request + data_field_type_tests = \ + data_field_type_tests("/courses", "post", "teacher", + {"name": "test", "ufora_id": "test"}, + {"name": [None, 0], "ufora_id": [0]} + ) + \ + data_field_type_tests("/courses/@course_id", "patch", "teacher", + {}, + {"name": [None, 0], "ufora_id": [0], "teacher": [None, 0, "student"]} + ) + \ + data_field_type_tests("/courses/@course_id/students", "post", "teacher", + {"students": ["student_other"]}, + {"students": [None, [None], ["no_user"], ["student"]]} + ) + \ + data_field_type_tests("/courses/@course_id/students", "delete", "teacher", + {"students": ["student"]}, + {"students": [None, [None], ["no_user"], ["student_other"]]} + ) + \ + data_field_type_tests("/courses/@course_id/admins", "post", "teacher", + {"admin_uid": "admin_other"}, + {"admin_uid": [None, "no_user", "admin"]} + ) + \ + data_field_type_tests("/courses/@course_id/admins", "delete", "teacher", + {"admin_uid": ["admin"]}, + {"admin_uid": [None, "no_user", "admin_other"]} + ) + + @mark.parametrize("data_field_type_test", data_field_type_tests, indirect=True) + def test_data_fields(self, data_field_type_test: tuple[str, Any, str, dict[str, Any]]): + """Test a data field typing""" + super().data_field_type(data_field_type_test) + + + + ### QUERY PARAMETER ### + # Test a query parameter, should return [] for wrong values + query_parameter_tests = \ + query_parameter_tests("/courses", "get", "teacher", [f.name for f in fields(Course)]) + + @mark.parametrize("query_parameter_test", query_parameter_tests, indirect=True) + def test_query_parameters(self, query_parameter_test: tuple[str, Any, str, bool]): + """Test a query parameter""" + super().query_parameter(query_parameter_test) + + + + ### COURSES ### + def test_get_courses(self, client: FlaskClient, courses: list[Course]): + """Test getting all courses""" + csrf = get_csrf_from_login(client, "teacher") + response = client.get("/courses", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + data = [course["name"] for course in response.json["data"]] + assert all(course.name in data for course in courses) + + def test_get_courses_name(self, client: FlaskClient, course: Course): + """Test getting courses for a given course name""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?name={course.name}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"][0]["name"] == course.name + + def test_get_courses_ufora_id(self, client: FlaskClient, course: Course): + """Test getting courses for a given ufora_id""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?ufora_id={course.ufora_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"][0]["ufora_id"] == course.ufora_id + + def test_get_courses_teacher(self, client: FlaskClient, course: Course): + """Test getting courses for a given teacher""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?teacher={course.teacher}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"][0]["teacher"] == course.teacher + + def test_get_courses_name_ufora_id(self, client: FlaskClient, course: Course): + """Test getting courses for a given course name and ufora_id""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?name={course.name}&ufora_id={course.ufora_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["name"] == course.name + assert data["ufora_id"] == course.ufora_id + + def test_get_courses_name_teacher(self, client: FlaskClient, course: Course): + """Test getting courses for a given course name and teacher""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?name={course.name}&teacher={course.teacher}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["name"] == course.name + assert data["teacher"] == course.teacher + + def test_get_courses_ufora_id_teacher(self, client: FlaskClient, course: Course): + """Test getting courses for a given ufora_id and teacher""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?ufora_id={course.ufora_id}&teacher={course.teacher}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["ufora_id"] == course.ufora_id + assert data["teacher"] == course.teacher + + def test_get_courses_name_ufora_id_teacher(self, client: FlaskClient, course: Course): + """Test getting courses for a given name, ufora_id and teacher""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses?name={course.name}&ufora_id={course.ufora_id}&teacher={course.teacher}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["name"] == course.name + assert data["ufora_id"] == course.ufora_id + assert data["teacher"] == course.teacher + + def test_post_courses(self, client: FlaskClient, teacher: User): + """Test posting a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.post("/courses", headers = {"X-CSRF-TOKEN":csrf}, + json = { + "name": "test", + "ufora_id": "test" + } + ) + assert response.status_code == 201 + response = client.get("/courses?name=test", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["ufora_id"] == "test" + assert data["teacher"] == teacher.uid + + + + ### COURSE ### + def test_get_course(self, client: FlaskClient, course: Course): + """Test getting a course""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses/{course.course_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"] + assert data["name"] == course.name + assert data["ufora_id"] == course.ufora_id + assert data["teacher"] == course.teacher + + def test_patch_course(self, client: FlaskClient, course: Course): + """Test patching a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.patch( + f"/courses/{course.course_id}", + headers = {"X-CSRF-TOKEN":csrf}, + json = {"name": "test"} + ) + assert response.status_code == 200 + assert response.json["data"]["name"] == "test" + + def test_delete_course(self, client: FlaskClient, course: Course): + """Test deleting a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.delete( + f"/courses/{course.course_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses/{course.course_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 404 + + + + ### COURSE STUDENTS ### + def test_get_students(self, client: FlaskClient, api_host: str, course: Course): + """Test getting the students fo a course""" + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses/{course.course_id}/students", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"][0]["uid"] == f"{api_host}/users/student" + + def test_post_students( + self, client: FlaskClient, api_host: str, course: Course, student_other: User + ): + """Test adding students to a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.post( + f"/courses/{course.course_id}/students", + headers = {"X-CSRF-TOKEN":csrf}, + json = { + "students": [student_other.uid] + } + ) + assert response.status_code == 201 + assert response.json["data"]["students"][0] == f"{api_host}/users/student_other" + + def test_delete_students( + self, client: FlaskClient, course: Course, student: User + ): + """Test deleting students from a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.delete( + f"/courses/{course.course_id}/students", + headers = {"X-CSRF-TOKEN":csrf}, + json = { + "students": [student.uid] + } + ) + assert response.status_code == 200 + csrf = get_csrf_from_login(client, "student") + response = client.get( + f"/courses/{course.course_id}/students", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"] == [] + + + + ### COURSE ADMINS ### + def test_get_admins(self, client: FlaskClient, api_host: str, course: Course): + """Test getting the admins of a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.get( + f"/courses/{course.course_id}/admins", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"][0]["uid"] == f"{api_host}/users/admin" + + def test_post_admins(self, client: FlaskClient, course: Course, admin_other: User): + """Test adding an admin to a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.post( + f"/courses/{course.course_id}/admins", + headers = {"X-CSRF-TOKEN":csrf}, + json = { + "admin_uid": admin_other.uid + } + ) + assert response.status_code == 201 + assert response.json["data"]["uid"] == admin_other.uid + + def test_delete_admins(self, client: FlaskClient, course: Course, admin: User): + """Test deleting an admin from a course""" + csrf = get_csrf_from_login(client, "teacher") + response = client.delete( + f"/courses/{course.course_id}/admins", + headers = {"X-CSRF-TOKEN":csrf}, + json = { + "admin_uid": admin.uid + } + ) + assert response.status_code == 204 + response = client.get( + f"/courses/{course.course_id}/admins", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + assert response.json["data"] == [] diff --git a/backend/tests/endpoints/course/share_link_test.py b/backend/tests/endpoints/course/share_link_test.py new file mode 100644 index 00000000..a01706f0 --- /dev/null +++ b/backend/tests/endpoints/course/share_link_test.py @@ -0,0 +1,58 @@ +""" +This file contains the tests for the share link endpoints of the course resource. +""" + +from tests.utils.auth_login import get_csrf_from_login + + +class TestCourseShareLinks: + """ + Class that will respond to the /courses/course_id/students link + teachers should be able to assign and remove students from courses, + and everyone should be able to list all students assigned to a course + """ + + def test_get_share_links(self, client, course): + """Test whether the share links are accessible""" + csrf = get_csrf_from_login(client, "teacher") + response = client.get(f"courses/{course.course_id}/join_codes", + headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + + def test_post_share_links(self, client, course): + """Test whether the share links are accessible to post to""" + csrf = get_csrf_from_login(client, "teacher") + response = client.post( + f"courses/{course.course_id}/join_codes", + json={"for_admins": True}, headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 201 + + def test_delete_share_links(self, client, share_code_admin): + """Test whether the share links are accessible to delete""" + csrf = get_csrf_from_login(client, "teacher") + response = client.delete( + f"courses/{share_code_admin.course_id}/join_codes/{share_code_admin.join_code}", + headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + + def test_get_share_links_404(self, client): + """Test whether the share links are accessible""" + csrf = get_csrf_from_login(client, "teacher2") + response = client.get("courses/0/join_codes", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 404 + + def test_post_share_links_404(self, client): + """Test whether the share links are accessible to post to""" + csrf = get_csrf_from_login(client, "teacher2") + response = client.post("courses/0/join_codes", + json={"for_admins": True}, + headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 404 + + def test_for_admins_required(self, client, course): + """Test whether the for_admins field is required""" + csrf = get_csrf_from_login(client, "teacher") + response = client.post(f"courses/{course.course_id}/join_codes", + json={}, + headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 400 diff --git a/backend/tests/endpoints/endpoint.py b/backend/tests/endpoints/endpoint.py new file mode 100644 index 00000000..09767842 --- /dev/null +++ b/backend/tests/endpoints/endpoint.py @@ -0,0 +1,124 @@ +"""Base class for endpoint tests""" + +from typing import Any +from pytest import param + +def authentication_tests(endpoint: str, methods: list[str]) -> list[Any]: + """Transform the format to single authentication tests""" + tests = [] + + for method in methods: + for token in [None, "0123456789", "login"]: + allowed = token == "login" + tests.append(param( + (endpoint, method, token, allowed), + id = f"{endpoint} {method.upper()} " \ + f"({token} {'allowed' if allowed else 'disallowed'})" + )) + + return tests + +def authorization_tests( + endpoint: str, method: str, allowed_tokens: list[str], disallowed_tokens: list[str] + ) -> list[Any]: + """Transform the format to single authorization tests""" + tests = [] + + for token in (allowed_tokens + disallowed_tokens): + allowed: bool = token in allowed_tokens + tests.append(param( + (endpoint, method, token, allowed), + id = f"{endpoint} {method.upper()} ({token} {'allowed' if allowed else 'disallowed'})" + )) + + return tests + +def data_field_type_tests( + endpoint: str, method: str, token: str, data: dict[str, Any], changes: dict[str, list[Any]] + ) -> list[Any]: + """Transform the format to single data_field_type tests""" + tests = [] + + # Test by adding an incorrect field + new_data = dict(data) + new_data["field"] = None + tests.append(param( + (endpoint, method, token, new_data), + id = f"{endpoint} {method.upper()} {token} (field None 400)" + )) + + # Test the with the given changes + for key, values in changes.items(): + for value in values: + new_data = dict(data) + new_data[key] = value + tests.append(param( + (endpoint, method, token, new_data), + id = f"{endpoint} {method.upper()} {token} ({key} {value} 400)" + )) + + return tests + +def query_parameter_tests( + endpoint: str, method: str, token: str, parameters: list[str] + ) -> list[Any]: + """Transform the format to single query_parameter tests""" + tests = [] + + # Test with an incorrect parameter + new_endpoint = endpoint + "?parameter=0" + tests.append(param( + (new_endpoint, method, token, True), + id = f"{new_endpoint} {method.upper()} {token} (parameter 0 400)" + )) + + for parameter in parameters: + new_endpoint = endpoint + f"?{parameter}=0" + tests.append(param( + (new_endpoint, method, token, False), + id = f"{new_endpoint} {method.upper()} {token} ({parameter} 0 200&[])" + )) + + return tests + +class TestEndpoint: + """Base class for endpoint tests""" + + def authentication(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test if the authentication for the given endpoint works""" + + endpoint, method, csrf, allowed, data = auth_test + + if csrf: + response = method(endpoint, headers = {"X-CSRF-TOKEN":csrf}, data = data) + else: + response = method(endpoint, json = data) + assert allowed == (response.status_code != 401) + + def authorization(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test if the authorization for the given endpoint works""" + + endpoint, method, csrf, allowed, data = auth_test + + response = method(endpoint, headers = {"X-CSRF-TOKEN":csrf}, data = data) + assert allowed == (response.status_code != 403) + + def data_field_type(self, test: tuple[str, Any, str, dict[str, Any]]): + """Test if the datatypes are properly checked for data fields""" + + endpoint, method, csrf, data = test + + response = method(endpoint, headers = {"X-CSRF-TOKEN":csrf}, json = data) + assert response.status_code == 400 + + def query_parameter(self, test: tuple[str, Any, str, bool]): + """Test the query parameter""" + + endpoint, method, csrf, wrong_parameter = test + + response = method(endpoint, headers = {"X-CSRF-TOKEN":csrf}) + if wrong_parameter: + assert wrong_parameter == (response.status_code == 200) + + if not wrong_parameter: + assert response.json["data"] == [] diff --git a/backend/tests/endpoints/index_test.py b/backend/tests/endpoints/index_test.py new file mode 100644 index 00000000..9f1cceee --- /dev/null +++ b/backend/tests/endpoints/index_test.py @@ -0,0 +1,19 @@ +"""Test the base routes of the application""" + +import yaml + + +def test_home(client): + """Test whether the index page is accesible""" + response = client.get("/") + assert response.status_code == 200 + + +def test_openapi_spec(client): + """Test whether the required fields of the openapi spec are present""" + response = client.get("/") + response_text = response.text + response_yaml = yaml.safe_load(response_text) + + assert "openapi" in response_yaml + assert "info" in response_yaml diff --git a/backend/tests/endpoints/project_test.py b/backend/tests/endpoints/project_test.py new file mode 100644 index 00000000..2c4f56ab --- /dev/null +++ b/backend/tests/endpoints/project_test.py @@ -0,0 +1,260 @@ +"""Tests for project endpoints.""" + +from typing import Any +import json + +from pytest import mark +from flask.testing import FlaskClient + +from project.models.project import Project +from tests.utils.auth_login import get_csrf_from_login +from tests.endpoints.endpoint import ( + TestEndpoint, + authentication_tests, + authorization_tests, + query_parameter_tests +) + +class TestProjectsEndpoint(TestEndpoint): + """Class to test the projects API endpoint""" + + ### AUTHENTICATION ### + # Where is login required + authentication_tests = \ + authentication_tests("/projects", ["get", "post"]) + \ + authentication_tests("/projects/@project_id", ["get", "patch", "delete"]) + \ + authentication_tests("/projects/@project_id/assignment", ["get"]) + \ + authentication_tests("/projects/@project_id/submissions-download", ["get"]) + \ + authentication_tests("/projects/@project_id/latest-per-user", ["get"]) + + @mark.parametrize("auth_test", authentication_tests, indirect=True) + def test_authentication(self, auth_test: tuple[str, Any, str, bool]): + """Test the authentication""" + super().authentication(auth_test) + + + + ### AUTHORIZATION ### + # Who can access what + authorization_tests = \ + authorization_tests("/projects", "get", + ["student", "student_other", "teacher", "teacher_other", "admin", "admin_other"], + []) + \ + authorization_tests("/projects", "post", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/projects/@project_id", "get", + ["student", "teacher", "admin"], + ["student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/projects/@project_id", "patch", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/projects/@project_id", "delete", + ["teacher"], + ["student", "student_other", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/projects/@project_id/assignment", "get", + ["student", "teacher", "admin"], + ["student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/projects/@project_id/submissions-download", "get", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("/projects/@project_id/latest-per-user", "get", + ["teacher", "admin"], + ["student_other", "teacher_other", "admin_other"]) + + @mark.parametrize("auth_test", authorization_tests, indirect=True) + def test_authorization(self, auth_test: tuple[str, Any, str, bool]): + """Test the authorization""" + super().authorization(auth_test) + + + + ### QUERY PARAMETER ### + # Test a query parameter, should return [] for wrong values + query_parameter_tests = \ + query_parameter_tests("/projects", "get", "student", ["project_id", "title", "course_id"]) + + @mark.parametrize("query_parameter_test", query_parameter_tests, indirect=True) + def test_query_parameters(self, query_parameter_test: tuple[str, Any, str, bool]): + """Test a query parameter""" + super().query_parameter(query_parameter_test) + + + + ### PROJECTS ### + def test_get_projects(self, client: FlaskClient, projects: list[Project]): + """Test getting all projects""" + response = client.get( + "/projects", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"] + assert [project["title"] in ["project", "archived project"] for project in data] + + def test_get_projects_project_id( + self, client: FlaskClient, api_host: str, project: Project, projects: list[Project] + ): + """Test getting all projects for a given project_id""" + response = client.get( + f"/projects?project_id={project.project_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "teacher")} + ) + assert response.status_code == 200 + data = response.json["data"] + assert len(data) == 1 + assert data[0]["project_id"] == f"{api_host}/projects/{project.project_id}" + + def test_get_projects_title( + self, client: FlaskClient, project: Project, projects: list[Project] + ): + """Test getting all projects for a given title""" + response = client.get( + f"/projects?title={project.title}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "teacher")} + ) + assert response.status_code == 200 + data = response.json["data"] + assert len(data) == 1 + assert data[0]["title"] == project.title + + def test_get_projects_course_id( + self, client: FlaskClient, project: Project, projects: list[Project] + ): + """Test getting all projects for a given course_id""" + response = client.get( + f"/projects?course_id={project.course_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "teacher")} + ) + assert response.status_code == 200 + assert len(response.json["data"]) == len(projects) + + + + ### PROJECT ### + def test_patch_project(self, client: FlaskClient, project: Project): + """Test patching a project""" + csrf = get_csrf_from_login(client, "teacher") + response = client.patch( + f"/projects/{project.project_id}", + headers = {"X-CSRF-TOKEN":csrf}, + data = { + "title": "A new title" + } + ) + assert response.status_code == 200 + response = client.get( + f"/projects/{project.project_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + data = response.json["data"] + assert data["title"] == "A new title" + + def test_delete_project(self, client: FlaskClient, project: Project): + """Test deleting a project""" + csrf = get_csrf_from_login(client, "teacher") + response = client.delete( + f"/projects/{project.project_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + response = client.get( + f"/projects/{project.project_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 404 + + + +### OLD TESTS ### +def test_assignment_download(client, valid_project): + """ + Method for assignment download + """ + + valid_project["deadlines"] = json.dumps(valid_project["deadlines"]) + with open("tests/resources/testzip.zip", "rb") as zip_file: + valid_project["assignment_file"] = zip_file + # post the project + csrf = get_csrf_from_login(client, "teacher") + response = client.post( + "/projects", + headers = {"X-CSRF-TOKEN":csrf}, + data=valid_project, + content_type='multipart/form-data', + ) + assert response.status_code == 201 + project_id = response.json["data"]["project_id"] + response = client.get(f"/projects/{project_id}/assignment", headers = {"X-CSRF-TOKEN":csrf}) + # 404 because the file is not found, no assignment.md in zip file + assert response.status_code == 404 + +def test_not_found_download(client): + """ + Test a not present project download + """ + csrf = get_csrf_from_login(client, "teacher2") + response = client.get("/projects", headers = {"X-CSRF-TOKEN":csrf}) + # get an index that doesnt exist + response = client.get("/projects/-1/assignments", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 404 + +def test_projects_home(client): + """Test home project endpoint.""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.get("/projects", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + +def test_getting_all_projects(client): + """Test getting all projects""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.get("/projects", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + assert isinstance(response.json['data'], list) + +def test_post_project(client, valid_project): + """Test posting a project to the database and testing if it's present""" + valid_project["deadlines"] = json.dumps(valid_project["deadlines"]) + csrf = get_csrf_from_login(client, "teacher") + with open("tests/resources/testzip.zip", "rb") as zip_file: + valid_project["assignment_file"] = zip_file + # post the project + response = client.post( + "/projects", + data=valid_project, + content_type='multipart/form-data', headers = {"X-CSRF-TOKEN":csrf} + ) + + assert response.status_code == 201 + + # check if the project with the id is present + project_id = response.json["data"]["project_id"] + response = client.get(f"/projects/{project_id}", headers = {"X-CSRF-TOKEN":csrf}) + + assert response.status_code == 200 + +def test_remove_project(client, valid_project_entry): + """Test removing a project to the datab and fetching it, testing if it's not present anymore""" + csrf = get_csrf_from_login(client, "teacher") + project_id = valid_project_entry.project_id + response = client.delete(f"/projects/{project_id}", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + + # check if the project isn't present anymore and the delete indeed went through + response = client.get(f"/projects/{project_id}", headers = {"X-CSRF-TOKEN":csrf}) + assert response.status_code == 404 + +def test_patch_project(client, valid_project_entry): + """Test functionality of the PATCH method for projects""" + csrf = get_csrf_from_login(client, "teacher") + project_id = valid_project_entry.project_id + + new_title = valid_project_entry.title + "hallo" + new_archived = not valid_project_entry.archived + + response = client.patch(f"/projects/{project_id}", json={ + "title": new_title, "archived": new_archived + }, headers = {"X-CSRF-TOKEN":csrf}) + + assert response.status_code == 200 diff --git a/backend/tests/endpoints/submissions_test.py b/backend/tests/endpoints/submissions_test.py new file mode 100644 index 00000000..5e34ed0c --- /dev/null +++ b/backend/tests/endpoints/submissions_test.py @@ -0,0 +1,218 @@ +"""Test the submissions API endpoint""" + +from os import getenv +from typing import Any + +from pytest import mark +from flask.testing import FlaskClient + +from project.models.user import User +from project.models.project import Project +from project.models.submission import Submission +from tests.utils.auth_login import get_csrf_from_login +from tests.endpoints.endpoint import ( + TestEndpoint, + authentication_tests, + authorization_tests, + query_parameter_tests +) + +API_HOST = getenv("API_HOST") + +class TestSubmissionsEndpoint(TestEndpoint): + """Class to test the submissions API endpoint""" + + ### AUTHENTICATION ### + # Where is login required + authentication_tests = \ + authentication_tests("/submissions", ["get", "post"]) + \ + authentication_tests("/submissions/@submission_id", ["get", "patch"]) + \ + authentication_tests("/submissions/@submission_id/download", ["get"]) + + @mark.parametrize("auth_test", authentication_tests, indirect=True) + def test_authentication(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test the authentication""" + super().authentication(auth_test) + + + + ### AUTHORIZATION ### + # Who can access what + authorization_tests = \ + authorization_tests("/submissions", "get", + ["student", "student_other", "teacher", "teacher_other", "admin", "admin_other"], + []) + \ + authorization_tests("/submissions", "post", + ["student"], + ["student_other", "teacher", "teacher_other", "admin", "admin_other"]) + \ + authorization_tests("/submissions/@submission_id", "get", + ["student", "teacher", "admin"], + ["student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("submissions/@submission_id", "patch", + ["teacher", "admin"], + ["student", "student_other", "teacher_other", "admin_other"]) + \ + authorization_tests("submissions/@submission_id/download", "get", + ["student", "teacher", "admin"], + ["student_other", "teacher_other", "admin_other"]) + + @mark.parametrize("auth_test", authorization_tests, indirect=True) + def test_authorization(self, auth_test: tuple[str, Any, str, bool, dict[str, Any]]): + """Test the authorization""" + super().authorization(auth_test) + + + + ### QUERY PARAMETER ### + # Test a query parameter, should return [] for wrong values + query_parameter_tests = \ + query_parameter_tests("/submissions", "get", "student", ["uid", "project_id"]) + + @mark.parametrize("query_parameter_test", query_parameter_tests, indirect=True) + def test_query_parameters(self, query_parameter_test: tuple[str, Any, str, bool]): + """Test a query parameter""" + super().query_parameter(query_parameter_test) + + + + ### SUBMISSIONS ### + def test_get_submissions(self, client: FlaskClient, api_host: str, submission: Submission): + """Test getting all submissions""" + response = client.get( + "/submissions", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + + def test_get_submissions_user( + self, client: FlaskClient, api_host: str, student: User, submission: Submission + ): + """Test getting all submissions for a given user""" + response = client.get( + f"/submissions?uid={student.uid}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + assert data["uid"] == f"{api_host}/users/{student.uid}" + + def test_get_submissions_project( + self, client: FlaskClient, api_host: str, project: Project, submission: Submission + ): + """Test getting all submissions for a given project""" + response = client.get( + f"/submissions?project_id={project.project_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + assert data["project_id"] == f"{api_host}/projects/{project.project_id}" + + def test_get_submissions_user_project( + self, client: FlaskClient, api_host: str, + student: User, project: Project, submission: Submission + ): + """Test getting all submissions for a given user and project""" + response = client.get( + f"/submissions?uid={student.uid}&project_id={project.project_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"][0] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + assert data["uid"] == f"{api_host}/users/{student.uid}" + assert data["project_id"] == f"{api_host}/projects/{project.project_id}" + + def test_post_submissions(self, client: FlaskClient, project: Project, files): + """Test posting a submission""" + csrf = get_csrf_from_login(client, "student") + response = client.post( + "/submissions", + headers = {"X-CSRF-TOKEN":csrf}, + data = {"project_id":project.project_id, "files": files} + ) + assert response.status_code == 201 + submission_id = response.json["data"]["submission_id"].split("/")[-1] + response = client.get( + f"/submissions/{submission_id}", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 + + def test_post_submissions_invalid_project_id(self, client: FlaskClient, files): + """Test posting a submission when given an invalid project""" + response = client.post( + "/submissions", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")}, + data = {"project_id":"zero", "files": files} + ) + assert response.status_code == 400 + + def test_post_submissions_invalid_file(self, client: FlaskClient, file_no_name): + """Test posting a submission when given a file with no name""" + response = client.post( + "/submissions", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")}, + data = {"project_id":"zero", "files": file_no_name} + ) + assert response.status_code == 400 + + + + ### SUBMISSION ### + def test_get_submission(self, client: FlaskClient, api_host: str, submission: Submission): + """Test getting a submission""" + response = client.get( + f"/submissions/{submission.submission_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "student")} + ) + assert response.status_code == 200 + data = response.json["data"] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + + def test_patch_submission_grading( + self, client: FlaskClient, api_host: str, submission: Submission + ): + """Test patching the grading to a submission""" + response = client.patch( + f"/submissions/{submission.submission_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "teacher")}, + data = {"grading":20} + ) + assert response.status_code == 200 + data = response.json["data"] + assert data["submission_id"] == f"{api_host}/submissions/{submission.submission_id}" + assert data["grading"] == 20.0 + + def test_patch_submission_invalid_grading(self, client: FlaskClient, submission: Submission): + """Test posting a submission when given an invalid project""" + response = client.patch( + f"/submissions/{submission.submission_id}", + headers = {"X-CSRF-TOKEN":get_csrf_from_login(client, "teacher")}, + data = {"grading":"zero"} + ) + assert response.status_code == 400 + + + + ### SUBMISSION DOWNLOAD ### + def test_get_submission_download( + self, client: FlaskClient, project: Project, files + ): + """Test downloading a submission""" + csrf = get_csrf_from_login(client, "student") + response = client.post( + "/submissions", + headers = {"X-CSRF-TOKEN":csrf}, + data = {"project_id":project.project_id, "files": files} + ) + assert response.status_code == 201 + submission_id = response.json["data"]["submission_id"].split("/")[-1] + response = client.get( + f"/submissions/{submission_id}/download", + headers = {"X-CSRF-TOKEN":csrf} + ) + assert response.status_code == 200 diff --git a/backend/tests/endpoints/user_test.py b/backend/tests/endpoints/user_test.py new file mode 100644 index 00000000..70e5390f --- /dev/null +++ b/backend/tests/endpoints/user_test.py @@ -0,0 +1,201 @@ +""" +This module tests user management endpoints. + +- test_post_delete_user: Tests user creation, deletion, and error handling for deletion + of non-existent user. +- test_get_users: Tests retrieval of all users, ensuring the response is a list. +- test_patch_user: Tests user update functionality and error handling for updating + non-existent user. +""" +from dataclasses import asdict +import pytest +from sqlalchemy.orm import sessionmaker +from sqlalchemy import create_engine +from project.models.user import User,Role +from project.db_in import db +from tests import db_url +from tests.utils.auth_login import get_csrf_from_login + +engine = create_engine(db_url) +Session = sessionmaker(bind=engine) +@pytest.fixture +def user_db_session(): + """Create a new database session for the user tests. + After the test, all changes are rolled back and the session is closed.""" + db.metadata.create_all(engine) + session = Session() + session.add_all( + [User(uid="del", role=Role.TEACHER), + User(uid="pat", role=Role.TEACHER), + User(uid="u_get", role=Role.TEACHER), + User(uid="query_user", role=Role.ADMIN) + ] + ) + session.commit() + yield session + session.rollback() + session.close() # pylint: disable=duplicate-code; + for table in reversed(db.metadata.sorted_tables): + session.execute(table.delete()) + session.commit() + + +class TestUserEndpoint: + """Class to test user management endpoints.""" + + def test_delete_user(self, client, valid_user_entry): + """Test deleting a user.""" + # Delete the user + csrf = get_csrf_from_login(client, "student1") + response = client.delete(f"/users/{valid_user_entry.uid}", + headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + + csrf = get_csrf_from_login(client, "teacher1") + # If student 1 sends this request, he would get added again + get_response = client.get(f"/users/{valid_user_entry.uid}", + headers={"X-CSRF-TOKEN":csrf}) + + assert get_response.status_code == 404 + + def test_delete_user_not_yourself(self, client, valid_user_entry): + """Test deleting a user that is not the user the authentication belongs to.""" + # Delete the user + csrf = get_csrf_from_login(client, "teacher1") + response = client.delete(f"/users/{valid_user_entry.uid}", + headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 403 + + get_response = client.get(f"/users/{valid_user_entry.uid}", + headers={"X-CSRF-TOKEN":csrf}) + + assert get_response.status_code == 200 + + def test_delete_not_present(self, client): + """Test deleting a user that does not exist.""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.delete("/users/-20", headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 403 # User does not exist, so you are not the user + + def test_post_no_authentication(self, client, user_invalid_field): + """Test posting without authentication.""" + response = client.post("/users", json=user_invalid_field) + assert response.status_code == 403 # POST to /users is not allowed + + def test_post_authenticated(self, client, valid_user): + """Test posting with wrong authentication.""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.post("/users", data=valid_user, + headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 403 # POST to /users is not allowed + + def test_wrong_form_post(self, client, user_invalid_field): + """Test posting with a wrong form.""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.post("/users", data=user_invalid_field, + headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 403 + + def test_get_all_users(self, client, valid_user_entries): + """Test getting all users.""" + csrf = get_csrf_from_login(client, "teacher1") + response = client.get("/users", headers={"X-CSRF-TOKEN":csrf}) + assert response.status_code == 200 + # Check that the response is a list (even if it's empty) + assert isinstance(response.json["data"], list) + for valid_user in valid_user_entries: + assert valid_user.uid in [user["uid"] for user in response.json["data"]] + + def test_get_all_users_no_authentication(self, client): + """Test getting all users without authentication.""" + response = client.get("/users") + assert response.status_code == 401 + + def test_get_all_users_wrong_authentication(self, client): + """Test getting all users with wrong authentication.""" + client.get("/auth?code=wrong") + response = client.get("/users") + assert response.status_code == 401 + + def test_get_one_user(self, client, valid_user_entry): + """Test getting a single user.""" + client.get("/auth?code=teacher1") + response = client.get(f"users/{valid_user_entry.uid}") + assert response.status_code == 200 + assert "data" in response.json + + def test_get_one_user_no_authentication(self, client, valid_user_entry): + """Test getting a single user without authentication.""" + response = client.get(f"users/{valid_user_entry.uid}") + assert response.status_code == 401 + + def test_get_one_user_wrong_authentication(self, client, valid_user_entry): + """Test getting a single user with wrong authentication.""" + res = client.get("/auth?code=wrong") + assert res.status_code == 401 + response = client.get(f"users/{valid_user_entry.uid}") + assert response.status_code == 401 + + def test_patch_user_not_authorized(self, client, admin, valid_user_entry): + """Test updating a user.""" + + if valid_user_entry.role == Role.TEACHER: + new_role = Role.ADMIN + if valid_user_entry.role == Role.ADMIN: + new_role = Role.STUDENT + else: + new_role = Role.TEACHER + new_role = new_role.name + csrf = get_csrf_from_login(client, "student01") + response = client.patch(f"/users/{valid_user_entry.uid}", json={ + 'role': new_role + }, headers={'X-CSRF-TOKEN':csrf}) + assert response.status_code == 403 # Patching a user is not allowed as a not-admin + + def test_patch_user(self, client, admin, valid_user_entry): + """Test updating a user.""" + + if valid_user_entry.role == Role.TEACHER: + new_role = Role.ADMIN + if valid_user_entry.role == Role.ADMIN: + new_role = Role.STUDENT + else: + new_role = Role.TEACHER + new_role = new_role.name + csrf = get_csrf_from_login(client, "admin") + response = client.patch(f"/users/{valid_user_entry.uid}", json={ + 'role': new_role + }, headers={'X-CSRF-TOKEN':csrf}) + assert response.status_code == 200 + + def test_patch_non_existent(self, client, admin): + """Test updating a non-existent user.""" + csrf = get_csrf_from_login(client, "admin") + response = client.patch("/users/-20", json={ + 'role': Role.TEACHER.name + }, headers={'X-CSRF-TOKEN':csrf}) + assert response.status_code == 404 + + def test_patch_non_json(self, client, admin, valid_user_entry): + """Test sending a non-JSON patch request.""" + valid_user_form = asdict(valid_user_entry) + if valid_user_form["role"] == Role.TEACHER.name: + valid_user_form["role"] = Role.STUDENT.name + else: + valid_user_form["role"] = Role.TEACHER.name + csrf = get_csrf_from_login(client, "admin") + response = client.patch(f"/users/{valid_user_form['uid']}", data=valid_user_form, + headers={'X-CSRF-TOKEN':csrf}) + assert response.status_code == 415 + + def test_get_users_with_query(self, client, valid_user_entries): + """Test getting users with a query.""" + get_csrf_from_login(client, "admin") + # Send a GET request with query parameters, this is a nonsense entry but good for testing + response = client.get("/users?role=ADMIN") + assert response.status_code == 200 + + # Check that the response contains only the user that matches the query + users = response.json["data"] + for user in users: + assert Role[user["role"]] == Role.ADMIN diff --git a/backend/tests/models/course_relation_test.py b/backend/tests/models/course_relation_test.py new file mode 100644 index 00000000..ba8fa238 --- /dev/null +++ b/backend/tests/models/course_relation_test.py @@ -0,0 +1,83 @@ +"""Course relation tests""" + +from pytest import raises, mark +from sqlalchemy.orm import Session +from sqlalchemy.exc import IntegrityError +from project.models.course import Course +from project.models.course_relation import CourseAdmin + +class TestCourseRelationModel: + """Class to test the CourseRelation model""" + + def test_create_course_relation(self, session: Session): + """Test if a course relation can be created""" + course_id = session.query(Course).filter_by(name="AD3").first().course_id + relation = CourseAdmin(course_id=course_id, uid="laermans") + session.add(relation) + session.commit() + assert session.get(CourseAdmin, (course_id, "laermans")) is not None + + def test_query_course_relation(self, session: Session): + """Test if a course relation can be queried""" + assert session.query(CourseAdmin).count() == 2 + relation = session.query(CourseAdmin).filter_by(uid="brinkmann").first() + assert relation is not None + assert relation.course_id == \ + session.query(Course).filter_by(name="AD3").first().course_id + + def test_update_course_relation(self, session: Session): + """Test if a course relation can be updated""" + relation = session.query(CourseAdmin).filter_by(uid="brinkmann").first() + course = session.query(Course).filter_by(name="RAF").first() + relation.course_id = course.course_id + session.commit() + assert session.get(CourseAdmin, (course.course_id, "brinkmann")) is not None + + def test_delete_course_relation(self, session: Session): + """Test if a course relation can be deleted""" + relation = session.query(CourseAdmin).first() + session.delete(relation) + session.commit() + assert session.get(CourseAdmin, (relation.course_id,relation.uid)) is None + assert session.query(CourseAdmin).count() == 1 + + def test_primary_key(self, session: Session): + """Test the primary key""" + relations = session.query(CourseAdmin).all() + with raises(IntegrityError): + relations[0].course_id = relations[1].course_id + relations[0].uid = relations[1].uid + session.commit() + session.rollback() + + def test_foreign_key_course_id(self, session: Session): + """Test the foreign key course_id""" + course = session.query(Course).filter_by(name="RAF").first() + relation = session.query(CourseAdmin).filter_by(uid="brinkmann").first() + relation.course_id = course.course_id + session.commit() + assert session.get(CourseAdmin, (course.course_id, "brinkmann")) is not None + with raises(IntegrityError): + relation.course_id = 0 + session.commit() + session.rollback() + + def test_foreign_key_uid(self, session: Session): + """Test the foreign key uid""" + relation = session.query(CourseAdmin).filter_by(uid="brinkmann").first() + relation.uid = "laermans" + session.commit() + assert session.get(CourseAdmin, (relation.course_id,relation.uid)) is not None + with raises(IntegrityError): + relation.uid = "unknown" + session.commit() + session.rollback() + + @mark.parametrize("property_name", ["course_id", "uid"]) + def test_property_not_nullable(self, session: Session, property_name: str): + """Test if the property is not nullable""" + relation = session.query(CourseAdmin).first() + with raises(IntegrityError): + setattr(relation, property_name, None) + session.commit() + session.rollback() diff --git a/backend/tests/models/course_test.py b/backend/tests/models/course_test.py new file mode 100644 index 00000000..3c17ecad --- /dev/null +++ b/backend/tests/models/course_test.py @@ -0,0 +1,59 @@ +"""Course model tests""" + +from pytest import raises, mark +from sqlalchemy.orm import Session +from sqlalchemy.exc import IntegrityError +from project.models.course import Course + +class TestCourseModel: + """Class to test the Course model""" + + def test_create_course(self, session: Session): + """Test if a course can be created""" + course = Course(name="SEL2", ufora_id="C003784A_2023", teacher="brinkmann") + session.add(course) + session.commit() + assert session.get(Course, course.course_id) is not None + assert session.query(Course).count() == 3 + + def test_query_course(self, session: Session): + """Test if a course can be queried""" + assert session.query(Course).count() == 2 + course = session.query(Course).filter_by(name="AD3").first() + assert course is not None + assert course.teacher == "brinkmann" + + def test_update_course(self, session: Session): + """Test if a course can be updated""" + course = session.query(Course).filter_by(name="AD3").first() + course.name = "AD2" + session.commit() + assert session.get(Course, course.course_id).name == "AD2" + + def test_delete_course(self, session: Session): + """Test if a course can be deleted""" + course = session.query(Course).first() + session.delete(course) + session.commit() + assert session.get(Course, course.course_id) is None + assert session.query(Course).count() == 1 + + def test_foreign_key_teacher(self, session: Session): + """Test the foreign key teacher""" + course = session.query(Course).filter_by(name="AD3").first() + course.teacher = "laermans" + session.commit() + assert session.get(Course, course.course_id).teacher == "laermans" + with raises(IntegrityError): + course.teacher = "unknown" + session.commit() + session.rollback() + + @mark.parametrize("property_name", ["name","teacher"]) + def test_property_not_nullable(self, session: Session, property_name: str): + """Test if the property is not nullable""" + course = session.query(Course).first() + with raises(IntegrityError): + setattr(course, property_name, None) + session.commit() + session.rollback() diff --git a/backend/tests/models/group_test.py b/backend/tests/models/group_test.py new file mode 100644 index 00000000..1844fe9e --- /dev/null +++ b/backend/tests/models/group_test.py @@ -0,0 +1,52 @@ +"""Tests for the Group and GroupStudent model""" +from sqlalchemy.orm import Session + +from project.models.project import Project +from project.models.group import Group +from project.models.group_student import GroupStudent +from project.models.user import User + + +class TestGroupModel: + """Test class for Group and GroupStudent tests""" + + def test_group_model(self, session: Session): + "Group create test" + project = session.query(Project).first() + group = Group(project_id=project.project_id, group_size=4) + session.add(group) + session.commit() + assert session.query(Group).filter_by( + group_id=group.group_id, project_id=project.project_id) is not None + assert session.query(Group).first().group_size == 4 + + def test_group_join(self, session: Session): + """Group join test""" + project = session.query(Project).filter_by(title="B+ Trees").first() + group = session.query(Group).filter_by( + project_id=project.project_id).first() + student = session.query(User).first() + + student_group = GroupStudent( + group_id=group.group_id, uid=student.uid, project_id=project.project_id) + session.add(student_group) + session.commit() + assert session.query(GroupStudent).first().uid == student.uid + + def test_group_leave(self, session: Session): + """Group leave test""" + project = session.query(Project).filter_by(title="B+ Trees").first() + group = session.query(Group).filter_by( + project_id=project.project_id).first() + student = session.query(User).first() + + student_group = GroupStudent( + group_id=group.group_id, uid=student.uid, project_id=project.project_id) + session.add(student_group) + session.commit() + + session.delete(student_group) + session.commit() + + assert session.query(GroupStudent).filter_by( + uid=student.uid, group_id=group.group_id, project_id=project.project_id).first() is None diff --git a/backend/tests/models/project_test.py b/backend/tests/models/project_test.py new file mode 100644 index 00000000..cda7c562 --- /dev/null +++ b/backend/tests/models/project_test.py @@ -0,0 +1,76 @@ +"""Project model tests""" + +from datetime import datetime +from pytest import raises, mark +from sqlalchemy.orm import Session +from sqlalchemy.exc import IntegrityError +from project.models.course import Course +from project.models.project import Project + +class TestProjectModel: + """Class to test the Project model""" + + def test_create_project(self, session: Session): + """Test if a project can be created""" + course = session.query(Course).first() + project = Project( + title="Pigeonhole", + description="A new project", + deadlines=[("Deadline 1", datetime(2024,12,31,23,59,59))], + course_id=course.course_id, + visible_for_students=True, + archived=False, + regex_expressions=[r".*"] + ) + session.add(project) + session.commit() + assert project.project_id is not None + assert session.query(Project).count() == 3 + + def test_query_project(self, session: Session): + """Test if a project can be queried""" + assert session.query(Project).count() == 2 + project = session.query(Project).filter_by(title="Predicaten").first() + assert project is not None + assert project.course_id == session.query(Course).filter_by(name="RAF").first().course_id + + def test_update_project(self, session: Session): + """Test if a project can be updated""" + project = session.query(Project).filter_by(title="B+ Trees").first() + project.title = "Trees" + project.description = "Implement 3 trees of your choosing" + session.commit() + updated_project = session.get(Project, project.project_id) + assert updated_project.title == "Trees" + assert updated_project.description == "Implement 3 trees of your choosing" + + def test_delete_project(self, session: Session): + """Test if a project can be deleted""" + project = session.query(Project).first() + session.delete(project) + session.commit() + assert session.get(Project, project.project_id) is None + assert session.query(Project).count() == 1 + + def test_foreign_key_course_id(self, session: Session): + """Test the foreign key course_id""" + course = session.query(Course).filter_by(name="RAF").first() + project = session.query(Project).filter_by(title="B+ Trees").first() + project.course_id = course.course_id + session.commit() + assert project.course_id == course.course_id + with raises(IntegrityError): + project.course_id = 0 + session.commit() + session.rollback() + + @mark.parametrize("property_name", + ["title","description","course_id","visible_for_students","archived"] + ) + def test_property_not_nullable(self, session: Session, property_name: str): + """Test if the property is not nullable""" + project = session.query(Project).first() + with raises(IntegrityError): + setattr(project, property_name, None) + session.commit() + session.rollback() diff --git a/backend/tests/models/submission_test.py b/backend/tests/models/submission_test.py new file mode 100644 index 00000000..28918c5e --- /dev/null +++ b/backend/tests/models/submission_test.py @@ -0,0 +1,92 @@ +"""Submission model tests""" + +from datetime import datetime +from pytest import raises, mark +from sqlalchemy.orm import Session +from sqlalchemy.exc import IntegrityError +from project.models.project import Project +from project.models.submission import Submission, SubmissionStatus + +class TestSubmissionModel: + """Class to test the Submission model""" + + def test_create_submission(self, session: Session): + """Test if a submission can be created""" + project = session.query(Project).filter_by(title="B+ Trees").first() + submission = Submission( + uid="student01", + project_id=project.project_id, + submission_time=datetime(2023,3,15,13,0,0), + submission_path="/submissions", + submission_status=SubmissionStatus.SUCCESS + ) + session.add(submission) + session.commit() + assert submission.submission_id is not None + assert session.query(Submission).count() == 4 + + def test_query_submission(self, session: Session): + """Test if a submission can be queried""" + assert session.query(Submission).count() == 3 + submission = session.query(Submission).filter_by(uid="student01").first() + assert submission is not None + + def test_update_submission(self, session: Session): + """Test if a submission can be updated""" + submission = session.query(Submission).filter_by(uid="student01").first() + submission.uid = "student02" + submission.grading = 20 + session.commit() + updated_submission = session.get(Submission, submission.submission_id) + assert updated_submission.uid == "student02" + assert updated_submission.grading == 20 + + def test_delete_submission(self, session: Session): + """Test if a submission can be deleted""" + submission = session.query(Submission).first() + session.delete(submission) + session.commit() + assert session.get(Submission, submission.submission_id) is None + assert session.query(Submission).count() == 2 + + def test_foreign_key_uid(self, session: Session): + """Test the foreign key uid""" + submission = session.query(Submission).filter_by(uid="student01").first() + submission.uid = "student02" + session.commit() + assert submission.uid == "student02" + with raises(IntegrityError): + submission.uid = "unknown" + session.commit() + session.rollback() + + def test_foreign_key_project_id(self, session: Session): + """Test the foreign key project_id""" + submission = session.query(Submission).filter_by(uid="student01").first() + project = session.query(Project).filter_by(title="Predicaten").first() + submission.project_id = project.project_id + session.commit() + assert submission.project_id == project.project_id + with raises(IntegrityError): + submission.project_id = 0 + session.commit() + session.rollback() + + @mark.parametrize("property_name", + ["uid","project_id","submission_time","submission_path","submission_status"] + ) + def test_property_not_nullable(self, session: Session, property_name: str): + """Test if the property is not nullable""" + submission = session.query(Submission).first() + with raises(IntegrityError): + setattr(submission, property_name, None) + session.commit() + session.rollback() + + def test_grading_constraint(self, session: Session): + """Test if the grading is between 0 and 20""" + submission = session.query(Submission).first() + with raises(IntegrityError): + submission.grading = 80 + session.commit() + session.rollback() diff --git a/backend/tests/models/user_test.py b/backend/tests/models/user_test.py new file mode 100644 index 00000000..d607ebad --- /dev/null +++ b/backend/tests/models/user_test.py @@ -0,0 +1,57 @@ +"""User model tests""" + +from pytest import raises, mark +from sqlalchemy.orm import Session +from sqlalchemy.exc import IntegrityError +from project.models.user import User,Role + +class TestUserModel: + """Class to test the User model""" + + def test_create_user(self, session: Session): + """Test if a user can be created""" + user = User(uid="user01", role=Role.STUDENT) + session.add(user) + session.commit() + assert session.get(User, "user01") is not None + assert session.query(User).count() == 12 + + def test_query_user(self, session: Session): + """Test if a user can be queried""" + assert session.query(User).count() == 11 + teacher = session.query(User).filter_by(uid="brinkmann").first() + assert teacher is not None + assert teacher.role == Role.ADMIN + + def test_update_user(self, session: Session): + """Test if a user can be updated""" + student = session.query(User).filter_by(uid="student01").first() + student.role = Role.ADMIN + session.commit() + assert session.get(User, "student01").role == Role.ADMIN + + def test_delete_user(self, session: Session): + """Test if a user can be deleted""" + user = session.query(User).first() + session.delete(user) + session.commit() + assert session.get(User, user.uid) is None + assert session.query(User).count() == 10 + + @mark.parametrize("property_name", ["uid"]) + def test_property_not_nullable(self, session: Session, property_name: str): + """Test if the property is not nullable""" + user = session.query(User).first() + with raises(IntegrityError): + setattr(user, property_name, None) + session.commit() + session.rollback() + + @mark.parametrize("property_name", ["uid"]) + def test_property_unique(self, session: Session, property_name: str): + """Test if the property is unique""" + users = session.query(User).all() + with raises(IntegrityError): + setattr(users[0], property_name, getattr(users[1], property_name)) + session.commit() + session.rollback() diff --git a/backend/tests/resources/testzip.zip b/backend/tests/resources/testzip.zip new file mode 100644 index 0000000000000000000000000000000000000000..f99b6a05484f7a0a5ffa496e382505de4987825a GIT binary patch literal 175 zcmWIWW@h1H00H-^>Y!K#PkYOlEEiTb3sVE5z;bdT5CiFgaB@mZZa5FHn zykKTv023fJX_+~xTmjyUOmfV)43hxa!N3T_TN*(ugwd=JqtT2F@MdKLsbd5}KOpT5 H;xGUJBf=uQ literal 0 HcmV?d00001 diff --git a/backend/tests/test_base.py b/backend/tests/test_base.py deleted file mode 100644 index 803b8456..00000000 --- a/backend/tests/test_base.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Test the base routes of the application""" - -def test_home(client): - """Test whether the index page is accesible""" - response = client.get("/") - assert response.status_code == 200 diff --git a/backend/tests/utils/__init__.py b/backend/tests/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/utils/auth_login.py b/backend/tests/utils/auth_login.py new file mode 100644 index 00000000..90f3d3d8 --- /dev/null +++ b/backend/tests/utils/auth_login.py @@ -0,0 +1,13 @@ +"""A file for utility functions to help handling the authentication in tests""" + +def get_csrf_from_login(client, code): + """Log the user in, adding the access token cookie and + return the csrf token cookie to be used in the requests + """ + response = client.get(f"/auth?code={code}") + csrf = next((cookie for cookie + in response.headers.getlist('Set-Cookie') + if 'csrf_access_token' in cookie), "") + if csrf != "": + csrf = csrf.split(";")[0].split("=")[1] + return csrf diff --git a/backend/tests/utils/submission_evaluators/__init__.py b/backend/tests/utils/submission_evaluators/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/utils/submission_evaluators/base_evaluators_test.py b/backend/tests/utils/submission_evaluators/base_evaluators_test.py new file mode 100644 index 00000000..8eac4f5e --- /dev/null +++ b/backend/tests/utils/submission_evaluators/base_evaluators_test.py @@ -0,0 +1,19 @@ +""" +This file contains tests for functions that are applicable to all evaluators. +""" +from os import path +from shutil import rmtree +from project.utils.submissions.file_handling import create_submission_folder + +def test_create_submission_folder_creates(submission_root): + """ + Test whether the create_submission_folder function creates the submission folder. + """ + submission_id = 1 + project_id = 1 + submission_path = create_submission_folder(submission_id, project_id) + assert path.join(submission_path) \ + == path.join(submission_root, str(project_id), str(submission_id)) + assert path.exists(submission_path) + assert path.exists(path.join(submission_path, "submission")) + rmtree(submission_path) diff --git a/backend/tests/utils/submission_evaluators/conftest.py b/backend/tests/utils/submission_evaluators/conftest.py new file mode 100644 index 00000000..92fd363b --- /dev/null +++ b/backend/tests/utils/submission_evaluators/conftest.py @@ -0,0 +1,44 @@ +""" +This file contains the global fixtures for the submission evaluators tests. +""" +from shutil import rmtree +from os import environ, makedirs, path +import pytest +from project.models.submission import Submission +from project.models.project import Project + +@pytest.fixture +def submission_root(): + """ + Create a submission root folder for the tests. + When the tests are done, the folder is removed recursively. + """ + submission_root = path.join(path.dirname(__file__), "submissions-root") + environ["SUBMISSIONS_ROOT_PATH"] = submission_root + makedirs(submission_root, exist_ok=True) + yield submission_root + rmtree(submission_root) + +def prep_submission(submission_root: str) -> tuple[Submission, Project]: + """ + Prepare a submission for testing by creating the appropriate files and + submission and project model objects. + + Args: + submission_root (str): The folder of the submission to prepare. + + Returns: + tuple: The submission and project model objects. + """ + project_id = 2 + submission = Submission(submission_id=2, project_id=project_id) + root = path.join(path.dirname(__file__), "resources", submission_root) + submission.submission_path = path.join(root, "submission") + makedirs(path.join(submission.submission_path, "output"), exist_ok=True) + return submission, path.join(root, "assignment") + +def cleanup_after_test(submission_root: str) -> None: + """ + Remove the submission output root folder after a test. + """ + rmtree(path.join(submission_root, "output")) diff --git a/backend/tests/utils/submission_evaluators/python_test.py b/backend/tests/utils/submission_evaluators/python_test.py new file mode 100644 index 00000000..0d8b548c --- /dev/null +++ b/backend/tests/utils/submission_evaluators/python_test.py @@ -0,0 +1,76 @@ +""" +This file contains tests for the python submission evaluator. +""" + +from os import path +import pytest +from project.utils.submissions.evaluator import evaluate +from project.utils.submissions.file_handling import create_submission_folder +from project.models.submission import Submission +from project.models.project import Project +from .conftest import prep_submission, cleanup_after_test + +@pytest.fixture +def project_path_succes(): + """ + Return the path to a project with a succesful test case. + """ + return path.join(path.dirname(__file__), "resources", "python", "tc_1/assignment") + +@pytest.fixture +def evaluate_python(submission_root, project_path_succes): + """Evaluate a python submission with a succesful test case.""" + project_id = 1 + submission = Submission(submission_id=1, project_id=project_id) + submission.submission_path = create_submission_folder(submission_root, project_id) + return evaluate(submission, project_path_succes, "PYTHON", False), submission.submission_path + +def prep_submission_and_clear_after_py(tc_folder: str) -> tuple[Submission, Project]: + """ + Prepare a submission for testing by creating the appropriate files and + submission and project model objects. + + Args: + tc_folder (str): The folder of the test case to prepare. + + Returns: + tuple: The submission and project model objects. + """ + return prep_submission(path.join("python", tc_folder)) + +def test_base_python_evaluator(evaluate_python): + """Test whether the base python evaluator works.""" + exit_code, _ = evaluate_python + assert exit_code == 0 + +def test_makes_output_folder(evaluate_python): + """Test whether the evaluator makes the output folder.""" + _, submission_path = evaluate_python + assert path.exists(path.join(submission_path, "output")) + +def test_makes_log_file(evaluate_python): + """Test whether the evaluator makes the log file.""" + _, submission_path = evaluate_python + assert path.exists(path.join(submission_path, "output", "test_output.log")) + +def test_logs_output(evaluate_python): + """Test whether the evaluator logs the output of the script.""" + _, submission_path = evaluate_python + with open(path.join(submission_path, "output", "test_output.log",), + "r", + encoding="utf-8") as output_file: + assert "Hello, World!" in output_file.read() + +def test_with_dependency(): + """Test whether the evaluator works with a dependency.""" + submission, project = prep_submission_and_clear_after_py("tc_2") + exit_code = evaluate(submission, project, "PYTHON", False) + cleanup_after_test(submission.submission_path) + assert exit_code == 0 + +def test_dependency_manifest(): + """Test whether the evaluator works with a dependency manifest.""" + submission, project = prep_submission_and_clear_after_py("tc_3") + exit_code = evaluate(submission, project, "PYTHON", False) + cleanup_after_test(submission.submission_path) + assert exit_code != 0 diff --git a/backend/tests/utils/submission_evaluators/resources/python/__init__.py b/backend/tests/utils/submission_evaluators/resources/python/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_test.zip b/backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_test.zip new file mode 100644 index 0000000000000000000000000000000000000000..8d1ad5d86ede7f51c979b2291880c946429049cc GIT binary patch literal 184 zcmWIWW@h1H0D%dUJ0ld&HH*mr*&xgf#6_if@g=FnC3?jfsmU4n3Q8WSIXU?{3gP)h zIVp-tTwJLYnI#Ga0p5&E_6)d;Q2`nR0t#Rf#ZWG&AR~hWgMXLkw^?1c7@?}*RDd@t P8;HXQgt0){6)Xb)*T5iZ literal 0 HcmV?d00001 diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_tests.sh b/backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_tests.sh new file mode 100644 index 00000000..d2eab023 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_1/assignment/run_tests.sh @@ -0,0 +1,3 @@ +echo "Hello, World!" + +exit 0 \ No newline at end of file diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_2/assignment/run_tests.sh b/backend/tests/utils/submission_evaluators/resources/python/tc_2/assignment/run_tests.sh new file mode 100644 index 00000000..1d2231f3 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_2/assignment/run_tests.sh @@ -0,0 +1,3 @@ + + +python /submission/hello_world.py \ No newline at end of file diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/hello_world.py b/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/hello_world.py new file mode 100644 index 00000000..eae889e9 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/hello_world.py @@ -0,0 +1,4 @@ +import emoji + +if __name__ == "__main__": + print(emoji.emojize("Hello, World! :red_heart:")) diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/requirements.txt b/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/requirements.txt new file mode 100644 index 00000000..cdd21623 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_2/submission/submission/requirements.txt @@ -0,0 +1 @@ +emoji diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/req-manifest.txt b/backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/req-manifest.txt new file mode 100644 index 00000000..e69de29b diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/run_tests.sh b/backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/run_tests.sh new file mode 100644 index 00000000..1d2231f3 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_3/assignment/run_tests.sh @@ -0,0 +1,3 @@ + + +python /submission/hello_world.py \ No newline at end of file diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/hello_world.py b/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/hello_world.py new file mode 100644 index 00000000..eae889e9 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/hello_world.py @@ -0,0 +1,4 @@ +import emoji + +if __name__ == "__main__": + print(emoji.emojize("Hello, World! :red_heart:")) diff --git a/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/requirements.txt b/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/requirements.txt new file mode 100644 index 00000000..cdd21623 --- /dev/null +++ b/backend/tests/utils/submission_evaluators/resources/python/tc_3/submission/submission/requirements.txt @@ -0,0 +1 @@ +emoji diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..8f007744 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' + +services: + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + ports: + - "8080:80" + depends_on: + - backend + + backend: + build: + context: ./backend + dockerfile: Dockerfile + ports: + - "5000:5000" + diff --git a/documentation/.gitignore b/documentation/.gitignore new file mode 100644 index 00000000..e6e9ac43 --- /dev/null +++ b/documentation/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/documentation/README.md b/documentation/README.md new file mode 100644 index 00000000..a0daa9a7 --- /dev/null +++ b/documentation/README.md @@ -0,0 +1,27 @@ +# UGent-3 project peristerónas user guide + +## Introduction +Project peristerónas has a lot of features, therefore a detailed user guide is available to consult. + +## Usage +### Development +If you want to develop on the site, run the following command: + ```sh + npm run start + ``` +This creates a lightweight version of the site, if you want to test a certain language version of the site you can use the command: + ```sh + npm run start -- --locale [language] + ``` + + ### Deployment + When you're ready to deploy, run the following command to run the proper version of the site: + ```sh + npm run build + ``` + + A static version will be built that you can access in the directory `build/`, you can then run the static site by using the command: + + ```sh + npm run serve + ``` diff --git a/documentation/babel.config.js b/documentation/babel.config.js new file mode 100644 index 00000000..e00595da --- /dev/null +++ b/documentation/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/documentation/docs/evaluators/_category_.json b/documentation/docs/evaluators/_category_.json new file mode 100644 index 00000000..b5b1ee5e --- /dev/null +++ b/documentation/docs/evaluators/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Evaluators", + "position": 3, + "link": { + "type": "generated-index", + "description": "Choose an evaluator of which you need to learn the usage." + } +} \ No newline at end of file diff --git a/documentation/docs/evaluators/custom_evaluator.md b/documentation/docs/evaluators/custom_evaluator.md new file mode 100644 index 00000000..017ee51e --- /dev/null +++ b/documentation/docs/evaluators/custom_evaluator.md @@ -0,0 +1,3 @@ +# Custom evaluator +When selecting the custom runner the user has to provide his own Dockerfile. +This gives freedom to do everything you want with it, and it is completely customizable to your own needs. \ No newline at end of file diff --git a/documentation/docs/evaluators/general_evaluator.md b/documentation/docs/evaluators/general_evaluator.md new file mode 100644 index 00000000..0b644869 --- /dev/null +++ b/documentation/docs/evaluators/general_evaluator.md @@ -0,0 +1,7 @@ +# General evaluator +The general runner is capable of running the following languages with only the standard libraries included +- Python +- Ruby +- Java + +All the user has to is upload a run_tests.sh in the project files and the script will run when a submission is uploaded by a student. \ No newline at end of file diff --git a/documentation/docs/evaluators/python_evaluator.md b/documentation/docs/evaluators/python_evaluator.md new file mode 100644 index 00000000..c50653c8 --- /dev/null +++ b/documentation/docs/evaluators/python_evaluator.md @@ -0,0 +1,13 @@ +# Python evaluator +## General usage +This evaluator is responsible for running and executing tests on a student's Python code. + +## Structure +When submitting the project a teacher can add a requirements manifest `req-manifest.txt`, this way only the packages in the requirements file are usable on the evaluator. + +When no manifest is present, students are able to install their own depedencies with a `requirements.txt` and a `dev-requirements.txt`. +Or the teacher can add a `requirements.txt` if they want to pre install dependencies that a are present for testing the project. + +## Running tests +When a `run_tests.sh` is present in the project assignment files, it will be run when the student is submitting their code. +When running tests, it's important to note that the root of the student's submission will be `/submission`. diff --git a/documentation/docs/intro.md b/documentation/docs/intro.md new file mode 100644 index 00000000..7f0840ef --- /dev/null +++ b/documentation/docs/intro.md @@ -0,0 +1,7 @@ +--- +sidebar_position: 1 +--- + +# Project user guide + +If you need help using project Péristeronas you can read the user guide below. diff --git a/documentation/docs/projectform/_category_.json b/documentation/docs/projectform/_category_.json new file mode 100644 index 00000000..79ce8b28 --- /dev/null +++ b/documentation/docs/projectform/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Project upload form", + "position": 4, + "link": { + "type": "generated-index", + "description": "User guide on how to upload a new project" + } +} \ No newline at end of file diff --git a/documentation/docs/projectform/image.png b/documentation/docs/projectform/image.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c70ee8b1c258a172da803d792ea9072893b45c GIT binary patch literal 2313 zcmbW3`9Bj39LFa;EK#mP?vkVA7|XRNL*&ec97|*7XmiXJb3M*I5h^0bgeP)Dk7GGQ z=GsJZBpM+s$0JO`uxHPo@I2qw>;3({zOUE!_4@wu`5u4R+1wQ1JI4nA00b<|P3$>w zo`W-xhvP3u?;<(jc(Abr9LTXKAd0}rB|=Q^gunvOA>l}z7r@&;0PA%n*c0dFxCyBnP zW9@xLl)|LDmeh~i>(X%f~%p%e$Y1`xVUIB#Z0IM4Hc=%+FO zH4YG&^2WyOJF3rq6!*)ysfo#Cq?DADSe@=Mcf4v;ESu4%7qzQ#w>D>f-b0m2VPq-@ zOp|;A0?J>$OwtQpQts8R(tKXF6?GKA;yuLx-V$z&%<|{4EQfNvlHK?85Y|S%oU7XT_v$t zETDP10MQAhr?y#f7NNTFX@#bzyJXWNEP zC+7F&Q!jnuughK65I^4eBV?Y*Qn_-aXFZI&UEb`xP+ndhp~nL=O%mvswG9moRZO{t zD%Cf^As#Hp7@w8=Y&n9kDb-l|71FKYjw&FVTR^H#vsmarZG7UTzr} zP;Xk=$*l}X1cSl5QSV}?3gOn#hO%AvGC7T5FcA_K27_sRg36Faq&-~Drn~yjMNixh z2}N`&W{BWPKPRbYs%M*2!T2eqa}_NA%(~j>{4=Af^Q_ojog?jRUa>;taJtj3ledhi ztny300q-XEkV+bt@QB!Coyy=>^`XV}Law{lf`|tvV9M@qvW6Xp(e^kRg1wa8dFq$c zfs#_|$y{yh)ss1D-o-Y{rV_Z&QNb>g+< zhq#2zy{N2b&+OgZZ8gNnt2^g9@+<4h4ktrMH}$aA?-8IjPck_+Z#Np6CUIF7dFbR6 zyzyO`MU2dgR${dkRh4JA+p?30tuiRYy1t=Ktkh#MQr+P<2}~SW4mZY#!X(Uio zuk7fBAdMO12+NUrd?Z#oxaC#Bw53|$ueGF9s;){0&2-^@fROdquGfGG-Lf3K{}hnx z{9_;>rX#k~Yh`7H2az(np(F@YHhJotwC&7F7>~A@U=YEy`W-RIHd(fL$F=CaL7Htp zCHz~Hy@aE@Y5MQ!K;Z(t;AA43Cn75P4g0Ol+Mil_H(W(>b&qYwda&sfu(jkXx$!5%atcux zf?zsnxr&O4W*UUbyR(;~t)ySn!&7zWlv@rCXFB6F(@hdPFN&@5K7klY`JmVE5#1<# z=ci`=#R*X@bgOJMGMu>BJ~rnO5BpFXjH9PyKxrUY+o-aS5oJUq+R?x7LBuL^@?h|G zOD$88SHli-;mn**sf4D$Wt|*|fz3g+z;{s4trJNb$-uP(xrlJM$w&# z6&u{C8`S+I)I$4vOj--tjCnj{ zhjtKACTrsqb2Pq0{sC2&o)__QuqtSb2ah8ltsCKE?B;x8o5i5(rbWT9blZ`nY_O!| zyDgw6`zM4I2C?uQ)^#I3|N1seg&BGCs3aQHYpwvA*Fu8G<_frR`HQx@xiTJ(Y@xhE z7PJ0dSG*7nU1DIPl%&ho;1ml^-qx}tYU7&SFq3cO*FjGDW?$PPv^a~q+NF^~uP@uj zo+~SeKX0mQTv=Hes9#9-_-l*??iS+bfqj;@P8Sp{5m$={w~`Yy$1l~_)TpgvCMPDs z1`v8>FoH(|g+duafCun5YZb)#ITL@HF@x~j#{l)6FF4ETm0m2W1o9+QNVclS@?R3? zFC#iJ_M)6MCF6~=RByvz37=Ol3IYXFd+b{af9Mw4`1$$Oc_>=h6P|#d)OG<=x)ZyR z?U$emPwT*>E;{NFflIXHzfosMR*hkfzbY*n@2t}|$)TF!@%Vo))Y!~SI(3o4&`8S~ zmyd+VxVX3w%u4rXC+?B3B9F{`eSNzYHc^qfW|S3X-ZAn*kc+G9=n*1RGljbNeqqxN z4$t~gEUvN&6>XM4?bKBCe=wGRD1QBa@GVwPz7IX|clJlln*y*fwK1tNz8C)wq{cxb literal 0 HcmV?d00001 diff --git a/documentation/docs/projectform/project_upload_form.md b/documentation/docs/projectform/project_upload_form.md new file mode 100644 index 00000000..670cadd2 --- /dev/null +++ b/documentation/docs/projectform/project_upload_form.md @@ -0,0 +1,34 @@ +# Project upload guide +A teacher can upload a new project of their course by going to the url ```projects/create``` where they will need to fill out data corresponding to the project they want to upload. +![Projectform](/img/project_form_1.png) + +For the first 3 fields of the form, you just need to fill in the title you want for the project, the description and select the course you want the project to be for. The course selection is in a dropdown menu where you can see all the courses that you are the teacher of. + +![Projectform](/img/project_form_2.png) + +Next there's a calender where you need to choose deadlines of the project, every deadline can have a description and a timestamp. +As seen in the image above you'll see a table of every deadline you added. If you want to remove a deadline, simply click on the calender date itself and click the remove icon. + +![Projectform](/img/project_upload_form_3.png) + +Then there is a checkbox that contains the value visible for students, this dictates if a project should be immediately visible on upload or not. +When the box is ticked, the value will be set to true and the project will be visible on upload. + +![Projectform](/img/project_upload_form_4.png) + +To upload assignment files you can use the given file uploader. Files must be uploaded as a .zip file. +You can drag & drop your files or click the button and when the files are uploaded, you get a table that shows which files are in the selected .zip file. + +![Projectform](/img/project_upload_form_5.png) + +You can specify file restrictions for submissions of students with the above part of the form. +There you can choose what you need the filename to start with, for example. + +![Projectform](/img/project_upload_form_6.png) + +If you're familiar with regex you can also use the advanced mode to specify file restrictions. If you don't know how to use regex, but are still interested in using this functionality, you can consult the following [cheatsheet](https://cheatography.com/davechild/cheat-sheets/regular-expressions/). + +Finally there's the dropdown menu for the runner. +The explanation for this menu can be found in this [section](/docs/category/evaluators) + +![Runner](/img/project_upload_form_7.png) diff --git a/documentation/docusaurus.config.ts b/documentation/docusaurus.config.ts new file mode 100644 index 00000000..1396432a --- /dev/null +++ b/documentation/docusaurus.config.ts @@ -0,0 +1,94 @@ +import {themes as prismThemes} from 'prism-react-renderer'; +import type {Config} from '@docusaurus/types'; +import type * as Preset from '@docusaurus/preset-classic'; + +const config: Config = { + title: 'Project péristeronas', + tagline: 'An assignment manager for teacher', + favicon: 'img/logo_ugent.png', + + // Set the production url of your site here + url: 'https://sel2-3.ugent.be/', + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: '/', + + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: 'Ugent', // Usually your GitHub org/user name. + projectName: 'péristeronas', // Usually your repo name. + + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'warn', + + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: 'en', + locales: ['en', 'nl'], + }, + + presets: [ + [ + 'classic', + { + docs: { + sidebarPath: './sidebars.ts', + }, + theme: { + customCss: './src/css/custom.css', + }, + } satisfies Preset.Options, + ], + ], + + themeConfig: { + // Replace with your project's social card + image: 'img/docusaurus-social-card.jpg', + navbar: { + title: 'Project péristeronas', + logo: { + alt: 'Project péristorenas', + src: 'img/logo_app.png', + }, + items: [ + { + type: 'docSidebar', + sidebarId: 'tutorialSidebar', + position: 'left', + label: 'User guide', + }, + { + href: 'https://github.com/SELab-2/UGent-3', + label: 'GitHub', + position: 'right', + }, + { + type: 'localeDropdown', + }, + ], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Docs', + items: [ + { + label: 'Tutorial', + to: '/docs/intro', + }, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`, + }, + prism: { + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + }, + } satisfies Preset.ThemeConfig, +}; + +export default config; diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/_category_.json b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/_category_.json new file mode 100644 index 00000000..6efbdbff --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Evaluators", + "position": 3, + "link": { + "type": "generated-index", + "description": "Kies een evaluator die je wilt leren gebruiken." + } +} \ No newline at end of file diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/custom_evaluator.md b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/custom_evaluator.md new file mode 100644 index 00000000..b24c64c4 --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/custom_evaluator.md @@ -0,0 +1,2 @@ +# Custom evaluator +Bij het selecteren van de aangepaste runner moet de gebruiker zijn eigen Dockerfile aanleveren. Dit geeft de vrijheid om alles te doen wat je wilt, en het is volledig aan te passen aan je eigen behoeften. \ No newline at end of file diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/general_evaluator.md b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/general_evaluator.md new file mode 100644 index 00000000..43c722fd --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/general_evaluator.md @@ -0,0 +1,8 @@ +# General evaluator +De algemene runner is in staat om de volgende talen uit te voeren met enkel de standaardbibliotheken inbegrepen +- Javascript +- Python +- Ruby +- Java + +Het enige wat de gebruiker hoeft te doen is een run_tests.sh-bestand in de projectbestanden te uploaden en het script wordt uitgevoerd wanneer een inzending door een student wordt geüpload. \ No newline at end of file diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/python_evaluator.md b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/python_evaluator.md new file mode 100644 index 00000000..4bdf1d92 --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/evaluators/python_evaluator.md @@ -0,0 +1,13 @@ +# Python evaluator +## Algemeen gebruik +Deze evaluator is verantwoordelijk voor het uitvoeren en testen van de Python-code van een student. + +## Structuur +Bij het indienen van het project kan een leraar vereisten toevoegen via het bestand `req-manifest.txt`. Op deze manier zijn alleen de pakketten in het vereistenbestand bruikbaar op de evaluator. + +Wanneer er geen manifest aanwezig is, kunnen studenten hun eigen paketten installeren met een `requirements.txt` en een `dev-requirements.txt`. +Of de leraar kan een `requirements.txt` toevoegen als ze paketten vooraf willen installeren die aanwezig moeten zijn voor het testen van het project. + +## Tests uitvoeren +Als er een `run_tests.sh` aanwezig is in de projectopdrachtbestanden, wordt dit uitgevoerd wanneer de student zijn code indient. +Bij het uitvoeren van tests is het belangrijk op te merken dat de map van de inzending van de student `/submission` zal zijn. diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/intro.md b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/intro.md new file mode 100644 index 00000000..02c86b75 --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/intro.md @@ -0,0 +1,7 @@ +--- +sidebar_position: 1 +--- + +# Project user guide + +Indien je hulp nodig hebt met het gebruik van projecct Péristeronas kan je de onderstaande gebruikershandleiding raadplegen. diff --git a/documentation/i18n/nl/docusaurus-plugin-content-docs/current/projectform/project_upload_form.md b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/projectform/project_upload_form.md new file mode 100644 index 00000000..f8d6e027 --- /dev/null +++ b/documentation/i18n/nl/docusaurus-plugin-content-docs/current/projectform/project_upload_form.md @@ -0,0 +1,31 @@ +# Project upload handleiding +Een leraar kan een nieuw project van zijn cursus uploaden door naar de url `projects/create` te gaan, waar hij gegevens moet invullen die overeenkomen met het project dat hij wil uploaden. + +![Projectformulier](/img/project_form_1.png) + +Voor de eerste 3 velden van de formulier, hoef je alleen maar de titel in te vullen die je voor het project wilt, de beschrijving en de cursus te selecteren waarvoor je het project wilt. De cursusselectie bevindt zich in een vervolgkeuzemenu waarin je alle cursussen ziet waarvan je leraar bent. + +![Projectformulier](/img/project_form_2.png) + +Vervolgens is er een kalender waar je de deadlines van het project moet kiezen, elke deadline kan een beschrijving en een tijdstempel hebben. Zoals te zien is in de afbeelding hierboven, zie je een tabel van elke deadline die je hebt toegevoegd. Als je een deadline wilt verwijderen, klik dan gewoon op de datum in de kalender en klik op het verwijdersymbool. + +![Projectformulier](/img/project_upload_form_3.png) + +Daarna is er een selectievakje dat de waarde bevat die zichtbaar is voor studenten, dit bepaalt of een project direct zichtbaar moet zijn bij het uploaden of niet. +Als de box aangeduid is, zal deze waarde op true staat en zal het project direct zichtbaar worden na de upload. + +![Projectformulier](/img/project_upload_form_4.png) + +Om opdrachtbestanden te uploaden, kun je de gegeven bestandsuploader gebruiken, de bestanden moeten geüpload worden als een .zip-bestand. Je kunt je bestanden slepen en neerzetten of op de knop klikken en wanneer de bestanden geüpload zijn, krijg je een tabel die een overzicht geeft van welke bestanden in het zipbestand zitten. + +![Projectformulier](/img/project_upload_form_5.png) + +Je kunt bestandsbeperkingen specificeren voor de inzendingen van studenten met het bovenstaande deel van het formulier. Daar kun je kiezen met welke bestandsnaam je wilt dat het bestand begint, bijvoorbeeld. + +![Projectformulier](/img/project_upload_form_6.png) + +Als je bekend bent met regex, kun je ook naar de geavanceerde modus gaan om bestandsbeperkingen te specificeren. Als je niet weet hoe je regex moet gebruiken maar toch interesse hebt om deze functionaliteit te gebruiken, kun je de volgende [cheatsheet](https://cheatography.com/davechild/cheat-sheets/regular-expressions/) raadplegen. + +Tot slot is er het vervolgkeuzemenu voor de runner. Maar die worden uitgelegd in deze [sectie](/docs/category/evaluators). + +![Runner](/img/project_upload_form_7.png) diff --git a/documentation/package-lock.json b/documentation/package-lock.json new file mode 100644 index 00000000..e8e731d0 --- /dev/null +++ b/documentation/package-lock.json @@ -0,0 +1,14626 @@ +{ + "name": "documentation", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "documentation", + "version": "0.0.0", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/preset-classic": "3.2.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.2.1", + "@docusaurus/tsconfig": "3.2.1", + "@docusaurus/types": "3.2.1", + "typescript": "~5.2.2" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", + "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", + "dependencies": { + "@algolia/cache-common": "4.23.3" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", + "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", + "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", + "dependencies": { + "@algolia/cache-common": "4.23.3" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", + "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", + "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", + "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", + "dependencies": { + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", + "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", + "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" + }, + "node_modules/@algolia/logger-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", + "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==" + }, + "node_modules/@algolia/logger-console": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", + "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", + "dependencies": { + "@algolia/logger-common": "4.23.3" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", + "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", + "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", + "dependencies": { + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", + "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==" + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", + "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", + "dependencies": { + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", + "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", + "dependencies": { + "@algolia/cache-common": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", + "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dependencies": { + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz", + "integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", + "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", + "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", + "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", + "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", + "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", + "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz", + "integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", + "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", + "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", + "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", + "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", + "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", + "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", + "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", + "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", + "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", + "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", + "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", + "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", + "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", + "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", + "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", + "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", + "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", + "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", + "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", + "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", + "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.1", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.1.tgz", + "integrity": "sha512-QXp1U9x0R7tkiGB0FOk8o74jhnap0FlZ5gNkRIWdG3eP+SvMFg118e1zaWewDzgABb106QSKpVsD3Wgd8t6ifA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", + "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz", + "integrity": "sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", + "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", + "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", + "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", + "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", + "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.4.tgz", + "integrity": "sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.24.4", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", + "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", + "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", + "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", + "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz", + "integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==", + "dependencies": { + "@babel/compat-data": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.1", + "@babel/plugin-syntax-import-attributes": "^7.24.1", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.1", + "@babel/plugin-transform-async-generator-functions": "^7.24.3", + "@babel/plugin-transform-async-to-generator": "^7.24.1", + "@babel/plugin-transform-block-scoped-functions": "^7.24.1", + "@babel/plugin-transform-block-scoping": "^7.24.4", + "@babel/plugin-transform-class-properties": "^7.24.1", + "@babel/plugin-transform-class-static-block": "^7.24.4", + "@babel/plugin-transform-classes": "^7.24.1", + "@babel/plugin-transform-computed-properties": "^7.24.1", + "@babel/plugin-transform-destructuring": "^7.24.1", + "@babel/plugin-transform-dotall-regex": "^7.24.1", + "@babel/plugin-transform-duplicate-keys": "^7.24.1", + "@babel/plugin-transform-dynamic-import": "^7.24.1", + "@babel/plugin-transform-exponentiation-operator": "^7.24.1", + "@babel/plugin-transform-export-namespace-from": "^7.24.1", + "@babel/plugin-transform-for-of": "^7.24.1", + "@babel/plugin-transform-function-name": "^7.24.1", + "@babel/plugin-transform-json-strings": "^7.24.1", + "@babel/plugin-transform-literals": "^7.24.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", + "@babel/plugin-transform-member-expression-literals": "^7.24.1", + "@babel/plugin-transform-modules-amd": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-modules-systemjs": "^7.24.1", + "@babel/plugin-transform-modules-umd": "^7.24.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.24.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", + "@babel/plugin-transform-numeric-separator": "^7.24.1", + "@babel/plugin-transform-object-rest-spread": "^7.24.1", + "@babel/plugin-transform-object-super": "^7.24.1", + "@babel/plugin-transform-optional-catch-binding": "^7.24.1", + "@babel/plugin-transform-optional-chaining": "^7.24.1", + "@babel/plugin-transform-parameters": "^7.24.1", + "@babel/plugin-transform-private-methods": "^7.24.1", + "@babel/plugin-transform-private-property-in-object": "^7.24.1", + "@babel/plugin-transform-property-literals": "^7.24.1", + "@babel/plugin-transform-regenerator": "^7.24.1", + "@babel/plugin-transform-reserved-words": "^7.24.1", + "@babel/plugin-transform-shorthand-properties": "^7.24.1", + "@babel/plugin-transform-spread": "^7.24.1", + "@babel/plugin-transform-sticky-regex": "^7.24.1", + "@babel/plugin-transform-template-literals": "^7.24.1", + "@babel/plugin-transform-typeof-symbol": "^7.24.1", + "@babel/plugin-transform-unicode-escapes": "^7.24.1", + "@babel/plugin-transform-unicode-property-regex": "^7.24.1", + "@babel/plugin-transform-unicode-regex": "^7.24.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.1.tgz", + "integrity": "sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-transform-react-display-name": "^7.24.1", + "@babel/plugin-transform-react-jsx": "^7.23.4", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz", + "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-syntax-jsx": "^7.24.1", + "@babel/plugin-transform-modules-commonjs": "^7.24.1", + "@babel/plugin-transform-typescript": "^7.24.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.4.tgz", + "integrity": "sha512-VOQOexSilscN24VEY810G/PqtpFvx/z6UqDIjIWbDe2368HhDLkYN5TYwaEz/+eRCUkhJ2WaNLLmQAlxzfWj4w==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==" + }, + "node_modules/@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.2.1.tgz", + "integrity": "sha512-ZeMAqNvy0eBv2dThEeMuNzzuu+4thqMQakhxsgT5s02A8LqRcdkg+rbcnuNqUIpekQ4GRx3+M5nj0ODJhBXo9w==", + "dependencies": { + "@babel/core": "^7.23.3", + "@babel/generator": "^7.23.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@babel/runtime-corejs3": "^7.22.6", + "@babel/traverse": "^7.22.8", + "@docusaurus/cssnano-preset": "3.2.1", + "@docusaurus/logger": "3.2.1", + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "@svgr/webpack": "^6.5.1", + "autoprefixer": "^10.4.14", + "babel-loader": "^9.1.3", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.2", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.31.1", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^4.2.2", + "cssnano": "^5.1.15", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "html-minifier-terser": "^7.2.0", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.5.3", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.5", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.1", + "webpack-bundle-analyzer": "^4.9.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0", + "webpackbar": "^5.0.2" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.2.1.tgz", + "integrity": "sha512-wTL9KuSSbMJjKrfu385HZEzAoamUsbKqwscAQByZw4k6Ja/RWpqgVvt/CbAC+aYEH6inLzOt+MjuRwMOrD3VBA==", + "dependencies": { + "cssnano-preset-advanced": "^5.3.10", + "postcss": "^8.4.26", + "postcss-sort-media-queries": "^4.4.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.2.1.tgz", + "integrity": "sha512-0voOKJCn9RaM3np6soqEfo7SsVvf2C+CDTWhW+H/1AyBhybASpExtDEz+7ECck9TwPzFQ5tt+I3zVugUJbJWDg==", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.2.1.tgz", + "integrity": "sha512-Fs8tXhXKZjNkdGaOy1xSLXSwfjCMT73J3Zfrju2U16uGedRFRjgK0ojpK5tiC7TnunsL3tOFgp1BSMBRflX9gw==", + "dependencies": { + "@docusaurus/logger": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.2.1.tgz", + "integrity": "sha512-FyViV5TqhL1vsM7eh29nJ5NtbRE6Ra6LP1PDcPvhwPSlA7eiWGRKAn3jWwMUcmjkos5SYY+sr0/feCdbM3eQHQ==", + "dependencies": { + "@docusaurus/react-loadable": "5.5.2", + "@docusaurus/types": "3.2.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@5.5.2" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.2.1.tgz", + "integrity": "sha512-lOx0JfhlGZoZu6pEJfeEpSISZR5dQbJGGvb42IP13G5YThNHhG9R9uoWuo4IOimPqBC7sHThdLA3VLevk61Fsw==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/logger": "3.2.1", + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.2.1.tgz", + "integrity": "sha512-GHe5b/lCskAR8QVbfWAfPAApvRZgqk7FN3sOHgjCtjzQACZxkHmq6QqyqZ8Jp45V7lVck4wt2Xw2IzBJ7Cz3bA==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/logger": "3.2.1", + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/module-type-aliases": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.2.1.tgz", + "integrity": "sha512-TOqVfMVTAHqWNEGM94Drz+PUpHDbwFy6ucHFgyTx9zJY7wPNSG5EN+rd/mU7OvAi26qpOn2o9xTdUmb28QLjEQ==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.2.1.tgz", + "integrity": "sha512-AMKq8NuUKf2sRpN1m/sIbqbRbnmk+rSA+8mNU1LNxEl9BW9F/Gng8m9HKlzeyMPrf5XidzS1jqkuTLDJ6KIrFw==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.2.1.tgz", + "integrity": "sha512-/rJ+9u+Px0eTCiF4TNcNtj3kHf8cp6K1HCwOTdbsSlz6Xn21syZYcy+f1VM9wF6HrvUkXUcbM5TDCvg2IRL6bQ==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.2.1.tgz", + "integrity": "sha512-XtuJnlMvYfppeVdUyKiDIJAa/gTJKCQU92z8CLZZ9ibJdgVjFOLS10s0hIC0eL5z0U2u2loJz2rZ63HOkNHbBA==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.2.1.tgz", + "integrity": "sha512-wiS/kE0Ny5pnjTxVCs8ljRnkL1RVMj59t6jmSsgEX7piDOoaXSMIUaoIt9ogS/v132uO0xEsxHstkRUZHQyPcQ==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.2.1.tgz", + "integrity": "sha512-uWZ7AxzdeaQSTCwD2yZtOiEm9zyKU+wqCmi/Sf25kQQqqFSBZUStXfaQ8OHP9cecnw893ZpZ811rPhB/wfujJw==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/logger": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.2.1.tgz", + "integrity": "sha512-E3OHSmttpEBcSMhfPBq3EJMBxZBM01W1rnaCUTXy9EHvkmB5AwgTfW1PwGAybPAX579ntE03R+2zmXdizWfKnQ==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/plugin-content-blog": "3.2.1", + "@docusaurus/plugin-content-docs": "3.2.1", + "@docusaurus/plugin-content-pages": "3.2.1", + "@docusaurus/plugin-debug": "3.2.1", + "@docusaurus/plugin-google-analytics": "3.2.1", + "@docusaurus/plugin-google-gtag": "3.2.1", + "@docusaurus/plugin-google-tag-manager": "3.2.1", + "@docusaurus/plugin-sitemap": "3.2.1", + "@docusaurus/theme-classic": "3.2.1", + "@docusaurus/theme-common": "3.2.1", + "@docusaurus/theme-search-algolia": "3.2.1", + "@docusaurus/types": "3.2.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/react-loadable": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.2.1.tgz", + "integrity": "sha512-+vSbnQyoWjc6vRZi4vJO2dBU02wqzynsai15KK+FANZudrYaBHtkbLZAQhgmxzBGVpxzi87gRohlMm+5D8f4tA==", + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/module-type-aliases": "3.2.1", + "@docusaurus/plugin-content-blog": "3.2.1", + "@docusaurus/plugin-content-docs": "3.2.1", + "@docusaurus/plugin-content-pages": "3.2.1", + "@docusaurus/theme-common": "3.2.1", + "@docusaurus/theme-translations": "3.2.1", + "@docusaurus/types": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.2.1.tgz", + "integrity": "sha512-d+adiD7L9xv6EvfaAwUqdKf4orsM3jqgeqAM+HAjgL/Ux0GkVVnfKr+tsoe+4ow4rHe6NUt+nkkW8/K8dKdilA==", + "dependencies": { + "@docusaurus/mdx-loader": "3.2.1", + "@docusaurus/module-type-aliases": "3.2.1", + "@docusaurus/plugin-content-blog": "3.2.1", + "@docusaurus/plugin-content-docs": "3.2.1", + "@docusaurus/plugin-content-pages": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.2.1.tgz", + "integrity": "sha512-bzhCrpyXBXzeydNUH83II2akvFEGfhsNTPPWsk5N7e+odgQCQwoHhcF+2qILbQXjaoZ6B3c48hrvkyCpeyqGHw==", + "dependencies": { + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.2.1", + "@docusaurus/logger": "3.2.1", + "@docusaurus/plugin-content-docs": "3.2.1", + "@docusaurus/theme-common": "3.2.1", + "@docusaurus/theme-translations": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-validation": "3.2.1", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.2.1.tgz", + "integrity": "sha512-jAUMkIkFfY+OAhJhv6mV8zlwY6J4AQxJPTgLdR2l+Otof9+QdJjHNh/ifVEu9q0lp3oSPlJj9l05AaP7Ref+cg==", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/tsconfig": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.2.1.tgz", + "integrity": "sha512-+biUwtsYW3oChLxYezzA+NIgS3Q9KDRl7add/YT54RXs9Q4rKInebxdHdG6JFs5BaTg45gyjDu0rvNVcGeHODg==", + "dev": true + }, + "node_modules/@docusaurus/types": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.2.1.tgz", + "integrity": "sha512-n/toxBzL2oxTtRTOFiGKsHypzn/Pm+sXyw+VSk1UbqbXQiHOwHwts55bpKwbcUgA530Is6kix3ELiFOv9GAMfw==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.2.1.tgz", + "integrity": "sha512-DPkIS/EPc+pGAV798PUXgNzJFM3HJouoQXgr0KDZuJVz1EkWbDLOcQwLIz8Qx7liI9ddfkN/TXTRQdsTPZNakw==", + "dependencies": { + "@docusaurus/logger": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "@svgr/webpack": "^6.5.1", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.2.1.tgz", + "integrity": "sha512-N5vadULnRLiqX2QfTjVEU3u5vo6RG2EZTdyXvJdzDOdrLCGIZAfnf/VkssinFZ922sVfaFfQ4FnStdhn5TWdVg==", + "dependencies": { + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.2.1.tgz", + "integrity": "sha512-+x7IR9hNMXi62L1YAglwd0s95fR7+EtirjTxSN4kahYRWGqOi3jlQl1EV0az/yTEvKbxVvOPcdYicGu9dk4LJw==", + "dependencies": { + "@docusaurus/logger": "3.2.1", + "@docusaurus/utils": "3.2.1", + "@docusaurus/utils-common": "3.2.1", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/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==" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz", + "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz", + "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz", + "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz", + "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz", + "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz", + "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz", + "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1", + "@svgr/babel-plugin-remove-jsx-attribute": "*", + "@svgr/babel-plugin-remove-jsx-empty-expression": "*", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1", + "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1", + "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1", + "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1", + "@svgr/babel-plugin-transform-svg-component": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz", + "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==", + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz", + "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==", + "dependencies": { + "@babel/types": "^7.20.0", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz", + "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==", + "dependencies": { + "@babel/core": "^7.19.6", + "@svgr/babel-preset": "^6.5.1", + "@svgr/hast-util-to-babel-ast": "^6.5.1", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "^6.0.0" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz", + "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==", + "dependencies": { + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "svgo": "^2.8.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz", + "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==", + "dependencies": { + "@babel/core": "^7.19.6", + "@babel/plugin-transform-react-constant-elements": "^7.18.12", + "@babel/preset-env": "^7.19.4", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@svgr/core": "^6.5.1", + "@svgr/plugin-jsx": "^6.5.1", + "@svgr/plugin-svgo": "^6.5.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz", + "integrity": "sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, + "node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prismjs": { + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.2.79", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", + "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", + "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-account": "4.23.3", + "@algolia/client-analytics": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-personalization": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/recommend": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.18.0.tgz", + "integrity": "sha512-ZXvA8r6VG46V343jnIE7Tei8Xr0/9N8YhD27joC0BKxeogQyvNu7O37i510wA7FnrDjoa/tFhK90WUaBlkaqnw==", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "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/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-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==" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request/node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "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" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "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", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", + "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.0.tgz", + "integrity": "sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", + "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.37.0.tgz", + "integrity": "sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz", + "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==", + "dependencies": { + "cssnano": "^5.1.8", + "jest-worker": "^29.1.2", + "postcss": "^8.4.17", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz", + "integrity": "sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ==", + "dependencies": { + "autoprefixer": "^10.4.12", + "cssnano-preset-default": "^5.2.14", + "postcss-discard-unused": "^5.1.0", + "postcss-merge-idents": "^5.1.1", + "postcss-reduce-idents": "^5.2.0", + "postcss-zindex": "^5.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "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-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", + "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + } + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/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==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "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.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.747", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.747.tgz", + "integrity": "sha512-+FnSWZIAvFHbsNVmUxhEqWiaOiPMcfum1GQzlWCg/wLigVtshOsjXHyEFfmt6cFK6+HkS3QOJBv6/3OPumbBfw==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.0.1.tgz", + "integrity": "sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "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==", + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.0.tgz", + "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==" + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.1.tgz", + "integrity": "sha512-5mvUrF2suuv5f5cGDnDphIy4/gW86z82kl5qG6mM9z04SEQI4FB5Apmaw/TGEf3l55nLtMs5s51dmhUzvAHQCA==", + "dependencies": { + "@types/estree": "^1.0.0", + "is-plain-obj": "^4.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "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": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "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/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "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" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "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==" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.2.tgz", + "integrity": "sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "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", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.43", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", + "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.0.tgz", + "integrity": "sha512-9qcrTyoBmFZRNHeVP4edKqIUEgFzq7MHvTNSDuHSqkpOPtiBkgNgcmTSqmiw1kw9tdKaiddvIDv/eCJDxmqWCA==", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.0.tgz", + "integrity": "sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz", + "integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz", + "integrity": "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz", + "integrity": "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz", + "integrity": "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", + "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-emoji": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "node_modules/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==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/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==", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-unused": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz", + "integrity": "sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss-merge-idents": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz", + "integrity": "sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz", + "integrity": "sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", + "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", + "dependencies": { + "sort-css-media-queries": "2.1.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.16" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss-zindex": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-5.1.0.tgz", + "integrity": "sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz", + "integrity": "sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-json-view-lite": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.3.0.tgz", + "integrity": "sha512-aN1biKC5v4DQkmQBlZjuMFR09MKZGMPtIg+cut8zEeg2HXd6gl2gRy0n4HMacHf0dznQgo0SVXN7eT8zV3hEuQ==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz", + "integrity": "sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==", + "dependencies": { + "@types/react": "*", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "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", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", + "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==" + }, + "node_modules/rtlcss": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.1.1.tgz", + "integrity": "sha512-/oVHgBtnPNcggP2aVXQjSy6N1mMAfHg4GSag0QtZBlD5bdDgAHwr4pydqJGd+SUCu9260+Pjqbjwtvu7EMH1KQ==", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz", + "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/sitemap": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.1.tgz", + "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz", + "integrity": "sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA==", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "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" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.30.4", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.4.tgz", + "integrity": "sha512-xRdd0v64a8mFK9bnsKVdoNP9GQIKUAaJPTaqEQDL4w/J8WaW4sWXXoMZ+6SimPkfT5bElreXf8m9HnmPc3E1BQ==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "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==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", + "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpack": { + "version": "5.91.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", + "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.16.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/documentation/package.json b/documentation/package.json new file mode 100644 index 00000000..020ddfb6 --- /dev/null +++ b/documentation/package.json @@ -0,0 +1,47 @@ +{ + "name": "documentation", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids", + "typecheck": "tsc" + }, + "dependencies": { + "@docusaurus/core": "3.2.1", + "@docusaurus/preset-classic": "3.2.1", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.2.1", + "@docusaurus/tsconfig": "3.2.1", + "@docusaurus/types": "3.2.1", + "typescript": "~5.2.2" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/documentation/sidebars.ts b/documentation/sidebars.ts new file mode 100644 index 00000000..acc7685a --- /dev/null +++ b/documentation/sidebars.ts @@ -0,0 +1,31 @@ +import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; + +/** + * Creating a sidebar enables you to: + - create an ordered group of docs + - render a sidebar for each doc of that group + - provide next/previous navigation + + The sidebars can be generated from the filesystem, or explicitly defined here. + + Create as many sidebars as you want. + */ +const sidebars: SidebarsConfig = { + // By default, Docusaurus generates a sidebar from the docs folder structure + tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], + + // But you can create a sidebar manually + /* + tutorialSidebar: [ + 'intro', + 'hello', + { + type: 'category', + label: 'Tutorial', + items: ['tutorial-basics/create-a-document'], + }, + ], + */ +}; + +export default sidebars; diff --git a/documentation/src/components/HomepageFeatures/index.tsx b/documentation/src/components/HomepageFeatures/index.tsx new file mode 100644 index 00000000..50a9e6f4 --- /dev/null +++ b/documentation/src/components/HomepageFeatures/index.tsx @@ -0,0 +1,70 @@ +import clsx from 'clsx'; +import Heading from '@theme/Heading'; +import styles from './styles.module.css'; + +type FeatureItem = { + title: string; + Svg: React.ComponentType>; + description: JSX.Element; +}; + +const FeatureList: FeatureItem[] = [ + { + title: 'Easy to Use', + Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, + description: ( + <> + Docusaurus was designed from the ground up to be easily installed and + used to get your website up and running quickly. + + ), + }, + { + title: 'Focus on What Matters', + Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, + description: ( + <> + Docusaurus lets you focus on your docs, and we'll do the chores. Go + ahead and move your docs into the docs directory. + + ), + }, + { + title: 'Powered by React', + Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, + description: ( + <> + Extend or customize your website layout by reusing React. Docusaurus can + be extended while reusing the same header and footer. + + ), + }, +]; + +function Feature({title, Svg, description}: FeatureItem) { + return ( +
+
+ +
+
+ {title} +

{description}

+
+
+ ); +} + +export default function HomepageFeatures(): JSX.Element { + return ( +
+
+
+ {FeatureList.map((props, idx) => ( + + ))} +
+
+
+ ); +} diff --git a/documentation/src/components/HomepageFeatures/styles.module.css b/documentation/src/components/HomepageFeatures/styles.module.css new file mode 100644 index 00000000..b248eb2e --- /dev/null +++ b/documentation/src/components/HomepageFeatures/styles.module.css @@ -0,0 +1,11 @@ +.features { + display: flex; + align-items: center; + padding: 2rem 0; + width: 100%; +} + +.featureSvg { + height: 200px; + width: 200px; +} diff --git a/documentation/src/css/custom.css b/documentation/src/css/custom.css new file mode 100644 index 00000000..f953a02f --- /dev/null +++ b/documentation/src/css/custom.css @@ -0,0 +1,30 @@ +/** + * Any CSS included here will be global. The classic template + * bundles Infima by default. Infima is a CSS framework designed to + * work well for content-centric websites. + */ + +/* You can override the default Infima variables here. */ +:root { + --ifm-color-primary: #2e64e8; /* Primary Blue */ + --ifm-color-primary-dark: #2350c1; /* Darker Blue */ + --ifm-color-primary-darker: #1a3d9b; /* Even Darker Blue */ + --ifm-color-primary-darkest: #122d7a; /* Darkest Blue */ + --ifm-color-primary-light: #3a7ae3; /* Light Blue */ + --ifm-color-primary-lighter: #4b96ff; /* Lighter Blue */ + --ifm-color-primary-lightest: #63adff; /* Lightest Blue */ + --ifm-code-font-size: 95%; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); +} + +/* For readability concerns, you should choose a lighter palette in dark mode. */ +[data-theme='dark'] { + --ifm-color-primary: #25c2a0; + --ifm-color-primary-dark: #21af90; + --ifm-color-primary-darker: #1fa588; + --ifm-color-primary-darkest: #1a8870; + --ifm-color-primary-light: #29d5b0; + --ifm-color-primary-lighter: #32d8b4; + --ifm-color-primary-lightest: #4fddbf; + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); +} diff --git a/documentation/src/pages/index.module.css b/documentation/src/pages/index.module.css new file mode 100644 index 00000000..9f71a5da --- /dev/null +++ b/documentation/src/pages/index.module.css @@ -0,0 +1,23 @@ +/** + * CSS files with the .module.css suffix will be treated as CSS modules + * and scoped locally. + */ + +.heroBanner { + padding: 4rem 0; + text-align: center; + position: relative; + overflow: hidden; +} + +@media screen and (max-width: 996px) { + .heroBanner { + padding: 2rem; + } +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/documentation/src/pages/index.tsx b/documentation/src/pages/index.tsx new file mode 100644 index 00000000..edcfa6b6 --- /dev/null +++ b/documentation/src/pages/index.tsx @@ -0,0 +1,43 @@ +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import HomepageFeatures from '@site/src/components/HomepageFeatures'; +import Heading from '@theme/Heading'; + +import styles from './index.module.css'; + +function HomepageHeader() { + const {siteConfig} = useDocusaurusContext(); + return ( +
+
+ + {siteConfig.title} + +

{siteConfig.tagline}

+
+ + User guide + +
+
+
+ ); +} + +export default function Home(): JSX.Element { + const {siteConfig} = useDocusaurusContext(); + return ( + + +
+ +
+
+ ); +} diff --git a/documentation/static/.nojekyll b/documentation/static/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/documentation/static/img/logo_app.png b/documentation/static/img/logo_app.png new file mode 100644 index 0000000000000000000000000000000000000000..7a36d43ced7a9641bec3ff2ec4c0607d9bcb853d GIT binary patch literal 704 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&i3a$DxcX!k>UaGFp-wRB`f1Sh zvr;Q*CQt!eNswPKLx@J(-EF4xl_vp3I14-?iy0W0Uw|;<*6N^a1_mZoPZ!6KiaBqi zPER^)z+s&52Z*Qs`ExQ~t(EE5Jci^ejBB<#eR-9s^8T}X zmwTfP=MBBaxN43skMG#dD_MCVAzpUH#RKP=e%(7eVNK(`6B+q>n$!6oS#clfn^?yo za_Zi``z-r4ewvwVV6YPkD3rZ8v7zg=2jBUGMh07xz|o?mm&`=EZU!T<63wTyF*&yQl> z=`lZqd0$5TG=_ay^+Eip4R(v$t&YgYG0SbVcVy_j#Qr_t*iYr`1BbsIzt&*$rO{MC zzWz$-k;QMh*D>yV)W5p%$4lj`19iWhvknM`8xMMU8L8I5TQRq31-C+gk{KG66*m(xRL?`a0!C*=|c8oyQZEbypuXH}Ut zf8n>=9|Tkmf8w4t-}!d>HO`Xn7XQV%k0x#T-&I@Nx3#`vw!hL%+5M|c`(kYEPtUZe zxOw-coM?WLR9a!axy2bF?T6po|9@Dam(co+?V#EPImrb=8Q*yVIJZ=@8T>o;faTUS zM!m+e(+f%(tMr-ANbGYibWUJS6wc^9$hl?OPK`>=jDL_we|Cg_-ImzD?Fp7yz*NMS f8sVAd>&u`8WOD#92wV!D45B<;{an^LB{Ts5F^D&V literal 0 HcmV?d00001 diff --git a/frontend/public/logo_ugent.png b/documentation/static/img/logo_ugent.png similarity index 100% rename from frontend/public/logo_ugent.png rename to documentation/static/img/logo_ugent.png diff --git a/documentation/static/img/project_form_1.png b/documentation/static/img/project_form_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d2bd71081bd78657d229a6fb5aea43257f8a532e GIT binary patch literal 10483 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

gQ0 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 literal 0 HcmV?d00001 diff --git a/documentation/static/img/project_upload_form_3.png b/documentation/static/img/project_upload_form_3.png new file mode 100644 index 0000000000000000000000000000000000000000..71b525a315cf92ffd1df5ea43159927703919557 GIT binary patch literal 3966 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�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

rB@Yj5284B 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 literal 0 HcmV?d00001 diff --git a/documentation/static/img/project_upload_form_7.png b/documentation/static/img/project_upload_form_7.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c70ee8b1c258a172da803d792ea9072893b45c GIT binary patch literal 2313 zcmbW3`9Bj39LFa;EK#mP?vkVA7|XRNL*&ec97|*7XmiXJb3M*I5h^0bgeP)Dk7GGQ z=GsJZBpM+s$0JO`uxHPo@I2qw>;3({zOUE!_4@wu`5u4R+1wQ1JI4nA00b<|P3$>w zo`W-xhvP3u?;<(jc(Abr9LTXKAd0}rB|=Q^gunvOA>l}z7r@&;0PA%n*c0dFxCyBnP zW9@xLl)|LDmeh~i>(X%f~%p%e$Y1`xVUIB#Z0IM4Hc=%+FO zH4YG&^2WyOJF3rq6!*)ysfo#Cq?DADSe@=Mcf4v;ESu4%7qzQ#w>D>f-b0m2VPq-@ zOp|;A0?J>$OwtQpQts8R(tKXF6?GKA;yuLx-V$z&%<|{4EQfNvlHK?85Y|S%oU7XT_v$t zETDP10MQAhr?y#f7NNTFX@#bzyJXWNEP zC+7F&Q!jnuughK65I^4eBV?Y*Qn_-aXFZI&UEb`xP+ndhp~nL=O%mvswG9moRZO{t zD%Cf^As#Hp7@w8=Y&n9kDb-l|71FKYjw&FVTR^H#vsmarZG7UTzr} zP;Xk=$*l}X1cSl5QSV}?3gOn#hO%AvGC7T5FcA_K27_sRg36Faq&-~Drn~yjMNixh z2}N`&W{BWPKPRbYs%M*2!T2eqa}_NA%(~j>{4=Af^Q_ojog?jRUa>;taJtj3ledhi ztny300q-XEkV+bt@QB!Coyy=>^`XV}Law{lf`|tvV9M@qvW6Xp(e^kRg1wa8dFq$c zfs#_|$y{yh)ss1D-o-Y{rV_Z&QNb>g+< zhq#2zy{N2b&+OgZZ8gNnt2^g9@+<4h4ktrMH}$aA?-8IjPck_+Z#Np6CUIF7dFbR6 zyzyO`MU2dgR${dkRh4JA+p?30tuiRYy1t=Ktkh#MQr+P<2}~SW4mZY#!X(Uio zuk7fBAdMO12+NUrd?Z#oxaC#Bw53|$ueGF9s;){0&2-^@fROdquGfGG-Lf3K{}hnx z{9_;>rX#k~Yh`7H2az(np(F@YHhJotwC&7F7>~A@U=YEy`W-RIHd(fL$F=CaL7Htp zCHz~Hy@aE@Y5MQ!K;Z(t;AA43Cn75P4g0Ol+Mil_H(W(>b&qYwda&sfu(jkXx$!5%atcux zf?zsnxr&O4W*UUbyR(;~t)ySn!&7zWlv@rCXFB6F(@hdPFN&@5K7klY`JmVE5#1<# z=ci`=#R*X@bgOJMGMu>BJ~rnO5BpFXjH9PyKxrUY+o-aS5oJUq+R?x7LBuL^@?h|G zOD$88SHli-;mn**sf4D$Wt|*|fz3g+z;{s4trJNb$-uP(xrlJM$w&# z6&u{C8`S+I)I$4vOj--tjCnj{ zhjtKACTrsqb2Pq0{sC2&o)__QuqtSb2ah8ltsCKE?B;x8o5i5(rbWT9blZ`nY_O!| zyDgw6`zM4I2C?uQ)^#I3|N1seg&BGCs3aQHYpwvA*Fu8G<_frR`HQx@xiTJ(Y@xhE z7PJ0dSG*7nU1DIPl%&ho;1ml^-qx}tYU7&SFq3cO*FjGDW?$PPv^a~q+NF^~uP@uj zo+~SeKX0mQTv=Hes9#9-_-l*??iS+bfqj;@P8Sp{5m$={w~`Yy$1l~_)TpgvCMPDs z1`v8>FoH(|g+duafCun5YZb)#ITL@HF@x~j#{l)6FF4ETm0m2W1o9+QNVclS@?R3? zFC#iJ_M)6MCF6~=RByvz37=Ol3IYXFd+b{af9Mw4`1$$Oc_>=h6P|#d)OG<=x)ZyR z?U$emPwT*>E;{NFflIXHzfosMR*hkfzbY*n@2t}|$)TF!@%Vo))Y!~SI(3o4&`8S~ zmyd+VxVX3w%u4rXC+?B3B9F{`eSNzYHc^qfW|S3X-ZAn*kc+G9=n*1RGljbNeqqxN z4$t~gEUvN&6>XM4?bKBCe=wGRD1QBa@GVwPz7IX|clJlln*y*fwK1tNz8C)wq{cxb literal 0 HcmV?d00001 diff --git a/documentation/static/img/undraw_docusaurus_mountain.svg b/documentation/static/img/undraw_docusaurus_mountain.svg new file mode 100644 index 00000000..af961c49 --- /dev/null +++ b/documentation/static/img/undraw_docusaurus_mountain.svg @@ -0,0 +1,171 @@ + + Easy to Use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/undraw_docusaurus_react.svg b/documentation/static/img/undraw_docusaurus_react.svg new file mode 100644 index 00000000..94b5cf08 --- /dev/null +++ b/documentation/static/img/undraw_docusaurus_react.svg @@ -0,0 +1,170 @@ + + Powered by React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/static/img/undraw_docusaurus_tree.svg b/documentation/static/img/undraw_docusaurus_tree.svg new file mode 100644 index 00000000..d9161d33 --- /dev/null +++ b/documentation/static/img/undraw_docusaurus_tree.svg @@ -0,0 +1,40 @@ + + Focus on What Matters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documentation/tsconfig.json b/documentation/tsconfig.json new file mode 100644 index 00000000..314eab8a --- /dev/null +++ b/documentation/tsconfig.json @@ -0,0 +1,7 @@ +{ + // This file is not used in compilation. It is here just for a nice editor experience. + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": "." + } +} diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index c685b20b..dd2f81ab 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -26,7 +26,7 @@ module.exports = { "jsdoc/check-access": 1, "tsdoc/syntax": "warn", "jsdoc/check-alignment": 1, - "jsdoc/check-param-names": 1, + "jsdoc/check-param-names": 0, "jsdoc/check-property-names": 1, "jsdoc/check-tag-names": 1, "jsdoc/check-types": 1, @@ -37,10 +37,10 @@ module.exports = { "jsdoc/no-multi-asterisks": 1, "jsdoc/no-undefined-types": 1, "jsdoc/require-jsdoc": 1, - "jsdoc/require-param": 1, + "jsdoc/require-param": 0, "jsdoc/require-param-description": 1, "jsdoc/require-param-name": 1, - "jsdoc/require-param-type": 1, + "jsdoc/require-param-type": 0, "jsdoc/require-property": 1, "jsdoc/require-property-description": 1, "jsdoc/require-property-name": 1, @@ -51,5 +51,6 @@ module.exports = { "jsdoc/require-yields-check": 1, "jsdoc/tag-lines": 1, "jsdoc/valid-types": 1, + "no-console": "error" }, }; diff --git a/frontend/.gitignore b/frontend/.gitignore index a547bf36..fd154402 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -11,6 +11,9 @@ node_modules dist dist-ssr *.local +coverage +screenshots +.env # Editor directories and files .vscode/* diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 043eb166..44c3f196 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,6 +1,6 @@ FROM node:18 as build WORKDIR /app -COPY package*.json . +COPY package*.json ./ RUN npm install COPY . . RUN npm run build @@ -9,4 +9,4 @@ FROM nginx:alpine WORKDIR /usr/share/nginx/html RUN rm -rf ./* COPY --from=build /app/dist /usr/share/nginx/html -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/README.md b/frontend/README.md index 0d6babed..b2c30576 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,30 +1,64 @@ -# React + TypeScript + Vite +# Project pigeonhole frontend +![tests](https://github.com/SELab-2/UGent-3/actions/workflows/ci-test-frontend.yaml/badge.svg) +![linter](https://github.com/SELab-2/UGent-3/actions/workflows/ci-linter-frontend.yaml/badge.svg) +## Prerequisites +**1. Clone the repo** + ```sh + git clone git@github.com:SELab-2/UGent-3.git + ``` -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +**2. Installing required packages** +Run the command below to install the needed dependencies. + ```sh + cd frontend + npm install + ``` +After this you can run the development or the production build with one of the following command + - Deployment + ```sh + npm run build + ``` +After running this command the build can be found in the `dist` directory. +You can choose your own preferred webserver like for example `nginx`, `serve` or something else. + + - Development + ```sh + npm run dev + ``` -Currently, two official plugins are available: +## Setting up the environment variables -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh +This application requires a couple of environment variables to run. +Setting values for these variables can be done with a method to your own liking. -## Expanding the ESLint configuration +| Variable | Description | +|------------------------|------------------------------------------------------------------------------------| +| VITE_API_HOST | URL of the API | +| VITE_APP_TENANT_ID | [Tenant id](https://learn.microsoft.com/nl-nl/entra/fundamentals/whatis) | +| VITE_APP_CLIENT_ID | [Client id](https://learn.microsoft.com/nl-nl/entra/identity-platform/v2-protocols) | -If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: +## Maintaining the codebase +### Writing tests +When writing new code it is important to maintain the right functionality so +writing tests is mandatory for this, the test library used in this codebase is [cypres e2e](https://www.cypress.io/). -- Configure the top-level `parserOptions` property like this: +If you want to write tests we highly advise to read the cypres e2e documentation on how +to write tests, so they are kept conventional. -```js -export default { - // other rules... - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: ['./tsconfig.json', './tsconfig.node.json'], - tsconfigRootDir: __dirname, - }, -} -``` +For executing the tests and testing your newly added functionality +you can run: +```sh +npm run dev +``` +After the development build is running, you can run the following command on another terminal: +```sh +npm run test +``` +### Running the linter +This codebase is kept clean by the [eslint](https://eslint.org) linter. -- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` -- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` -- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list +If you want to execute the linter on all files in the project it can simply be done +with the command: +```sh +npm run lint +``` diff --git a/frontend/cypress/e2e/ErrorPage.cy.tsx b/frontend/cypress/e2e/ErrorPage.cy.tsx new file mode 100644 index 00000000..7d998994 --- /dev/null +++ b/frontend/cypress/e2e/ErrorPage.cy.tsx @@ -0,0 +1,16 @@ +describe('Error page test', () => { + it('Error page should load appropriately', () => { + expect( + () => { + cy.request({ + method: 'POST', + path: '**', + body: {name: "fail"}, + failOnStatusCode: false + }).then(response => { + expect(response.status).to.be(404) // is supposed to be 404 + }) + } + ) + }) +}) diff --git a/frontend/cypress/e2e/Header.cy.tsx b/frontend/cypress/e2e/Header.cy.tsx new file mode 100644 index 00000000..c810af0c --- /dev/null +++ b/frontend/cypress/e2e/Header.cy.tsx @@ -0,0 +1,31 @@ +describe("Header look not logged in", () => { + it("App name in header", () => { + cy.visit("/"); + cy.get("header").contains("Peristerónas"); + }); + it("Login in header", () => { + cy.visit("/"); + cy.get("header").contains("Login"); + }); + it("Language in header", () => { + cy.visit("/"); + cy.get("header").contains("en"); + }); +}); + +describe("Header functionality not logged in", () => { + it("Header Login", () => { + cy.visit("/"); + cy.contains("Login") + .should("be.visible") + .should("have.attr", "href") + .and("include", "login.microsoftonline.com"); + }); + + it("Header change language en -> nl", () => { + cy.visit("/"); + cy.contains("en").should("be.visible").click(); + cy.contains("Nederlands").should("be.visible").click(); + cy.contains("nl").should("be.visible"); + }); +}); diff --git a/frontend/cypress/e2e/HomePageTests.cy.tsx b/frontend/cypress/e2e/HomePageTests.cy.tsx new file mode 100644 index 00000000..7676ac39 --- /dev/null +++ b/frontend/cypress/e2e/HomePageTests.cy.tsx @@ -0,0 +1,20 @@ +describe("Homepage functionality not logged in ", () => { + it("Header Visible", () => { + cy.visit("/"); + cy.contains("Peristerónas"); + cy.get("header").should("be.visible"); + }); + + it("Center button Login", () => { + cy.visit("/"); + cy.contains("Peristerónas"); + cy.contains( + "Welcome to Peristerónas, the online submission platform of UGent" + ) + .parent() + .contains("Login") + .should("be.visible") + .should("have.attr", "href") + .and("include", "login.microsoftonline.com"); + }); +}); diff --git a/frontend/cypress/tsconfig.json b/frontend/cypress/tsconfig.json new file mode 100644 index 00000000..18edb199 --- /dev/null +++ b/frontend/cypress/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress", "node"] + }, + "include": ["**/*.ts"] +} diff --git a/frontend/index.html b/frontend/index.html index d42d4487..18eb2100 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,8 +1,8 @@ - + - + Ugent-3 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4fc8aea3..dc2cdc9a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,30 +8,61 @@ "name": "ugent-3", "version": "0.0.0", "dependencies": { - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.15.10", - "@mui/material": "^5.15.10", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.15", + "@mui/lab": "^5.0.0-alpha.170", + "@mui/material": "^5.15.15", "@mui/styled-engine-sc": "^6.0.0-alpha.16", + "@mui/x-data-grid": "^7.1.1", + "@mui/x-date-pickers": "^7.1.1", + "axios": "^1.6.8", + "dayjs": "^1.11.10", + "debounce": "^2.0.0", + "downloadjs": "^1.4.7", + "i18next-browser-languagedetector": "^7.2.0", + "i18next-http-backend": "^2.5.0", + "jszip": "^3.10.1", + "prettier": "^3.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.1.0", + "react-markdown": "^9.0.1", "react-router-dom": "^6.22.1", + "stream": "^0.0.2", "styled-components": "^6.1.8" }, "devDependencies": { + "@testing-library/react": "^15.0.7", + "@types/downloadjs": "^1.4.6", + "@types/history": "^4.7.11", "@types/react": "^18.2.55", "@types/react-dom": "^18.2.19", + "@types/react-router-dom": "^5.3.3", + "@types/scheduler": "^0.23.0", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react": "^4.2.1", - "cypress": "^13.6.4", + "@vitest/coverage-v8": "^1.5.2", + "cypress": "^13.8.1", "eslint": "^8.56.0", "eslint-plugin-jsdoc": "^48.1.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "eslint-plugin-tsdoc": "^0.2.17", - "typescript": "^5.2.2", - "vite": "^5.1.0" + "i18next": "^23.10.1", + "i18next-browser-languagedetector": "^7.2.1", + "i18next-http-backend": "^2.5.0", + "jest": "^29.7.0", + "jsdom": "^24.0.0", + "npm-run-all": "^4.1.5", + "react-i18next": "^14.1.0", + "scheduler": "^0.23.0", + "start-server-and-test": "^2.0.3", + "ts-jest": "^29.1.2", + "typescript": "^5.4.5", + "vite": "^5.1.7", + "vitest": "^1.5.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -44,55 +75,55 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -107,6 +138,12 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -117,14 +154,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -147,6 +184,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -156,6 +202,12 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/@babel/helper-environment-visitor": { "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", @@ -191,11 +243,11 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -221,9 +273,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -254,9 +306,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } @@ -279,36 +331,101 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -317,13 +434,73 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", - "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -332,13 +509,100 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", - "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -348,9 +612,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -359,33 +623,33 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -393,10 +657,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -406,15 +679,11 @@ "node": ">=6.9.0" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "node_modules/@cypress/request": { "version": "3.0.1", @@ -445,6 +714,20 @@ "node": ">= 6" } }, + "node_modules/@cypress/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/@cypress/xvfb": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", @@ -482,21 +765,15 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/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==" + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/cache": { "version": "11.11.0", @@ -510,28 +787,33 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/cache/node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", - "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", "dependencies": { "@emotion/memoize": "^0.8.1" } }, - "node_modules/@emotion/memoize": { + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { - "version": "11.11.3", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.3.tgz", - "integrity": "sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==", + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", @@ -552,9 +834,9 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", "dependencies": { "@emotion/hash": "^0.9.1", "@emotion/memoize": "^0.8.1", @@ -563,25 +845,30 @@ "csstype": "^3.0.2" } }, + "node_modules/@emotion/serialize/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, "node_modules/@emotion/serialize/node_modules/@emotion/unitless": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "version": "11.11.5", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz", + "integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==", "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", + "@emotion/is-prop-valid": "^1.2.2", + "@emotion/serialize": "^1.1.4", "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@emotion/utils": "^1.2.1" }, @@ -595,11 +882,6 @@ } } }, - "node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" - }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", @@ -632,10 +914,28 @@ "node": ">=16" } }, + "node_modules/@es-joy/jsdoccomment/node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@es-joy/jsdoccomment/node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -649,9 +949,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -665,9 +965,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -681,9 +981,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -697,9 +997,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -713,9 +1013,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -729,9 +1029,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -745,9 +1045,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -761,9 +1061,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -777,9 +1077,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -793,9 +1093,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -809,9 +1109,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -825,9 +1125,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -841,9 +1141,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -857,9 +1157,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -873,9 +1173,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -889,9 +1189,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -905,9 +1205,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -921,9 +1221,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -937,9 +1237,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -953,9 +1253,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -969,9 +1269,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -985,9 +1285,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -1024,75 +1324,6 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/@floating-ui/core": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", @@ -1127,40 +1358,19 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz", "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "dev": true }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "@hapi/hoek": "^9.0.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1177,172 +1387,463 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "engines": { - "node": ">=6.0.0" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@mui/base": { - "version": "5.0.0-beta.36", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.36.tgz", - "integrity": "sha512-6A8fYiXgjqTO6pgj31Hc8wm1M3rFYCxDRh09dBVk0L0W4cb2lnurRJa3cAyic6hHY+we1S58OdGYRbKmOsDpGQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.23.9", - "@floating-ui/react-dom": "^2.0.8", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.9", - "@popperjs/core": "^2.11.8", - "clsx": "^2.1.0", - "prop-types": "^15.8.1" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">=8" } }, - "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.10", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.10.tgz", - "integrity": "sha512-qPv7B+LeMatYuzRjB3hlZUHqinHx/fX4YFBiaS19oC02A1e9JFuDKDvlyRQQ5oRSbJJt0QlaLTlr0IcauVcJRQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@mui/icons-material": { - "version": "5.15.10", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.10.tgz", - "integrity": "sha512-9cF8oUHZKo9oQ7EQ3pxPELaZuZVmphskU4OI6NiJNDVN7zcuvrEsuWjYo1Zh4fLiC39Nrvm30h/B51rcUjvSGA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.23.9" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=12.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "@types/react": { + "node-notifier": { "optional": true } } }, - "node_modules/@mui/material": { - "version": "5.15.10", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.10.tgz", - "integrity": "sha512-YJJGHjwDOucecjDEV5l9ISTCo+l9YeWrho623UajzoHRYxuKUmwrGVYOW4PKwGvCx9SU9oklZnbbi2Clc5XZHw==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.36", - "@mui/core-downloads-tracker": "^5.15.10", - "@mui/system": "^5.15.9", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.9", - "@types/react-transition-group": "^4.4.10", - "clsx": "^2.1.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1", - "react-is": "^18.2.0", - "react-transition-group": "^4.4.5" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { "node": ">=12.0.0" @@ -1352,31 +1853,70 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { + "@types/react": { "optional": true - }, + } + } + }, + "node_modules/@mui/base/node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.15.tgz", + "integrity": "sha512-aXnw29OWQ6I5A47iuWEI6qSSUfH6G/aCsW9KmW3LiFqr7uXZBK4Ks+z8G+qeIub8k0T5CMqlT2q0L+ZJTMrqpg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.15.tgz", + "integrity": "sha512-kkeU/pe+hABcYDH6Uqy8RmIsr2S/y5bP2rp+Gat4CcRjCcVne6KudS1NrZQhUCRysrTDCAhcbcf9gt+/+pGO2g==", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { "@types/react": { "optional": true } } }, - "node_modules/@mui/private-theming": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.9.tgz", - "integrity": "sha512-/aMJlDOxOTAXyp4F2rIukW1O0anodAMCkv1DfBh/z9vaKHY3bd5fFf42wmP+0GRmwMinC5aWPpNfHXOED1fEtg==", + "node_modules/@mui/lab": { + "version": "5.0.0-alpha.170", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.170.tgz", + "integrity": "sha512-0bDVECGmrNjd3+bLdcLiwYZ0O4HP5j5WSQm5DV6iA/Z9kr8O6AnvZ1bv9ImQbbX7Gj3pX4o43EKwCutj3EQxQg==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.9", + "@mui/base": "5.0.0-beta.40", + "@mui/system": "^5.15.15", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", "prop-types": "^15.8.1" }, "engines": { @@ -1387,24 +1927,42 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": ">=5.15.0", "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, "@types/react": { "optional": true } } }, - "node_modules/@mui/styled-engine": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.9.tgz", - "integrity": "sha512-NRKtYkL5PZDH7dEmaLEIiipd3mxNnQSO+Yo8rFNBNptY8wzQnQ+VjayTq39qH7Sast5cwHKYFusUrQyD+SS4Og==", + "node_modules/@mui/material": { + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", + "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@emotion/cache": "^11.11.0", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.15", + "@mui/system": "^5.15.15", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" }, "engines": { "node": ">=12.0.0" @@ -1414,9 +1972,11 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@emotion/react": "^11.4.1", + "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -1424,13 +1984,16 @@ }, "@emotion/styled": { "optional": true + }, + "@types/react": { + "optional": true } } }, "node_modules/@mui/styled-engine-sc": { - "version": "6.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-6.0.0-alpha.16.tgz", - "integrity": "sha512-hZT4xPk/zvFtNvUS/VumrtSe+sV2eZB2Z048z0RGgxMDLTGgWAIs4kJ+YAS16ugmE2nwrlaZhpfr/1lD7gd7xg==", + "version": "6.0.0-alpha.18", + "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-6.0.0-alpha.18.tgz", + "integrity": "sha512-W3mqR1K01rPL0BVNTgGpIYxdbQ/nTAlwYaohRdmX7FZvbm1yKw9F90OIGxM503dfRMVBi6a/neYPgIUebcGsHw==", "dependencies": { "@babel/runtime": "^7.23.9", "csstype": "^3.1.3", @@ -1449,15 +2012,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.9.tgz", - "integrity": "sha512-SxkaaZ8jsnIJ77bBXttfG//LUf6nTfOcaOuIgItqfHv60ZCQy/Hu7moaob35kBb+guxVJnoSZ+7vQJrA/E7pKg==", + "version": "5.15.15", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz", + "integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.9", - "@mui/styled-engine": "^5.15.9", - "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.9", + "@mui/private-theming": "^5.15.14", + "@mui/styled-engine": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -1487,10 +2050,67 @@ } } }, + "node_modules/@mui/system/node_modules/@mui/private-theming": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", + "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.14", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/system/node_modules/@mui/styled-engine": { + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", + "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, "node_modules/@mui/types": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", + "version": "7.2.14", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", + "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0" }, @@ -1501,9 +2121,9 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.9", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.9.tgz", - "integrity": "sha512-yDYfr61bCYUz1QtwvpqYy/3687Z8/nS4zv7lv/ih/6ZFGMl1iolEvxRmR84v2lOYxlds+kq1IVYbXxDKh8Z9sg==", + "version": "5.15.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", + "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", "dependencies": { "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", @@ -1527,62 +2147,108 @@ } } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, + "node_modules/@mui/x-data-grid": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-7.1.1.tgz", + "integrity": "sha512-hNvz927lkAznFdy45QPE7mIZVyQhlqveHmTK9+SD0N1us4sSTij90uUJ/roTNDod0VA9f5GqWmNz+5h8ihpz6Q==", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/runtime": "^7.24.0", + "@mui/system": "^5.15.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", + "prop-types": "^15.8.1", + "reselect": "^4.1.8" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.15.14", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "node_modules/@mui/x-date-pickers": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.1.1.tgz", + "integrity": "sha512-doSaoNfYR4nAXSN2mz5MwktYUmPt37jZ8/t5QrPgFtEFc3KWZoBps0YEcno5qUynY1ISpOjvnVr18zqszzG+RA==", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/runtime": "^7.24.0", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "node": ">=14.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14", + "date-fns": "^2.25.0 || ^3.2.0", + "date-fns-jalali": "^2.13.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } } }, "node_modules/@remix-run/router": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", - "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", "engines": { "node": ">=14.0.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", - "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz", + "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==", "cpu": [ "arm" ], @@ -1593,9 +2259,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", - "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz", + "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==", "cpu": [ "arm64" ], @@ -1606,9 +2272,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", - "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz", + "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==", "cpu": [ "arm64" ], @@ -1619,9 +2285,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", - "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz", + "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==", "cpu": [ "x64" ], @@ -1632,9 +2298,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", - "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz", + "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==", "cpu": [ "arm" ], @@ -1645,9 +2311,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", - "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz", + "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==", "cpu": [ "arm64" ], @@ -1658,9 +2324,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", - "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz", + "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==", "cpu": [ "arm64" ], @@ -1670,10 +2336,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz", + "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==", + "cpu": [ + "ppc64le" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", - "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz", + "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==", "cpu": [ "riscv64" ], @@ -1683,10 +2362,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz", + "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", - "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz", + "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==", "cpu": [ "x64" ], @@ -1697,9 +2389,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", - "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz", + "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==", "cpu": [ "x64" ], @@ -1710,9 +2402,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", - "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz", + "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==", "cpu": [ "arm64" ], @@ -1723,9 +2415,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", - "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz", + "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==", "cpu": [ "ia32" ], @@ -1736,9 +2428,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", - "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz", + "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==", "cpu": [ "x64" ], @@ -1748,6 +2440,132 @@ "win32" ] }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@testing-library/react": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1789,24 +2607,104 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/downloadjs": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@types/downloadjs/-/downloadjs-1.4.6.tgz", + "integrity": "sha512-mp3w70vsaiLRT9ix92fmI9Ob2yJAPZm6tShJtofo2uHbN11G2i6a0ApIEjBl/kv3e9V7Pv7jMjk1bUwYWvMHvA==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, "node_modules/@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, - "optional": true, "dependencies": { "undici-types": "~5.26.4" } @@ -1817,29 +2715,49 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.2.56", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.56.tgz", - "integrity": "sha512-NpwHDMkS/EFZF2dONFQHgkPRwhvgq/OAvIaGQzxGSBmaeR++kTg6njr15Vatz0/2VcCEwJQFi6Jf4Q0qBu0rLA==", + "version": "18.2.75", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.75.tgz", + "integrity": "sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==", "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.2.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", - "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", + "version": "18.2.24", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.24.tgz", + "integrity": "sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==", "dev": true, "dependencies": { "@types/react": "*" } }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "dev": true, + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "dev": true, + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.10", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", @@ -1849,14 +2767,15 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==", + "dev": true }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/sinonjs__fake-timers": { @@ -1871,11 +2790,37 @@ "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", "dev": true }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, "node_modules/@types/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==" }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -1949,51 +2894,7 @@ } } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", @@ -2006,7 +2907,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree": { + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", @@ -2034,39 +2935,38 @@ } } }, - "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "dev": true, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/scope-manager": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2076,1542 +2976,6510 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/@vitejs/plugin-react": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", - "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@babel/core": "^7.23.5", - "@babel/plugin-transform-react-jsx-self": "^7.23.3", - "@babel/plugin-transform-react-jsx-source": "^7.23.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.0" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=0.4.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { - "node": ">=6" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" }, "engines": { - "node": ">=4" + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "node_modules/@vitejs/plugin-react/node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", + "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/are-docs-informative": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", - "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "node_modules/@vitejs/plugin-react/node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.1.tgz", + "integrity": "sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==", "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=14" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/@vitest/coverage-v8": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.5.2.tgz", + "integrity": "sha512-QJqxRnbCwNtbbegK9E93rBmhN3dbfG1bC/o52Bqr0zGCYhQzwgwvrJBG7Q8vw3zilX6Ryy6oa/mkZku2lLJx1Q==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.5.2" + } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/@vitest/expect": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.2.tgz", + "integrity": "sha512-rf7MTD1WCoDlN3FfYJ9Llfp0PbdtOMZ3FIF0AVkDnKbp3oiMW1c8AmvRZBcqbAhDUAvF52e9zx4WQM1r3oraVA==", "dev": true, "dependencies": { - "safer-buffer": "~2.1.0" + "@vitest/spy": "1.5.2", + "@vitest/utils": "1.5.2", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/@vitest/runner": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.2.tgz", + "integrity": "sha512-7IJ7sJhMZrqx7HIEpv3WrMYcq8ZNz9L6alo81Y6f8hV5mIE6yVZsFoivLZmr0D777klm1ReqonE9LyChdcmw6g==", "dev": true, - "engines": { - "node": ">=0.8" + "dependencies": { + "@vitest/utils": "1.5.2", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { + "node_modules/@vitest/runner/node_modules/yocto-queue": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "node_modules/@vitest/snapshot": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.2.tgz", + "integrity": "sha512-CTEp/lTYos8fuCc9+Z55Ga5NVPKUgExritjF5VY7heRFUfheoAqBneUlvXSUJHUZPjnPmyZA96yLRJDP1QATFQ==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/@vitest/spy": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.2.tgz", + "integrity": "sha512-xCcPvI8JpCtgikT9nLpHPL1/81AYqZy1GCy4+MCHBE7xi8jgsYkULpW5hrx5PGLgOQjUpb6fd15lqcriJ40tfQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "tinyspy": "^2.2.0" }, - "engines": { - "node": ">=10", - "npm": ">=6" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/@vitest/utils": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.2.tgz", + "integrity": "sha512-sWOmyofuXLJ85VvXNsroZur7mOJGiQeM0JN3/0D1uU8U9bGFM69X1iqHaRXl6R8BwaLY6yPCogP257zxTzkUdA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { - "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" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/ajv/node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "punycode": "^2.1.0" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "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" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001588", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001588.tgz", - "integrity": "sha512-+hVY9jE44uKLkH0SrUTqxjxqNTOWHsbnQDIKjwkZ3lNTzUUVdBLBGXtj/q5Mp5u98r3droaZAewQuEDzjQdZlQ==", + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "consulting", + "url": "https://feross.org/support" } ] }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">=14" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" + "dequal": "^2.0.3" } }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "string-width": "^4.2.0" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": "10.* || >= 12.*" + "node": ">= 0.4" }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cli-truncate": { + "node_modules/array-union": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "safer-buffer": "~2.1.0" } }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, "engines": { - "node": ">= 6" + "node": ">=0.8" } }, - "node_modules/comment-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", - "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { - "node": ">= 12.0.0" + "node": "*" } }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 4.0.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/cypress": { - "version": "13.6.4", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.4.tgz", - "integrity": "sha512-pYJjCfDYB+hoOoZuhysbbYhEmNW7DEDsqn+ToCLwuVowxUXppIWRr7qk4TVRIU471ksfzyZcH+mkoF0CQUKnpw==", + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@cypress/request": "^3.0.0", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.6.0", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/cypress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=8" } }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cypress/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dependencies": { - "color-name": "~1.1.4" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10", + "npm": ">=6" } }, - "node_modules/cypress/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "node_modules/cypress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + ] }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "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" + "tweetnacl": "^0.14.3" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "path-type": "^4.0.0" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "esutils": "^2.0.2" + "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" }, "engines": { - "node": ">=6.0.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "node-int64": "^0.4.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.673", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.673.tgz", - "integrity": "sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/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==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "once": "^1.4.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, "engines": { - "node": ">=8.6" + "node": "*" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, - "node_modules/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==", + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { - "node": ">= 0.4" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "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": ">=12" + "node": ">= 0.4" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/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==", + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, "engines": { - "node": ">=0.8.0" + "node": ">=4" } }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", + "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, + "node_modules/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==" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cypress": { + "version": "13.8.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.8.1.tgz", + "integrity": "sha512-Uk6ovhRbTg6FmXjeZW/TkbRM07KPtvM5gah1BIMp4Y2s+i/NMxgaLw0+PbYTOdw1+egE0FP3mWRiGcRkjjmhzA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.0", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-2.0.0.tgz", + "integrity": "sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/downloadjs": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz", + "integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.746", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.746.tgz", + "integrity": "sha512-jeWaIta2rIG2FzHaYIhSuVWqC6KJYo7oSBX4Jv7g+aVujKztfvdpf+n6MGwZdC5hQXbax4nntykLH2juIQrfPg==", + "dev": true + }, + "node_modules/emitter-component": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.2.tgz", + "integrity": "sha512-QdXO3nXOzZB4pAjM0n6ZE+R9/+kPpECA/XSELIcc54NeYVnBqIk+4DFiBgK+8QbV3mdvTG6nedl7dTYgO+5wDw==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/escalade": { + "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" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "48.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.3.tgz", + "integrity": "sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.42.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.6.0", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.6.tgz", + "integrity": "sha512-NjGXdm7zgcKRkKMua34qVO9doI7VOxZ6ancSvBELJSSoX97jyndXcSoa8XBh69JoB31dNz3EEzlMcizZl7LaMA==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@microsoft/tsdoc": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "dev": true + }, + "node_modules/eslint-plugin-tsdoc/node_modules/@microsoft/tsdoc-config": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.14.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/eslint-plugin-tsdoc/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/eslint/node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.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/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "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": { + "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" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-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==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/globby/node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/globby/node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/globby/node_modules/fast-glob": { + "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", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/globby/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/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.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/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "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": { + "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" + } + }, + "node_modules/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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dev": true, + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/i18next": { + "version": "23.11.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.0.tgz", + "integrity": "sha512-VwFtlgy2LDbY0Qs6VfekIm6mv5/JmSJrtBf4aszl7Vby8+GcBlri0/7dkMZXmzTfiBMPUPBOmYCdQK7K4emkGQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.1.tgz", + "integrity": "sha512-h/pM34bcH6tbz8WgGXcmWauNpQupCGr25XPp9cZwZInR9XHSjIFDYp1SIok7zSPsTOMxdvuLyu86V+g2Kycnfw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-http-backend": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.0.tgz", + "integrity": "sha512-Z/aQsGZk1gSxt2/DztXk92DuDD20J+rNudT7ZCdTrNOiK8uQppfvdjq9+DFQfpAnFPn3VZS+KQIr1S/W1KxhpQ==", + "dev": true, + "dependencies": { + "cross-fetch": "4.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "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/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, + "node_modules/joi": { + "version": "17.13.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.1.tgz", + "integrity": "sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", + "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", + "dev": true, + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.7", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.6.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.3", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.16.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dev": true, + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/magicast": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", + "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.4", + "@babel/types": "^7.24.0", + "source-map-js": "^1.2.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", + "dev": true + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-mdx-jsx/node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast/node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mlly": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz", + "integrity": "sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.0.3", + "ufo": "^1.3.2" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { - "eslint": "bin/eslint.js" + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/eslint-plugin-jsdoc": { - "version": "48.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.1.0.tgz", - "integrity": "sha512-g9S8ukmTd1DVcV/xeBYPPXOZ6rc8WJ4yi0+MVxJ1jBOrz5kmxV9gJJQ64ltCqIWFnBChLIhLVx3tbTSarqVyFA==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.42.0", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.6.0", - "spdx-expression-parse": "^4.0.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=18" + "node": "4.x || >=6.0.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" + "encoding": "^0.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/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, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", - "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "peerDependencies": { - "eslint": ">=7" + "bin": { + "semver": "bin/semver" } }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">= 4" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "color-convert": "^1.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=4" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "color-name": "1.1.3" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4.8" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=0.8.0" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "shebang-regex": "^1.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "has-flag": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "which": "bin/which" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "path-key": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, + "node_modules/nwsapi": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", + "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", + "dev": true + }, + "node_modules/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==", "engines": { - "node": ">=0.10" + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/object.assign": { + "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.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "wrappy": "1" } }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { - "pify": "^2.2.0" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", "dev": true }, - "node_modules/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==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">= 10.17.0" + "node": ">=10" }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8.6.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/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, "dependencies": { - "is-glob": "^4.0.1" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "dependencies": { - "reusify": "^1.0.4" + "engines": { + "node": ">=6" } }, - "node_modules/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==", - "dev": true, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dependencies": { - "pend": "~1.2.0" + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dependencies": { - "escape-string-regexp": "^1.0.5" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" @@ -3620,1008 +9488,1111 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "entities": "^4.4.0" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, "engines": { "node": ">=8" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=8" } }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { "node": "*" } }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" + "through": "~2.3" } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/function-bind": { - "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/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, - "dependencies": { - "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" + "node": ">= 6" } }, - "node_modules/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==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { - "pump": "^3.0.0" + "find-up": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "async": "^3.2.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "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" + "p-try": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/pkg-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.0.tgz", + "integrity": "sha512-/RpmvKdxKf8uILTtoOhAgf30wYbP2Qw+L9p3Rvshx1JZVX+XQNZQFjlbmGHEGIm4CkVPlSn+NXmIM8+9oWQaSA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "confbox": "^0.1.7", + "mlly": "^1.6.1", + "pathe": "^1.1.2" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "ini": "2.0.0" + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^10 || ^12 || >=14" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "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/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "es-define-property": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6.0" } }, - "node_modules/hasown": { + "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, "engines": { - "node": ">= 0.4" + "node": ">= 6" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dependencies": { - "react-is": "^16.7.0" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { + "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/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==" + }, + "node_modules/ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" }, "engines": { - "node": ">=0.10" + "node": ">= 0.10" } }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { - "node": ">=8.12.0" + "node": ">=6" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "opencollective", + "url": "https://opencollective.com/fast-check" } ] }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "side-channel": "^1.0.4" }, "engines": { - "node": ">=6" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "engines": { - "node": ">=8" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, + "loose-envify": "^1.1.0" + }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": "^18.2.0" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "node_modules/react-i18next": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.0.tgz", + "integrity": "sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==", "dev": true, "dependencies": { - "ci-info": "^3.2.0" + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" }, - "bin": { - "is-ci": "bin.js" + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dependencies": { - "hasown": "^2.0.0" + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/react-refresh": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", + "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/react-router": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", + "dependencies": { + "@remix-run/router": "1.15.3" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "node_modules/react-router-dom": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", "dependencies": { - "is-extglob": "^2.1.1" + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, "engines": { - "node": ">=0.12.0" + "node": ">=4" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "dependencies": { - "argparse": "^2.0.1" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", "dev": true, - "engines": { - "node": ">=12.0.0" + "dependencies": { + "throttleit": "^1.0.0" } }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/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, - "bin": { - "jsesc": "bin/jsesc" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=8" } }, - "node_modules/jsprim": { + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" + "engines": { + "node": ">=10" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "dependencies": { - "json-buffer": "3.0.1" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { - "node": "> 0.8" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "node_modules/rollup": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz", + "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==", "dev": true, "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" + "@types/estree": "1.0.5" }, - "engines": { - "node": ">=10.0.0" + "bin": { + "rollup": "dist/bin/rollup" }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.14.1", + "@rollup/rollup-android-arm64": "4.14.1", + "@rollup/rollup-darwin-arm64": "4.14.1", + "@rollup/rollup-darwin-x64": "4.14.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.1", + "@rollup/rollup-linux-arm64-gnu": "4.14.1", + "@rollup/rollup-linux-arm64-musl": "4.14.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1", + "@rollup/rollup-linux-riscv64-gnu": "4.14.1", + "@rollup/rollup-linux-s390x-gnu": "4.14.1", + "@rollup/rollup-linux-x64-gnu": "4.14.1", + "@rollup/rollup-linux-x64-musl": "4.14.1", + "@rollup/rollup-win32-arm64-msvc": "4.14.1", + "@rollup/rollup-win32-ia32-msvc": "4.14.1", + "@rollup/rollup-win32-x64-msvc": "4.14.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/rxjs": { + "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": { - "p-locate": "^5.0.0" + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, "engines": { - "node": ">=10" + "node": ">=0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">=8" + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "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": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" } }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -4629,1110 +10600,1217 @@ "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" + "node_modules/source-map-js": { + "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" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/spdx-exceptions": { + "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": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/spdx-license-ids": { + "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": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", "dev": true, + "dependencies": { + "through": "2" + }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/start-server-and-test": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.3.tgz", + "integrity": "sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.3.4", + "execa": "5.1.1", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "7.2.0" + }, "bin": { - "nanoid": "bin/nanoid.cjs" + "server-test": "src/bin/start.js", + "start-server-and-test": "src/bin/start.js", + "start-test": "src/bin/start.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=16" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/start-server-and-test/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/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==", + "node_modules/start-server-and-test/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "node_modules/start-server-and-test/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.17.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "dev": true + }, + "node_modules/stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", + "integrity": "sha512-gCq3NDI2P35B2n6t76YJuOp7d6cN/C7Rt0577l91wllh0sY9ZBuw9KaSGqH/b0hzn3CWWJbpbW0W0WvQ1H/Q7g==", + "dependencies": { + "emitter-component": "^1.1.1" + } + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", "dev": true, "dependencies": { - "wrappy": "1" + "duplexer": "~0.1.1" } }, - "node_modules/onetime": { + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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==", + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "aggregate-error": "^3.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "dependencies": { - "callsites": "^3.0.0" + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-exists": { + "node_modules/strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/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==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/path-key": { + "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/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==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + }, + "node_modules/strip-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", + "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", "dev": true, - "engines": { - "node": ">=8.6" + "dependencies": { + "js-tokens": "^9.0.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", + "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", + "dev": true + }, + "node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "dependencies": { + "inline-style-parser": "0.2.3" } }, - "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/styled-components": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.8.tgz", + "integrity": "sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==", "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "@emotion/is-prop-valid": "1.2.1", + "@emotion/unitless": "0.8.0", + "@types/stylis": "4.2.0", + "css-to-react-native": "3.2.0", + "csstype": "3.1.2", + "postcss": "8.4.31", + "shallowequal": "1.1.0", + "stylis": "4.3.1", + "tslib": "2.5.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" } }, - "node_modules/postcss-value-parser": { + "node_modules/styled-components/node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/styled-components/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/styled-components/node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/styled-components/node_modules/stylis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", + "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" + }, + "node_modules/stylis": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, + "node_modules/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==", "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=8" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "node_modules/tinybench": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", "dev": true }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", "dev": true, "engines": { - "node": ">=6" + "node": ">=14.0.0" } }, - "node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.14" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0" } }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, - "peerDependencies": { - "react": "^18.2.0" + "engines": { + "node": ">=6" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 4.0.0" } }, - "node_modules/react-router": { - "version": "6.22.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz", - "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==", - "dependencies": { - "@remix-run/router": "1.15.1" - }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, "engines": { - "node": ">=14.0.0" + "node": ">=16" }, "peerDependencies": { - "react": ">=16.8" + "typescript": ">=4.2.0" } }, - "node_modules/react-router-dom": { - "version": "6.22.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz", - "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==", + "node_modules/ts-jest": { + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", + "dev": true, "dependencies": { - "@remix-run/router": "1.15.1", - "react-router": "6.22.1" + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" }, "engines": { - "node": ">=14.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "dependencies": { - "throttleit": "^1.0.0" + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "prelude-ls": "^1.2.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, "engines": { "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rollup": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", - "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.12.0", - "@rollup/rollup-android-arm64": "4.12.0", - "@rollup/rollup-darwin-arm64": "4.12.0", - "@rollup/rollup-darwin-x64": "4.12.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", - "@rollup/rollup-linux-arm64-gnu": "4.12.0", - "@rollup/rollup-linux-arm64-musl": "4.12.0", - "@rollup/rollup-linux-riscv64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-musl": "4.12.0", - "@rollup/rollup-win32-arm64-msvc": "4.12.0", - "@rollup/rollup-win32-ia32-msvc": "4.12.0", - "@rollup/rollup-win32-x64-msvc": "4.12.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "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" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dependencies": { - "loose-envify": "^1.1.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { - "semver": "bin/semver.js" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=10" + "node": ">=14.17" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "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==", "dev": true }, - "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", "dependencies": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "dependencies": { - "shebang-regex": "^3.0.0" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", - "dev": true, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 10.0.0" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "color-convert": "^2.0.1" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "update-browserslist-db": "cli.js" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "node_modules/source-map-js": { + "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/spdx-exceptions": { - "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/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" } }, - "node_modules/spdx-license-ids": { - "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==", + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/strip-ansi": { + "node_modules/vfile": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", "dependencies": { - "ansi-regex": "^5.0.1" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/vite": { + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz", + "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==", "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=8" + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/styled-components": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.8.tgz", - "integrity": "sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==", + "node_modules/vite-node": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.2.tgz", + "integrity": "sha512-Y8p91kz9zU+bWtF7HGt6DVw2JbhyuB2RlZix3FPYAYmUyZ3n7iTp8eSyLyY6sxtPegvxQtmlTMhfPhUfCUF93A==", + "dev": true, "dependencies": { - "@emotion/is-prop-valid": "1.2.1", - "@emotion/unitless": "0.8.0", - "@types/stylis": "4.2.0", - "css-to-react-native": "3.2.0", - "csstype": "3.1.2", - "postcss": "8.4.31", - "shallowequal": "1.1.0", - "stylis": "4.3.1", - "tslib": "2.5.0" + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "node": ">= 16" + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0" + "url": "https://opencollective.com/vitest" } }, - "node_modules/styled-components/node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" - }, - "node_modules/styled-components/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "node_modules/vite/node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, "funding": [ { "type": "opencollective", @@ -5748,360 +11826,363 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, - "node_modules/styled-components/node_modules/stylis": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz", - "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==" - }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/vitest": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.2.tgz", + "integrity": "sha512-l9gwIkq16ug3xY7BxHwcBQovLZG75zZL0PlsiYQbf76Rz6QGs54416UWMtC0jXeihvHvcHrf2ROEjkQRVpoZYw==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "@vitest/expect": "1.5.2", + "@vitest/runner": "1.5.2", + "@vitest/snapshot": "1.5.2", + "@vitest/spy": "1.5.2", + "@vitest/utils": "1.5.2", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.5.2", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">=4" - } - }, - "node_modules/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==", - "engines": { - "node": ">= 0.4" + "node": "^18.0.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.5.2", + "@vitest/ui": "1.5.2", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/vitest/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { - "rimraf": "^3.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/vitest/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, "engines": { - "node": ">=8.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "node_modules/vitest/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, "engines": { - "node": ">=6" + "node": ">=16.17.0" } }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/vitest/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "node_modules/vitest/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "engines": { - "node": ">=16" + "node": ">=12" }, - "peerDependencies": { - "typescript": ">=4.2.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/vitest/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" + "path-key": "^4.0.0" }, "engines": { - "node": "*" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/vitest/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/vitest/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "node_modules/vitest/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, "engines": { - "node": ">=14.17" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/vitest/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, - "optional": true + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=0.10.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "node_modules/wait-on": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", + "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "axios": "^1.6.1", + "joi": "^17.11.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.1" }, "bin": { - "update-browserslist-db": "cli.js" + "wait-on": "bin/wait-on" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=12.0.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, "dependencies": { - "punycode": "^2.1.0" + "makeerror": "1.0.12" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/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==", + "dev": true + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=18" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/vite": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz", - "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.35", - "rollup": "^4.2.0" + "isexe": "^2.0.0" }, "bin": { - "vite": "bin/vite.js" + "node-which": "bin/node-which" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "siginfo": "^2.0.0", + "stackback": "0.0.2" }, "bin": { - "node-which": "bin/node-which" + "why-is-node-running": "cli.js" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, "node_modules/wrap-ansi": { @@ -6121,49 +12202,74 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, "engines": { - "node": ">=7.0.0" + "node": ">=18" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/yaml": { @@ -6174,6 +12280,33 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/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, + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -6195,6 +12328,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/frontend/package.json b/frontend/package.json index 4645a37b..b2c066b0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,33 +8,68 @@ "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview --port 5173", - "cypress:test": "cypress run", - "test": "npm run cypress:test" + "cy:test": "start-server-and-test dev http://localhost:5173 cy:run", + "cy:run": "cypress run", + "cy:open": "cypress open", + "vi:test": "vitest run", + "coverage": "vitest run --coverage", + "test": "npm-run-all -p vi:test cy:test" }, "dependencies": { - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.15.10", - "@mui/material": "^5.15.10", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.15.15", + "@mui/lab": "^5.0.0-alpha.170", + "@mui/material": "^5.15.15", "@mui/styled-engine-sc": "^6.0.0-alpha.16", + "@mui/x-data-grid": "^7.1.1", + "@mui/x-date-pickers": "^7.1.1", + "axios": "^1.6.8", + "dayjs": "^1.11.10", + "debounce": "^2.0.0", + "downloadjs": "^1.4.7", + "i18next-browser-languagedetector": "^7.2.0", + "i18next-http-backend": "^2.5.0", + "jszip": "^3.10.1", + "prettier": "^3.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-i18next": "^14.1.0", + "react-markdown": "^9.0.1", "react-router-dom": "^6.22.1", + "stream": "^0.0.2", "styled-components": "^6.1.8" }, "devDependencies": { + "@testing-library/react": "^15.0.7", + "@types/downloadjs": "^1.4.6", + "@types/history": "^4.7.11", "@types/react": "^18.2.55", "@types/react-dom": "^18.2.19", + "@types/react-router-dom": "^5.3.3", + "@types/scheduler": "^0.23.0", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react": "^4.2.1", - "cypress": "^13.6.4", + "@vitest/coverage-v8": "^1.5.2", + "cypress": "^13.8.1", "eslint": "^8.56.0", "eslint-plugin-jsdoc": "^48.1.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", "eslint-plugin-tsdoc": "^0.2.17", - "typescript": "^5.2.2", - "vite": "^5.1.0" + "i18next": "^23.10.1", + "i18next-browser-languagedetector": "^7.2.1", + "i18next-http-backend": "^2.5.0", + "jest": "^29.7.0", + "jsdom": "^24.0.0", + "npm-run-all": "^4.1.5", + "react-i18next": "^14.1.0", + "scheduler": "^0.23.0", + "start-server-and-test": "^2.0.3", + "ts-jest": "^29.1.2", + "typescript": "^5.4.5", + "vite": "^5.1.7", + "vitest": "^1.5.2" } } diff --git a/frontend/public/img/error_pigeon.png b/frontend/public/img/error_pigeon.png new file mode 100644 index 0000000000000000000000000000000000000000..f2264ead5c834fc6b0e317a2497ae8d11a88d241 GIT binary patch literal 2358 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 literal 0 HcmV?d00001 diff --git a/frontend/public/img/logo_ugent.png b/frontend/public/img/logo_ugent.png new file mode 100644 index 0000000000000000000000000000000000000000..c4358cedab5461ab8c6d053a3a8b542b99c7093c GIT binary patch literal 6422 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 + errorElement={} + loader={fetchMe} + > + } loader={fetchProjectPage} /> + }> + } loader={fetchProjectPage} /> + } loader={fetchProjectPage} /> + + } + loader={dataLoaderCourses} + /> + + } + loader={dataLoaderCourseDetail} + /> + + + } + loader={fetchProjectPage} + /> + } + /> + } + loader={loadProjectViewData} + > + } + loader={fetchProjectForm} + /> + + + + ) +); /** - * This component is the main application component that will be rendered by the ReactDOM. + * This component is the main application component that will be rendered by the ReactDOM. * @returns - The main application component */ -function App(): JSX.Element { - return ( - -

- - } /> - - - ); +export default function App(): React.JSX.Element { + return ; } - -export default App; diff --git a/frontend/src/components/Calender/DeadlineCalender.tsx b/frontend/src/components/Calender/DeadlineCalender.tsx new file mode 100644 index 00000000..5ac8ad6d --- /dev/null +++ b/frontend/src/components/Calender/DeadlineCalender.tsx @@ -0,0 +1,250 @@ +import { + DateCalendar, + LocalizationProvider, + PickersDay, + PickersDayProps, + TimeField, +} from "@mui/x-date-pickers"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import dayjs, { Dayjs } from "dayjs"; +import { Deadline } from "../../types/deadline"; +import { + Badge, + Box, + Divider, + Grid, + IconButton, + List, + ListItem, + Menu, + TextField, + Typography, +} from "@mui/material"; +import { useState } from "react"; +import SendIcon from "@mui/icons-material/Send"; +import ClearIcon from "@mui/icons-material/Clear"; +import { useTranslation } from "react-i18next"; + +interface DeadlineCalenderProps { + deadlines: Deadline[]; + onChange: (deadline: Deadline[]) => void; + editable?: boolean; +} + +/** + * + * @param params - The deadlines and the onChange function + * @returns - The DeadlineCalender component that displays the deadlines + */ +export default function DeadlineCalender({ + deadlines, + onChange, + editable = false, +}: DeadlineCalenderProps) { + const [deadlinesS, setDeadlines] = useState(deadlines); + const { i18n } = useTranslation(); + + const handleNewDeadline = (deadline: Deadline) => { + const newDeadlines = [...deadlinesS, deadline]; + setDeadlines(newDeadlines); + onChange(newDeadlines); + }; + + const handleDeadlineRemoved = (deadline: Deadline) => { + const newDeadlines = deadlinesS.filter((d) => d !== deadline); + setDeadlines(newDeadlines); + onChange(newDeadlines); + }; + + return ( + + + + ); +} + +/** + * + * @param props - The day and the deadlines + * @returns - The DeadlineDay component that displays the deadlines for a specific day + */ +function DeadlineDay( + props: PickersDayProps & { + deadlines?: Deadline[]; + editable?: boolean; + handleNewDeadline?: (deadline: Deadline) => void; + handleDeadlineRemoved?: (deadline: Deadline) => void; + } +) { + const { + deadlines = [], + day, + outsideCurrentMonth, + editable = false, + handleNewDeadline, + handleDeadlineRemoved, + ...other + } = props; + const [descriptionMenuAnchor, setDescriptionMenuAnchor] = + useState(null); + + const handleDescriptionMenu = (event: React.MouseEvent) => { + setDescriptionMenuAnchor(event.currentTarget); + }; + + const handleCloseDescriptionMenu = () => { + setDescriptionMenuAnchor(null); + }; + + const isDeadline = + !outsideCurrentMonth && + deadlines.filter((deadline) => { + return dayjs(deadline.deadline).isSame(day, "day"); + }).length > 0; + + return ( + + + {(isDeadline || editable) && ( + + + + )} + + ); +} + +/** + * + * @param params - The deadlines, the day, editable, onNewDeadline and onDeadlineRemoved functions + * @returns - The DeadlineDescriptionMenu component that displays the deadlines for a specific day + */ +function DeadlineDescriptionMenu({ + deadlines, + day, + editable, + onNewDeadline, + onDeadlineRemoved, +}: { + deadlines: Deadline[]; + day: Dayjs; + editable: boolean; + onNewDeadline?: (deadline: Deadline) => void; + onDeadlineRemoved?: (deadline: Deadline) => void; +}) { + const [description, setDescription] = useState(""); + const [time, setTime] = useState(null); + + const handleNewDeadline = () => { + if (time && onNewDeadline && description.length > 0) { + let newDeadline = day.clone(); + newDeadline = newDeadline.hour(time.hour()); + newDeadline = newDeadline.minute(time.minute()); + onNewDeadline({ deadline: newDeadline.toString(), description }); + } + setDescription(""); + setTime(null); + }; + + const handleDeadlineRemoved = (deadline: Deadline) => { + if (onDeadlineRemoved) { + onDeadlineRemoved(deadline); + } + }; + + return ( + + + + {deadlines + .filter((deadline) => { + return dayjs(deadline.deadline).isSame(day, "day"); + }) + .map((deadline, index) => { + return ( +
+ + {deadline.description} + + + {dayjs(deadline.deadline).format("HH:mm")} + + {editable && ( + handleDeadlineRemoved(deadline)} + > + + + )} + + +
+ ); + })} +
+
+ {editable && ( + + + + setDescription(event.target.value)} + /> + + + { + setTime(newValue); + }} + /> + + + + + + + + + )} +
+ ); +} diff --git a/frontend/src/components/Courses/AllCoursesTeacher.tsx b/frontend/src/components/Courses/AllCoursesTeacher.tsx new file mode 100644 index 00000000..fb3a3b62 --- /dev/null +++ b/frontend/src/components/Courses/AllCoursesTeacher.tsx @@ -0,0 +1,110 @@ +import { + Button, + Dialog, + DialogActions, + DialogTitle, + FormControl, + FormHelperText, + Grid, + Input, + InputLabel, +} from "@mui/material"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { SideScrollableCourses } from "./CourseUtilComponents"; +import { Course, callToApiToCreateCourse, ProjectDetail } from "./CourseUtils"; +import { Title } from "../Header/Title"; +import { useLoaderData } from "react-router-dom"; +import { Me } from "../../types/me"; + +/** + * @returns A jsx component representing all courses for a teacher + */ +export function AllCoursesTeacher(): JSX.Element { + const [open, setOpen] = useState(false); + const { courses, projects, me } = useLoaderData() as { + courses: Course[]; + me: Me; + projects: { [courseId: string]: ProjectDetail[] }; + }; + + const [courseName, setCourseName] = useState(""); + const [error, setError] = useState(""); + + const navigate = useNavigate(); + + const { t } = useTranslation("translation", { + keyPrefix: "allCoursesTeacher", + }); + + const handleClickOpen = () => { + setOpen(true); + }; + + const handleClose = () => { + setOpen(false); + }; + + const handleInputChange = (event: React.ChangeEvent) => { + setCourseName(event.target.value); + setError(""); // Clearing error message when user starts typing + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); // Prevents the default form submission behaviour + + if (!courseName.trim()) { + setError(t("emptyCourseNameError")); + return; + } + + const data = { name: courseName }; + callToApiToCreateCourse(JSON.stringify(data), navigate); + }; + return ( + <> + + + + + {t("courseForm")} +
+ + {t("courseName")} + + {error && ( + {error} + )} + + + + + +
+
+ {me && me.role === "TEACHER" && ( + + + + )} +
+ + ); +} diff --git a/frontend/src/components/Courses/CourseDetailStudent.tsx b/frontend/src/components/Courses/CourseDetailStudent.tsx new file mode 100644 index 00000000..9a211db2 --- /dev/null +++ b/frontend/src/components/Courses/CourseDetailStudent.tsx @@ -0,0 +1,94 @@ +import { + Grid, + Paper, + Typography, +} from "@mui/material"; +import { useTranslation } from "react-i18next"; +import { + Course, ProjectDetail, +} from "./CourseUtils"; +import { + useLoaderData, +} from "react-router-dom"; +import { Title } from "../Header/Title"; +import { Me } from "../../types/me"; +import {EmptyOrNotProjects} from "./CourseDetailTeacher" + +/** + * + * @returns A jsx component representing the course detail page for a teacher + */ +export default function CourseDetailStudent() { + + const courseDetail = useLoaderData() as { + course: Course; + projects: ProjectDetail[]; + adminMes: Me[]; + studentMes: Me[]; + me:Me; + }; + const { course, projects, adminMes } = courseDetail; + const { t } = useTranslation("translation", { + keyPrefix: "courseDetailTeacher", + }); + + return ( + <> + + + + +
+ {t("projects")}: + +
+
+
+ + + + + {t("admins")}: + + {adminMes.map((admin: Me) => ( + + + + {admin.display_name} + + + + + ))} + + + + + +
+ + ); +} diff --git a/frontend/src/components/Courses/CourseDetailTeacher.tsx b/frontend/src/components/Courses/CourseDetailTeacher.tsx new file mode 100644 index 00000000..4b512ccc --- /dev/null +++ b/frontend/src/components/Courses/CourseDetailTeacher.tsx @@ -0,0 +1,617 @@ +import { + Box, + Button, + Card, + CardActions, + CardContent, + CardHeader, + Checkbox, + FormControlLabel, + Grid, + IconButton, + Input, + InputLabel, + Menu, + MenuItem, + Paper, + Tooltip, + Typography, +} from "@mui/material"; +import { ChangeEvent, useCallback, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { + Course, + apiHost, + getIdFromLink, + getNearestFutureDate, + ProjectDetail, +} from "./CourseUtils"; +import { + Link, + useNavigate, + NavigateFunction, + useLoaderData, +} from "react-router-dom"; +import { Title } from "../Header/Title"; +import ClearIcon from "@mui/icons-material/Clear"; +import { timeDifference } from "../../utils/date-utils"; +import { authenticatedFetch } from "../../utils/authenticated-fetch"; +import i18next from "i18next"; +import { Me } from "../../types/me"; +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; + +interface UserUid { + uid: string; +} + +/** + * Handles the deletion of an admin. + * @param navigate - The navigate function from react-router-dom. + * @param courseId - The ID of the course. + * @param uid - The UID of the admin. + */ +function handleDeleteAdmin( + navigate: NavigateFunction, + courseId: string, + uid: string +): void { + authenticatedFetch(`${apiHost}/courses/${courseId}/admins`, { + method: "DELETE", + body: JSON.stringify({ + admin_uid: uid, + }), + }).then(() => { + navigate(0); + }); +} + +/** + * Handles the deletion of a student. + * @param navigate - The navigate function from react-router-dom. + * @param courseId - The ID of the course. + * @param uid - The UID of the admin. + */ +function handleDeleteStudent( + navigate: NavigateFunction, + courseId: string, + uids: string[] +): void { + authenticatedFetch(`${apiHost}/courses/${courseId}/students`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + students: uids, + }), + }).then(() => { + navigate(0); + }); +} + +/** + * Handles the deletion of a course. + * @param navigate - The navigate function from react-router-dom. + * @param courseId - The ID of the course. + */ +function handleDeleteCourse( + navigate: NavigateFunction, + courseId: string +): void { + authenticatedFetch(`${apiHost}/courses/${courseId}`, { + method: "DELETE", + }).then((response) => { + if (response.ok) { + navigate(-1); + } else if (response.status === 404) { + navigate(-1); + } + }); +} + +/** + * + * @returns A jsx component representing the course detail page for a teacher + */ +export default function CourseDetailTeacher() { + const [selectedStudents, setSelectedStudents] = useState([]); + const [anchorEl, setAnchorElStudent] = useState(null); + const openCodes = Boolean(anchorEl); + const handleClickCodes = (event: React.MouseEvent) => { + setAnchorElStudent(event.currentTarget); + }; + const handleCloseCodes = () => { + setAnchorElStudent(null); + }; + + const courseDetail = useLoaderData() as { + course: Course; + projects: ProjectDetail[]; + adminMes: Me[]; + studentMes: Me[]; + me:Me; + }; + const { course, projects, adminMes, studentMes } = courseDetail; + const { t } = useTranslation("translation", { + keyPrefix: "courseDetailTeacher", + }); + const lang = i18next.resolvedLanguage; + const navigate = useNavigate(); + + const handleCheckboxChange = ( + event: ChangeEvent, + uid: string + ) => { + if (event.target.checked) { + setSelectedStudents((prevSelected) => [...prevSelected, uid]); + } else { + setSelectedStudents((prevSelected) => + prevSelected.filter((student) => student !== uid) + ); + } + }; + + return ( + <> + + + + +
+ {t("projects")}: + +
+
+ + + +
+ + + + + {t("admins")}: + + {adminMes.map((admin: Me) => ( + + + + {admin.display_name} + + + + + ))} + + + + + + {t("students")}: + + + + + + + + + + + + + + handleDeleteStudent( + navigate, + course.course_id, + selectedStudents + ) + } + > + + {t("deleteSelected")} + + + + +
+ + ); +} + +/** + * @param projects - The array of projects. + * @returns Either a place holder for no projects or a grid of cards describing the projects. + */ +export function EmptyOrNotProjects({ + projects, +}: { + projects: ProjectDetail[]; +}): JSX.Element { + const { t } = useTranslation("translation", { + keyPrefix: "courseDetailTeacher", + }); + if (projects === undefined || projects.length === 0) { + return {t("noProjects")}; + } else { + return ( + + {projects?.map((project) => ( + + + + + + + {getNearestFutureDate(project.deadlines) && ( + + {`${t("deadline")}: ${getNearestFutureDate(project.deadlines)?.date.toLocaleDateString()}`} + + )} + + + + + + + + + ))} + + ); + } +} + +/** + * @param navigate - The navigate function from react-router-dom. + * @param course - The course against which we will check if the uid is of the teacher. + * @param admin - The admin in question. + * @returns Either nothing, if the admin uid is of teacher or a delete button. + */ +function EitherDeleteIconOrNothing({ + admin, + course, + navigate, +}: { + admin: UserUid; + course: Course; + navigate: NavigateFunction; +}): JSX.Element { + if (course.teacher === getIdFromLink(admin.uid)) { + return <>; + } else { + return ( + + + handleDeleteAdmin( + navigate, + course.course_id, + getIdFromLink(admin.uid) + ) + } + > + + + + ); + } +} + +/** + * @param students - The array of students. + * @param selectedStudents - The array of selected students. + * @param handleCheckboxChange - The function to handle the checkbox change. + * @returns Either a place holder for no students or a grid of checkboxes for the students. + */ +function EmptyOrNotStudents({ + students, + selectedStudents, + handleCheckboxChange, +}: { + students: Me[]; + selectedStudents: string[]; + handleCheckboxChange: ( + event: React.ChangeEvent, + studentId: string + ) => void; +}): JSX.Element { + if (students.length === 0) { + return ( + + No students found + + ); + } else { + return ( + + {students.map((student) => ( + + + + handleCheckboxChange(event, getIdFromLink(student.uid)) + } + /> + + + {student.display_name} + + + ))} + + ); + } +} + +interface JoinCode { + join_code: string; + expiry_time: string; + for_admins: boolean; +} + +/** + * Renders the JoinCodeMenu component. + * @param open - Whether the dialog is open or not. + * @param handleClose - Function to handle the dialog close event. + * @param handleNewCode - Function to handle the creation of a new join code. + * @param handleDeleteCode - Function to handle the deletion of a join code. + * @param getCodes - Function to get the list of join codes. + * @returns The rendered JoinCodeDialog component. + */ +function JoinCodeMenu({ + courseId, + open, + handleClose, + anchorEl, +}: { + courseId: string; + open: boolean; + handleClose: () => void; + anchorEl: HTMLElement | null; +}) { + const { t } = useTranslation("translation", { + keyPrefix: "courseDetailTeacher", + }); + + const [codes, setCodes] = useState([]); + const [expiry_time, setExpiryTime] = useState(null); + const [for_admins, setForAdmins] = useState(false); + + const handleInputChange = (event: React.ChangeEvent) => { + setExpiryTime(new Date(event.target.value)); + }; + + const handleCopyToClipboard = (join_code: string) => { + const host = window.location.host; + navigator.clipboard.writeText( + `${window.location.protocol}//${host}/${i18next.resolvedLanguage}/courses/join?code=${join_code}` + ); + }; + + const getCodes = useCallback(() => { + authenticatedFetch(`${apiHost}/courses/${courseId}/join_codes`, { + method: "GET", + }) + .then((response) => response.json()) + .then((data) => { + const filteredData = data.data.filter((code: JoinCode) => { + // Filter out expired codes + let expired = false; + if (code.expiry_time !== null) { + const expiryTime = new Date(code.expiry_time); + const now = new Date(); + expired = expiryTime < now; + } + + return !expired; + }); + setCodes(filteredData); + }); + }, [courseId]); + + const handleNewCode = () => { + const bodyContent: { for_admins: boolean; expiry_time?: string } = { + for_admins: for_admins, + }; + if (expiry_time !== null) { + bodyContent.expiry_time = expiry_time.toISOString(); + } + + authenticatedFetch(`${apiHost}/courses/${courseId}/join_codes`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(bodyContent), + }).then(() => getCodes()); + }; + + const handleDeleteCode = (joinCode: string) => { + authenticatedFetch( + `${apiHost}/courses/${courseId}/join_codes/${joinCode}`, + { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + join_code: joinCode, + }), + } + ).then(() => getCodes()); + }; + + useEffect(() => { + getCodes(); + }, [t, getCodes]); + + return ( + + + + {t("joinCodes")} + + + {codes.map((code: JoinCode) => ( + + + + + + {code.expiry_time + ? timeDifference(code.expiry_time) + : t("noExpiryDate")} + + + {code.for_admins ? t("forAdmins") : t("forStudents")} + + + handleCopyToClipboard(code.join_code)} + > + + + + + + + handleDeleteCode(code.join_code)}> + + + + + + ))} + + + + {t("expiryDate")}:{" "} + + + setForAdmins(event.target.checked)} + name="forAdmins" + color="primary" + /> + } + /> + + + + + ); +} diff --git a/frontend/src/components/Courses/CourseUtilComponents.tsx b/frontend/src/components/Courses/CourseUtilComponents.tsx new file mode 100644 index 00000000..70889c63 --- /dev/null +++ b/frontend/src/components/Courses/CourseUtilComponents.tsx @@ -0,0 +1,311 @@ +import { + Box, + Button, + Card, + CardActions, + CardContent, + CardHeader, + Grid, + Paper, + TextField, + Typography, +} from "@mui/material"; +import { + Course, + ProjectDetail, + getIdFromLink, + getNearestFutureDate, +} from "./CourseUtils"; +import { Link, useNavigate, useLocation } from "react-router-dom"; +import { useState, useEffect, useMemo } from "react"; +import { useTranslation } from "react-i18next"; +import debounce from "debounce"; +import i18next from "i18next"; + +/** + * @param text - The text to be displayed + * @returns Typography that overflow into ... when text is too long + */ +export function EpsilonTypography({ text }: { text: string }): JSX.Element { + return ( + + {text} + + ); +} + +/** + * @param label - The label of the search box + * @param searchTerm - The current search term + * @param handleSearchChange - The function to handle search term changes + * @returns a Grid item containing a TextField, used for searching/filtering + */ +export function SearchBox({ + label, + searchTerm, + handleSearchChange, +}: { + label: string; + searchTerm: string; + handleSearchChange: (event: React.ChangeEvent) => void; +}): JSX.Element { + return ( + + + + + + ); +} + +/** + * We should reuse this in the student course view since it will be mainly the same except the create button. + * @param props - The component props requiring the courses that will be displayed in the scroller. + * @returns A component to display courses in horizontal scroller where each course is a card containing its name. + */ +export function SideScrollableCourses({ + courses,projects +}: { + courses: Course[]; + projects: {[courseId: string]: ProjectDetail[];}; +}): JSX.Element { + //const navigate = useNavigate(); + const location = useLocation(); + const navigate = useNavigate(); + + // Get initial state from URL + const urlParams = useMemo( + () => new URLSearchParams(location.search), + [location.search] + ); //useMemo so only recompute when location.search changes + const initialSearchTerm = urlParams.get("name") || ""; + const initialUforaIdFilter = urlParams.get("ufora_id") || ""; + const initialTeacherNameFilter = urlParams.get("teacher") || ""; + + const [searchTerm, setSearchTerm] = useState(initialSearchTerm); + const [uforaIdFilter, setUforaIdFilter] = useState(initialUforaIdFilter); + const [teacherNameFilter, setTeacherNameFilter] = useState( + initialTeacherNameFilter + ); + + const debouncedHandleSearchChange = useMemo( + () => + debounce((key: string, value: string) => { + if (value === "") { + urlParams.delete(key); + } else { + urlParams.set(key, value); + } + const newUrl = `${location.pathname}?${urlParams.toString()}`; + navigate(newUrl, { replace: true }); + }, 500), + [urlParams, navigate, location.pathname] + ); + + useEffect(() => { + debouncedHandleSearchChange("name", searchTerm); + }, [searchTerm, debouncedHandleSearchChange]); + + useEffect(() => { + debouncedHandleSearchChange("ufora_id", uforaIdFilter); + }, [uforaIdFilter, debouncedHandleSearchChange]); + + useEffect(() => { + debouncedHandleSearchChange("teacher", teacherNameFilter); + }, [teacherNameFilter, debouncedHandleSearchChange]); + + const handleSearchChange = (event: React.ChangeEvent) => { + const newSearchTerm = event.target.value; + setSearchTerm(newSearchTerm); + }; + + const handleUforaIdFilterChange = ( + event: React.ChangeEvent + ) => { + const newUforaIdFilter = event.target.value; + setUforaIdFilter(newUforaIdFilter); + }; + + const handleTeacherNameFilterChange = ( + event: React.ChangeEvent + ) => { + const newTeacherNameFilter = event.target.value; + setTeacherNameFilter(newTeacherNameFilter); + }; + + const filteredCourses = courses.filter( + (course) => + course.name.toLowerCase().includes(searchTerm.toLowerCase()) && + (course.ufora_id + ? course.ufora_id.toLowerCase().includes(uforaIdFilter.toLowerCase()) + : !uforaIdFilter) && + course.teacher.toLowerCase().includes(teacherNameFilter.toLowerCase()) + ); + + return ( + + + + + + + + + ); +} + +/** + * Empty or not. + * @returns either a place holder or the actual content. + */ +function EmptyOrNotFilteredCourses({ + filteredCourses, + projects, +}: { + filteredCourses: Course[]; + projects: { [courseId: string]: ProjectDetail[] }; +}): JSX.Element { + const { t } = useTranslation("translation", { + keyPrefix: "courseDetailTeacher", + }); + if (filteredCourses.length === 0) { + return ( + + {t("noCoursesFound")} + + ); + } + + return ( + + + {filteredCourses.map((course, index) => ( + + + } /> + + {course.ufora_id && ( + <> + Ufora_id: {course.ufora_id} +
+ + )} + Teacher: {course.teacher} + + } + /> + + {t("projects")}: + + + + + + + +
+
+ ))} +
+
+ ); +} +/** + * @param projects - The projects to be displayed if not empty + * @returns either a place holder with text for no projects or the projects + */ +function EmptyOrNotProjects({ + projects, + noProjectsText, +}: { + projects: ProjectDetail[]; + noProjectsText: string; +}): JSX.Element { + const lang = i18next.resolvedLanguage; + if (projects === undefined || projects.length === 0) { + return ( + + {noProjectsText} + + ); + } else { + const now = new Date(); + return ( + <> + {projects.slice(0, 3).map((project) => { + let timeLeft = ""; + if (project.deadlines.length > 0) { + const deadline = getNearestFutureDate(project.deadlines); + if (deadline !== null) { + const deadlineDate = deadline.date; + const diffTime = Math.abs(deadlineDate.getTime() - now.getTime()); + const diffHours = Math.ceil(diffTime / (1000 * 60 * 60)); + const diffDays = Math.floor(diffHours / 24); + + timeLeft = + diffDays >= 1 ? `${diffDays} days` : `${diffHours} hours`; + } + } + return ( + + + + + + ); + })} + + ); + } +} diff --git a/frontend/src/components/Courses/CourseUtils.tsx b/frontend/src/components/Courses/CourseUtils.tsx new file mode 100644 index 00000000..d06202ff --- /dev/null +++ b/frontend/src/components/Courses/CourseUtils.tsx @@ -0,0 +1,270 @@ +import { NavigateFunction, Params } from "react-router-dom"; +import { authenticatedFetch } from "../../utils/authenticated-fetch"; +import { Me } from "../../types/me"; +import { fetchMe } from "../../utils/fetches/FetchMe"; + +export interface Course { + course_id: string; + name: string; + teacher: string; + ufora_id: string; + url: string; +} + +export interface Project { + title: string; + project_id: string; +} + +export interface ProjectDetail { + title: string; + project_id: string; + deadlines: Deadline[]; +} + +interface Deadline { + description: string; + date: Date; +} + +export const apiHost = import.meta.env.VITE_APP_API_HOST; +/** + * @returns The uid of the acces token of the logged in user + */ +export function loggedInToken() { + return "teacher1"; +} + +/** + * Get the username based on the provided uid. + * @param uid - The uid of the user. + * @returns The username. + */ +export async function getUser(uid: string): Promise { + return authenticatedFetch(`${apiHost}/users/${getIdFromLink(uid)}`).then( + (response) => { + if (response.ok) { + return response.json().then((data) => { + return data.data; + }); + } + } + ); +} + +/** + * @returns The Uid of the logged in user + */ +export function loggedInUid() { + return "Gunnar"; +} + +/** + * On a succesfull post the function will redirect to the data.url of the response, this should point to the detail page + * @param data - course data to send to the api + * @param navigate - function that allows the app to redirect + */ +export function callToApiToCreateCourse( + data: string, + navigate: NavigateFunction +) { + authenticatedFetch(`${apiHost}/courses`, { + headers: { + "Content-Type": "application/json", + }, + method: "POST", + body: data, + }) + .then((response) => response.json()) + .then((data) => { + navigate(getIdFromLink(data.url)); // navigate to data.url + }); +} + +/** + * @param link - the link to the api endpoint + * @returns the Id at the end of the link + */ +export function getIdFromLink(link: string): string { + const parts = link.split("/"); + return parts[parts.length - 1]; +} + +/** + * Function to find the nearest future deadline from a list of deadlines + * @param deadlines - List of deadlines + * @returns The nearest future deadline + */ +export function getNearestFutureDate(deadlines: Deadline[]): Deadline | null { + const now = new Date(); + const futureDeadlines = deadlines.filter((deadline) => deadline.date > now); + if (futureDeadlines.length === 0) return null; + return futureDeadlines.reduce((nearest, current) => + current < nearest ? current : nearest + ); +} + +/** + * Load courses for courses teacher page, this filters courses on logged in teacher uid + * @returns A Promise that resolves to the loaded courses data. + */ + +const fetchData = async (url: string, params?: URLSearchParams) => { + let uri = `${apiHost}/${url}`; + if (params) { + uri += `?${params}`; + } + const res = await authenticatedFetch(uri); + if (res.status !== 200) { + throw new Response("Failed to fetch data", { status: res.status }); + } + const jsonResult = await res.json(); + + return jsonResult.data; +}; + +export const dataLoaderCourses = async () => { + //const params = new URLSearchParams({ 'teacher': loggedInUid() }); + + const courses = await fetchData(`courses`); + const projects = await fetchProjectsCourse(courses); + const me = await fetchMe(); + for (const c of courses) { + const teacher = await fetchData(`users/${c.teacher}`); + c.teacher = teacher.display_name; + } + return { courses, projects, me }; +}; + +/** + * Fetch the projects for the Course component + * @param courses - All the courses + * @returns the projects + */ +export async function fetchProjectsCourse(courses: Course[]) { + const projectPromises = courses.map((course) => + authenticatedFetch( + `${apiHost}/projects?course_id=${getIdFromLink(course.course_id)}` + ).then((response) => response.json()) + ); + + const projectResults = await Promise.all(projectPromises); + const projectsMap: { [courseId: string]: ProjectDetail[] } = {}; + for await (const [index, result] of projectResults.entries()) { + projectsMap[getIdFromLink(courses[index].course_id)] = await Promise.all( + result.data.map(async (item: Project) => { + const projectRes = await authenticatedFetch(item.project_id); + if (projectRes.status !== 200) { + throw new Response("Failed to fetch project data", { + status: projectRes.status, + }); + } + const projectJson = await projectRes.json(); + const projectData = projectJson.data; + let projectDeadlines = []; + if (projectData.deadlines) { + projectDeadlines = projectData.deadlines.map( + ([description, dateString]: [string, string]) => ({ + description, + date: new Date(dateString), + }) + ); + } + const project: ProjectDetail = { + ...item, + deadlines: projectDeadlines, + }; + return project; + }) + ); + } + return { ...projectsMap }; +} + +const dataLoaderCourse = async (courseId: string) => { + return fetchData(`courses/${courseId}`); +}; + +const dataLoaderProjects = async (courseId: string) => { + const params = new URLSearchParams({ course_id: courseId }); + const uri = `${apiHost}/projects?${params}`; + + const res = await authenticatedFetch(uri); + if (res.status !== 200) { + throw new Response("Failed to fetch data", { status: res.status }); + } + const jsonResult = await res.json(); + const projects: ProjectDetail[] = jsonResult.data.map( + async (item: Project) => { + const projectRes = await authenticatedFetch(item.project_id); + if (projectRes.status !== 200) { + throw new Response("Failed to fetch project data", { + status: projectRes.status, + }); + } + const projectJson = await projectRes.json(); + const projectData = projectJson.data; + let projectDeadlines = []; + if (projectData.deadlines) { + projectDeadlines = projectData.deadlines.map((deadline: Deadline) => ({ + description: deadline.description, + date: new Date(deadline.date), + })); + } + const project: ProjectDetail = { + ...item, + deadlines: projectDeadlines, + }; + return project; + } + ); + + return Promise.all(projects); +}; + +const dataLoaderAdmins = async (courseId: string) => { + return fetchData(`courses/${courseId}/admins`); +}; + +const dataLoaderStudents = async (courseId: string) => { + return fetchData(`courses/${courseId}/students`); +}; + +const fetchMes = async (uids: string[]) => { + return Promise.all(uids.map((uid) => getUser(uid))); +}; + +export const dataLoaderCourseDetail = async ({ + params, +}: { + params: Params; +}) => { + const { courseId } = params; + if (!courseId) { + throw new Error("Course ID is undefined."); + } + const me = await fetchMe(); + + const course = await dataLoaderCourse(courseId); + + const courseAdminuids = course["admins"].map((admin: string) => { + const urlSplit = admin.split("/"); + return urlSplit[urlSplit.length - 1]; + }); + + const projects = await dataLoaderProjects(courseId); + let adminMes: Me[] = []; + if (me.uid === course.teacher || courseAdminuids.includes(me.uid)) { + const admins = await dataLoaderAdmins(courseId); + const adminUids = admins.map((admin: { uid: string }) => + getIdFromLink(admin.uid) + ); + adminMes = await fetchMes([course.teacher, ...adminUids]); + } + const students = await dataLoaderStudents(courseId); + const student_uids = students.map((student: { uid: string }) => + getIdFromLink(student.uid) + ); + const studentMes = await fetchMes(student_uids); + return { course, projects, adminMes, studentMes, me }; +}; diff --git a/frontend/src/components/Courses/CoursesDetail.tsx b/frontend/src/components/Courses/CoursesDetail.tsx new file mode 100644 index 00000000..a697f58b --- /dev/null +++ b/frontend/src/components/Courses/CoursesDetail.tsx @@ -0,0 +1,24 @@ +import {useLoaderData} from "react-router-dom"; +import {Me} from "../../types/me.ts"; +import {Course, ProjectDetail} from "./CourseUtils.tsx"; +import CourseDetailTeacher from "./CourseDetailTeacher.tsx"; +import CourseDetailStudent from "./CourseDetailStudent.tsx"; + +/** + * gives the right detail page + * @returns - detail page + */ +export default function CoursesDetail() :JSX.Element { + const loader = useLoaderData() as { + course: Course; + projects: ProjectDetail[]; + adminMes: Me[]; + studentMes: Me[]; + me:Me; + }; + if (loader.course.teacher === loader.me.uid) { + return ; + } else { + return ; + } +} \ No newline at end of file diff --git a/frontend/src/components/Courses/courses.ts b/frontend/src/components/Courses/courses.ts new file mode 100644 index 00000000..a532f88d --- /dev/null +++ b/frontend/src/components/Courses/courses.ts @@ -0,0 +1,22 @@ +import { authenticatedFetch } from "../../utils/authenticated-fetch.ts"; +const API_URL = import.meta.env.VITE_APP_API_HOST; + +/** + * @param user_uid - the user to fetch the courses from where it is a teacher + * @returns Courses[] + */ +export async function fetchProjectFormCourses(user_uid: string){ + try { + const response = await authenticatedFetch( + `${API_URL}/courses?teacher=${user_uid}`, + ); + const jsonData = await response.json(); + if (jsonData.data) { + return jsonData.data; + } else { + return []; + } + } catch (_) { + return []; + } +} diff --git a/frontend/src/components/DeadlineView/DeadlineGrid.tsx b/frontend/src/components/DeadlineView/DeadlineGrid.tsx new file mode 100644 index 00000000..154442da --- /dev/null +++ b/frontend/src/components/DeadlineView/DeadlineGrid.tsx @@ -0,0 +1,43 @@ +import {Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@mui/material"; +import {Deadline} from "../../types/deadline.ts"; +import {useTranslation} from "react-i18next"; + +interface Props { + deadlines: Deadline[]; + minWidth: number +} + +/** + * @returns grid that displays deadlines in a grid + */ +export default function DeadlineGrid({deadlines, minWidth}: Props) { + + const { t } = useTranslation('translation', { keyPrefix: 'projectForm' }); + + return ( + + + + + {t("deadline")} + {t("description")} + + + + {deadlines.length === 0 ? ( // Check if deadlines is empty + + {t("noDeadlinesPlaceholder")} + + ) : ( + deadlines.map((deadline, index) => ( + + {deadline.deadline} + {deadline.description} + + )) + )} + +
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/components/FolderUpload/FolderUpload.tsx b/frontend/src/components/FolderUpload/FolderUpload.tsx new file mode 100644 index 00000000..36a71258 --- /dev/null +++ b/frontend/src/components/FolderUpload/FolderUpload.tsx @@ -0,0 +1,134 @@ +import { Button, Grid, Paper, Typography, styled } from "@mui/material"; +import { verifyZipContents, getFileExtension } from "../../utils/file-utils"; +import JSZip from "jszip"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; + +interface FolderDragDropProps { + onFileDrop?: (file: File) => void; + regexRequirements?: string[]; + onWrongInput?: (message: string) => void; +} + +const supportedFileTypes = ["application/x-zip-compressed", "application/zip"]; + +const FolderDragDrop: React.FC = ({ + onFileDrop, + regexRequirements, + onWrongInput, +}) => { + const { t } = useTranslation('projectformTranslation', { keyPrefix: 'dragAndDrop' }); + + const [isDraggingOver, setIsDraggingOver] = useState(false); + + const VisuallyHiddenInput = styled("input")({ + clip: "rect(0 0 0 0)", + clipPath: "inset(50%)", + height: 1, + overflow: "hidden", + position: "absolute", + bottom: 0, + left: 0, + whiteSpace: "nowrap", + width: 1, + }); + + const handleDragOver = (event: React.DragEvent) => { + event.preventDefault(); + setIsDraggingOver(true); + }; + + const handleDragLeave = () => { + setIsDraggingOver(false); + }; + + const handleNewFile = async (entry: File) => { + if (onFileDrop && supportedFileTypes.includes(entry.type)) { + const fileName: string = entry.name; + const fileExtension: string = getFileExtension(fileName); + if (fileExtension === "zip" && regexRequirements) { + try { + const regexReport = await JSZip.loadAsync(entry).then((zip) => { + return verifyZipContents(zip, regexRequirements); + }); + if (regexReport.isValid) { + onFileDrop(entry); + } else { + onWrongInput && + onWrongInput( + `Missing required files: ${regexReport.missingFiles.join( + ", " + )}.` + ); + } + } catch { + onWrongInput && + onWrongInput("Something went wrong parsing your zip."); + } + } else { + onFileDrop(entry); + } + } else { + onWrongInput && onWrongInput("The file must be zipped."); + } + }; + + const handleDrop = async (event: React.DragEvent) => { + event.preventDefault(); + setIsDraggingOver(false); + + const items = event.dataTransfer?.items; + if (items && onFileDrop) { + const folderItem = items[0]; + if (folderItem.kind === "file") { + const entry = folderItem.getAsFile(); + if (entry) { + handleNewFile(entry); + } else { + onWrongInput && + onWrongInput("Something went wrong getting your file."); + } + } else { + onWrongInput && onWrongInput("Your input must be a file."); + } + } + }; + + const handleFileUpload = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + handleNewFile(file); + } + } + + return ( + + + + {t('dragDropHere')} + + + + + ); +}; + +export default FolderDragDrop; diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index 860086fd..17913190 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -1,31 +1,211 @@ import { AppBar, Box, - Button, IconButton, + Menu, + MenuItem, Toolbar, Typography, + List, + Drawer, + Grid, + ListItemButton, + ListItemText, } from "@mui/material"; +import { useTranslation } from "react-i18next"; import MenuIcon from "@mui/icons-material/Menu"; +import React, { useState } from "react"; +import LanguageIcon from "@mui/icons-material/Language"; +import AccountCircleIcon from "@mui/icons-material/AccountCircle"; +import { Link } from "react-router-dom"; +import { TitlePortal } from "./TitlePortal"; +import { Me } from "../../types/me.ts"; +import {LoginButton} from "./Login.tsx"; +interface HeaderProps { + me: Me; +} /** * The header component for the application that will be rendered at the top of the page. * @returns - The header component */ -export function Header(): JSX.Element { +export function Header({ me }: HeaderProps): JSX.Element { + const API_URL = import.meta.env.VITE_APP_API_HOST; + const { t, i18n } = useTranslation("translation", { keyPrefix: "header" }); + const [languageMenuAnchor, setLanguageMenuAnchor] = + useState(null); + + const handleLanguageMenu = (event: React.MouseEvent) => { + setLanguageMenuAnchor(event.currentTarget); + }; + + const handleChangeLanguage = (language: string) => { + i18n.changeLanguage(language); + setLanguageMenuAnchor(null); + }; + + const handleCloseLanguageMenu = () => { + setLanguageMenuAnchor(null); + }; + + const [open, setOpen] = useState(false); + const [listItems, setListItems] = useState([ + { link: "/", text: t("homepage") }, + ]); + + const [anchorEl, setAnchorEl] = React.useState( + null, + ); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + React.useEffect(() => { + const baseItems = [{ link: "/", text: t("homepage") }]; + const additionalItems = [ + { link: "/projects", text: t("myProjects") }, + { link: "/courses", text: t("myCourses") }, + ]; + if (me.loggedIn) { + setListItems([...baseItems, ...additionalItems]); + } else { + setListItems(baseItems); + } + }, [me, t]); + return ( - - - + + setOpen(!open)} + sx={{ color: "white", marginLeft: 0 }} + > + - - Home - - + + + Peristerónas + + + + {!me.loggedIn && ( + + )} + {me.loggedIn && ( + <> + + + + {me.display_name} + + + setAnchorEl(null)} + > + + {me.display_name} + + + {t("logout")} + + + + )} +
+ + + + {t("tag")} + + + + handleChangeLanguage("en")}> + English + + handleChangeLanguage("nl")}> + Nederlands + + +
+ setOpen(false)} + listItems={listItems} + />
); } + +/** + * Renders the drawer menu component. + * @param open - Whether the drawer menu is open or not. + * @param onClose - Function to handle the close event of the drawer menu. + * @param listItems - Array of objects representing the list items in the drawer menu. + * @returns The Side Bar + */ +function DrawerMenu({ + open, + onClose, + listItems, +}: { + open: boolean; + onClose: () => void; + listItems: { link: string; text: string }[]; +}) { + return ( + + + + + + + + + {listItems.map((listItem, index) => ( + + + + ))} + + + + ); +} diff --git a/frontend/src/components/Header/Layout.tsx b/frontend/src/components/Header/Layout.tsx new file mode 100644 index 00000000..2b3097c7 --- /dev/null +++ b/frontend/src/components/Header/Layout.tsx @@ -0,0 +1,58 @@ +import { + Outlet, + useLoaderData, + useLocation, + useNavigate, +} from "react-router-dom"; +import { Header } from "./Header.tsx"; +import { Me } from "../../types/me.ts"; +import { useEffect } from "react"; +import i18next from "i18next"; + +/** + * Basic layout component that will be used on all routes. + * @returns The Layout component + */ +export default function Layout(): JSX.Element { + const meData: Me = useLoaderData() as Me; + useEnsureLangCodeInPath(); + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + if ( + !meData.loggedIn && + !( + location.pathname === "/" || + /\/([a-z]{2})\/home/.test(location.pathname) || + location.pathname === `/${i18next.resolvedLanguage}` + ) + ) { + navigate(`${i18next.resolvedLanguage}/home`); + } + }, [meData.loggedIn, location.pathname, navigate]); + + return ( + <> +
+ + + ); +} + +const useEnsureLangCodeInPath = () => { + const location = useLocation(); + const navigate = useNavigate(); + + useEffect(() => { + const pathParts = location.pathname.split("/").filter(Boolean); + const langCode = i18next.resolvedLanguage; + + // Check if the URL starts with the lang code + if (pathParts[0] !== langCode) { + // Prepend the lang code to the path + const newPath = `/${langCode}/${pathParts.join("/")}`; + navigate(newPath); + } + }, [location, navigate]); +}; diff --git a/frontend/src/components/Header/Login.tsx b/frontend/src/components/Header/Login.tsx new file mode 100644 index 00000000..82548735 --- /dev/null +++ b/frontend/src/components/Header/Login.tsx @@ -0,0 +1,22 @@ +import { Button } from "@mui/material"; +import { Link } from "react-router-dom"; +import { useTranslation } from "react-i18next"; + +const CLIENT_ID = import.meta.env.VITE_APP_CLIENT_ID; +const REDIRECT_URI = encodeURIComponent(import.meta.env.VITE_APP_API_HOST + "/auth"); +const TENANT_ID = import.meta.env.VITE_APP_TENANT_ID; + +/** + * The login component for the application that will redirect to the correct login link. + * @returns - A login button + */ +export function LoginButton(): JSX.Element { + const link = `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/authorize?prompt=select_account&response_type=code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=.default`; + const { t } = useTranslation("translation", { keyPrefix: "home" }); + + return ( + + ); +} diff --git a/frontend/src/components/Header/Logout.tsx b/frontend/src/components/Header/Logout.tsx new file mode 100644 index 00000000..2e569bd0 --- /dev/null +++ b/frontend/src/components/Header/Logout.tsx @@ -0,0 +1,14 @@ +import {Button} from "@mui/material"; +import {Link} from 'react-router-dom'; + +const API_HOST = import.meta.env.VITE_APP_API_HOST; + +/** + * The Logout component for the application that will redirect to the correct logout link. + * @returns - A Logout button + */ +export function LogoutButton(): JSX.Element { + const link = `${API_HOST}/logout`; + + return +} \ No newline at end of file diff --git a/frontend/src/components/Header/PageTitle.tsx b/frontend/src/components/Header/PageTitle.tsx new file mode 100644 index 00000000..c471095d --- /dev/null +++ b/frontend/src/components/Header/PageTitle.tsx @@ -0,0 +1,14 @@ +export const PageTitle = ({ title, defaultTitle, className }: {title:string,defaultTitle:string,className:string}) => { + + return ( + + {!title ? ( + {defaultTitle} + ) : typeof title === 'string' ? ( + {title} + ) : ( + title + )} + + ); +}; \ No newline at end of file diff --git a/frontend/src/components/Header/Title.tsx b/frontend/src/components/Header/Title.tsx new file mode 100644 index 00000000..0b014b00 --- /dev/null +++ b/frontend/src/components/Header/Title.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; +import PropTypes from 'prop-types'; + +export const Title = (props: TitleProps) => { + const { defaultTitle, title } = props; + const [container, setContainer] = useState(() => + typeof document !== 'undefined' + ? document.getElementById('react-admin-title') + : null + ); + + // on first mount, we don't have the container yet, so we wait for it + useEffect(() => { + setContainer(container => { + const isInTheDom = + typeof document !== 'undefined' && + document.body.contains(container); + if (container && isInTheDom) return container; + return typeof document !== 'undefined' + ? document.getElementById('react-admin-title') + : null; + }); + }, []); + + if (!container) return null; + + return createPortal( + <>{title || defaultTitle}, + container + ); +}; + +export const TitlePropType = PropTypes.oneOfType([ + PropTypes.string, + PropTypes.element, +]); + +Title.propTypes = { + defaultTitle: PropTypes.string, + className: PropTypes.string, + record: PropTypes.any, + title: TitlePropType, +}; + +export interface TitleProps { + className?: string; + defaultTitle?: string; + title?: string; + preferenceKey?: string; +} \ No newline at end of file diff --git a/frontend/src/components/Header/TitlePortal.tsx b/frontend/src/components/Header/TitlePortal.tsx new file mode 100644 index 00000000..edb9502b --- /dev/null +++ b/frontend/src/components/Header/TitlePortal.tsx @@ -0,0 +1,14 @@ +import { Typography, TypographyProps } from '@mui/material'; + +export const TitlePortal = (props: TypographyProps) => ( + +); \ No newline at end of file diff --git a/frontend/src/components/LanguagePath.tsx b/frontend/src/components/LanguagePath.tsx new file mode 100644 index 00000000..2ade3383 --- /dev/null +++ b/frontend/src/components/LanguagePath.tsx @@ -0,0 +1,28 @@ +// https://stackoverflow.com/questions/71769484/react-router-v6-nested-routes-with-i18n +import { useEffect } from "react"; +import { Outlet, useParams, useNavigate } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import i18next from "i18next"; + +const SUPPORTED_LANGUAGES = ["en", "nl"]; + +/** + * + * @returns - An outlet that detects the language and assigns it to i18next directly. + */ +export default function LanguagePath() { + const { i18n } = useTranslation(); + const { lang } = useParams(); + const navigate = useNavigate(); + const curPath = location.pathname; + useEffect(() => { + if (lang && i18next.resolvedLanguage !== lang) { + if (SUPPORTED_LANGUAGES.includes(lang)) { + i18next.changeLanguage(lang); + } else { + navigate("/" + i18next.resolvedLanguage + curPath, { replace: true }); + } + } + }, [lang, curPath, i18n, navigate]); + return ; +} diff --git a/frontend/src/components/ProjectForm/AdvancedRegex.tsx b/frontend/src/components/ProjectForm/AdvancedRegex.tsx new file mode 100644 index 00000000..5ebc685d --- /dev/null +++ b/frontend/src/components/ProjectForm/AdvancedRegex.tsx @@ -0,0 +1,53 @@ +import {Button, IconButton, Stack, TextField, Tooltip, Typography} from "@mui/material"; +import {useTranslation} from "react-i18next"; +import {useState} from "react"; +import {Link} from "react-router-dom"; +import {InfoOutlined} from "@mui/icons-material"; + +interface Props { + handleSubmit: (regex: string) => boolean; + regexError: boolean; +} + +/** + * @returns Component for adding advanced regexes + */ +export default function AdvancedRegex({ handleSubmit, regexError } : Props) { + + const [regex, setRegex] = useState(""); + + const {t} = useTranslation('projectformTranslation', {keyPrefix: 'advancedRegex'}); + + const handleAdvancedSubmit = () => { + const result = handleSubmit(regex); + if (result) { + setRegex(""); + } + } + + return ( + + {t("title")} + + setRegex(event.target.value)} + > + {t("regexInfo")} {t("cheatsheet")}}> + + + + + + + + ) +} \ No newline at end of file diff --git a/frontend/src/components/ProjectForm/FileStructureForm.tsx b/frontend/src/components/ProjectForm/FileStructureForm.tsx new file mode 100644 index 00000000..2acbe783 --- /dev/null +++ b/frontend/src/components/ProjectForm/FileStructureForm.tsx @@ -0,0 +1,99 @@ +import {Autocomplete, Button, Stack, TextField, Typography} from "@mui/material"; +import {useState} from "react"; +import {useTranslation} from "react-i18next"; + +interface Props { + handleSubmit: (regex: string) => boolean; + regexError: boolean; +} + +/** + * @returns Component for adding file restrictions + */ +export default function FileStuctureForm({ handleSubmit, regexError } : Props) { + + const extensions = [".txt", ".pdf", ".zip", ".7z", ".csv", ".doc", ".py", ".java", ".c"]; + + const {t} = useTranslation('projectformTranslation', {keyPrefix: 'filestructure'}); + + const [startsWith, setStartsWith] = useState(""); + const [endsWith, setEndsWith] = useState(""); + const [contains, setContains] = useState(""); + const [extension, setExtension] = useState(""); + + const handleExtensionChange = (value: string | null) => { + if (value) { + setExtension(value); + } + } + + const handleRegexSubmit = () => { + let regex = ""; + if (startsWith) { + regex += "^" + startsWith + } + if (contains) { + regex += "*" + contains + "*"; + } else if (startsWith || endsWith) { + regex += "*" + } + if (endsWith != "" && extension != "") { + regex += endsWith + extension + "$"; + } else if (endsWith != "") { + regex += endsWith + "$"; + } + const result = handleSubmit(regex); + if (result) { + setStartsWith(""); + setExtension(""); + setEndsWith(""); + setContains(""); + } + } + + return ( + + {t("title")} + setStartsWith(e.target.value)} + /> + setEndsWith(e.target.value)} + /> + setContains(e.target.value)} + /> + handleExtensionChange(value)} + renderInput={(params) => } + options={extensions.map((t) => t)} + /> + + + ) +} \ No newline at end of file diff --git a/frontend/src/components/ProjectForm/ProjectForm.tsx b/frontend/src/components/ProjectForm/ProjectForm.tsx new file mode 100644 index 00000000..46f8863a --- /dev/null +++ b/frontend/src/components/ProjectForm/ProjectForm.tsx @@ -0,0 +1,447 @@ +import { + Button, + Checkbox, + FormControlLabel, + FormHelperText, + Grid, + InputLabel, + MenuItem, Select, SelectChangeEvent, + TextField, + FormControl, Box, Typography, + Stack, TableContainer, Table, + TableRow, + TableCell, + TableHead, + TableBody, Paper, + Tooltip, IconButton, Tabs, Tab, +} from "@mui/material"; +import React, {useEffect, useState, useTransition} from "react"; +import JSZip from 'jszip'; +import {useTranslation} from "react-i18next"; +import DeleteIcon from "@mui/icons-material/Delete"; +import DeadlineCalender from "../Calender/DeadlineCalender.tsx"; +import { Deadline } from "../../types/deadline"; +import {InfoOutlined} from "@mui/icons-material"; +import {Link, useLoaderData, useLocation, useNavigate} from "react-router-dom"; +import FolderDragDrop from "../FolderUpload/FolderUpload.tsx"; +import TabPanel from "@mui/lab/TabPanel"; +import {TabContext} from "@mui/lab"; +import FileStuctureForm from "./FileStructureForm.tsx"; +import AdvancedRegex from "./AdvancedRegex.tsx"; +import RunnerSelecter from "./RunnerSelecter.tsx"; +import { authenticatedFetch } from "../../utils/authenticated-fetch.ts"; +import i18next from "i18next"; +import DeadlineGrid from "../DeadlineView/DeadlineGrid.tsx"; + +interface Course { + course_id: string; + name: string; + teacher: string; + ufora_id: string; +} + +interface RegexData { + key: number; + regex: string; +} + +const API_URL = import.meta.env.VITE_APP_API_HOST + +/** + * @returns Form for uploading project + */ +export default function ProjectForm() { + + const { t } = useTranslation('translation', { keyPrefix: 'projectForm' }); + + // all the stuff needed for submitting a project + const [title, setTitle] = useState(''); + const [, setTransition] = useTransition(); + const [titleError, setTitleError] = useState(false); + + const [description, setDescription] = useState(''); + const [descriptionError, setDescriptionError] = useState(false); + + const [deadlines, setDeadlines] = useState([]) + const [files, setFiles] = useState([]); + + const [visibleForStudents, setVisibleForStudents] = useState(false); + + const [regexExpressions, setRegexExpressions] = useState([]); + const [regexError, setRegexError] = useState(false); + + const [assignmentFile, setAssignmentFile] = useState(); + const [filename, setFilename] = useState(""); + + const [containsDockerfile, setContainsDockerfile] = useState(false); + const [containsRuntest, setContainsRuntest] = useState(false); + + const [advanced, setAdvanced] = useState('1'); + const [runner, setRunner] = useState(''); + const [validRunner, setValidRunner] = useState(true); + const [validSubmission, setValidSubmission] = useState(true); + const [errorMessage, setErrorMessage] = useState(''); + + const courses = useLoaderData() as Course[] + + const [courseId, setCourseId] = useState(''); + const [courseName, setCourseName] = useState(''); + const location = useLocation(); + + const navigate = useNavigate(); + + useEffect(() =>{ + const urlParams = new URLSearchParams(location.search); + const initialCourseId = urlParams.get('course_id') || ''; + let initialCourseName = '' + for( const c of courses){ + const parts = c.course_id.split('/'); + const courseId = parts[parts.length - 1]; + if (courseId === initialCourseId){ + initialCourseName = c.name + } + } + setCourseId(initialCourseId) + setCourseName(initialCourseName) + } + ,[courses,location]) + + const handleRunnerSwitch = (newRunner: string) => { + if (newRunner === t('clearSelected')) { + setRunner(''); + } else { + setRunner(newRunner); + } + } + + const handleTabSwitch = (_event: React.SyntheticEvent, newAdvanced: string) => { + setAdvanced(newAdvanced); + }; + + const handleFileUpload2 = async (file: File) => { + setFiles([]); + setContainsRuntest(false); + setContainsDockerfile(false); + const zip = await JSZip.loadAsync(file); + const newFiles = []; + + let constainsDocker = false; + let containsRuntest = false; + for (const [, zipEntry] of Object.entries(zip.files)) { + if (!zipEntry.dir) { + if (zipEntry.name.trim().toLowerCase() === 'dockerfile') { + constainsDocker = true; + } + if (zipEntry.name.trim().toLowerCase() == 'run_tests.sh') { + containsRuntest = true; + } + newFiles.push(zipEntry.name); + } + } + + setFiles(newFiles); + setContainsDockerfile(constainsDocker) + setContainsRuntest(containsRuntest); + const {name} = file; + setAssignmentFile(file) + setFilename(name); + + if (runner === "CUSTOM") { + setValidRunner(constainsDocker); + if (!constainsDocker) { + setErrorMessage(t("faultySubmission")); + } + setValidSubmission(constainsDocker); + } else if(runner === ''){ + setValidRunner(true); + } + else { + setValidRunner(containsRuntest); + if(!containsRuntest) { + setErrorMessage(t("faultySubmission")); + } + setValidSubmission(containsRuntest); + } + } + + const appendRegex = (r: string) => { + if (r == '' || regexExpressions.some(reg => reg.regex == r)) { + setRegexError(true); + return false; + } + setRegexError(false); + let index; + const lastRegex = regexExpressions[regexExpressions.length-1]; + if (regexExpressions.length == 0) { + index = 0; + } else { + index = lastRegex.key+1; + } + + const newRegexExpressions = [...regexExpressions, { key: index, regex: r}]; + setRegexExpressions(newRegexExpressions); + + return true; + }; + + const handleSubmit = async (event: React.MouseEvent) => { + event.preventDefault(); + + description == '' ? setDescriptionError(true) : setDescriptionError(false); + title == '' ? setTitleError(true) : setTitleError(false); + + if (!assignmentFile || !validRunner) { + setValidSubmission(false); + setErrorMessage(t("faultySubmission")); + return; + } + + const assignmentFileBlob = new Blob([assignmentFile], { type: assignmentFile.type }); + + const formData = new FormData(); + + // Append fields to the FormData object + formData.append('title', title); + formData.append('description', description); + formData.append('visible_for_students', visibleForStudents.toString()); + formData.append('archived', 'false'); + formData.append('assignment_file', assignmentFileBlob, filename); + formData.append('course_id', courseId.toString()); + regexExpressions.forEach((expression,) => { + formData.append(`regex_expressions`, expression.regex); + }); + deadlines.forEach((deadline: Deadline) => { + formData.append("deadlines", + JSON.stringify({ + "deadline": deadline.deadline, + "description": deadline.description + }) + ); + }); + if (runner !== '') { + formData.append("runner", runner); + } + + const response = await authenticatedFetch(`${API_URL}/projects`, { + method: "post", + body: formData, + }) + + if (!response.ok) { + setValidSubmission(false); + if (response.status === 403) { + setErrorMessage(t("unauthorized")); + } + else { + setErrorMessage(t("submissionError")); + } + return; + } + + response.json().then((data) => { + const projectData = data.data; + navigate(`/${i18next.resolvedLanguage}/projects/${projectData.project_id}`); + }) + } + + const handleCourseChange = (e: SelectChangeEvent) => { + const selectedCourseName = e.target.value as string; + const selectedCourse = courses.find(course => course.name === selectedCourseName); + if (selectedCourse) { + setCourseName(selectedCourse.name); + const parts = selectedCourse.course_id.split('/'); + const courseId = parts[parts.length - 1]; + setCourseId(courseId); + } + }; + + const handleDeadlineChange = (deadlines: Deadline[]) => { + setDeadlines(deadlines); + } + + const removeRegex = (regexToDelete: RegexData) => () => { + setRegexExpressions((regexes) => regexes.filter((regex) => regex.key !== regexToDelete.key)); + }; + + return ( + + + + + { + setTransition(() => { + setTitle(event.target.value); + }) + }} + /> + + + { + setTransition(() => { + setDescription(event.target.value); + }) + }} + /> + + + + {t("projectCourse")} + + {t("selectCourseText")} + + + + handleDeadlineChange(deadlines)} + editable={true} /> + + + + + } label={t("visibleForStudents")} onChange={e=>setVisibleForStudents((e.target as HTMLInputElement).checked)}/> + {t("visibleForStudentsTooltip")}}> + + + + + + + + + + + handleFileUpload2(file)} regexRequirements={[]} /> + {t("fileInfo")}: {t("userDocs")}}> + + + + + + + + + + {t("zipFile")}: {filename} + + + + {files.length === 0 ? ( // Check if files is empty + + {t("noFilesPlaceholder")} {/* Placeholder row */} + + ) : ( + files.map((file, index) => ( + + {file} + + )) + )} + +
+
+ {filename !== "" && (!containsRuntest && !containsDockerfile) && ( + + {t("testWarning")} ⚠️ + + )} +
+ + + + + + + + + + + + + + + + Regex + + + + + {regexExpressions.length === 0 ? ( // Check if regexExpressions is empty + + {t("noRegexPlaceholder")} {/* Placeholder row */} + + ) : ( + regexExpressions.map((regexData: RegexData) => ( + + {regexData.regex} + + + + + + + )) + )} + +
+
+
+ + + + + + { + !validSubmission && ( + + {errorMessage} ⚠️ + + ) + } + +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/components/ProjectForm/RunnerSelecter.tsx b/frontend/src/components/ProjectForm/RunnerSelecter.tsx new file mode 100644 index 00000000..73804945 --- /dev/null +++ b/frontend/src/components/ProjectForm/RunnerSelecter.tsx @@ -0,0 +1,84 @@ +import { + FormControl, + InputLabel, + MenuItem, + Select, + SelectChangeEvent, + Typography, + Tooltip, + Stack, IconButton +} from "@mui/material"; +import { Dispatch, SetStateAction } from "react"; +import { useTranslation } from "react-i18next"; +import {InfoOutlined} from "@mui/icons-material"; +import {Link} from "react-router-dom"; + +interface Props { + handleSubmit: (runner: string) => void; + runner: string; + containsDocker: boolean; + containsRuntests: boolean; + isValid: boolean; + setIsValid: Dispatch>; +} + +/** + * @returns Component for selecting an appropriate runner + */ +export default function RunnerSelecter({ handleSubmit, runner, containsDocker, containsRuntests, isValid, setIsValid }: Props) { + + const { t } = useTranslation('projectformTranslation', { keyPrefix: 'runnerComponent' }); + + const runnerMapping: { [key: string]: boolean } = { + "GENERAL": containsRuntests, + "PYTHON": containsRuntests, + "CUSTOM": containsDocker, + [t("clearSelected")]: true + } + + const handleRunnerChange = (event: SelectChangeEvent) => { + const runner: string = event.target.value as string; + handleSubmit(runner); + setIsValid(runnerMapping[runner]); + } + + return ( + <> + + + Runner + + + {t("tooltipRunner")} {t("userDocs")}}> + + + + + + { + !isValid && ( + + {t("testWarning")} ⚠️ + + ) + } + + ) +} diff --git a/frontend/src/components/ProjectForm/project-form.ts b/frontend/src/components/ProjectForm/project-form.ts new file mode 100644 index 00000000..ec282569 --- /dev/null +++ b/frontend/src/components/ProjectForm/project-form.ts @@ -0,0 +1,11 @@ +import { fetchMe } from "../../utils/fetches/FetchMe.ts"; +import {fetchProjectFormCourses} from "../Courses/courses.ts"; + +/** + * Fetches the courses of the current user + * @returns Course[] + */ +export async function fetchProjectForm (){ + const me = await fetchMe(); + return await fetchProjectFormCourses(me.uid); +} \ No newline at end of file diff --git a/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverview.tsx b/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverview.tsx new file mode 100644 index 00000000..956d2f51 --- /dev/null +++ b/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverview.tsx @@ -0,0 +1,59 @@ +import { Box, Button, Typography } from "@mui/material"; +import { useLoaderData, useParams } from "react-router-dom"; +import ProjectSubmissionsOverviewDatagrid from "./ProjectSubmissionOverviewDatagrid.tsx"; +import download from "downloadjs"; +import { useTranslation } from "react-i18next"; +import { authenticatedFetch } from "../../utils/authenticated-fetch.ts"; +import { Project } from "../Courses/CourseUtils.tsx"; +import { Submission } from "../../types/submission.ts"; + +const APIURL = import.meta.env.VITE_APP_API_HOST; + +/** + * @returns Overview page for submissions + */ +export default function ProjectSubmissionOverview() { + const { t } = useTranslation("submissionOverview", { + keyPrefix: "submissionOverview", + }); + + const { projectId } = useParams<{ projectId: string }>(); + const { projectData, submissionsWithUsers } = useLoaderData() as { + projectData: Project; + submissionsWithUsers: Submission[]; + }; + + const downloadProjectSubmissions = async () => { + await authenticatedFetch( + `${APIURL}/projects/${projectId}/submissions-download` + ) + .then((res) => { + return res.blob(); + }) + .then((blob) => { + download(blob, "submissions.zip"); + }); + }; + + return ( + + + + {projectData["title"]} + + + + + + ); +} diff --git a/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverviewDatagrid.tsx b/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverviewDatagrid.tsx new file mode 100644 index 00000000..1dd22b0c --- /dev/null +++ b/frontend/src/components/ProjectSubmissionOverview/ProjectSubmissionOverviewDatagrid.tsx @@ -0,0 +1,155 @@ +import { + DataGrid, + GridEditInputCell, + GridPreProcessEditCellProps, + GridRenderCellParams, + GridRenderEditCellParams +} from "@mui/x-data-grid"; +import {Box, IconButton, styled, Tooltip, tooltipClasses, TooltipProps} from "@mui/material"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; +import { green, red } from "@mui/material/colors"; +import CancelIcon from "@mui/icons-material/Cancel"; +import DownloadIcon from "@mui/icons-material/Download"; +import download from "downloadjs"; +import { authenticatedFetch } from "../../utils/authenticated-fetch"; +import { Submission } from "../../types/submission"; +import {useTranslation} from "react-i18next"; +import {TFunction} from "i18next"; +const APIURL = import.meta.env.VITE_APP_API_HOST; + +/** + * @returns unique id for datarows + */ +function getRowId(row: Submission) { + return row.submission_id; +} + +const fetchSubmissionsFromUser = async (submission_id: string) => { + await authenticatedFetch(`${APIURL}/submissions/${submission_id}/download`) + .then((res) => { + return res.blob(); + }) + .then((blob) => { + download(blob, `submissions_${submission_id}.zip`); + }); +}; + +const editGrade = (submission: Submission, errorMessage: string) => { + const submission_id = submission.submission_id; + const newGrade = submission.grading; + + if (newGrade < 0 || newGrade > 20) { + throw new Error(errorMessage); + } + + const formData = new FormData(); + formData.append('grading', newGrade.toString()); + + authenticatedFetch(`${APIURL}/submissions/${submission_id}`, { + method: "PATCH", + body: formData + }) + + return submission +}; + +const StyledTooltip = styled(({ className, ...props }: TooltipProps) => ( + +))(({ theme }) => ({ + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: theme.palette.error.main, + color: theme.palette.error.contrastText, + }, +})); + +/** + * @returns Component for input edit cell + */ +function NameEditInputCell(props: GridRenderEditCellParams) { + const { error, msg } = props; + + return ( + + + + ); +} + +/** + * @returns component for passing params + */ +function renderEditScore(params: GridRenderEditCellParams) { + return ; +} + +const getTranslatedRows = (t: TFunction) => { + return [ + { field: "submission_id", headerName: t("submissionID"), flex: 0.4, editable: false }, + { field: "display_name", headerName: t("student"), width: 160, flex: 0.4, editable: false }, + { + field: "grading", + headerName: t("grading"), + editable: true, + flex: 0.2, + preProcessEditCellProps: (params: GridPreProcessEditCellProps) => { + const hasError = params.props.value > 20 || params.props.value < 0; + return { ...params.props, error: hasError, msg: t("scoreError") }; + }, + renderEditCell: renderEditScore + }, + { + field: "submission_status", + headerName: t("status"), + editable: false, + renderCell: (params: GridRenderCellParams) => ( + <> + {params.row.submission_status === "SUCCESS" ? ( + + ) : ( + + )} + + ), + }, + { + field: "submission_path", + headerName: t("download"), + renderCell: (params: GridRenderCellParams) => ( + fetchSubmissionsFromUser(params.row.submission_id)} + > + + + ), + }, + ]; +} + +/** + * @returns the datagrid for displaying submissions + */ +export default function ProjectSubmissionsOverviewDatagrid({ + submissions, +}: { + submissions: Submission[]; +}) { + + const { t } = useTranslation('submissionOverview', { keyPrefix: 'submissionOverview' }); + + const errorMsg = t("scoreError"); + + return ( + + + editGrade(updatedRow, errorMsg) + } + /> + + ); +} diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js new file mode 100644 index 00000000..a6055822 --- /dev/null +++ b/frontend/src/i18n.js @@ -0,0 +1,26 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import Backend from 'i18next-http-backend'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +const detectionOptions = { + order: ['path', 'navigator', 'localStorage', 'subdomain', 'queryString', 'htmlTag'], + lookupFromPathIndex: 0 +} + +i18n + .use(Backend) + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: 'en', + debug: true, + detection: detectionOptions, + interpolation: { + escapeValue: false, + }, + supportedLngs: ['en', 'nl'], + nonExplicitSupportedLngs: true + }); + +export default i18n; diff --git a/frontend/src/loaders/join-code.ts b/frontend/src/loaders/join-code.ts new file mode 100644 index 00000000..bfc08b1b --- /dev/null +++ b/frontend/src/loaders/join-code.ts @@ -0,0 +1,35 @@ +import { redirect } from "react-router-dom"; +import i18next from "i18next"; +import { authenticatedFetch } from "../utils/authenticated-fetch"; + +const API_URL = import.meta.env.VITE_APP_API_HOST; + +/** + * This function sends a request to the server to join a course with a given join code. + * @returns - Redirects to the course page if the join code is valid + */ +export async function synchronizeJoinCode() { + const queryParams = new URLSearchParams(window.location.search); + const joinCode = queryParams.get("code"); + + if (joinCode) { + const response = await authenticatedFetch( + `${API_URL}/courses/join`,{ + method: "POST", + body: JSON.stringify({ join_code: joinCode }), + headers: { "Content-Type": "application/json" }, + } + ); + + if (response.ok || response.status === 409) { + const responseData = await response.json(); + return redirect( + `/${i18next.language}/courses/${responseData.data.course_id}` + ); + } else { + throw new Error("Invalid join code"); + } + } else { + throw new Error("No join code provided"); + } +} diff --git a/frontend/src/loaders/project-view-loader.ts b/frontend/src/loaders/project-view-loader.ts new file mode 100644 index 00000000..0a9cf6f8 --- /dev/null +++ b/frontend/src/loaders/project-view-loader.ts @@ -0,0 +1,84 @@ +import { Params } from "react-router-dom"; +import { Deadline } from "../types/deadline"; +import { authenticatedFetch } from "../utils/authenticated-fetch"; +import { fetchMe } from "../utils/fetches/FetchMe"; +import i18next from "i18next"; + +const API_URL = import.meta.env.VITE_APP_API_HOST; + +/** + * + * @param param0 - params: Params + * @returns - projectData: projectData, + * courseData: courseData, + * me: me, + * assignmentText: assignmentText, + * isAdmin: isAdmin + */ +export default async function loadProjectViewData({ + params, +}: { + params: Params; +}) { + const me = await fetchMe(); + + const projectId = params.projectId; + + const assignmentResponse = await authenticatedFetch( + `${API_URL}/projects/${projectId}/assignment?lang=${i18next.resolvedLanguage}` + ); + + let assignmentText; + + if (assignmentResponse.ok) { + assignmentText = await assignmentResponse.text(); + } else { + throw new Response(assignmentResponse.statusText, { + status: assignmentResponse.status, + }); + } + + const response = await authenticatedFetch(`${API_URL}/projects/${projectId}`); + if (response.ok) { + const data = await response.json(); + const projectData = data["data"]; + + const transformedDeadlines = projectData.deadlines.map( + (deadlineArray: string[]): Deadline => ({ + description: deadlineArray[0], + deadline: deadlineArray[1], + }) + ); + + projectData["deadlines"] = transformedDeadlines; + + const courseResponse = await authenticatedFetch( + `${API_URL}/courses/${projectData.course_id}` + ); + + let courseData; + if (courseResponse.ok) { + courseData = (await courseResponse.json())["data"]; + } else { + throw new Response(response.statusText, { status: response.status }); + } + + courseData["admins"] = courseData["admins"].map((admin: string) => { + const urlSplit = admin.split("/"); + return urlSplit[urlSplit.length - 1]; + }); + + const isAdmin = + me.uid === courseData["teacher"] || courseData["admins"].includes(me.uid); + + return { + projectData: projectData, + courseData: courseData, + me: me, + assignmentText: assignmentText, + isAdmin: isAdmin, + }; + } else { + throw new Response(response.statusText, { status: response.status }); + } +} diff --git a/frontend/src/loaders/submission-overview-loader.ts b/frontend/src/loaders/submission-overview-loader.ts new file mode 100644 index 00000000..26008260 --- /dev/null +++ b/frontend/src/loaders/submission-overview-loader.ts @@ -0,0 +1,67 @@ +import { Params } from "react-router-dom"; +import { Me } from "../types/me"; +import { Submission } from "../types/submission"; +import { authenticatedFetch } from "../utils/authenticated-fetch"; + +const APIURL = import.meta.env.VITE_APP_API_HOST; + +const fetchDisplaynameByUid = async (uids: [string]) => { + const uidParams = new URLSearchParams(); + for (const uid of uids) { + uidParams.append("uid", uid); + } + const uidUrl = `${APIURL}/users?` + uidParams; + const response = await authenticatedFetch(uidUrl); + const jsonData = await response.json(); + + return jsonData.data; +}; + +/** + * + * @param param0 - projectId + * @returns - projectData and submissionsWithUsers + */ +export default async function loadSubmissionOverview({ + params, +}: { + params: Params; +}) { + + const projectId = params.projectId; + const projectResponse = await authenticatedFetch( + `${APIURL}/projects/${projectId}` + ); + + if (!projectResponse.ok) { + if (projectResponse.status == 403) { + throw new Response("Not authenticated", {status: 403}); + } else if (projectResponse.status == 404) { + throw new Response("Not found", {status: 404}); + } + } + + const projectData = (await projectResponse.json())["data"]; + + const overviewResponse = await authenticatedFetch( + `${APIURL}/projects/${projectId}/latest-per-user` + ); + const jsonData = await overviewResponse.json(); + const uids = jsonData.data.map((submission: Submission) => submission.uid); + const users = await fetchDisplaynameByUid(uids); + + const submissionsWithUsers = jsonData.data.map((submission: Submission) => { + // Find the corresponding user for this submission's UID + const user = users.find((user: Me) => user.uid === submission.uid); + // Add user information to the submission + return { + ...submission, + display_name: user.display_name, + }; + }); + + return { + projectData, + submissionsWithUsers, + }; +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 3d7150da..9b684efc 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -2,6 +2,7 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' +import './i18n' ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/frontend/src/pages/create_project/ProjectCreateHome.tsx b/frontend/src/pages/create_project/ProjectCreateHome.tsx new file mode 100644 index 00000000..fb43731b --- /dev/null +++ b/frontend/src/pages/create_project/ProjectCreateHome.tsx @@ -0,0 +1,29 @@ +/** + * + */ +import { Title } from "../../components/Header/Title.tsx"; +import ProjectForm from "../../components/ProjectForm/ProjectForm.tsx"; +import {Box} from "@mui/material"; +import {useTranslation} from "react-i18next"; + +/** + * Renders the home page for creating a project. + * @returns ProjectCreateHome - Returns the JSX element representing the home page for creating a project. + */ +export default function ProjectCreateHome() { + + const { t } = useTranslation('translation', { keyPrefix: 'projectForm' }); + + return ( + + + <ProjectForm/> + </Box> + ) + ; +} diff --git a/frontend/src/pages/error/ErrorBoundary.tsx b/frontend/src/pages/error/ErrorBoundary.tsx new file mode 100644 index 00000000..8a0f7155 --- /dev/null +++ b/frontend/src/pages/error/ErrorBoundary.tsx @@ -0,0 +1,69 @@ +import { useRouteError, isRouteErrorResponse } from "react-router-dom"; +import { ErrorPage } from "./ErrorPage.tsx"; +import { useTranslation } from "react-i18next"; +import { useEffect, useState } from "react"; +import { fetchMe } from "../../utils/fetches/FetchMe.ts"; +import { Me } from "../../types/me.ts"; +import { Header } from "../../components/Header/Header.tsx"; + +/** + * This component will render the ErrorPage component with the appropriate data when an error occurs. + * @returns The ErrorBoundary component + */ +export function ErrorBoundary() { + const [me, setMe] = useState<Me | null>(null); + + useEffect(() => { + fetchMe().then((data) => { + setMe(data); + }); + }, []); + + return ( + <> + {me && <Header me={me} />} + <ErrorBoundaryPage /> + </> + ); +} + +const ErrorBoundaryPage = () => { + const error = useRouteError(); + const { t } = useTranslation("translation", { keyPrefix: "error" }); + + if (isRouteErrorResponse(error)) { + if (error.status == 404) { + return ( + <ErrorPage + statusCode={"404"} + statusTitle={t("pageNotFound")} + message={t("pageNotFoundMessage")} + /> + ); + } else if (error.status == 403) { + return ( + <ErrorPage + statusCode={"403"} + statusTitle={t("forbidden")} + message={t("forbiddenMessage")} + /> + ); + } else if (error.status >= 400 && error.status <= 499) { + return ( + <ErrorPage + statusCode={error.statusText} + statusTitle={t("clientError")} + message={t("clientErrorMessage")} + /> + ); + } else if (error.status >= 500 && error.status <= 599) { + return ( + <ErrorPage + statusCode={error.statusText} + statusTitle={t("serverError")} + message={t("serverErrorMessage")} + /> + ); + } + } +}; diff --git a/frontend/src/pages/error/ErrorPage.tsx b/frontend/src/pages/error/ErrorPage.tsx new file mode 100644 index 00000000..edabd86e --- /dev/null +++ b/frontend/src/pages/error/ErrorPage.tsx @@ -0,0 +1,51 @@ +import { Grid, Typography } from "@mui/material"; + +/** + * This component will be rendered when an error occurs. + * @param statusCode - The status code of the error + * @param statusTitle - The name of the error + * @param message - Additional information about the error + * @returns The ErrorPage component + */ +export function ErrorPage( + { statusCode, statusTitle, message }: { statusCode: string, statusTitle: string, message: string } +): React.JSX.Element { + return ( + <Grid + container + justifyContent="center" + alignItems="center" + direction="column" + sx={{ minHeight: "100vh" }} + spacing={2} + > + <Grid item> + <Grid + container + justifyContent="center" + alignItems="center" + spacing={4} + > + <Grid item> + <Typography variant="h1"> + { statusCode } + </Typography> + </Grid> + <Grid item> + <img src="/img/error_pigeon.png" height="150vh" alt="icon" /> + </Grid> + </Grid> + </Grid> + <Grid item> + <Typography variant="h3"> + { statusTitle } + </Typography> + </Grid> + <Grid item> + <Typography variant="body1"> + { message } + </Typography> + </Grid> + </Grid> + ); +} diff --git a/frontend/src/pages/home/Home.tsx b/frontend/src/pages/home/Home.tsx index 80610e7c..953060ff 100644 --- a/frontend/src/pages/home/Home.tsx +++ b/frontend/src/pages/home/Home.tsx @@ -1,12 +1,52 @@ +import { useTranslation } from "react-i18next"; +import { Container, Typography, Box } from "@mui/material"; +import { LoginButton } from "../../components/Header/Login.tsx"; /** * This component is the home page component that will be rendered when on the index route. * @returns - The home page component */ export default function Home() { + const { t } = useTranslation("translation", { keyPrefix: "home" }); return ( - <div> - <h1>HomePage</h1> - </div> + <Container maxWidth="sm"> + <Box + sx={{ + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + height: "100vh", + textAlign: "center", + gap: 3, + }} + > + <Box + component="img" + src="/img/logo_ugent.png" + alt="University Logo" + sx={{ width: 100, height: 100 }} + /> + + <Typography variant="h2" component="h1" gutterBottom> + <Box + component="img" + src="/img/logo_app.png" + alt="University Logo" + sx={{ + position: "relative", + top: "14px", + width: 90, + height: 90, + }} + /> + Peristerónas + </Typography> + <Typography variant="h6" component="p"> + {t("welcomeDescription", "Welcome to Peristeronas.")} + </Typography> + <LoginButton /> + </Box> + </Container> ); } diff --git a/frontend/src/pages/home/HomePage.tsx b/frontend/src/pages/home/HomePage.tsx new file mode 100644 index 00000000..94956541 --- /dev/null +++ b/frontend/src/pages/home/HomePage.tsx @@ -0,0 +1,214 @@ +import { useTranslation } from "react-i18next"; +import { + Card, + CardContent, + Typography, + Grid, + Container, + Badge, + CardHeader, +} from "@mui/material"; +import { DateCalendar } from "@mui/x-date-pickers/DateCalendar"; +import { DayCalendarSkeleton, LocalizationProvider } from "@mui/x-date-pickers"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import React, { useState, useEffect } from "react"; +import dayjs, { Dayjs } from "dayjs"; +import { PickersDay, PickersDayProps } from "@mui/x-date-pickers/PickersDay"; +import { ProjectDeadlineCard } from "../project/projectDeadline/ProjectDeadlineCard.tsx"; +import { ProjectDeadline } from "../project/projectDeadline/ProjectDeadline.tsx"; +import { useLoaderData } from "react-router-dom"; +import { Me } from "../../types/me.ts"; +interface DeadlineInfoProps { + selectedDay: Dayjs; + deadlines: ProjectDeadline[]; +} + +type ExtendedPickersDayProps = PickersDayProps<Dayjs> & { + highlightedDays?: number[]; +}; + +/** + * Displays the deadlines on a given day + * @param selectedDay - The day of interest + * @param deadlines - All the deadlines to consider + * @returns Element + */ +const DeadlineInfo: React.FC<DeadlineInfoProps> = ({ + selectedDay, + deadlines, +}) => { + const { t } = useTranslation("translation", { keyPrefix: "student" }); + const deadlinesOnSelectedDay = deadlines.filter( + (project) => + project.deadline && dayjs(project.deadline).isSame(selectedDay, "day"), + ); + //list of the corresponding assignment + return ( + <div> + {deadlinesOnSelectedDay.length === 0 ? ( + <Card style={{ margin: "10px 0" }}> + <CardContent> + <Typography variant="body1">{t("noDeadline")}</Typography> + </CardContent> + </Card> + ) : ( + <ProjectDeadlineCard deadlines={deadlinesOnSelectedDay} /> + )} + </div> + ); +}; + +/** + * + * @param props - The day and the deadlines + * @returns - The ServerDay component that displays a badge for specific days + */ +function ServerDay( + props: PickersDayProps<Dayjs> & { highlightedDays?: number[] }, +) { + const { highlightedDays = [], day, outsideCurrentMonth, ...other } = props; + + const isSelected = + !props.outsideCurrentMonth && + highlightedDays.indexOf(props.day.date()) >= 0; + + return ( + <Badge + key={props.day.toString()} + overlap="circular" + badgeContent={isSelected ? "🔴" : undefined} + sx={{ + ".MuiBadge-badge": { + fontSize: "0.5em", + top: 8, + right: 8, + }, + }} + > + <PickersDay + {...other} + outsideCurrentMonth={outsideCurrentMonth} + day={day} + /> + </Badge> + ); +} +const handleMonthChange = ( + date: Dayjs, + projects: ProjectDeadline[], + setHighlightedDays: React.Dispatch<React.SetStateAction<number[]>>, +) => { + setHighlightedDays([]); + // projects are now only fetched on page load + const hDays: number[] = []; + projects.map((project) => { + if ( + project.deadline && + project.deadline.getMonth() == date.month() && + project.deadline.getFullYear() == date.year() + ) { + hDays.push(project.deadline.getDate()); + } + }); + setHighlightedDays(hDays); +}; + +/** + * This component is the home page component that will be rendered when on the index route. + * @returns - The home page component + */ +export default function HomePage() { + const { t } = useTranslation("translation", { keyPrefix: "student" }); + + const [highlightedDays, setHighlightedDays] = React.useState<number[]>([]); + + const [selectedDay, setSelectedDay] = useState<Dayjs>(dayjs(Date.now())); + const loader = useLoaderData() as { + projects: ProjectDeadline[]; + me: Me; + }; + const projects = loader.projects; + + // Update selectedDay state when a day is selected + const handleDaySelect = (day: Dayjs) => { + setSelectedDay(day); + }; + const futureProjects = projects + .filter((p) => p.deadline && dayjs(dayjs()).isBefore(p.deadline)) + .sort((a, b) => dayjs(a.deadline).diff(dayjs(b.deadline))) + .slice(0, 3); // only show the first 3 + + const pastDeadlines = projects + .filter((p) => p.deadline && dayjs().isAfter(p.deadline)) + .sort((a, b) => dayjs(b.deadline).diff(dayjs(a.deadline))) + .slice(0, 3); // only show the first 3 + const noDeadlineProject = projects.filter((p) => p.deadline === undefined); + + useEffect(() => { + handleMonthChange(selectedDay, projects, setHighlightedDays); + }, [projects, selectedDay]); + + return ( + <Container style={{ paddingTop: "50px" }}> + <Grid container spacing={2} wrap="nowrap"> + <Grid item xs={6}> + <Card> + <CardHeader title={t("myProjects")} /> + <CardContent> + {futureProjects.length + noDeadlineProject.length > 0 ? ( + <> + <ProjectDeadlineCard deadlines={futureProjects} /> + <ProjectDeadlineCard deadlines={noDeadlineProject} /> + </> + ) : ( + <Typography variant="body1">{t("no_projects")}</Typography> + )} + </CardContent> + </Card> + </Grid> + + <Grid item xs={6}> + <Card> + <CardHeader title={t("deadlines")} /> + <CardContent> + {pastDeadlines.length > 0 ? ( + <ProjectDeadlineCard deadlines={pastDeadlines} /> + ) : ( + <Typography variant="body1">{t("no_projects")}</Typography> + )} + </CardContent> + </Card> + </Grid> + + <Grid item xs={6}> + <Card> + <LocalizationProvider dateAdapter={AdapterDayjs}> + <DateCalendar + value={selectedDay} + onMonthChange={(date: Dayjs) => { + handleMonthChange(date, projects, setHighlightedDays); + }} + onChange={handleDaySelect} + renderLoading={() => <DayCalendarSkeleton />} + slots={{ + day: ServerDay, + }} + slotProps={{ + day: { + highlightedDays, + } as ExtendedPickersDayProps, + }} + /> + </LocalizationProvider> + <CardContent> + <Typography variant="body2"> + {t("deadlinesOnDay")} {selectedDay.format("MMMM D, YYYY")} + </Typography> + <DeadlineInfo selectedDay={selectedDay} deadlines={projects} /> + </CardContent> + </Card> + </Grid> + </Grid> + </Container> + ); +} diff --git a/frontend/src/pages/home/HomePages.tsx b/frontend/src/pages/home/HomePages.tsx new file mode 100644 index 00000000..60d26c68 --- /dev/null +++ b/frontend/src/pages/home/HomePages.tsx @@ -0,0 +1,21 @@ +import HomePage from './HomePage.tsx'; +import Home from "./Home.tsx"; +import {useLoaderData} from "react-router-dom"; +import {ProjectDeadline} from "../project/projectDeadline/ProjectDeadline.tsx"; +import {Me} from "../../types/me.ts" + +/** + * Gives the requested home page based on the login status + * @returns - The home page component + */ +export default function HomePages() { + const loader = useLoaderData() as { + projects: ProjectDeadline[]; + me: Me; + }; + if (!loader.me.loggedIn) { + return <Home />; + } else { + return <HomePage />; + } +} diff --git a/frontend/src/pages/project/projectDeadline/ProjectDeadline.tsx b/frontend/src/pages/project/projectDeadline/ProjectDeadline.tsx new file mode 100644 index 00000000..d16f3e3e --- /dev/null +++ b/frontend/src/pages/project/projectDeadline/ProjectDeadline.tsx @@ -0,0 +1,50 @@ +export interface ProjectDeadline { + project_id:string , + title :string, + description:string, + assignment_file:string, + deadline:Date|undefined, + deadline_description:string, + course_id:number, + visible_for_students:boolean, + archived:boolean, + test_path:string, + script_name:string, + regex_expressions:string[], + short_submission: ShortSubmission, + course:Course + +} +export interface Project { + project_id:string , + title :string, + description:string, + assignment_file:string, + deadlines:string[][], + course_id:number, + visible_for_students:boolean, + archived:boolean, + test_path:string, + script_name:string, + regex_expressions:string[], + short_submission: ShortSubmission, + course:Course + +} +export interface Deadline { + description: string; + deadline: Date; +} + +export interface Course { + course_id: string; + name: string; + teacher: string; + ufora_id: string; +} +export interface ShortSubmission { + submission_id:number, + submission_time:Date, + submission_status:string, + grading: number +} diff --git a/frontend/src/pages/project/projectDeadline/ProjectDeadlineCard.tsx b/frontend/src/pages/project/projectDeadline/ProjectDeadlineCard.tsx new file mode 100644 index 00000000..28f0583f --- /dev/null +++ b/frontend/src/pages/project/projectDeadline/ProjectDeadlineCard.tsx @@ -0,0 +1,79 @@ +import {CardActionArea, Card, CardContent, Link, Typography, Box, Button} from '@mui/material'; +import { useTranslation } from "react-i18next"; +import dayjs from "dayjs"; +import {ProjectDeadline} from "./ProjectDeadline.tsx"; +import React from "react"; +import { useNavigate } from 'react-router-dom'; +import i18next from 'i18next'; + +interface ProjectCardProps{ + deadlines:ProjectDeadline[], + showCourse?:boolean +} + +/** + * A clickable display of a project deadline + * @param deadlines - A list of all the deadlines + * @param pred - A predicate to filter the deadlines + * @returns Element + */ +export const ProjectDeadlineCard: React.FC<ProjectCardProps> = ({ deadlines, showCourse = true }) => { + const { t } = useTranslation('translation', { keyPrefix: 'student' }); + const navigate = useNavigate(); + + //list of the corresponding assignment + return ( + <Box> + {deadlines.map((project, index) => ( + + <Card key={index} style={{margin: '10px 0'}}> + <CardActionArea LinkComponent={Link} href={`/${i18next.resolvedLanguage}/projects/${project.project_id}`}> + <CardContent> + <Typography variant="h6" style={{color: project.short_submission ? + (project.short_submission.submission_status === 'SUCCESS' ? 'green' : + (project.short_submission.submission_status === 'RUNNING' ? '#686868' : 'red') + ) : '#686868'}}> + {project.title} + </Typography> + {showCourse && ( + <Typography variant="subtitle1"> + {t('course')}: + <Button + style={{ + color: 'inherit', + textTransform: 'none' + }} + onMouseDown={event => event.stopPropagation()} + onClick={(event) => { + event.stopPropagation(); // stops the event from reaching CardActionArea + event.preventDefault(); + navigate(`/${i18next.resolvedLanguage}/courses/${project.course.course_id}`) + }} + > + {project.course.name} + </Button> + </Typography> + )} + <Typography variant="body2" color="textSecondary"> + {t('last_submission')}: {project.short_submission ? + t(project.short_submission.submission_status.toString()) : t('no_submission_yet')} + </Typography> + {project.deadline && ( + <Typography variant="body2" color="textSecondary"> + Deadline: {dayjs(project.deadline).format('MMMM D, YYYY')} + </Typography> + )} + {project.short_submission?.grading && ( + <Typography variant="body2" align="right"> + {project.short_submission.grading}/20 + </Typography> + )} + </CardContent> + </CardActionArea> + </Card> + )) + + } + </Box> + ); +}; diff --git a/frontend/src/pages/project/projectOverview.tsx b/frontend/src/pages/project/projectOverview.tsx new file mode 100644 index 00000000..320ccb00 --- /dev/null +++ b/frontend/src/pages/project/projectOverview.tsx @@ -0,0 +1,97 @@ +import {ProjectDeadline} from "./projectDeadline/ProjectDeadline.tsx"; +import {Button, Card, CardContent, Container, Grid, Typography, Link} from "@mui/material"; +import {ProjectDeadlineCard} from "./projectDeadline/ProjectDeadlineCard.tsx"; +import { useTranslation } from "react-i18next"; +import {Title} from "../../components/Header/Title.tsx"; +import {useLoaderData, Link as RouterLink} from "react-router-dom"; +import dayjs from "dayjs"; +import i18next from "i18next"; + +/** + * Displays all the projects + * @returns the project page + */ +export default function ProjectOverView() { + const { t } = useTranslation('translation', { keyPrefix: 'projectsOverview' }); + const loader = useLoaderData() as { + projects: ProjectDeadline[], + me: string + } + const projects = loader.projects + const me = loader.me + + const projectReducer = (acc: {[key: string]: ProjectDeadline[]}, project: ProjectDeadline) => { + (acc[project.course.course_id] = acc[project.course.course_id] || []).push(project); + return acc; + } + const futureProjectsByCourse = projects + .filter((p) => (p.deadline && dayjs(dayjs()).isBefore(p.deadline))) + .sort((a, b) => dayjs(a.deadline).diff(dayjs(b.deadline))) + .reduce(projectReducer, {}); + const pastProjectsByCourse = projects + .filter((p) => p.deadline && (dayjs()).isAfter(p.deadline)) + .sort((a, b) => dayjs(b.deadline).diff(dayjs(a.deadline))) + .reduce(projectReducer, {}); + const noDeadlineProject = projects.filter((p) => p.deadline === undefined) + .reduce(projectReducer,{}); + + const projectItem = ([index, courseProjects] : [string, ProjectDeadline[]]) =>{ + return ( + <Grid container spacing={2} key={index}> + <Grid item xs={12}> + <Link href={`/${i18next.resolvedLanguage}/courses/${courseProjects[0].course.course_id}`} style={{color: 'inherit'}} + underline={'none'}> + <Typography variant="h6">{courseProjects[0].course.name} {courseProjects[0].course.ufora_id}</Typography> + </Link> + </Grid> + <Grid item xs={8}> + <ProjectDeadlineCard deadlines={courseProjects} showCourse={false} /> + </Grid> + </Grid> + ) + } + return ( + <Container style={{ paddingTop: '50px' }}> + <Title title={"Projects Overview"}/> + <Grid container spacing={2}> + <Grid item xs={2}> + {me === 'TEACHER' && ( + <Button component={RouterLink} to={`/${i18next.resolvedLanguage}/projects/create`}>{t('new_project')}</Button> + )} + </Grid> + <Grid item xs={5}> + <Card> + <CardContent> + <Typography variant="h5" style={{ color: '#3f51b5' }}>{t("future_deadline")}:</Typography> + {Object.keys(futureProjectsByCourse).length + Object.keys(noDeadlineProject).length === 0 ? ( + <Typography variant="body1"> + {t('no_projects')} + </Typography> + ) :( + [...Object.entries(futureProjectsByCourse), + ...Object.entries(noDeadlineProject)].map(projectItem) + )} + </CardContent> + </Card> + + </Grid> + <Grid item xs={5}> + <Card> + <CardContent> + <Typography variant="h5" style={{ color: '#3f51b5' }}>{t("past_deadline")}:</Typography> + { + Object.keys(pastProjectsByCourse).length === 0 ? ( + <Typography variant="body1"> + {t('no_projects')} + </Typography> + ):( + Object.entries(pastProjectsByCourse).map(projectItem) + ) + } + </CardContent> + </Card> + </Grid> + </Grid> + </Container> + ) +} \ No newline at end of file diff --git a/frontend/src/pages/project/projectView/ProjectView.tsx b/frontend/src/pages/project/projectView/ProjectView.tsx new file mode 100644 index 00000000..8d5a2484 --- /dev/null +++ b/frontend/src/pages/project/projectView/ProjectView.tsx @@ -0,0 +1,313 @@ +import { + Box, + Button, + Card, + CardContent, + CardHeader, + Container, + Fade, + Grid, + IconButton, + Stack, + TextField, + Typography, +} from "@mui/material"; +import { useState } from "react"; +import Markdown from "react-markdown"; +import { + useLoaderData, + useLocation, + useNavigate, + useParams, +} from "react-router-dom"; +import SubmissionCard from "./SubmissionCard"; +import { Course } from "../../../types/course"; +import { Title } from "../../../components/Header/Title"; +import { authenticatedFetch } from "../../../utils/authenticated-fetch"; +import i18next from "i18next"; +import { useTranslation } from "react-i18next"; +import { Me } from "../../../types/me.ts"; +import DeadlineGrid from "../../../components/DeadlineView/DeadlineGrid.tsx"; +import { Deadline } from "../../../types/deadline.ts"; +import EditIcon from "@mui/icons-material/Edit"; +import CheckIcon from "@mui/icons-material/Check"; +import CloseIcon from "@mui/icons-material/Close"; + +const API_URL = import.meta.env.VITE_APP_API_HOST; + +interface Project { + title: string; + description: string; + regex_expressions: string[]; + archived: string; + deadlines: Deadline[]; +} + +/** + * + * @returns - ProjectView component which displays the project details + * and submissions of the current user for that project + */ +export default function ProjectView() { + const location = useLocation(); + + const { projectData, courseData, assignmentText, isAdmin } = + useLoaderData() as { + me: Me; + projectData: Project; + courseData: Course; + assignmentText: string; + isAdmin: boolean; + }; + + const deadlines = projectData["deadlines"]; + + const { t } = useTranslation("translation", { keyPrefix: "projectView" }); + + const { projectId } = useParams<{ projectId: string }>(); + const [alertVisibility, setAlertVisibility] = useState(false); + const [edit, setEdit] = useState(false); + const [title, setTitle] = useState(projectData["title"]); + const [description, setDescription] = useState(projectData["description"]); + + const navigate = useNavigate(); + const deleteProject = () => { + authenticatedFetch(`${API_URL}/projects/${projectId}`, { + method: "DELETE", + }); + navigate("/projects"); + }; + + const patchTitleAndDescription = async () => { + setEdit(false); + const formData = new FormData(); + formData.append("title", title); + formData.append("description", description); + + const response = await authenticatedFetch( + `${API_URL}/projects/${projectId}`, + { + method: "PATCH", + body: formData, + } + ); + + // Check if the response is ok (status code 2xx) + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + }; + + const discardEditTitle = () => { + const title = projectData?.title; + setEdit(false); + if (title) setTitle(title); + + if (projectData?.description) setDescription(projectData?.description); + }; + + const archiveProject = async () => { + const newArchived = !projectData?.archived; + const formData = new FormData(); + formData.append("archived", newArchived.toString()); + + const response = await authenticatedFetch( + `${API_URL}/projects/${projectId}`, + { + method: "PATCH", + body: formData, + } + ); + + if (response.ok) { + navigate(0); + } + }; + + if (!projectId) return null; + + return ( + <Container> + <Grid container direction="row" spacing={2} margin="2rem 0"> + <Grid item sm={8}> + {projectData && ( + <Card> + <Title title={projectData.title} /> + <CardHeader + color="secondary" + title={ + <Box + display="flex" + justifyContent="space-between" + alignItems="center" + > + {!edit && <>{projectData.title}</>} + {edit && ( + <> + <TextField + id="edit-title" + label="title" + variant="outlined" + size="small" + defaultValue={title} + onChange={(event) => setTitle(event.target.value)} + /> + </> + )} + {courseData && ( + <Button + variant="outlined" + type="link" + href={`/${i18next.resolvedLanguage}/courses/${courseData.course_id}`} + > + {courseData.name} + </Button> + )} + </Box> + } + subheader={ + <Box + position="relative" + height="100%" + sx={{ marginTop: "10px" }} + > + <Stack direction="row" spacing={2}> + {!edit ? ( + <> + <Typography>{projectData.description}</Typography> + </> + ) : ( + edit && ( + <> + <TextField + id="edit-description" + label="description" + variant="outlined" + size="small" + defaultValue={description} + onChange={(event) => + setDescription(event.target.value) + } + /> + </> + ) + )} + <Typography flex="1" /> + </Stack> + </Box> + } + /> + <CardContent> + <Markdown>{assignmentText}</Markdown> + <Box display="flex" alignItems="flex-end" justifyContent="end"> + {isAdmin && + (edit ? ( + <> + <IconButton onClick={patchTitleAndDescription}> + <CheckIcon /> + </IconButton> + <IconButton onClick={discardEditTitle}> + <CloseIcon /> + </IconButton> + </> + ) : ( + <IconButton onClick={() => setEdit(true)}> + <EditIcon /> + </IconButton> + ))} + </Box> + </CardContent> + </Card> + )} + <Box marginTop="2rem"> + <SubmissionCard + regexRequirements={ + projectData ? projectData.regex_expressions : [] + } + submissionUrl={`${API_URL}/submissions`} + projectId={projectId} + /> + </Box> + {isAdmin && ( + <Box width="100%"> + <Box + display="flex" + flexDirection="row" + sx={{ + justifyContent: "space-around", + }} + pt={2} + width="100%" + > + <Box display="flex" flexDirection="row" pt={2} width="100%"> + <Button + type="link" + variant="contained" + href={location.pathname + "/overview"} + sx={{ marginRight: 1 }} + > + {t("projectOverview")} + </Button> + <Button variant="contained" onClick={archiveProject}> + {t("archive")} + </Button> + </Box> + <Box + display="flex" + flexDirection="row-reverse" + pt={2} + width="100%" + > + <Button + variant="contained" + color="error" + onClick={() => setAlertVisibility(true)} + > + {t("delete")} + </Button> + </Box> + </Box> + <Box display="flex" style={{ width: "100%" }}> + <div style={{ flexGrow: 1 }} /> + <Fade + style={{ width: "fit-content" }} + in={alertVisibility} + timeout={{ enter: 1000, exit: 1000 }} + addEndListener={() => { + setTimeout(() => { + setAlertVisibility(false); + }, 4000); + }} + > + <Box sx={{ border: 1, p: 1, bgcolor: "background.paper" }}> + <Typography> + {t("deleteProjectWarning")} + </Typography> + <Box + display="flex" + flexDirection="row" + sx={{ + justifyContent: "center", + }} + pt={2} + width="100%" + > + <Button variant="contained" onClick={deleteProject}> + {t("imSure")} + </Button> + </Box> + </Box> + </Fade> + </Box> + </Box> + )} + </Grid> + <Grid item sm={4}> + <Box marginTop="2rem"> + <DeadlineGrid deadlines={deadlines} minWidth={0} /> + </Box> + </Grid> + </Grid> + </Container> + ); +} diff --git a/frontend/src/pages/project/projectView/SubmissionCard.tsx b/frontend/src/pages/project/projectView/SubmissionCard.tsx new file mode 100644 index 00000000..72c599f8 --- /dev/null +++ b/frontend/src/pages/project/projectView/SubmissionCard.tsx @@ -0,0 +1,160 @@ +import { + Alert, + Card, + CardContent, + CardHeader, + Grid, + IconButton, + LinearProgress, + Tab, + Tabs, + Typography, +} from "@mui/material"; +import SendIcon from "@mui/icons-material/Send"; +import { useEffect, useState } from "react"; +import FolderDragDrop from "../../../components/FolderUpload/FolderUpload"; +import axios from "axios"; +import { useTranslation } from "react-i18next"; +import SubmissionsGrid from "./SubmissionsGrid"; +import { Submission } from "../../../types/submission"; +import { authenticatedFetch } from "../../../utils/authenticated-fetch"; +import { getCSRFCookie } from "../../../utils/csrf"; + +interface SubmissionCardProps { + regexRequirements?: string[]; + submissionUrl: string; + projectId: string; +} + +/** + * + * @param params - regexRequirements, submissionUrl, projectId + * @returns - SubmissionCard component which allows the user to submit files + * and view previous submissions + */ +export default function SubmissionCard({ + regexRequirements, + submissionUrl, + projectId, +}: SubmissionCardProps) { + const { t } = useTranslation("translation", { keyPrefix: "projectView" }); + const [activeTab, setActiveTab] = useState("submit"); + const [selectedFile, setSelectedFile] = useState<File | null>(null); + const [uploadProgress, setUploadProgress] = useState<number | null>(null); + const [errorMessage, setErrorMessage] = useState<string | null>(null); + + const [previousSubmissions, setPreviousSubmissions] = useState<Submission[]>( + [] + ); + const handleFileDrop = (file: File) => { + setSelectedFile(file); + }; + + useEffect(() => { + authenticatedFetch(`${submissionUrl}?project_id=${projectId}`).then( + (response) => { + if (response.ok) { + response.json().then((data) => { + setPreviousSubmissions(data["data"]); + }); + } + } + ); + }, [projectId, submissionUrl]); + + const handleSubmit = async () => { + const form = new FormData(); + if (!selectedFile) { + setErrorMessage(t("noFileSelected")); + return; + } + form.append("files", selectedFile); + form.append("project_id", projectId); + try { + const response = await axios.post(submissionUrl, form, { + withCredentials: true, + headers: { + "Content-Type": "multipart/form-data", + "X-CSRF-TOKEN": getCSRFCookie() + }, + onUploadProgress: (progressEvent) => { + if (progressEvent.total) { + setUploadProgress( + Math.round((progressEvent.loaded * 100) / progressEvent.total) + ); + } + }, + }); + + if (response.status === 201) { + setSelectedFile(null); + setPreviousSubmissions((prev) => [...prev, response.data["data"]]); + setActiveTab("submissions"); + } else { + setErrorMessage(t("submitNetworkError")); + } + } catch (error) { + setErrorMessage(t("submitNetworkError")); + } + + setUploadProgress(null); + }; + + return ( + <Card> + <CardHeader + title={ + <Tabs + value={activeTab} + onChange={(_, newValue) => { + setActiveTab(newValue); + }} + > + <Tab value="submit" label={t("submit")} /> + <Tab value="submissions" label={t("previousSubmissions")} /> + </Tabs> + } + /> + <CardContent> + {activeTab === "submit" ? ( + <Grid container direction="column" rowGap={1}> + <Grid item> + <FolderDragDrop + regexRequirements={regexRequirements} + onFileDrop={handleFileDrop} + onWrongInput={(message) => setErrorMessage(message)} + /> + </Grid> + <Grid item> + {selectedFile && ( + <Typography variant="subtitle1">{`${t("selected")}: ${selectedFile.name}`}</Typography> + )} + </Grid> + <Grid item> + <IconButton disabled={!selectedFile} onClick={handleSubmit}> + <SendIcon /> + </IconButton> + </Grid> + <Grid item> + {uploadProgress && ( + <LinearProgress variant="determinate" value={uploadProgress} /> + )} + </Grid> + <Grid item> + {errorMessage && ( + <Alert severity="error" onClose={() => setErrorMessage(null)}> + {errorMessage} + </Alert> + )} + </Grid> + </Grid> + ) : ( + <SubmissionsGrid + submissionUrl={submissionUrl} + rows={previousSubmissions} + /> + )} + </CardContent> + </Card> + ); +} diff --git a/frontend/src/pages/project/projectView/SubmissionsGrid.tsx b/frontend/src/pages/project/projectView/SubmissionsGrid.tsx new file mode 100644 index 00000000..93bf14ed --- /dev/null +++ b/frontend/src/pages/project/projectView/SubmissionsGrid.tsx @@ -0,0 +1,92 @@ +import { DataGrid, GridColDef } from "@mui/x-data-grid"; +import DownloadIcon from "@mui/icons-material/Download"; +import { IconButton } from "@mui/material"; +import { useTranslation } from "react-i18next"; +import { timeDifference } from "../../../utils/date-utils"; +import { Submission } from "../../../types/submission"; + +interface SubmissionsGridProps { + submissionUrl: string; + rows: Submission[]; +} + +/** + * + * @param param - submissionUrl, rows + * @returns - SubmissionsGrid component which displays the submissions of the current user + */ +export default function SubmissionsGrid({ + submissionUrl, + rows, +}: SubmissionsGridProps) { + const { t } = useTranslation("translation", { + keyPrefix: "projectView.submissionGrid", + }); + + const stateMapper = { + LATE: t("late"), + FAIL: t("fail"), + RUNNING: t("running"), + SUCCESS: t("success"), + }; + + const columns: GridColDef[] = [ + { + field: "id", + type: "string", + width: 50, + headerName: "", + }, + { + field: "submission_time", + headerName: t("submitTime"), + type: "string", + flex: 1, + valueFormatter: (value) => timeDifference(value, true), + }, + { + field: "submission_status", + headerName: t("status"), + type: "string", + flex: 1, + valueFormatter: (value) => stateMapper[value], + }, + { + field: "actions", + type: "actions", + width: 50, + getActions: (props) => [ + <IconButton href={`${submissionUrl}/${props.id}/download`}> + <DownloadIcon /> + </IconButton>, + ], + }, + ]; + + return ( + <DataGrid + autosizeOnMount + columns={columns} + disableColumnResize + disableColumnFilter + disableColumnSelector + disableColumnSorting + disableDensitySelector + disableColumnMenu + disableVirtualization + showColumnVerticalBorder={false} + showCellVerticalBorder={false} + disableRowSelectionOnClick + disableEval + disableMultipleRowSelection + hideFooter + autoHeight + sortModel={[{ field: "submission_time", sort: "desc" }]} + getRowId={(row) => { + const urlTags = row.submission_id.split("/"); + return urlTags[urlTags.length - 1]; + }} + rows={rows} + /> + ); +} diff --git a/frontend/src/pages/submission_overview/SubmissionsOverview.tsx b/frontend/src/pages/submission_overview/SubmissionsOverview.tsx new file mode 100644 index 00000000..7318891d --- /dev/null +++ b/frontend/src/pages/submission_overview/SubmissionsOverview.tsx @@ -0,0 +1,17 @@ +import {useTranslation} from "react-i18next"; +import { Title } from "../../components/Header/Title.tsx"; +import ProjectSubmissionOverview from "../../components/ProjectSubmissionOverview/ProjectSubmissionOverview.tsx"; + +/** + * + * @returns Wrapper for page of submissions overview + */ +export default function SubmissionsOverview() { + + const { t } = useTranslation('submissionOverview', { keyPrefix: 'submissionOverview' }); + + return (<> + <Title title={t("submissionOverviewHeader")}/> + <ProjectSubmissionOverview/> + </>) +} \ No newline at end of file diff --git a/frontend/src/types/course.ts b/frontend/src/types/course.ts new file mode 100644 index 00000000..6b365ff9 --- /dev/null +++ b/frontend/src/types/course.ts @@ -0,0 +1,4 @@ +export interface Course { + name: string; + course_id: string; +} diff --git a/frontend/src/types/deadline.ts b/frontend/src/types/deadline.ts new file mode 100644 index 00000000..80200211 --- /dev/null +++ b/frontend/src/types/deadline.ts @@ -0,0 +1,4 @@ +export interface Deadline { + deadline: string; + description: string; +} \ No newline at end of file diff --git a/frontend/src/types/me.ts b/frontend/src/types/me.ts new file mode 100644 index 00000000..6788d7b4 --- /dev/null +++ b/frontend/src/types/me.ts @@ -0,0 +1,6 @@ +export interface Me { + role: string; + display_name: string; + uid: string; + loggedIn: boolean; +} diff --git a/frontend/src/types/submission.ts b/frontend/src/types/submission.ts new file mode 100644 index 00000000..173970d6 --- /dev/null +++ b/frontend/src/types/submission.ts @@ -0,0 +1,7 @@ +export interface Submission { + submission_id: string; + submission_time: string; + submission_status: string; + uid: string; + grading: number; +} diff --git a/frontend/src/utils/authenticated-fetch.ts b/frontend/src/utils/authenticated-fetch.ts new file mode 100644 index 00000000..b18b03d5 --- /dev/null +++ b/frontend/src/utils/authenticated-fetch.ts @@ -0,0 +1,17 @@ +import { getCSRFCookie } from "./csrf"; + +/** + * A helper function to automatically add the necessary authentication options to fetch + * @returns the result of the fetch with given options and default authentication options included + */ +export function authenticatedFetch( + url: string | URL | globalThis.Request, + init?: RequestInit +): Promise<Response> { + const update = { ...init, credentials: "include"}; + update.headers = { + ...update.headers, + "X-CSRF-TOKEN": getCSRFCookie() + } + return fetch(url, Object.assign(update)); +} diff --git a/frontend/src/utils/csrf.ts b/frontend/src/utils/csrf.ts new file mode 100644 index 00000000..195e98f3 --- /dev/null +++ b/frontend/src/utils/csrf.ts @@ -0,0 +1,11 @@ +/** + * A helper function to easily retrieve the crsf_access_token cookie + * @returns the crsf_access_token cookie + */ +export function getCSRFCookie(): string { + const cookie = document.cookie + .split("; ") + .find((row) => row.startsWith("csrf_access_token=")) + ?.split("=")[1]; + return cookie ? cookie : ""; +} \ No newline at end of file diff --git a/frontend/src/utils/date-utils.ts b/frontend/src/utils/date-utils.ts new file mode 100644 index 00000000..e1330607 --- /dev/null +++ b/frontend/src/utils/date-utils.ts @@ -0,0 +1,41 @@ +import i18next from "i18next"; + +/** + * + * @param date - date string to be converted to time difference + * @returns - time difference between the current date and the given date + */ +export function timeDifference(date: string, past: boolean = false) { + const t = (key: string) => { + return i18next.t(`time.${key}`); + }; + + const current = new Date(); + const previous = new Date(date); + let diff = 0; + if (past) { + diff = current.getTime() - previous.getTime(); + } else { + diff = previous.getTime() - current.getTime(); + } + const minutes = Math.floor(diff / 60000); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const months = Math.floor(days / 30); + const years = Math.floor(months / 12); + if (past) { + if (years > 0) return `${years} ${t("yearsAgo")}`; + if (months > 0) return `${months} ${t("monthsAgo")}`; + if (days > 0) return `${days} ${t("daysAgo")}`; + if (hours > 0) return `${hours} ${t("hoursAgo")}`; + if (minutes > 0) return `${minutes} ${t("minutesAgo")}`; + } + else{ + if (years > 0) return `${years} ${t("yearsLater")}`; + if (months > 0) return `${months} ${t("monthsLater")}`; + if (days > 0) return `${days} ${t("daysLater")}`; + if (hours > 0) return `${hours} ${t("hoursLater")}`; + if (minutes > 0) return `${minutes} ${t("minutesLater")}`; + } + return t("justNow"); +} diff --git a/frontend/src/utils/fetches/FetchMe.ts b/frontend/src/utils/fetches/FetchMe.ts new file mode 100644 index 00000000..d5e56fe0 --- /dev/null +++ b/frontend/src/utils/fetches/FetchMe.ts @@ -0,0 +1,20 @@ +import {authenticatedFetch} from "../authenticated-fetch.ts"; + +const API_URL = import.meta.env.VITE_APP_API_HOST; + +export const fetchMe = async () => { + try { + const response = await authenticatedFetch(`${API_URL}/me`, { + credentials: "include", + }); + if (response.status == 200) { + const data = await response.json(); + data.data.loggedIn = true + return data.data; + } else { + return {loggedIn: false }; + } + } catch (e) { + return { loggedIn: false }; + } +}; diff --git a/frontend/src/utils/fetches/FetchProjects.tsx b/frontend/src/utils/fetches/FetchProjects.tsx new file mode 100644 index 00000000..969bf154 --- /dev/null +++ b/frontend/src/utils/fetches/FetchProjects.tsx @@ -0,0 +1,116 @@ +import { fetchMe } from "./FetchMe.ts"; +import { authenticatedFetch } from "../authenticated-fetch.ts"; +import { + Project, + ProjectDeadline, + ShortSubmission, +} from "../../pages/project/projectDeadline/ProjectDeadline.tsx"; +import { Me } from "../../types/me.ts"; +const API_URL = import.meta.env.VITE_APP_API_HOST; + +export const fetchProjectPage = async () => { + const me = await fetchMe(); + const projects = await fetchProjects(me); + return { projects, me }; +}; + +export const fetchProjects = async (me: Me) => { + try { + const response = await authenticatedFetch(`${API_URL}/projects`); + const jsonData = await response.json(); + let formattedData: ProjectDeadline[] = await Promise.all( + jsonData.data.map(async (item: Project) => { + try { + const url_split = item.project_id.split("/"); + const project_id = url_split[url_split.length - 1]; + const response_submissions = await ( + await authenticatedFetch( + encodeURI(`${API_URL}/submissions?project_id=${project_id}&uid=${me.uid}`) + ) + ).json(); + + //get the latest submission + const latest_submission = response_submissions.data + .map((submission: ShortSubmission) => ({ + submission_id: submission.submission_id, //this is the path + submission_time: new Date(submission.submission_time), + submission_status: submission.submission_status, + grading: submission.grading, + })) + .sort( + (a: ShortSubmission, b: ShortSubmission) => + b.submission_time.getTime() - a.submission_time.getTime(), + )[0]; + // fetch the course id of the project + const project_item = await ( + await authenticatedFetch( + encodeURI(`${API_URL}/projects/${project_id}`) + ) + ).json(); + + //fetch the course + const response_courses = await ( + await authenticatedFetch( + encodeURI(`${API_URL}/courses/${project_item.data.course_id}`) + ) + ).json(); + const course = { + course_id: response_courses.data.course_id, + name: response_courses.data.name, + teacher: response_courses.data.teacher, + ufora_id: response_courses.data.ufora_id, + }; + if (project_item.data.deadlines) { + return project_item.data.deadlines.map((d: string[]) => { + return { + project_id: project_id, + title: project_item.data.title, + description: project_item.data.description, + assignment_file: project_item.data.assignment_file, + deadline: new Date(d[1]), + deadline_description: d[0], + course_id: Number(project_item.data.course_id), + visible_for_students: Boolean( + project_item.data.visible_for_students, + ), + archived: Boolean(project_item.data.archived), + test_path: project_item.data.test_path, + script_name: project_item.data.script_name, + regex_expressions: project_item.data.regex_expressions, + short_submission: latest_submission, + course: course, + }; + }); + } + // contains no dealine: + return [ + { + project_id: project_id, + title: project_item.data.title, + description: project_item.data.description, + assignment_file: project_item.data.assignment_file, + deadline: undefined, + deadline_description: undefined, + course_id: Number(project_item.data.course_id), + visible_for_students: Boolean( + project_item.data.visible_for_students, + ), + archived: Boolean(project_item.data.archived), + test_path: project_item.data.test_path, + script_name: project_item.data.script_name, + regex_expressions: project_item.data.regex_expressions, + short_submission: latest_submission, + course: course, + }, + ]; + } catch (e) { + return []; + } + }), + ); + formattedData = formattedData.flat(); + return formattedData; + } catch (_) { + return []; + } +}; diff --git a/frontend/src/utils/file-utils.ts b/frontend/src/utils/file-utils.ts new file mode 100644 index 00000000..8fa2cfe5 --- /dev/null +++ b/frontend/src/utils/file-utils.ts @@ -0,0 +1,42 @@ +import JSZip from "jszip"; + +type FileCheckResult = { + isValid: boolean; + missingFiles: string[]; +}; + +/** + * Checks if the zipObject contains at least all the files that match the regexList + * @param zipObject - JSZip object to match the regex against + * @param regexList - List of regex strings to match against the zipObject + * @returns true if all regex strings are found in the zipObject, false otherwise + */ +export function verifyZipContents( + zipObject: JSZip, + regexList: string[] +): FileCheckResult { + const missingFiles: string[] = []; + const status = regexList.every((regex) => { + let found: boolean = false; + zipObject.forEach((relativePath) => { + if (new RegExp(regex).test(relativePath)) { + found = true; + } + }); + if (!found) { + missingFiles.push(regex); + } + return found; + }); + + return { isValid: status, missingFiles: missingFiles }; +} + +/** + * Gets the extension of a given filename + * @param filename - The name of the file to get the extension of + * @returns The extension of the file + */ +export function getFileExtension(filename: string) { + return filename.slice(((filename.lastIndexOf(".") - 1) >>> 0) + 2); +} diff --git a/frontend/tests/unit/header.test.tsx b/frontend/tests/unit/header.test.tsx new file mode 100644 index 00000000..76834646 --- /dev/null +++ b/frontend/tests/unit/header.test.tsx @@ -0,0 +1,6 @@ +import { describe, test } from "vitest"; +//import { render } from "@testing-library/react"; + +describe("Header", () => { + test.todo("Header test"); +}); diff --git a/frontend/tests/unit/homepage.test.tsx b/frontend/tests/unit/homepage.test.tsx new file mode 100644 index 00000000..bea65bd5 --- /dev/null +++ b/frontend/tests/unit/homepage.test.tsx @@ -0,0 +1,3 @@ +import { test } from "vitest"; + +test.todo("Homepage test"); diff --git a/frontend/tests/unit/type-tests/me.test.tsx b/frontend/tests/unit/type-tests/me.test.tsx new file mode 100644 index 00000000..305172d9 --- /dev/null +++ b/frontend/tests/unit/type-tests/me.test.tsx @@ -0,0 +1,5 @@ +import { describe, test } from "vitest"; + +describe("Me is properly defined", () => { + test.todo("Me.role is string"); +}); diff --git a/frontend/tests/utils/data.ts b/frontend/tests/utils/data.ts new file mode 100644 index 00000000..8ad42080 --- /dev/null +++ b/frontend/tests/utils/data.ts @@ -0,0 +1,7 @@ +export const courses = [{}]; + +export const projects = [{}]; + +export const submissions = [{}]; + +export const users = [{}]; diff --git a/frontend/tests/utils/me-fixture.ts b/frontend/tests/utils/me-fixture.ts new file mode 100644 index 00000000..ad160476 --- /dev/null +++ b/frontend/tests/utils/me-fixture.ts @@ -0,0 +1,5 @@ +export default { + uid: "TestUID", + role: "STUDENT", + display_name: "Terry Tester", +}; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 046f3fef..9a5bee7f 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -21,8 +21,14 @@ "noFallthroughCasesInSwitch": true, "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": true + "strictNullChecks": true, + + /* Testing */ + "types": ["vitest/globals"] }, - "include": ["src"], + "include": [ + "src", + "node_modules/cypress/types/jquery/misc.d.ts" + ], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 5a33944a..4e0a261b 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,12 @@ +/// <reference types="vitest" /> import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + test: { + environment: 'jsdom', + globals: true, + }, }) diff --git a/usecases/edit_links.txt b/usecases/edit_links.txt new file mode 100644 index 00000000..d83b589b --- /dev/null +++ b/usecases/edit_links.txt @@ -0,0 +1,3 @@ +Student edit link: https://lucid.app/lucidchart/3c9eb437-dbcf-4d42-879d-80fa55b52ed6/edit?viewport_loc=-682%2C-251%2C1891%2C896%2C0_0&invitationId=inv_d4c3257f-edfa-4a59-973a-310ca62f84d2 + +Teacher/admin edit link: https://lucid.app/lucidchart/cf630b96-4f49-4153-8405-75ea7dd9dbb2/edit?viewport_loc=-187%2C364%2C2125%2C1107%2C0_0&invitationId=inv_f2ab6115-7288-4b6e-b546-9e19638fb580 diff --git a/usecases/usecase_student.pdf b/usecases/usecase_student.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6be165f2d40918f3b021425c170aedca92d474f1 GIT binary patch literal 17142 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%0ArKD_FIa#Lr~~tGfU@ek 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 NFb^gZlbpKz{{gOZ^zr}z literal 0 HcmV?d00001 diff --git a/usecases/usecase_teacher_admin.pdf b/usecases/usecase_teacher_admin.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fb9057a956f9394d8babd528460d11edeb4e13e2 GIT binary patch literal 25563 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 BRn!0g literal 0 HcmV?d00001