diff --git a/.gitattributes b/.gitattributes index 4a3b8d5..f6217f1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,4 +17,5 @@ castor.php export-ignore node_modules export-ignore public/js/tests export-ignore tests export-ignore -vendor export-ignore \ No newline at end of file +vendor export-ignore +__tests__ export-ignore \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2f37a4..bdf1a2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,13 +33,13 @@ jobs: - name: Run PHPStan run: vendor/bin/phpstan analyse - jest: - name: Jest (Node ${{ matrix.node }}) + vitest: + name: Vitest (Node ${{ matrix.node }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: - node: [ '18', '20', '22', '24' ] + node: [ '20', '22', '24' ] steps: - name: Checkout code uses: actions/checkout@v4 @@ -53,8 +53,8 @@ jobs: - name: Install Node dependencies run: npm ci - - name: Run Jest tests - run: npm test -- --ci --reporters=default + - name: Run Vitest tests + run: npm test tests: name: Tests (PHP ${{ matrix.php }}, PHPUnit ${{ matrix.phpunit-version }}) @@ -92,7 +92,7 @@ jobs: name: Create Release runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') - needs: ["code-quality", "jest", "tests"] + needs: ["code-quality", "vitest", "tests"] permissions: contents: write steps: diff --git a/.gitignore b/.gitignore index 547eba7..86bfeb9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,66 @@ composer.lock .env.* node_modules package-lock.json +/public/build/css/styles.css +/public/build/js/components/header/filter/FilterPanelButton.js +/public/build/js/components/header/filter/FilterPanelButton.vue +/public/build/js/components/header/filter/FilterPanelContent.js +/public/build/js/components/header/filter/FilterPanelContent.vue +/public/build/js/components/header/ClearResultsButton.js +/public/build/js/components/header/ClearResultsButton.vue +/public/build/js/components/header/FilterPanel.js +/public/build/js/components/header/FilterPanel.vue +/public/build/js/components/header/HeaderTitle.js +/public/build/js/components/header/HeaderTitle.vue +/public/build/js/components/header/RunFailedButton.js +/public/build/js/components/header/RunFailedButton.vue +/public/build/js/components/header/RunStopAllButton.js +/public/build/js/components/header/RunStopAllButton.vue +/public/build/js/components/sidebar/TestItem.js +/public/build/js/components/sidebar/TestItem.vue +/public/build/js/components/sidebar/TestList.js +/public/build/js/components/sidebar/TestList.vue +/public/build/js/components/sidebar/TestSearchBar.js +/public/build/js/components/sidebar/TestSearchBar.vue +/public/build/js/components/sidebar/TestSuite.js +/public/build/js/components/sidebar/TestSuite.vue +/public/build/js/components/sidebar/TestSuiteHeader.js +/public/build/js/components/sidebar/TestSuiteHeader.vue +/public/build/js/components/CoverageReport.js +/public/build/js/components/CoverageReport.vue +/public/build/js/components/FileCoverageDetail.js +/public/build/js/components/FileCoverageDetail.vue +/public/build/js/components/GroupedTestResults.js +/public/build/js/components/GroupedTestResults.vue +/public/build/js/components/Header.js +/public/build/js/components/Header.vue +/public/build/js/components/IndividualTestResults.js +/public/build/js/components/IndividualTestResults.vue +/public/build/js/components/MainContent.js +/public/build/js/components/MainContent.vue +/public/build/js/components/ResultsSummary.js +/public/build/js/components/ResultsSummary.vue +/public/build/js/components/TabNavigation.js +/public/build/js/components/TabNavigation.vue +/public/build/js/components/TestDetails.js +/public/build/js/components/TestDetails.vue +/public/build/js/components/TestSidebar.js +/public/build/js/components/TestSidebar.vue +/public/build/js/tests/mocks/vue.js +/public/build/js/tests/.gitkeep +/public/build/js/tests/api.test.js +/public/build/js/tests/app.test.js +/public/build/js/tests/store.test.js +/public/build/js/tests/utils.test.js +/public/build/js/tests/websocket.test.js +/public/build/js/api.js +/public/build/js/app.js +/public/build/js/App.vue +/public/build/js/main.js +/public/build/js/store.js +/public/build/js/utils.js +/public/build/js/websocket.js +/public/build/index.html +/public/build/assets/favicon-failure.svg +/public/build/assets/favicon-neutral.svg +/public/build/assets/favicon-success.svg diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache index 7121ef8..ac23417 100644 --- a/.php-cs-fixer.cache +++ b/.php-cs-fixer.cache @@ -1 +1 @@ -{"php":"8.2.29","version":"3.90.0:v3.90.0#ad732c2e9299c9743f9c55ae53cc0e7642ab1155","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"modifier_keywords":true,"new_with_parentheses":{"anonymous_class":true},"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_fn_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"after_heredoc":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"octal_notation":true,"clean_namespace":true,"no_unset_cast":true,"assign_null_coalescing_to_coalesce_equal":true,"normalize_index_brace":true,"heredoc_indentation":true,"no_whitespace_before_comma_in_array":{"after_heredoc":true},"trailing_comma_in_multiline":{"after_heredoc":true},"list_syntax":true,"ternary_to_null_coalescing":true,"array_syntax":true,"no_unused_imports":true,"fully_qualified_strict_types":true},"hashes":{"src\/Command\/Router.php":"b2a306bfe90da3e771413b8dea77f416","src\/Command\/ServeCommand.php":"4c45cbcf7c8fe646c68c1ec35d9a4984","src\/Command\/RouterInterface.php":"857c4c498de00c34e01b83ab26b626c2","src\/Coverage\/Coverage.php":"73ff8293849648e1a2100158f75feb39","src\/Util\/Composer.php":"0ece8bbf75bbb97e7d0a583404824538","src\/PHPUnit\/PhpUnitHubExtension.php":"6e23b8845965ecfa033c74078508ffb6","src\/Discoverer\/TestDiscoverer.php":"26db9dbb92284349b05b7320d1250a6f","src\/Parser\/JUnitParser.php":"1a064753b2a0cf80b35c2c6131b3407d","src\/WebSocket\/StatusHandler.php":"e65bbba93f1f1c8bb116140370023aa1","src\/Http\/DecoratedHttpServer.php":"796efd5b1f3413200c4216eacd07baf4","src\/TestRunner\/TestRunner.php":"1ddbf207ccb2a53d2e0674775fa7d074","tests\/Command\/RouterTest.php":"64de0dd90223ca85ef11ab21d9e9f624","tests\/Command\/ServeCommandTest.php":"98e0865c6fd11eb3726bf182e37012e7","tests\/Coverage\/CoverageTest.php":"2f7938f8f414ceb10d8d3b80264fd675","tests\/Discoverer\/TestDiscovererTest.php":"a4354743436349d6c8fdde06e9f3e969","tests\/Parser\/JUnitParserTest.php":"ac9265156b4482b074eef22a06fbd604","tests\/WebSocket\/StatusHandlerTest.php":"532eaf4611becdc32d805efc6411f665","tests\/TestRunner\/TestRunnerTest.php":"f9945b179ecc18a986fd81ad0a4278d8","src\/Util\/ProjectRootResolver.php":"cfc86290611994f3efe9355e84ae4049","src\/PHPUnit\/TestSubscriber.php":"15b9ac0382ea6e9ec64132f357a19076","src\/Discoverer\/PhpUnitCommandExecutor.php":"eda5d8493de9db65695d45770a768efc","tests\/Util\/ProjectRootResolverTest.php":"b77b8208c37629acedd90b4b675f761e","tests\/Util\/ComposerTest.php":"d9c61117c9f424c3bd45724c13a9ef87","tests\/PHPUnit\/TestSubscriberTest.php":"c0ee01fba41bedcd24f36a84baa71191","tests\/Http\/DecoratedHttpServerTest.php":"eca8426406a227d192f817bac2853cb2","src\/Util\/PhpUnitCommandExecutor.php":"84274486bc5836d4dfa6a15ae4711dcc","tests\/Util\/PhpUnitCommandExecutorTest.php":"2f9d8ada0f682222427c4e5689e88d98","tests\/Command\/RouterNewTest.php":"f0925a34a802304469d530db333ea8ef"}} \ No newline at end of file +{"php":"8.2.29","version":"3.91.2:v3.91.2#f171dc216bc8a4192d5a0876a899cce6f9e379d6","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"modifier_keywords":true,"new_with_parentheses":{"anonymous_class":true},"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_fn_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"after_heredoc":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"octal_notation":true,"clean_namespace":true,"no_unset_cast":true,"assign_null_coalescing_to_coalesce_equal":true,"normalize_index_brace":true,"heredoc_indentation":true,"no_whitespace_before_comma_in_array":{"after_heredoc":true},"trailing_comma_in_multiline":{"after_heredoc":true},"list_syntax":true,"ternary_to_null_coalescing":true,"array_syntax":true,"no_unused_imports":true,"fully_qualified_strict_types":true},"hashes":{"src\/Command\/Router.php":"8956c9552a204df48b3825c48a7ade4c","src\/Command\/ServeCommand.php":"4c45cbcf7c8fe646c68c1ec35d9a4984","src\/Command\/RouterInterface.php":"5dd19ba932d4c43c920427003b3c1c3c","src\/Coverage\/Coverage.php":"0cb07471a183377c0b8fc1e6828cd606","src\/Util\/ProjectRootResolver.php":"cfc86290611994f3efe9355e84ae4049","src\/Util\/Composer.php":"0ece8bbf75bbb97e7d0a583404824538","src\/Util\/PhpUnitCommandExecutor.php":"84274486bc5836d4dfa6a15ae4711dcc","src\/PHPUnit\/PhpUnitHubExtension.php":"fe86b1c890e1b827fba07f738a36b24c","src\/Discoverer\/TestDiscoverer.php":"26db9dbb92284349b05b7320d1250a6f","src\/WebSocket\/StatusHandler.php":"e65bbba93f1f1c8bb116140370023aa1","src\/Http\/DecoratedHttpServer.php":"796efd5b1f3413200c4216eacd07baf4","src\/TestRunner\/TestRunner.php":"55f494bb6094e554e31388e3ba8c3431","tests\/Command\/RouterTest.php":"fcbb7a575e2103f020e0aa797dd07e7c","tests\/Command\/ServeCommandTest.php":"98e0865c6fd11eb3726bf182e37012e7","tests\/Coverage\/CoverageTest.php":"2e6a24d482ff721a9deff2f194e0e2bd","tests\/Util\/ProjectRootResolverTest.php":"b77b8208c37629acedd90b4b675f761e","tests\/Util\/ComposerTest.php":"d9c61117c9f424c3bd45724c13a9ef87","tests\/Util\/PhpUnitCommandExecutorTest.php":"2f9d8ada0f682222427c4e5689e88d98","tests\/Discoverer\/TestDiscovererTest.php":"a4354743436349d6c8fdde06e9f3e969","tests\/WebSocket\/StatusHandlerTest.php":"532eaf4611becdc32d805efc6411f665","tests\/Http\/DecoratedHttpServerTest.php":"eca8426406a227d192f817bac2853cb2","tests\/TestRunner\/TestRunnerTest.php":"529b29a3acbe2b17fd709e54cc38c3da"}} \ No newline at end of file diff --git a/.phpunit.result.cache b/.phpunit.result.cache index de6c37f..cb61670 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":2,"defects":{"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithoutWatchOptionOutputsMessages":8,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitNotFoundOutputsError":1,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitFoundAndFileChangesTriggersTests":1,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunReturnsProcessInstance":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetCoverageReturnsCoverageData":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverage":8,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileReturnsCorrectData":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopAllEndpointTerminatesAllProcesses":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointTerminatesSpecificProcess":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopEndpointReturns400IfNoProcessIsRunning":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfRunIdNotFound":8,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithValidConfig":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunTestsEndpointStartsProcess":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testDiscoverTestsEndpointReturnsDiscovererResult":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageReturnsCoverageData":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentReturnsFileContent":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetLastRunContextReturnsCorrectData":8,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOption":8,"PhpUnitHub\\Tests\\Http\\DecoratedHttpServerTest::testConstructorSetsMaxSize":8,"PhpUnitHub\\Tests\\PHPUnit\\PhpUnitHubExtensionTest::testBootstrapRegistersSubscribers":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPreparedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPassedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesFailedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesErroredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesSkippedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestFinishedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPreparedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPassedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesFailedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesErroredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesSkippedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestFinishedEvent":7,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithFilters":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithSuites":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithGroups":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithOptions":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testCamelToKebab":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverageAndNoSource":8,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForEmptyCommand":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStatusEndpointReturns200":8,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testServesIndexHtml":7,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileContentErrorResponses":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesWebSocketError":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesHttpConnectionError":8,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWhenNoConfigFile":7,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithInvalidConfigFile":7,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testRisky":5,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testNotice":5,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #0":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #1":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #2":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #0":8,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #1":8,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #2":8},"times":{"PhpUnitHub\\Tests\\Command\\RouterTest::testStopAllEndpointTerminatesAllProcesses":0.021,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointTerminatesSpecificProcess":0.024,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopEndpointReturns400IfNoProcessIsRunning":0.019,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfRunIdNotFound":0.021,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testConfigure":0,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithoutWatchOptionOutputsMessages":0.004,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitNotFoundOutputsError":0.003,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitFoundAndFileChangesTriggersTests":0.003,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsDistConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsMainConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorPrefersDistOverMainConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsNoConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWhenNoConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithInvalidConfigFile":0.001,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithAllPassedTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithFailedTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithErrorTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithMixedTestStatuses":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithEmptyXmlContentThrowsException":0.001,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithZeroXmlContentThrowsException":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithInvalidXmlContentThrowsException":0.001,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithXmlContainingNoTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithXmlContainingEmptyTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithNestedTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithMissingAttributes":0,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunReturnsProcessInstance":0.002,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnOpenAttachesConnectionAndWritesToOutput":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnOpenWithoutOutputDoesNotWrite":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnMessageDoesNothing":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnCloseDetachesConnectionAndWritesToOutput":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnCloseWithoutOutputDoesNotWrite":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnErrorWritesToOutputAndClosesConnection":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnErrorWithoutOutputDoesNotWrite":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testBroadcastSendsMessageToAllConnections":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testBroadcastWithNoConnectionsDoesNothing":0,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetCoverageReturnsCoverageData":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseReturnsCorrectData":0.002,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverage":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileReturnsCorrectData":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseReturnsEmptyArrayForEmptyCoverage":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithNonExistentFile":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithInvalidXml":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithMissingProjectElement":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithFileOutsideSourceDirectories":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoStatements":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoPhpunitConfig":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithInvalidXml":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #0":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #1":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #2":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #0 ('1')\"":0.004,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #1 ('2')\"":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #2 ('3')\"":0.004,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithValidConfig":0.007,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithFilters":0.002,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithSuites":0.002,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithGroups":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunTestsEndpointStartsProcess":0.032,"PhpUnitHub\\Tests\\Command\\RouterTest::testDiscoverTestsEndpointReturnsDiscovererResult":0.019,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageReturnsCoverageData":0.008,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentReturnsFileContent":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetLastRunContextReturnsCorrectData":0.002,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOption":0.006,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverSuites":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverGroups":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverTests":0.001,"PhpUnitHub\\Tests\\Http\\DecoratedHttpServerTest::testConstructorSetsMaxSize":0,"PhpUnitHub\\Tests\\PHPUnit\\PhpUnitHubExtensionTest::testBootstrapRegistersSubscribers":0.003,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithOptions":0.002,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testCamelToKebab":0,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverageAndNoSource":0.003,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithNoComposerJson":0.001,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithInvalidComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithNoBinDirInComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithBinDirInComposerJson":0.001,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithVendorDirInCurrentDir":0.001,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithVendorDirInParentDir":0.001,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithNoVendorDir":0,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPreparedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPassedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesFailedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesErroredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesSkippedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":0,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":0,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestFinishedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPreparedEvent":0.003,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPassedEvent":0.003,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesFailedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesErroredEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesSkippedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":0.004,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestFinishedEvent":0.001,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsOutputOfValidCommand":0.002,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForInvalidCommand":0.001,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForEmptyCommand":0,"PhpUnitHub\\Tests\\Command\\RouterTest::testStatusEndpointReturns200":0.095,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testWebSocketConnection":0.105,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testRunFailedEndpointWithNoFailedTests":0.007,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testServesIndexHtml":0.006,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testNotFoundResponse":0.003,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetMimeType":0.001,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileCoverageErrorResponses":0.021,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileContentErrorResponses":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnMessageDelegatesToWebSocket":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnMessageDoesNotThrowWhenWebSocketPropertyIsNull":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnCloseCallsHttpServerOnCloseWhenWebSocketIsNotNull":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnCloseDoesNotThrowWhenWebSocketPropertyIsNull":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesWebSocketError":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesHttpConnectionError":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testWebSocketConnection":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunFailedEndpointWithNoFailedTests":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testServesIndexHtml":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testNotFoundResponse":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetMimeType":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageErrorResponses":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentErrorResponses":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testRisky":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testNotice":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #0":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #1":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #2":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #0":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #1":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #2":0}} \ No newline at end of file +{"version":2,"defects":{"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithoutWatchOptionOutputsMessages":8,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitNotFoundOutputsError":1,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitFoundAndFileChangesTriggersTests":1,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunReturnsProcessInstance":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetCoverageReturnsCoverageData":7,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverage":8,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileReturnsCorrectData":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopAllEndpointTerminatesAllProcesses":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointTerminatesSpecificProcess":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopEndpointReturns400IfNoProcessIsRunning":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfRunIdNotFound":8,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithValidConfig":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunTestsEndpointStartsProcess":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testDiscoverTestsEndpointReturnsDiscovererResult":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageReturnsCoverageData":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentReturnsFileContent":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetLastRunContextReturnsCorrectData":8,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOption":8,"PhpUnitHub\\Tests\\Http\\DecoratedHttpServerTest::testConstructorSetsMaxSize":8,"PhpUnitHub\\Tests\\PHPUnit\\PhpUnitHubExtensionTest::testBootstrapRegistersSubscribers":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPreparedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPassedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesFailedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesErroredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesSkippedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestFinishedEvent":8,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPreparedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPassedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesFailedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesErroredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesSkippedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":7,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestFinishedEvent":7,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithFilters":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithSuites":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithGroups":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithOptions":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testCamelToKebab":8,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverageAndNoSource":8,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForEmptyCommand":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testStatusEndpointReturns200":8,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testServesIndexHtml":7,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileContentErrorResponses":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesWebSocketError":8,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesHttpConnectionError":8,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWhenNoConfigFile":7,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithInvalidConfigFile":7,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testRisky":5,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testNotice":5,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #0":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #1":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #2":2,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #0":8,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #1":8,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #2":8,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseReturnsCorrectData":7,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoStatements":7,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoPhpunitConfig":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testServesIndexHtml":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfNoProcessIsRunning":7,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageErrorResponses":8},"times":{"PhpUnitHub\\Tests\\Command\\RouterTest::testStopAllEndpointTerminatesAllProcesses":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointTerminatesSpecificProcess":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopEndpointReturns400IfNoProcessIsRunning":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfRunIdNotFound":0.003,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testConfigure":0.001,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithoutWatchOptionOutputsMessages":0.007,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitNotFoundOutputsError":0.003,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOptionInotifywaitFoundAndFileChangesTriggersTests":0.003,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsDistConfigFile":0.011,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsMainConfigFile":0.003,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorPrefersDistOverMainConfigFile":0.002,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testConstructorFindsNoConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWhenNoConfigFile":0.001,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithInvalidConfigFile":0.004,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithAllPassedTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithFailedTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithErrorTests":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithMixedTestStatuses":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithEmptyXmlContentThrowsException":0.001,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithZeroXmlContentThrowsException":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithInvalidXmlContentThrowsException":0.001,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithXmlContainingNoTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithXmlContainingEmptyTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithNestedTestSuites":0,"PhpUnitHub\\Tests\\Parser\\JUnitParserTest::testParseWithMissingAttributes":0,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunReturnsProcessInstance":0.003,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnOpenAttachesConnectionAndWritesToOutput":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnOpenWithoutOutputDoesNotWrite":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnMessageDoesNothing":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnCloseDetachesConnectionAndWritesToOutput":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnCloseWithoutOutputDoesNotWrite":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnErrorWritesToOutputAndClosesConnection":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testOnErrorWithoutOutputDoesNotWrite":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testBroadcastSendsMessageToAllConnections":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testBroadcastWithNoConnectionsDoesNothing":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetCoverageReturnsCoverageData":0.021,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseReturnsCorrectData":0.003,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverage":0.003,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileReturnsCorrectData":0.007,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseReturnsEmptyArrayForEmptyCoverage":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithNonExistentFile":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithInvalidXml":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithMissingProjectElement":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithFileOutsideSourceDirectories":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoStatements":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseWithNoPhpunitConfig":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithInvalidXml":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode":0.002,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #0":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #1":0,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set #2":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #0 ('1')\"":0.004,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #1 ('2')\"":0.001,"PhpUnitHub\\Tests\\Coverage\\CoverageTest::testParseFileWithMissingFileNode with data set \" with data set #2 ('3')\"":0.004,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverWithValidConfig":0.007,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithFilters":0.004,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithSuites":0.006,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithGroups":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunTestsEndpointStartsProcess":0.119,"PhpUnitHub\\Tests\\Command\\RouterTest::testDiscoverTestsEndpointReturnsDiscovererResult":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageReturnsCoverageData":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentReturnsFileContent":0.004,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetLastRunContextReturnsCorrectData":0.005,"PhpUnitHub\\Tests\\Command\\ServeCommandTest::testExecuteWithWatchOption":0.008,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverSuites":0.004,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverGroups":0.002,"PhpUnitHub\\Tests\\Discoverer\\TestDiscovererTest::testDiscoverTests":0.004,"PhpUnitHub\\Tests\\Http\\DecoratedHttpServerTest::testConstructorSetsMaxSize":0.004,"PhpUnitHub\\Tests\\PHPUnit\\PhpUnitHubExtensionTest::testBootstrapRegistersSubscribers":0.003,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithOptions":0.004,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testCamelToKebab":0.003,"PhpUnitHub\\Tests\\TestRunner\\TestRunnerTest::testRunBuildsCorrectCommandWithCoverageAndNoSource":0.006,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithNoComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithInvalidComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithNoBinDirInComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ComposerTest::testGetComposerBinDirWithBinDirInComposerJson":0.002,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithVendorDirInCurrentDir":0.006,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithVendorDirInParentDir":0.002,"PhpUnitHub\\Tests\\Util\\ProjectRootResolverTest::testResolveWithNoVendorDir":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPreparedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPassedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesFailedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesErroredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesSkippedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":0,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":0,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\RealtimeTestSubscriberTest::testNotifyHandlesTestFinishedEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPreparedEvent":0.003,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPassedEvent":0.003,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesFailedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesErroredEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesSkippedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesMarkedIncompleteEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesWarningTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpDeprecationTriggeredEvent":0.001,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesPhpWarningTriggeredEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestSuiteStartedEvent":0.004,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestRunnerFinishedEvent":0.002,"PhpUnitHub\\Tests\\PHPUnit\\TestSubscriberTest::testNotifyHandlesTestFinishedEvent":0.001,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsOutputOfValidCommand":0.005,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForInvalidCommand":0.003,"PhpUnitHub\\Tests\\Util\\PhpUnitCommandExecutorTest::testExecuteReturnsNullForEmptyCommand":0.001,"PhpUnitHub\\Tests\\Command\\RouterTest::testStatusEndpointReturns200":0.095,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testWebSocketConnection":0.105,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testRunFailedEndpointWithNoFailedTests":0.007,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testServesIndexHtml":0.006,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testNotFoundResponse":0.003,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetMimeType":0.001,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileCoverageErrorResponses":0.021,"PhpUnitHub\\Tests\\Command\\RouterNewTest::testGetFileContentErrorResponses":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnMessageDelegatesToWebSocket":0.004,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnMessageDoesNotThrowWhenWebSocketPropertyIsNull":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnCloseCallsHttpServerOnCloseWhenWebSocketIsNotNull":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnCloseDoesNotThrowWhenWebSocketPropertyIsNull":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesWebSocketError":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testOnErrorHandlesHttpConnectionError":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testWebSocketConnection":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testRunFailedEndpointWithNoFailedTests":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testServesIndexHtml":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testNotFoundResponse":0.003,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetMimeType":0.002,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileCoverageErrorResponses":0.005,"PhpUnitHub\\Tests\\Command\\RouterTest::testGetFileContentErrorResponses":0.007,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testRisky":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testNotice":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #0":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #1":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testIncomplete2 with data set #2":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #0":0.001,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #1":0,"PhpUnitHub\\Tests\\WebSocket\\StatusHandlerTest::testData with data set #2":0,"PhpUnitHub\\Tests\\Command\\RouterTest::testStopSingleEndpointReturns404IfNoProcessIsRunning":0.003}} \ No newline at end of file diff --git a/public/css/input.css b/assets/css/styles.css similarity index 93% rename from public/css/input.css rename to assets/css/styles.css index e283692..dfd5efd 100644 --- a/public/css/input.css +++ b/assets/css/styles.css @@ -35,7 +35,7 @@ padding-bottom: 0; margin-bottom: 0; } - + input[type="radio"], input[type="checkbox"] { -webkit-appearance: none; @@ -266,4 +266,16 @@ left: 20px; animation-delay: 0; } + + [v-cloak] { + display: none; + } + + .token-keyword { color: #c586c0; } + .token-string { color: #ce9178; } + .token-comment { color: #6a9955; } + .token-variable { color: #9cdcfe; } + .token-default { color: #d4d4d4; } + .line-covered { background-color: rgba(16, 185, 129, 0.1); } + .line-uncovered { background-color: rgba(248, 113, 113, 0.1); } } diff --git a/assets/js/App.vue b/assets/js/App.vue new file mode 100644 index 0000000..1297ee7 --- /dev/null +++ b/assets/js/App.vue @@ -0,0 +1,58 @@ + + + diff --git a/assets/js/api.js b/assets/js/api.js new file mode 100644 index 0000000..202d425 --- /dev/null +++ b/assets/js/api.js @@ -0,0 +1,187 @@ +/** + * API client for PHPUnit Hub + */ + +export class ApiClient { + constructor(baseUrl = '') { + this.baseUrl = baseUrl; + } + + /** + * Utility function to retry a fetch request. + * @param {Function} fn The fetch function to retry. + * @param {number} retries The number of retries. + * @param {number} delay The delay between retries in milliseconds. + */ + async retry(fn, retries = 3, delay = 1000) { + for (let i = 0; i <= retries; i++) { + try { + return await fn(); + } catch (error) { + const isNetworkError = error instanceof TypeError && error.message === 'Failed to fetch'; + + if (isNetworkError && i < retries) { + console.warn(`Attempt ${i + 1} failed due to network error. Retrying in ${delay}ms...`); + await new Promise(resolve => setTimeout(resolve, delay)); + } else if (isNetworkError) { + const errorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + throw new Error(errorMessage); + } else { + throw error; // Re-throw non-network errors immediately + } + } + } + } + + /** + * Fetch available tests + */ + async fetchTests() { + try { + return await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/tests`); + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to fetch tests'); + } + return await response.json(); + }); + } catch (error) { + console.error('Failed to fetch tests:', error); + throw error; + } + } + + /** + * Run tests with specified options + */ + async runTests(payload) { + try { + return await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/run`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to run tests'); + } + + return await response.json(); + }); + } catch (error) { + console.error('Failed to run tests:', error); + throw error; + } + } + + /** + * Stop all tests + */ + async stopAllTests() { + try { + await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/stop`, { + method: 'POST' + }); + + if (!response.ok) { + throw new Error('Failed to stop tests'); + } + }); + } catch (error) { + console.error('Failed to stop tests:', error); + throw error; + } + } + + /** + * Stop a single test run + */ + async stopSingleTest() { + try { + await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/stop-single-test`, { + method: 'POST' + }); + + if (!response.ok) { + throw new Error(`Failed to stop test run`); + } + }); + } catch (error) { + console.error(`Failed to stop test run:`, error); + throw error; + } + } + + /** + * Fetch coverage report + */ + async fetchCoverage() { + try { + return await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/coverage`); + if (!response.ok) { + let errorDetails = 'Unknown error'; + try { + const errorData = await response.json(); + errorDetails = errorData.error || JSON.stringify(errorData); + } catch (jsonError) { + errorDetails = response.statusText; + } + throw new Error(`Failed to fetch coverage report: ${errorDetails}`); + } + return await response.json(); + }); + } catch (error) { + console.error('Failed to fetch coverage report:', error); + throw error; + } + } + + /** + * Fetch file coverage + */ + async fetchFileCoverage(filePath) { + try { + return await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/file-coverage?path=${encodeURIComponent(filePath)}`); + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || 'Failed to fetch file coverage'); + } + return await response.json(); + }); + } catch (error) { + console.error('Failed to fetch file coverage:', error); + throw error; + } + } + + /** + * Fetch file content + */ + async fetchFileContent(filePath) { + try { + return await this.retry(async () => { + const response = await fetch(`${this.baseUrl}/api/file-content?path=${encodeURIComponent(filePath)}`); + if (!response.ok) { + const errorText = await response.text(); + try { + const errorData = JSON.parse(errorText); + throw new Error(errorData.error || 'Failed to fetch file content'); + } catch (e) { + throw new Error(errorText || 'Failed to fetch file content'); + } + } + return await response.text(); + }); + } catch (error) { + console.error('Failed to fetch file content:', error); + throw error; + } + } +} diff --git a/assets/js/components/CoverageReport.vue b/assets/js/components/CoverageReport.vue new file mode 100644 index 0000000..a4d9b87 --- /dev/null +++ b/assets/js/components/CoverageReport.vue @@ -0,0 +1,62 @@ + + + diff --git a/assets/js/components/FileCoverageDetail.vue b/assets/js/components/FileCoverageDetail.vue new file mode 100644 index 0000000..b0b9eaf --- /dev/null +++ b/assets/js/components/FileCoverageDetail.vue @@ -0,0 +1,58 @@ + + + diff --git a/assets/js/components/GroupedTestResults.vue b/assets/js/components/GroupedTestResults.vue new file mode 100644 index 0000000..d6b4905 --- /dev/null +++ b/assets/js/components/GroupedTestResults.vue @@ -0,0 +1,115 @@ + + + diff --git a/assets/js/components/Header.vue b/assets/js/components/Header.vue new file mode 100644 index 0000000..9c78f85 --- /dev/null +++ b/assets/js/components/Header.vue @@ -0,0 +1,21 @@ + + + diff --git a/assets/js/components/IndividualTestResults.vue b/assets/js/components/IndividualTestResults.vue new file mode 100644 index 0000000..e189122 --- /dev/null +++ b/assets/js/components/IndividualTestResults.vue @@ -0,0 +1,79 @@ + + + diff --git a/assets/js/components/MainContent.vue b/assets/js/components/MainContent.vue new file mode 100644 index 0000000..7fcaa7c --- /dev/null +++ b/assets/js/components/MainContent.vue @@ -0,0 +1,59 @@ + + + diff --git a/assets/js/components/ResultsSummary.vue b/assets/js/components/ResultsSummary.vue new file mode 100644 index 0000000..ccd0923 --- /dev/null +++ b/assets/js/components/ResultsSummary.vue @@ -0,0 +1,70 @@ + + + diff --git a/assets/js/components/TabNavigation.vue b/assets/js/components/TabNavigation.vue new file mode 100644 index 0000000..3c1caa1 --- /dev/null +++ b/assets/js/components/TabNavigation.vue @@ -0,0 +1,26 @@ + + + diff --git a/assets/js/components/TestDetails.vue b/assets/js/components/TestDetails.vue new file mode 100644 index 0000000..64be888 --- /dev/null +++ b/assets/js/components/TestDetails.vue @@ -0,0 +1,33 @@ + + + diff --git a/assets/js/components/TestSidebar.vue b/assets/js/components/TestSidebar.vue new file mode 100644 index 0000000..6bdcb29 --- /dev/null +++ b/assets/js/components/TestSidebar.vue @@ -0,0 +1,74 @@ + + + diff --git a/assets/js/components/header/ClearResultsButton.vue b/assets/js/components/header/ClearResultsButton.vue new file mode 100644 index 0000000..1b71c24 --- /dev/null +++ b/assets/js/components/header/ClearResultsButton.vue @@ -0,0 +1,25 @@ + + + diff --git a/assets/js/components/header/FilterPanel.vue b/assets/js/components/header/FilterPanel.vue new file mode 100644 index 0000000..0675978 --- /dev/null +++ b/assets/js/components/header/FilterPanel.vue @@ -0,0 +1,18 @@ + + + diff --git a/assets/js/components/header/HeaderTitle.vue b/assets/js/components/header/HeaderTitle.vue new file mode 100644 index 0000000..dc20368 --- /dev/null +++ b/assets/js/components/header/HeaderTitle.vue @@ -0,0 +1,3 @@ + diff --git a/assets/js/components/header/RunFailedButton.vue b/assets/js/components/header/RunFailedButton.vue new file mode 100644 index 0000000..dbdde70 --- /dev/null +++ b/assets/js/components/header/RunFailedButton.vue @@ -0,0 +1,26 @@ + + + diff --git a/assets/js/components/header/RunStopAllButton.vue b/assets/js/components/header/RunStopAllButton.vue new file mode 100644 index 0000000..3730ac6 --- /dev/null +++ b/assets/js/components/header/RunStopAllButton.vue @@ -0,0 +1,43 @@ + + + diff --git a/assets/js/components/header/filter/FilterPanelButton.vue b/assets/js/components/header/filter/FilterPanelButton.vue new file mode 100644 index 0000000..3e61b7b --- /dev/null +++ b/assets/js/components/header/filter/FilterPanelButton.vue @@ -0,0 +1,7 @@ + diff --git a/assets/js/components/header/filter/FilterPanelContent.vue b/assets/js/components/header/filter/FilterPanelContent.vue new file mode 100644 index 0000000..9d22979 --- /dev/null +++ b/assets/js/components/header/filter/FilterPanelContent.vue @@ -0,0 +1,119 @@ + + + diff --git a/assets/js/components/sidebar/TestItem.vue b/assets/js/components/sidebar/TestItem.vue new file mode 100644 index 0000000..cae9d64 --- /dev/null +++ b/assets/js/components/sidebar/TestItem.vue @@ -0,0 +1,33 @@ + + + diff --git a/assets/js/components/sidebar/TestList.vue b/assets/js/components/sidebar/TestList.vue new file mode 100644 index 0000000..07bb571 --- /dev/null +++ b/assets/js/components/sidebar/TestList.vue @@ -0,0 +1,21 @@ + + + diff --git a/assets/js/components/sidebar/TestSearchBar.vue b/assets/js/components/sidebar/TestSearchBar.vue new file mode 100644 index 0000000..631cb27 --- /dev/null +++ b/assets/js/components/sidebar/TestSearchBar.vue @@ -0,0 +1,46 @@ + + + diff --git a/assets/js/components/sidebar/TestSuite.vue b/assets/js/components/sidebar/TestSuite.vue new file mode 100644 index 0000000..62dc2d0 --- /dev/null +++ b/assets/js/components/sidebar/TestSuite.vue @@ -0,0 +1,39 @@ + + + diff --git a/assets/js/components/sidebar/TestSuiteHeader.vue b/assets/js/components/sidebar/TestSuiteHeader.vue new file mode 100644 index 0000000..dd9ac9f --- /dev/null +++ b/assets/js/components/sidebar/TestSuiteHeader.vue @@ -0,0 +1,69 @@ + + + diff --git a/assets/js/composables/useResizer.js b/assets/js/composables/useResizer.js new file mode 100644 index 0000000..55bf966 --- /dev/null +++ b/assets/js/composables/useResizer.js @@ -0,0 +1,40 @@ +import { onMounted } from 'vue'; + +export function useResizer(resizerId, sidebarId) { + onMounted(() => { + const resizer = document.getElementById(resizerId); + const sidebar = document.getElementById(sidebarId); + + if (!resizer || !sidebar) return; + + let isResizing = false; + + const startResizing = (e) => { + e.preventDefault(); + isResizing = true; + document.body.style.cursor = 'col-resize'; + document.body.style.userSelect = 'none'; + document.addEventListener('mousemove', resize); + document.addEventListener('mouseup', stopResizing); + }; + + const resize = (e) => { + if (isResizing) { + const sidebarWidth = e.clientX; + if (sidebarWidth > 200 && sidebarWidth < window.innerWidth - 200) { + sidebar.style.width = `${sidebarWidth}px`; + } + } + }; + + const stopResizing = () => { + isResizing = false; + document.body.style.cursor = ''; + document.body.style.userSelect = ''; + document.removeEventListener('mousemove', resize); + document.removeEventListener('mouseup', stopResizing); + }; + + resizer.addEventListener('mousedown', startResizing); + }); +} diff --git a/assets/js/composables/useTestDetails.js b/assets/js/composables/useTestDetails.js new file mode 100644 index 0000000..97db6d7 --- /dev/null +++ b/assets/js/composables/useTestDetails.js @@ -0,0 +1,17 @@ +import { useStore } from '../store.js'; + +export function useTestDetails() { + const store = useStore(); + + function toggleTestDetails(testcase) { + if (store.state.expandedTestId === testcase.id) { + store.setExpandedTest(null); + } else { + store.setExpandedTest(testcase.id); + } + } + + return { + toggleTestDetails, + }; +} diff --git a/assets/js/composables/useTestResults.js b/assets/js/composables/useTestResults.js new file mode 100644 index 0000000..fe696c3 --- /dev/null +++ b/assets/js/composables/useTestResults.js @@ -0,0 +1,286 @@ +import { computed } from 'vue'; +import { useStore } from '../store.js'; + +export function useTestResults(results) { + const store = useStore(); + + const getResults = computed(() => { + const run = store.state.testRun; + + if (!run) return null; + + const defaultSummary = { + numberOfTests: 0, + numberOfAssertions: 0, + duration: 0, + numberOfFailures: 0, + numberOfErrors: 0, + numberOfWarnings: 0, + numberOfSkipped: 0, + numberOfDeprecations: 0, + numberOfIncomplete: 0, + numberOfRisky: 0, + numberOfNotices: 0, + }; + const summary = { ...defaultSummary, ...(run.summary || {}) }; + + if (run && !run.summary) { + const realtimeSummary = calculateRealtimeSummary(run); + summary.numberOfTests = realtimeSummary.tests; + summary.numberOfAssertions = realtimeSummary.assertions; + summary.numberOfFailures = realtimeSummary.failures; + summary.numberOfErrors = realtimeSummary.errors; + summary.numberOfWarnings = realtimeSummary.warnings; + summary.numberOfSkipped = realtimeSummary.skipped; + summary.numberOfDeprecations = realtimeSummary.deprecations; + summary.numberOfIncomplete = realtimeSummary.incomplete; + summary.numberOfRisky = realtimeSummary.risky; + summary.notices = realtimeSummary.notices; + } + + const transformedSuites = []; + for (const suiteName in run.suites) { + const suiteData = run.suites[suiteName]; + const testcases = []; + for (const testId in suiteData.tests) { + const testData = suiteData.tests[testId]; + testcases.push({ + name: testData.name, + class: testData.class, + id: testData.id, + duration: testData.duration || 0, + assertions: testData.assertions || 0, + status: testData.status, + message: testData.message, + trace: testData.trace, + warnings: testData.warnings || [], + deprecations: testData.deprecations || [], + notices: testData.notices || [], + }); + } + transformedSuites.push({ + name: suiteData.name, + testcases, + }); + } + + return { + summary: { + tests: summary.numberOfTests, + assertions: summary.numberOfAssertions, + time: run.sumOfDurations > 0 ? run.sumOfDurations : summary.duration, + failures: summary.numberOfFailures, + errors: summary.numberOfErrors, + warnings: summary.numberOfWarnings, + skipped: summary.numberOfSkipped, + deprecations: summary.numberOfDeprecations, + incomplete: summary.numberOfIncomplete, + risky: summary.numberOfRisky, + notices: summary.notices, + }, + suites: transformedSuites, + }; + }); + + const calculateRealtimeSummary = (run) => { + const summary = { + tests: 0, + assertions: 0, + failures: 0, + errors: 0, + warnings: 0, + skipped: 0, + deprecations: 0, + incomplete: 0, + risky: 0, + notices: 0, + }; + + if (!run || !run.suites) return summary; + + for (const suiteName in run.suites) { + for (const testId in run.suites[suiteName].tests) { + const testData = run.suites[suiteName].tests[testId]; + summary.tests++; + summary.assertions += testData.assertions || 0; + summary.warnings += testData.warnings?.length || 0; + summary.deprecations += testData.deprecations?.length || 0; + summary.notices += testData.notices?.length || 0; + + switch (testData.status) { + case 'failed': summary.failures++; break; + case 'errored': summary.errors++; break; + case 'skipped': summary.skipped++; break; + case 'incomplete': summary.incomplete++; break; + case 'risky': summary.risky++; break; + } + } + } + return summary; + }; + + const getStatusCounts = computed(() => { + const resultsVal = results.value; + if (!resultsVal) { + return { passed: 0, failed: 0, error: 0, warnings: 0, skipped: 0, deprecations: 0, incomplete: 0, risky: 0, notices: 0 }; + } + const s = resultsVal.summary; + const counts = { + passed: 0, + failed: s.failures || 0, + error: s.errors || 0, + warnings: s.warnings || 0, + skipped: s.skipped || 0, + deprecations: s.deprecations || 0, + incomplete: s.incomplete || 0, + risky: s.risky || 0, + notices: s.notices || 0, + }; + const actualFailures = counts.failed + counts.error + counts.skipped + counts.incomplete + counts.risky; + counts.passed = (s.tests || 0) - actualFailures; + return counts; + }); + + const getIndividualResults = computed(() => { + const resultsVal = results.value; + if (!resultsVal) return []; + + let allTests = []; + resultsVal.suites.forEach(suite => { + allTests.push(...suite.testcases); + }); + + allTests = allTests.filter(t => { + if (t.status === 'skipped' && !store.state.options.displaySkipped) return false; + if (t.status === 'incomplete' && !store.state.options.displayIncomplete) return false; + if (t.status === 'risky' && !store.state.options.displayRisky) return false; + if (t.warnings?.length > 0 && !store.state.options.displayWarnings) { + if (t.status === 'passed') return false; + } + if (t.deprecations?.length > 0 && !store.state.options.displayDeprecations) { + if (t.status === 'passed') return false; + } + if (t.notices?.length > 0 && !store.state.options.displayNotices) { + if (t.status ==='passed') return false; + } + return true; + }); + + allTests.sort((a, b) => { + const durationA = a.duration || 0; + const durationB = b.duration || 0; + + if (store.state.sortBy === 'duration') { + return store.state.sortDirection === 'asc' ? durationA - durationB : durationB - durationA; + } + + const statusOrder = { 'errored': 1, 'failed': 2, 'incomplete': 3, 'risky': 4, 'skipped': 5, 'warning': 6, 'deprecation': 7, 'notice': 8, 'passed': 9 }; + const statusA = statusOrder[a.status || 'passed'] || 99; + const statusB = statusOrder[b.status || 'passed'] || 99; + if (statusA !== statusB) { + return statusA - statusB; + } + + return durationB - durationA; + }); + + return allTests; + }); + + const getGroupedResults = computed(() => { + const resultsVal = results.value; + if (!resultsVal) return []; + + const groups = {}; + resultsVal.suites.forEach(suite => { + suite.testcases.forEach(tc => { + if (!groups[tc.class]) { + groups[tc.class] = { + className: tc.class, + testcases: [], + passed: 0, + failed: 0, + errored: 0, + skipped: 0, + warning: 0, + deprecation: 0, + incomplete: 0, + risky: 0, + notice: 0, + hasIssues: false + }; + } + + const group = groups[tc.class]; + group.testcases.push(tc); + const status = tc.status || 'passed'; + if (group[status] !== undefined) { + group[status]++; + } + + if (tc.warnings?.length > 0) { + group.warning += tc.warnings.length; + } + if (tc.deprecations?.length > 0) { + group.deprecation += tc.deprecations.length; + } + if (tc.notices?.length > 0) { + group.notice += tc.notices.length; + } + + if (tc.warnings?.length > 0 || tc.deprecations?.length > 0 || tc.notices?.length > 0 || status !== 'passed') { + group.hasIssues = true; + } + }); + }); + + const statusOrder = { 'errored': 1, 'failed': 2, 'incomplete': 3, 'risky': 4, 'skipped': 5, 'warning': 6, 'deprecation': 7, 'notice': 8, 'passed': 9 }; + + Object.values(groups).forEach(group => { + let highestPriorityStatus = statusOrder['passed']; + group.testcases.forEach(tc => { + const tcStatus = tc.status || 'passed'; + const priority = statusOrder[tcStatus]; + if (priority && priority < highestPriorityStatus) { + highestPriorityStatus = priority; + } + }); + group.suiteStatus = highestPriorityStatus; + }); + + const sortedGroups = Object.values(groups).sort((a, b) => { + if (a.suiteStatus !== b.suiteStatus) { + return a.suiteStatus - b.suiteStatus; + } + return a.className.localeCompare(b.className); + }); + + sortedGroups.forEach(group => { + group.testcases.sort((a, b) => { + const durationA = a.duration || 0; + const durationB = b.duration || 0; + if (store.state.sortBy === 'duration') { + if (durationA !== durationB) { + return store.state.sortDirection === 'asc' ? durationA - durationB : durationB - durationA; + } + } + + const statusA = statusOrder[a.status || 'passed'] || 99; + const statusB = statusOrder[b.status || 'passed'] || 99; + if (statusA !== statusB) { + return statusA - statusB; + } + return durationB - durationA; + }); + }); + + return sortedGroups; + }); + + return { + getResults, + getStatusCounts, + getIndividualResults, + getGroupedResults, + }; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..4e209bf --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import '../css/styles.css'; + +createApp(App).mount('#app'); diff --git a/assets/js/store.js b/assets/js/store.js new file mode 100644 index 0000000..0ee08cd --- /dev/null +++ b/assets/js/store.js @@ -0,0 +1,599 @@ +import { reactive } from 'vue'; +import { parseTestId, updateFavicon } from './utils.js'; +import { ApiClient } from './api.js'; + +const STORAGE_KEY = 'phpunit-hub-settings'; + +const defaultOptions = { + displayWarnings: true, + displayDeprecations: true, + displaySkipped: true, + displayIncomplete: true, + displayRisky: true, + displayNotices: true, + stopOnDefect: false, + stopOnError: false, + stopOnFailure: false, + stopOnWarning: false, + stopOnRisky: false, + displayMode: 'default', // 'default' or 'individual' +}; + +const state = reactive({ + // Test suites + testSuites: [], + availableSuites: [], + availableGroups: [], + + // UI state + isLoading: false, + isStarting: false, + expandedSuites: new Set(), + expandedTestcaseGroups: new Set(), + expandedTestId: null, + showFilterPanel: false, + activeTab: 'results', + sortBy: 'default', // 'default' or 'duration' + sortDirection: 'desc', // 'asc' or 'desc' + + // Filter options + selectedSuites: [], + selectedGroups: [], + options: { ...defaultOptions }, + coverage: false, + + // Test run + testRun: null, + isRunning: false, + isStopping: false, + + // Coverage + coverageReport: null, + isCoverageLoading: false, + fileCoverage: null, + coverageDriverMissing: false, +}); + +// --- Private Store Functions --- + +async function _runTests(runOptions = {}) { + if (state.isStarting) { + return; + } + + state.isStarting = true; + state.activeTab = 'results'; + + const api = new ApiClient(''); + const { displayMode, ...phpunitOptions } = state.options; + + const payload = { + filters: runOptions.filters || [], + groups: state.selectedGroups, + suites: state.selectedSuites, + options: { ...phpunitOptions, colors: true }, + coverage: !!state.coverage, + contextId: runOptions.contextId || 'global', + }; + + try { + await api.runTests(payload); + } catch (error) { + console.error('Failed to run tests:', error); + updateFavicon('failure'); + state.isStarting = false; + } +} + +// --- Public Store Functions / Actions --- + +function loadState() { + const savedState = localStorage.getItem(STORAGE_KEY); + if (savedState) { + try { + const parsedState = JSON.parse(savedState); + if (parsedState.options) { + const { resultUpdateMode, ...restOptions } = parsedState.options; + state.options = { ...state.options, ...restOptions }; + } + if (Array.isArray(parsedState.selectedSuites)) { + state.selectedSuites = parsedState.selectedSuites; + } + if (Array.isArray(parsedState.selectedGroups)) { + state.selectedGroups = parsedState.selectedGroups; + } + if(parsedState.coverage) { + state.coverage = parsedState.coverage; + } + } catch (e) { + console.error('Failed to load state from localStorage', e); + localStorage.removeItem(STORAGE_KEY); + } + } +} + +function saveState() { + const stateToSave = { + options: state.options, + selectedSuites: state.selectedSuites, + selectedGroups: state.selectedGroups, + coverage: state.coverage, + }; + localStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave)); +} + +function runTests(runOptions = {}) { + _runTests(runOptions); +} + +function runAllTests() { + runTests({ contextId: 'global' }); +} + +function runFailedTests() { + const failedTestIds = getFailedTestIds(); + if (failedTestIds.length === 0) { + console.log('No failed tests to run.'); + return; + } + runTests({ filters: failedTestIds, contextId: 'failed' }); +} + +function runSingleTest(testId) { + runTests({ filters: [testId], contextId: testId }); +} + +function runSuiteTests(suiteId) { + runTests({ filters: [suiteId], contextId: suiteId }); +} + +async function stopAllTests() { + const api = new ApiClient(''); + try { + markStopPending(); + await api.stopAllTests(); + } catch (error) { + console.error('Failed to stop tests:', error); + clearStopPending(); + } +} + +async function stopSingleTest() { + const api = new ApiClient(''); + try { + markStopPending(); + await api.stopSingleTest(); + } catch (error) { + console.error(`Failed to stop test run:`, error); + clearStopPending(); + } +} + +function setSortBy(sortBy) { + if (state.sortBy === sortBy) { + if (state.sortDirection === 'desc') { + state.sortDirection = 'asc'; + } else { + state.sortBy = 'default'; + state.sortDirection = 'desc'; + } + } else { + state.sortBy = sortBy; + state.sortDirection = 'desc'; + } +} + +function setDisplayMode(mode) { + state.options.displayMode = mode; +} + +function setStarting(isStarting) { + state.isStarting = isStarting; +} + +function initializeTestRun(contextId) { + state.isStarting = false; + state.isRunning = true; + state.isStopping = false; + + state.testRun = { + status: 'running', + contextId: contextId, + suites: {}, + summary: null, + failedTestIds: new Set(), + executionEnded: false, + sumOfDurations: 0, + }; + state.expandedTestId = null; + state.expandedTestcaseGroups = new Set(); + resetSidebarTestStatuses(); + + state.testSuites.forEach(suite => { + if (suite.id === contextId) { + suite.isRunning = true; + } + }); + + state.activeTab = 'results'; +} + +function handleTestEvent(eventData) { + const run = state.testRun; + + if (!run) { + console.warn(`Received event for unknown run`); + return; + } + + switch (eventData.event) { + case 'suite.started': + handleSuiteStarted(run, eventData); + break; + case 'test.prepared': + handleTestPrepared(run, eventData); + break; + case 'test.warning': + case 'test.deprecation': + handleTestWarningOrDeprecation(run, eventData); + break; + case 'test.notice': + handleTestNotice(run, eventData); + break; + case 'test.passed': + case 'test.failed': + case 'test.errored': + case 'test.skipped': + case 'test.incomplete': + case 'test.risky': + handleTestCompleted(run, eventData); + break; + case 'test.finished': + handleTestFinished(run, eventData); + break; + } +} + +function handleSuiteStarted(run, eventData) { + run.suites[eventData.data.name] = { + name: eventData.data.name, + count: eventData.data.count, + tests: {}, + passed: 0, + failed: 0, + errored: 0, + skipped: 0, + incomplete: 0, + warning: 0, + deprecation: 0, + notice: 0, + risky: 0, + hasIssues: false, + }; +} + +function handleTestPrepared(run, eventData) { + const { suiteName, testName } = parseTestId(eventData.data.testId); + + if (!run.suites[suiteName]) { + run.suites[suiteName] = { + name: suiteName, + count: 0, + tests: {}, + passed: 0, + failed: 0, + errored: 0, + skipped: 0, + incomplete: 0, + warning: 0, + deprecation: 0, + notice: 0, + risky: 0, + hasIssues: false, + }; + } + + run.suites[suiteName].tests[eventData.data.testId] = { + id: eventData.data.testId, + name: testName, + class: suiteName, + status: 'running', + duration: null, + assertions: 0, + message: null, + trace: null, + warnings: [], + deprecations: [], + notices: [], + }; + + updateSidebarTestStatus(suiteName, eventData.data.testId, 'running'); +} + +function handleTestWarningOrDeprecation(run, eventData) { + const { suiteName } = parseTestId(eventData.data.testId); + const testId = eventData.data.testId; + + if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { + const test = run.suites[suiteName].tests[testId]; + const suite = run.suites[suiteName]; + + if (eventData.event === 'test.warning') { + test.warnings.push(eventData.data.message || 'Some warning triggered'); + suite.warning++; + } else if (eventData.event === 'test.deprecation') { + test.deprecations.push(eventData.data.message || 'Some deprecation triggered'); + suite.deprecation++; + } + + suite.hasIssues = true; + } +} + +function handleTestNotice(run, eventData) { + const { suiteName } = parseTestId(eventData.data.testId); + const testId = eventData.data.testId; + + if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { + const test = run.suites[suiteName].tests[testId]; + const suite = run.suites[suiteName]; + + test.notices.push(eventData.data.message || 'Some notice triggered'); + suite.notice++; + suite.hasIssues = true; + } +} + +function handleTestCompleted(run, eventData) { + const { suiteName, testName } = parseTestId(eventData.data.testId); + const testId = eventData.data.testId; + + if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { + const test = run.suites[suiteName].tests[testId]; + const status = eventData.event.replace('test.', ''); + + test.status = status; + test.message = eventData.data.message || null; + test.trace = eventData.data.trace || null; + + const suite = run.suites[suiteName]; + if (suite[status] !== undefined) { + suite[status]++; + } + + if (status === 'failed' || status === 'errored') { + run.failedTestIds.add(testId); + suite.hasIssues = true; + } else if (status === 'passed') { + run.failedTestIds.delete(testId); + } else if (status !== 'passed') { + suite.hasIssues = true; + } + + updateSidebarTestStatus(suiteName, testId, status, test.duration); + } +} + +function handleTestFinished(run, eventData) { + const { suiteName } = parseTestId(eventData.data.testId); + const testId = eventData.data.testId; + + if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { + const test = run.suites[suiteName].tests[testId]; + test.duration = eventData.data.duration; + test.assertions = eventData.data.assertions; + run.sumOfDurations += test.duration; + + if (test.status) { + updateSidebarTestStatus(suiteName, testId, test.status, test.duration); + } + } +} + +function handleExecutionEnded(eventData) { + const run = state.testRun; + if (run) { + run.summary = eventData.data.summary; + run.executionEnded = true; + updateFavicon(run.summary.status === 'passed' ? 'success' : 'failure'); + } +} + +function finishTestRun() { + const run = state.testRun; + if (run) { + run.status = 'finished'; + } + state.isRunning = false; + state.isStopping = false; + state.isStarting = false; + updateSidebarAfterRun(); +} + +function updateSidebarTestStatus(suiteName, testId, status, time = null) { + state.testSuites.forEach(suite => { + if (suite.id === suiteName) { + suite.methods?.forEach(method => { + if (method.id === testId) { + method.status = status; + if (time !== null) method.duration = time; + } + }); + } + }); +} + +function resetSidebarTestStatuses() { + state.testSuites.forEach(suite => { + suite.isRunning = false; + suite.methods?.forEach(method => { + method.status = null; + method.duration = null; + }); + }); +} + +function stopTestRun() { + const run = state.testRun; + if (run) { + run.status = 'stopped'; + } + state.isRunning = false; + state.isStopping = false; + state.isStarting = false; + updateSidebarAfterRun(); +} + +function updateSidebarAfterRun() { + state.testSuites.forEach(suite => { + suite.isRunning = false; + }); +} + +function getTestRun() { + return state.testRun; +} + +function isTestRunning() { + return state.isRunning; +} + +function clearRunningTests() { + state.isRunning = false; + state.isStopping = false; +} + +function markStopPending() { + state.isStopping = true; +} + +function clearStopPending() { + state.isStopping = false; +} + +function toggleSuiteExpansion(suiteId) { + if (state.expandedSuites.has(suiteId)) { + state.expandedSuites.delete(suiteId); + } else { + state.expandedSuites.add(suiteId); + } +} + +function toggleTestcaseGroupExpansion(className) { + if (state.expandedTestcaseGroups.has(className)) { + state.expandedTestcaseGroups.delete(className); + } else { + state.expandedTestcaseGroups.add(className); + } +} + +function setExpandedTest(testId) { + state.expandedTestId = testId; +} + +function toggleFilterPanel() { + state.showFilterPanel = !state.showFilterPanel; +} + +function getFailedTestIds() { + const run = state.testRun; + return run ? Array.from(run.failedTestIds) : []; +} + +function hasFailedTests() { + const run = state.testRun; + return run ? run.failedTestIds.size > 0 : false; +} + +function clearFilters() { + state.selectedSuites = []; + state.selectedGroups = []; + state.coverage = false; + state.options = { ...defaultOptions }; +} + +function setActiveTab(tab) { + state.activeTab = tab; +} + +function setCoverageReport(report) { + state.coverageReport = report; +} + +function setCoverageLoading(isLoading) { + state.isCoverageLoading = isLoading; +} + +function setFileCoverage(coverage) { + state.fileCoverage = coverage; +} + +async function fetchCoverageReport() { + const api = new ApiClient(''); + try { + const report = await api.fetchCoverage(); + setCoverageReport(report); + } catch (error) { + console.error('Failed to fetch coverage report:', error); + } finally { + setCoverageLoading(false); + } +} + +loadState(); + +export function useStore() { + return { + state, + saveState, + runTests, + runAllTests, + runFailedTests, + runSingleTest, + runSuiteTests, + stopAllTests, + stopSingleTest, + setSortBy, + setDisplayMode, + setStarting, + initializeTestRun, + handleTestEvent, + handleSuiteStarted, + handleTestPrepared, + handleTestWarningOrDeprecation, + handleTestNotice, + handleTestCompleted, + handleTestFinished, + handleExecutionEnded, + finishTestRun, + stopTestRun, + getTestRun, + isTestRunning, + clearRunningTests, + markStopPending, + clearStopPending, + toggleSuiteExpansion, + toggleTestcaseGroupExpansion, + setExpandedTest, + toggleFilterPanel, + getFailedTestIds, + hasFailedTests, + clearAllResults() { + this.state.testRun = null; + this.state.expandedTestId = null; + this.state.expandedTestcaseGroups = new Set(); + this.state.coverageReport = null; + this.state.fileCoverage = null; + this.resetSidebarTestStatuses(); + updateFavicon('neutral'); + }, + clearFilters, + setActiveTab, + setCoverageReport, + setCoverageLoading, + setFileCoverage, + fetchCoverageReport, + resetSidebarTestStatuses, + updateSidebarAfterRun, + }; +} diff --git a/public/js/tests/.gitkeep b/assets/js/tests/.gitkeep similarity index 100% rename from public/js/tests/.gitkeep rename to assets/js/tests/.gitkeep diff --git a/assets/js/tests/api.test.js b/assets/js/tests/api.test.js new file mode 100644 index 0000000..9a489db --- /dev/null +++ b/assets/js/tests/api.test.js @@ -0,0 +1,525 @@ +// Mock the global fetch function +import { vi } from 'vitest'; // Import vi from vitest + +const mockFetch = vi.fn(); +global.fetch = mockFetch; + +import { ApiClient } from '../api.js'; + +describe('ApiClient', () => { + let api; + const baseUrl = 'http://localhost:8000'; + let consoleErrorSpy; + let consoleWarnSpy; + + beforeEach(() => { + api = new ApiClient(baseUrl); + mockFetch.mockClear(); + consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); // Suppress console.error during tests + consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); // Suppress console.warn during tests + }); + + afterEach(() => { + vi.restoreAllMocks(); // Restore console.error and console.warn + }); + + describe('fetchTests', () => { + test('should fetch tests successfully', async () => { + const mockResponseData = { suites: [], availableSuites: [], availableGroups: [] }; + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchTests(); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/tests`); + expect(result).toEqual(mockResponseData); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + // Mock 4 rejections (initial attempt + 3 retries) + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.fetchTests()).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); // 1 initial + 3 retries + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); // 3 warnings for 3 retries + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); // 1 error for the final failure + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + const mockResponseData = { suites: [], availableSuites: [], availableGroups: [] }; + + // Mock 2 rejections, then a success + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchTests(); + + expect(mockFetch).toHaveBeenCalledTimes(3); // 1 initial + 2 retries + expect(result).toEqual(mockResponseData); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response (no retry for non-network errors)', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({ error: 'Server error' }), + }); + + await expect(api.fetchTests()).rejects.toThrow('Server error'); + expect(mockFetch).toHaveBeenCalledTimes(1); // No retry for non-network errors + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch tests:', expect.any(Error)); + }); + }); + + describe('runTests', () => { + const payload = { filters: ['test1'], groups: [], suites: [], options: {} }; + + test('should run tests successfully', async () => { + const mockResponseData = { status: 'running' }; + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.runTests(payload); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/run`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + expect(result).toEqual(mockResponseData); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.runTests(payload)).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to run tests:', expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + const mockResponseData = { status: 'running' }; + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.runTests(payload); + + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(result).toEqual(mockResponseData); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response (no retry for non-network errors)', async () => { + const errorData = { error: 'Invalid payload' }; + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve(errorData), + }); + + await expect(api.runTests(payload)).rejects.toThrow('Invalid payload'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to run tests:', expect.any(Error)); + }); + + test('should throw a generic error if API returns non-ok response without specific error message (no retry for non-network errors)', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({}), + }); + + await expect(api.runTests(payload)).rejects.toThrow('Failed to run tests'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to run tests:', expect.any(Error)); + }); + }); + + describe('stopAllTests', () => { + test('should stop all tests successfully', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({}), + }); + + await expect(api.stopAllTests()).resolves.toBeUndefined(); + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/stop`, { + method: 'POST', + }); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.stopAllTests()).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to stop tests:', expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({}), + }); + + await expect(api.stopAllTests()).resolves.toBeUndefined(); + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response (no retry for non-network errors)', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({}), + }); + + await expect(api.stopAllTests()).rejects.toThrow('Failed to stop tests'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to stop tests:', expect.any(Error)); + }); + }); + + describe('stopSingleTest', () => { + test('should stop a single test successfully', async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({}), + }); + + await expect(api.stopSingleTest()).resolves.toBeUndefined(); + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/stop-single-test`, { + method: 'POST', + }); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.stopSingleTest()).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith(`Failed to stop test run:`, expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve({}), + }); + + await expect(api.stopSingleTest()).resolves.toBeUndefined(); + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response (no retry for non-network errors)', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({}), + }); + + await expect(api.stopSingleTest()).rejects.toThrow(`Failed to stop test run`); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith(`Failed to stop test run:`, expect.any(Error)); + }); + }); + + describe('fetchCoverage', () => { + test('should fetch coverage successfully', async () => { + const mockResponseData = { coverage: 'data' }; + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchCoverage(); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/coverage`); + expect(result).toEqual(mockResponseData); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.fetchCoverage()).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch coverage report:', expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + const mockResponseData = { coverage: 'data' }; + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchCoverage(); + + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(result).toEqual(mockResponseData); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({ error: 'Coverage not found' }), + }); + + await expect(api.fetchCoverage()).rejects.toThrow('Failed to fetch coverage report: Coverage not found'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch coverage report:', expect.any(Error)); + }); + + test('should throw an error if API returns non-ok response without specific error message', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({}), + }); + + await expect(api.fetchCoverage()).rejects.toThrow('Failed to fetch coverage report: {}'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch coverage report:', expect.any(Error)); + }); + + test('should throw an error if API returns non-ok response with statusText but no json', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.reject(new Error('Invalid JSON')), + statusText: 'Not Found', + }); + + await expect(api.fetchCoverage()).rejects.toThrow('Failed to fetch coverage report: Not Found'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch coverage report:', expect.any(Error)); + }); + }); + + describe('fetchFileCoverage', () => { + const filePath = '/path/to/file.php'; + + test('should fetch file coverage successfully', async () => { + const mockResponseData = { fileCoverage: 'data' }; + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchFileCoverage(filePath); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/file-coverage?path=${encodeURIComponent(filePath)}`); + expect(result).toEqual(mockResponseData); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.fetchFileCoverage(filePath)).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file coverage:', expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + const mockResponseData = { fileCoverage: 'data' }; + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchFileCoverage(filePath); + + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(result).toEqual(mockResponseData); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({ error: 'File coverage not found' }), + }); + + await expect(api.fetchFileCoverage(filePath)).rejects.toThrow('File coverage not found'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file coverage:', expect.any(Error)); + }); + + test('should throw a generic error if API returns non-ok response without specific error message', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + json: () => Promise.resolve({}), + }); + + await expect(api.fetchFileCoverage(filePath)).rejects.toThrow('Failed to fetch file coverage'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file coverage:', expect.any(Error)); + }); + }); + + describe('fetchFileContent', () => { + const filePath = '/path/to/file.php'; + + test('should fetch file content successfully', async () => { + const mockResponseData = 'file content'; + mockFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchFileContent(filePath); + + expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/file-content?path=${encodeURIComponent(filePath)}`); + expect(result).toEqual(mockResponseData); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + }); + + test('should throw a specific network error after multiple retries if fetch fails persistently', async () => { + const networkError = new TypeError('Failed to fetch'); + mockFetch.mockRejectedValue(networkError); + + const expectedErrorMessage = 'Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.'; + + await expect(api.fetchFileContent(filePath)).rejects.toThrow(expectedErrorMessage); + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(consoleWarnSpy).toHaveBeenCalledTimes(3); + expect(consoleErrorSpy).toHaveBeenCalledTimes(1); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file content:', expect.any(Error)); + expect(consoleErrorSpy.mock.calls[0][1].message).toBe(expectedErrorMessage); + }); + + test('should succeed after retrying if fetch fails initially', async () => { + const networkError = new TypeError('Failed to fetch'); + const mockResponseData = 'file content'; + + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockRejectedValueOnce(networkError); + mockFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockResponseData), + }); + + const result = await api.fetchFileContent(filePath); + + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(result).toEqual(mockResponseData); + expect(consoleWarnSpy).toHaveBeenCalledTimes(2); + expect(consoleErrorSpy).not.toHaveBeenCalled(); + }); + + test('should throw an error if API returns non-ok response', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + text: () => Promise.resolve('File not found'), + }); + + await expect(api.fetchFileContent(filePath)).rejects.toThrow('File not found'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file content:', expect.any(Error)); + }); + + test('should throw a generic error if API returns non-ok response without specific error message', async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + text: () => Promise.resolve(''), + }); + + await expect(api.fetchFileContent(filePath)).rejects.toThrow('Failed to fetch file content'); + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(consoleWarnSpy).not.toHaveBeenCalled(); + expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch file content:', expect.any(Error)); + }); + }); +}); diff --git a/public/js/tests/mocks/vue.js b/assets/js/tests/mocks/vue.js similarity index 100% rename from public/js/tests/mocks/vue.js rename to assets/js/tests/mocks/vue.js diff --git a/public/js/tests/store.test.js b/assets/js/tests/store.test.js similarity index 56% rename from public/js/tests/store.test.js rename to assets/js/tests/store.test.js index 0dae40b..ba1fb72 100644 --- a/public/js/tests/store.test.js +++ b/assets/js/tests/store.test.js @@ -1,44 +1,47 @@ // Mock Vue's reactive function -jest.mock('https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.prod.js', () => ({ - reactive: (obj) => obj, // Simply return the object for testing purposes +import { vi } from 'vitest'; + +vi.mock('vue', () => ({ + reactive: (obj) => obj, })); // Mock parseTestId from utils.js -const { parseTestId } = jest.requireActual('../utils.js'); // Use requireActual to get the real module, then mock specific functions -jest.mock('../utils.js', () => ({ - ...jest.requireActual('../utils.js'), // Import and retain default behavior - parseTestId: jest.fn((testId) => { // Mock only parseTestId - const separatorIndex = testId.indexOf('::'); - if (separatorIndex === -1) { +vi.mock('../utils.js', async () => { + const actualUtils = await vi.importActual('../utils.js'); + return { + ...actualUtils, + parseTestId: vi.fn((testId) => { + const separatorIndex = testId.indexOf('::'); + if (separatorIndex === -1) { + return { + suiteName: testId, + testName: undefined, + fullId: testId + }; + } return { - suiteName: testId, - testName: undefined, + suiteName: testId.substring(0, separatorIndex), + testName: testId.substring(separatorIndex + 2), fullId: testId }; - } - return { - suiteName: testId.substring(0, separatorIndex), - testName: testId.substring(separatorIndex + 2), - fullId: testId - }; - }), - updateFavicon: jest.fn(), -})); + }), + updateFavicon: vi.fn(), + }; +}); -import { Store } from '../store.js'; +import * as storeModule from '../store.js'; describe('Store', () => { let store; beforeEach(() => { - store = new Store(); - localStorage.clear(); - jest.clearAllMocks(); - jest.spyOn(console, 'warn').mockImplementation(() => {}); // Suppress console.warn + vi.clearAllMocks(); + store = storeModule.useStore(); + vi.spyOn(console, 'warn').mockImplementation(() => {}); }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); test('should initialize with correct default state', () => { @@ -50,10 +53,6 @@ describe('Store', () => { isLoading: false, isStarting: false, fileCoverage: null, - searchQuery: '', - coverage: false, - isCoverageLoading: false, - coverageReport: null, expandedSuites: new Set(), expandedTestcaseGroups: new Set(), expandedTestId: null, @@ -63,11 +62,26 @@ describe('Store', () => { sortDirection: 'desc', selectedSuites: [], selectedGroups: [], - options: Store.defaultOptions, - runningTestIds: {}, - stopPending: {}, - realtimeTestRuns: {}, - lastCompletedRunId: null, + coverage: false, + isCoverageLoading: false, + coverageReport: null, + testRun: null, + isRunning: false, + isStopping: false, + options: { + displayDeprecations: true, + displayIncomplete: true, + displayMode: "default", + displayNotices: true, + displayRisky: true, + displaySkipped: true, + displayWarnings: true, + stopOnDefect: false, + stopOnError: false, + stopOnFailure: false, + stopOnRisky: false, + stopOnWarning: false, + }, }); }); @@ -82,16 +96,17 @@ describe('Store', () => { }); describe('initializeTestRun', () => { - test('should set up a new test run and reset isStarting', () => { - const runId = 'run123'; + test('should set up a new test run and reset isStarting for global context', () => { const contextId = 'global'; store.state.isStarting = true; - store.state.stopPending[runId] = true; // Simulate a pending stop + store.state.isStopping = true; - store.initializeTestRun(runId, contextId); + store.initializeTestRun(contextId); expect(store.state.isStarting).toBe(false); - expect(store.state.realtimeTestRuns[runId]).toEqual({ + expect(store.state.isRunning).toBe(true); + expect(store.state.isStopping).toBe(false); + expect(store.state.testRun).toEqual({ status: 'running', contextId: contextId, executionEnded: false, @@ -100,100 +115,129 @@ describe('Store', () => { sumOfDurations: 0, failedTestIds: new Set(), }); - expect(store.state.runningTestIds[runId]).toBe(true); - expect(store.state.stopPending[runId]).toBeUndefined(); expect(store.state.activeTab).toBe('results'); }); test('should reset sidebar and expanded state for failed context', () => { - const runId = 'run123'; store.state.expandedTestId = 'someTest'; store.state.expandedTestcaseGroups.add('someGroup'); store.state.testSuites = [{ id: 'SuiteA', methods: [{ id: 'test1', status: 'passed' }] }]; - const resetSidebarSpy = jest.spyOn(store, 'resetSidebarTestStatuses'); + store.initializeTestRun('failed'); - store.initializeTestRun(runId, 'failed'); expect(store.state.expandedTestId).toBeNull(); expect(store.state.expandedTestcaseGroups.size).toBe(0); - expect(resetSidebarSpy).toHaveBeenCalled(); - }); - - test('should reset results for global context in reset mode', () => { - const runId = 'run123'; - store.state.options.resultUpdateMode = 'reset'; - store.state.realtimeTestRuns['oldRun'] = { status: 'finished' }; - store.state.lastCompletedRunId = 'oldRun'; - - store.initializeTestRun(runId, 'global'); - expect(store.state.realtimeTestRuns['oldRun']).toBeUndefined(); - expect(store.state.lastCompletedRunId).toBeNull(); + // Verify the effect of resetSidebarTestStatuses + expect(store.state.testSuites[0].methods[0].status).toBeNull(); }); }); describe('handleTestEvent', () => { let run; - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; - jest.spyOn(store, 'handleSuiteStarted'); - jest.spyOn(store, 'handleTestPrepared'); - jest.spyOn(store, 'handleTestWarningOrDeprecation'); - jest.spyOn(store, 'handleTestCompleted'); - jest.spyOn(store, 'handleTestFinished'); - jest.spyOn(store, 'handleExecutionEnded'); + store.initializeTestRun('global'); + run = store.state.testRun; }); test('should call handleSuiteStarted for suite.started event', () => { const eventData = { event: 'suite.started', data: { name: 'SuiteA', count: 1 } }; - store.handleTestEvent(runId, eventData); - expect(store.handleSuiteStarted).toHaveBeenCalledWith(run, eventData); + store.handleTestEvent(eventData); + + // Verify the effect instead of spying + expect(run.suites['SuiteA']).toBeDefined(); + expect(run.suites['SuiteA'].name).toBe('SuiteA'); }); test('should call handleTestPrepared for test.prepared event', () => { + run.suites['SuiteA'] = { name: 'SuiteA', tests: {} }; const eventData = { event: 'test.prepared', data: { testId: 'SuiteA::testMethod' } }; - store.handleTestEvent(runId, eventData); - expect(store.handleTestPrepared).toHaveBeenCalledWith(run, eventData, runId); + store.handleTestEvent(eventData); + + // Verify the effect + expect(run.suites['SuiteA'].tests['SuiteA::testMethod']).toBeDefined(); + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].status).toBe('running'); }); test('should call handleTestWarningOrDeprecation for test.warning event', () => { - const eventData = { event: 'test.warning', data: { testId: 'SuiteA::testMethod' } }; - store.handleTestEvent(runId, eventData); - expect(store.handleTestWarningOrDeprecation).toHaveBeenCalledWith(run, eventData); + run.suites['SuiteA'] = { + name: 'SuiteA', + tests: { + 'SuiteA::testMethod': { id: 'SuiteA::testMethod', warnings: [], deprecations: [] } + }, + warning: 0, + hasIssues: false, + }; + const eventData = { event: 'test.warning', data: { testId: 'SuiteA::testMethod', message: 'Warning!' } }; + store.handleTestEvent(eventData); + + // Verify the effect + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].warnings.length).toBe(1); + expect(run.suites['SuiteA'].warning).toBe(1); + }); + + test('should call handleTestNotice for test.notice event', () => { + run.suites['SuiteA'] = { + name: 'SuiteA', + tests: { + 'SuiteA::testMethod': { id: 'SuiteA::testMethod', notices: [] } + }, + notice: 0, + hasIssues: false, + }; + const eventData = { event: 'test.notice', data: { testId: 'SuiteA::testMethod', message: 'Notice!' } }; + store.handleTestEvent(eventData); + + // Verify the effect + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].notices.length).toBe(1); + expect(run.suites['SuiteA'].notice).toBe(1); }); test('should call handleTestCompleted for test.passed event', () => { + run.suites['SuiteA'] = { + name: 'SuiteA', + tests: { + 'SuiteA::testMethod': { id: 'SuiteA::testMethod', status: 'running' } + }, + passed: 0, + hasIssues: false, + }; const eventData = { event: 'test.passed', data: { testId: 'SuiteA::testMethod' } }; - store.handleTestEvent(runId, eventData); - expect(store.handleTestCompleted).toHaveBeenCalledWith(run, eventData, runId); + store.handleTestEvent(eventData); + + // Verify the effect + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].status).toBe('passed'); + expect(run.suites['SuiteA'].passed).toBe(1); }); test('should call handleTestFinished for test.finished event', () => { - const eventData = { event: 'test.finished', data: { testId: 'SuiteA::testMethod', duration: 0.1 } }; - store.handleTestEvent(runId, eventData); - expect(store.handleTestFinished).toHaveBeenCalledWith(run, eventData, 'run123'); - }); + run.suites['SuiteA'] = { + name: 'SuiteA', + tests: { + 'SuiteA::testMethod': { id: 'SuiteA::testMethod', duration: null, status: 'passed' } + } + }; + const eventData = { event: 'test.finished', data: { testId: 'SuiteA::testMethod', duration: 0.1, assertions: 5 } }; + store.handleTestEvent(eventData); - test('should call handleExecutionEnded for execution.ended event', () => { - const eventData = { event: 'execution.ended', data: { summary: {} } }; - store.handleTestEvent(runId, eventData); - expect(store.handleExecutionEnded).toHaveBeenCalledWith(run, eventData, runId); + // Verify the effect + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].duration).toBe(0.1); + expect(run.suites['SuiteA'].tests['SuiteA::testMethod'].assertions).toBe(5); }); - test('should warn for unknown runId', () => { + test('should warn for unknown run', () => { + store.state.testRun = null; // Simulate no active run const eventData = { event: 'test.passed', data: { testId: 'SuiteA::testMethod' } }; - store.handleTestEvent('unknownRun', eventData); - expect(console.warn).toHaveBeenCalledWith('Received event for unknown runId: unknownRun'); + store.handleTestEvent(eventData); + expect(console.warn).toHaveBeenCalledWith('Received event for unknown run'); }); }); describe('handleSuiteStarted', () => { let run; beforeEach(() => { - store.initializeTestRun('run123', 'global'); - run = store.state.realtimeTestRuns['run123']; + store.initializeTestRun('global'); + run = store.state.testRun; }); test('should add a new suite to the run', () => { @@ -212,17 +256,16 @@ describe('Store', () => { describe('handleTestPrepared', () => { let run; - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; + store.initializeTestRun('global'); + run = store.state.testRun; store.state.testSuites = [{ id: 'SuiteA', methods: [{ id: 'SuiteA::testMethod', status: null }] }]; }); test('should add a new test to an existing suite', () => { run.suites['SuiteA'] = { name: 'SuiteA', tests: {} }; const eventData = { event: 'test.prepared', data: { testId: 'SuiteA::testMethod' } }; - store.handleTestPrepared(run, eventData, runId); + store.handleTestPrepared(run, eventData); expect(run.suites['SuiteA'].tests['SuiteA::testMethod']).toEqual({ id: 'SuiteA::testMethod', @@ -234,12 +277,11 @@ describe('Store', () => { warnings: [], deprecations: [], notices: [] }); expect(store.state.testSuites[0].methods[0].status).toBe('running'); - expect(store.state.testSuites[0].methods[0].runId).toBe(runId); }); test('should create suite if it does not exist and add test', () => { const eventData = { event: 'test.prepared', data: { testId: 'SuiteB::testMethod' } }; - store.handleTestPrepared(run, eventData, runId); + store.handleTestPrepared(run, eventData); expect(run.suites['SuiteB']).toBeDefined(); expect(run.suites['SuiteB'].tests['SuiteB::testMethod']).toBeDefined(); @@ -249,10 +291,9 @@ describe('Store', () => { describe('handleTestWarningOrDeprecation', () => { let run; const testId = 'SuiteA::testMethod'; - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; + store.initializeTestRun('global'); + run = store.state.testRun; run.suites['SuiteA'] = { name: 'SuiteA', tests: { @@ -283,14 +324,39 @@ describe('Store', () => { }); }); + describe('handleTestNotice', () => { + let run; + const testId = 'SuiteA::testMethod'; + beforeEach(() => { + store.initializeTestRun('global'); + run = store.state.testRun; + run.suites['SuiteA'] = { + name: 'SuiteA', + tests: { + [testId]: { id: testId, notices: [] } + }, + notice: 0, + hasIssues: false, + }; + }); + + test('should add a notice to the test and update suite counts', () => { + const eventData = { event: 'test.notice', data: { testId: testId, message: 'Some notice' } }; + store.handleTestNotice(run, eventData); + + expect(run.suites['SuiteA'].tests[testId].notices).toEqual(['Some notice']); + expect(run.suites['SuiteA'].notice).toBe(1); + expect(run.suites['SuiteA'].hasIssues).toBe(true); + }); + }); + describe('handleTestCompleted', () => { let run; const testId = 'SuiteA::testMethod'; - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; + store.initializeTestRun('global'); + run = store.state.testRun; run.suites['SuiteA'] = { name: 'SuiteA', tests: { @@ -298,12 +364,12 @@ describe('Store', () => { }, passed: 0, failed: 0, errored: 0, skipped: 0, incomplete: 0, hasIssues: false, }; - store.state.testSuites = [{ id: 'SuiteA', methods: [{ id: testId, status: 'running', runId: runId }] }]; + store.state.testSuites = [{ id: 'SuiteA', methods: [{ id: testId, status: 'running' }] }]; }); test('should update test status and suite counts for passed test', () => { const eventData = { event: 'test.passed', data: { testId: testId } }; - store.handleTestCompleted(run, eventData, runId); + store.handleTestCompleted(run, eventData); const test = run.suites['SuiteA'].tests[testId]; expect(test.status).toBe('passed'); @@ -311,12 +377,11 @@ describe('Store', () => { expect(run.failedTestIds.has(testId)).toBe(false); expect(run.suites['SuiteA'].hasIssues).toBe(false); expect(store.state.testSuites[0].methods[0].status).toBe('passed'); - expect(store.state.testSuites[0].methods[0].runId).toBeNull(); }); test('should update test status for failed test and track it', () => { const eventData = { event: 'test.failed', data: { testId: testId, message: 'Failed!', trace: 'stack' } }; - store.handleTestCompleted(run, eventData, runId); + store.handleTestCompleted(run, eventData); const test = run.suites['SuiteA'].tests[testId]; expect(test.status).toBe('failed'); @@ -330,7 +395,7 @@ describe('Store', () => { test('should remove test from failedTestIds if it passes after being failed', () => { run.failedTestIds.add(testId); const eventData = { event: 'test.passed', data: { testId: testId } }; - store.handleTestCompleted(run, eventData, runId); + store.handleTestCompleted(run, eventData); expect(run.failedTestIds.has(testId)).toBe(false); }); }); @@ -338,10 +403,9 @@ describe('Store', () => { describe('handleTestFinished', () => { let run; const testId = 'SuiteA::testMethod'; - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; + store.initializeTestRun('global'); + run = store.state.testRun; run.suites['SuiteA'] = { name: 'SuiteA', tests: { @@ -353,7 +417,7 @@ describe('Store', () => { test('should update the duration and assertions of a test', () => { const eventData = { event: 'test.finished', data: { testId: testId, duration: 1.23, assertions: 5 } }; - store.handleTestFinished(run, eventData, runId); + store.handleTestFinished(run, eventData); const test = run.suites['SuiteA'].tests[testId]; expect(test.duration).toBe(1.23); expect(test.assertions).toBe(5); @@ -362,73 +426,47 @@ describe('Store', () => { }); }); - describe('handleExecutionEnded', () => { - let run; - const runId = 'run123'; - beforeEach(() => { - store.initializeTestRun(runId, 'global'); - run = store.state.realtimeTestRuns[runId]; - store.state.runningTestIds[runId] = true; - store.state.stopPending[runId] = true; - store.state.isStarting = true; - jest.spyOn(store, 'updateSidebarAfterRun'); - }); - - test('should set summary, status, clear flags, and reset isStarting', () => { - const summary = { numberOfTests: 10, numberOfFailures: 1, status: 'failure' }; - const eventData = { event: 'execution.ended', data: { summary: summary } }; - store.handleExecutionEnded(run, eventData, runId); - - expect(run.summary).toEqual(summary); - expect(run.status).toBe('finished'); - expect(store.state.lastCompletedRunId).toBe(runId); - expect(store.state.runningTestIds[runId]).toBeUndefined(); - expect(store.state.stopPending[runId]).toBeUndefined(); - expect(store.state.isStarting).toBe(false); - expect(store.updateSidebarAfterRun).toHaveBeenCalledWith(runId); - }); - }); - describe('stopTestRun', () => { - const runId = 'run123'; beforeEach(() => { - store.initializeTestRun(runId, 'global'); - store.state.runningTestIds[runId] = true; - store.state.stopPending[runId] = true; + store.initializeTestRun('global'); + store.state.isRunning = true; + store.state.isStopping = true; store.state.isStarting = true; - jest.spyOn(store, 'updateSidebarAfterRun'); }); test('should mark run as stopped, clear flags, and reset isStarting', () => { - store.stopTestRun(runId); - expect(store.state.realtimeTestRuns[runId].status).toBe('stopped'); - expect(store.state.runningTestIds[runId]).toBeUndefined(); - expect(store.state.stopPending[runId]).toBeUndefined(); + store.state.testSuites = [ + { id: 'SuiteA', isRunning: true, methods: [{ id: 'SuiteA::test1', status: 'running' }] }, + { id: 'SuiteB', isRunning: false, methods: [{ id: 'SuiteB::test2', status: 'passed' }] }, + ]; + + store.stopTestRun(); + expect(store.state.testRun.status).toBe('stopped'); + expect(store.state.isRunning).toBe(false); + expect(store.state.isStopping).toBe(false); expect(store.state.isStarting).toBe(false); - expect(store.updateSidebarAfterRun).toHaveBeenCalledWith(runId); + + expect(store.state.testSuites[0].isRunning).toBe(false); + expect(store.state.testSuites[0].methods[0].status).toBe('running'); + expect(store.state.testSuites[1].isRunning).toBe(false); + expect(store.state.testSuites[1].methods[0].status).toBe('passed'); }); }); describe('getFailedTestIds', () => { - test('should return failed test IDs from the last completed run in reset mode', () => { - store.state.options.resultUpdateMode = 'reset'; - const runId = 'run123'; - store.initializeTestRun(runId, 'global'); - store.state.lastCompletedRunId = runId; - store.state.realtimeTestRuns[runId].failedTestIds.add('test1'); - store.state.realtimeTestRuns[runId].failedTestIds.add('test2'); + test('should return failed test IDs from the current run', () => { + store.initializeTestRun('global'); + store.state.testRun.failedTestIds.add('test1'); + store.state.testRun.failedTestIds.add('test2'); expect(store.getFailedTestIds()).toEqual(['test1', 'test2']); }); }); describe('hasFailedTests', () => { - test('should return true if the last completed run has failed tests in reset mode', () => { - store.state.options.resultUpdateMode = 'reset'; - const runId = 'run123'; - store.initializeTestRun(runId, 'global'); - store.state.lastCompletedRunId = runId; - store.state.realtimeTestRuns[runId].failedTestIds.add('test1'); + test('should return true if the current run has failed tests', () => { + store.initializeTestRun('global'); + store.state.testRun.failedTestIds.add('test1'); expect(store.hasFailedTests()).toBe(true); }); @@ -436,18 +474,16 @@ describe('Store', () => { describe('clearAllResults', () => { test('should clear all test runs and reset state', () => { - store.initializeTestRun('run1', 'global'); - store.state.lastCompletedRunId = 'run1'; + store.initializeTestRun('global'); store.state.expandedTestId = 'someTest'; store.state.testSuites = [{ id: 'SuiteA', methods: [{ id: 'test1', status: 'passed' }] }]; - const resetSidebarSpy = jest.spyOn(store, 'resetSidebarTestStatuses'); store.clearAllResults(); - expect(store.state.realtimeTestRuns).toEqual({}); - expect(store.state.lastCompletedRunId).toBeNull(); + expect(store.state.testRun).toBeNull(); expect(store.state.expandedTestId).toBeNull(); - expect(resetSidebarSpy).toHaveBeenCalled(); + // Verify the effect of resetSidebarTestStatuses + expect(store.state.testSuites[0].methods[0].status).toBeNull(); }); }); }); diff --git a/public/js/tests/utils.test.js b/assets/js/tests/utils.test.js similarity index 94% rename from public/js/tests/utils.test.js rename to assets/js/tests/utils.test.js index e79f27a..757b1ab 100644 --- a/public/js/tests/utils.test.js +++ b/assets/js/tests/utils.test.js @@ -1,12 +1,14 @@ -/** @jest-environment jsdom */ +/** @vitest-environment jsdom */ // Mock btoa as it's not available in a Node.js test environment -global.btoa = jest.fn((str) => Buffer.from(str).toString('base64')); +import { vi } from 'vitest'; // Import vi from vitest + +global.btoa = vi.fn((str) => Buffer.from(str).toString('base64')); import { favicons, updateFavicon, parseTestId, formatTime, calculatePassedTests } from '../utils.js'; describe('utils.js', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('favicons', () => { @@ -24,7 +26,7 @@ describe('utils.js', () => { beforeEach(() => { mockFaviconLink = { href: '' }; - jest.spyOn(document, 'getElementById').mockReturnValue(mockFaviconLink); + vi.spyOn(document, 'getElementById').mockReturnValue(mockFaviconLink); }); test('should update favicon with neutral status by default', () => { @@ -60,7 +62,7 @@ describe('utils.js', () => { }); test('should do nothing if favicon element is not found', () => { - document.getElementById.mockReturnValue(null); + vi.spyOn(document, 'getElementById').mockReturnValue(null); // Use vi.spyOn here updateFavicon('success'); expect(document.getElementById).toHaveBeenCalledWith('favicon'); expect(global.btoa).not.toHaveBeenCalled(); diff --git a/assets/js/tests/vitest.setup.js b/assets/js/tests/vitest.setup.js new file mode 100644 index 0000000..13425aa --- /dev/null +++ b/assets/js/tests/vitest.setup.js @@ -0,0 +1,19 @@ +import { vi } from 'vitest'; + +const localStorageMock = (() => { + let store = {}; + return { + getItem: (key) => store[key] || null, + setItem: (key, value) => { + store[key] = value.toString(); + }, + clear: () => { + store = {}; + }, + removeItem: (key) => { + delete store[key]; + }, + }; +})(); + +vi.stubGlobal('localStorage', localStorageMock); diff --git a/assets/js/tests/websocket.test.js b/assets/js/tests/websocket.test.js new file mode 100644 index 0000000..db1dc65 --- /dev/null +++ b/assets/js/tests/websocket.test.js @@ -0,0 +1,203 @@ +import { vi } from 'vitest'; // Import vi from vitest + +// Mock the global WebSocket object +const mockWebSocketInstance = { + onopen: vi.fn(), // Make it a mock function + onmessage: vi.fn(), // Make it a mock function + onerror: vi.fn(), // Make it a mock function + onclose: vi.fn(), // Make it a mock function + close: vi.fn(), + send: vi.fn(), +}; +// Mock WebSocket as a constructor that returns mockWebSocketInstance +const MockWebSocket = vi.fn(function WebSocket(url) { + // In a real scenario, you might want to store the URL or other constructor args + // For now, just return the predefined mock instance + return mockWebSocketInstance; +}); +global.WebSocket = MockWebSocket; + +// Mock dependencies +import * as Utils from '../utils.js'; // Import the module +vi.mock('../utils.js'); // Mock the module + +class MockStore { + constructor() { + this.state = { + testRun: null, + isRunning: false, + options: { + resultUpdateMode: 'update', // Default to update mode + }, + }; + this.initializeTestRun = vi.fn(); + this.handleTestEvent = vi.fn(); + this.stopTestRun = vi.fn(); + this.clearRunningTests = vi.fn(); + this.getTestRun = vi.fn(() => this.state.testRun); + this.isTestRunning = vi.fn(() => this.state.isRunning); + this.finishTestRun = vi.fn(); + } +} + +import { WebSocketManager } from '../websocket.js'; + +describe('WebSocketManager', () => { + let wsManager; + let store; + const wsUrl = 'ws://localhost:8080/ws'; + + beforeEach(() => { + store = new MockStore(); + wsManager = new WebSocketManager(wsUrl, store); + + vi.clearAllMocks(); + Utils.updateFavicon.mockClear(); // Clear the mock here + vi.spyOn(console, 'log').mockImplementation(() => {}); + vi.spyOn(console, 'error').mockImplementation(() => {}); + vi.spyOn(console, 'warn').mockImplementation(() => {}); + vi.useFakeTimers(); // Mock timers for setTimeout + }); + + afterEach(() => { + vi.restoreAllMocks(); + vi.useRealTimers(); // Restore real timers + }); + + describe('connect', () => { + test('should create a new WebSocket instance', async () => { + const connectPromise = wsManager.connect(); + // Simulate connection open by calling the mocked onopen handler + mockWebSocketInstance.onopen(); + await connectPromise; + + expect(MockWebSocket).toHaveBeenCalledWith(wsUrl); + expect(console.log).toHaveBeenCalledWith('WebSocket connected'); + expect(wsManager.reconnectAttempts).toBe(0); + }); + + test('should reject if WebSocket connection fails', async () => { + const connectPromise = wsManager.connect(); + const error = new Error('Connection failed'); + // Simulate connection error by calling the mocked onerror handler + mockWebSocketInstance.onerror(error); + await expect(connectPromise).rejects.toThrow('Connection failed'); + expect(console.error).toHaveBeenCalledWith('WebSocket error:', error); + }); + + test('should reject if WebSocket constructor throws an error', async () => { + MockWebSocket.mockImplementationOnce(() => { throw new Error('Invalid URL'); }); + await expect(wsManager.connect()).rejects.toThrow('Invalid URL'); + }); + }); + + describe('handleDisconnect', () => { + test('should clear running tests and update favicon to neutral', () => { + wsManager.handleDisconnect(); + expect(store.clearRunningTests).toHaveBeenCalledTimes(1); + expect(Utils.updateFavicon).toHaveBeenCalledWith('neutral'); // Use Utils.updateFavicon + }); + + test('should attempt to reconnect if reconnect attempts are less than max', () => { + wsManager.reconnectAttempts = 0; + wsManager.maxReconnectAttempts = 1; + const connectSpy = vi.spyOn(wsManager, 'connect').mockResolvedValueOnce(); + + wsManager.handleDisconnect(); + expect(wsManager.reconnectAttempts).toBe(1); + expect(console.log).toHaveBeenCalledWith('Attempting to reconnect in 2000ms...'); + + vi.advanceTimersByTime(2000); + expect(connectSpy).toHaveBeenCalledTimes(1); + }); + + test('should not attempt to reconnect if reconnect attempts exceed max', () => { + wsManager.reconnectAttempts = wsManager.maxReconnectAttempts; + const connectSpy = vi.spyOn(wsManager, 'connect'); + + wsManager.handleDisconnect(); + expect(connectSpy).not.toHaveBeenCalled(); + expect(console.log).not.toHaveBeenCalledWith(expect.stringContaining('Attempting to reconnect')); + }); + }); + + describe('handleMessage', () => { + test('should call handleTestStart for "start" message type', () => { + const message = { type: 'start', contextId: 'global' }; + wsManager.handleMessage(message); + expect(store.initializeTestRun).toHaveBeenCalledWith('global'); + }); + + test('should call handleRealtimeEvent for "realtime" message type', () => { + const message = { type: 'realtime', data: JSON.stringify({ event: 'test.prepared' }) }; + wsManager.handleMessage(message); + expect(store.handleTestEvent).toHaveBeenCalledWith({ event: 'test.prepared' }); + }); + + test('should call handleTestExit for "exit" message type', () => { + const message = { type: 'exit' }; + const fetchCoverageReportSpy = vi.fn(); + wsManager.callbacks.fetchCoverageReport = fetchCoverageReportSpy; + store.state.coverage = true; + wsManager.handleMessage(message); + expect(fetchCoverageReportSpy).toHaveBeenCalled(); + }); + + test('should call handleTestStopped for "stopped" message type', () => { + const message = { type: 'stopped' }; + const updateFaviconSpy = vi.spyOn(wsManager, 'updateFaviconIfComplete'); + wsManager.handleMessage(message); + expect(store.stopTestRun).toHaveBeenCalled(); + expect(updateFaviconSpy).toHaveBeenCalledTimes(1); + }); + + test('should warn for unknown message type', () => { + const message = { type: 'unknown' }; + wsManager.handleMessage(message); + expect(console.warn).toHaveBeenCalledWith('Unknown message type:', 'unknown'); + }); + }); + + describe('handleRealtimeEvent', () => { + test('should parse message data and call store.handleTestEvent', () => { + const message = { data: JSON.stringify({ event: 'test.passed', data: { test: 'Suite::test' } }) }; + wsManager.handleRealtimeEvent(message); + expect(store.handleTestEvent).toHaveBeenCalledWith({ event: 'test.passed', data: { test: 'Suite::test' } }); + }); + + test('should log an error if message data is invalid JSON', () => { + const message = { data: 'invalid json' }; + wsManager.handleRealtimeEvent(message); + expect(console.error).toHaveBeenCalledWith('Failed to parse realtime event:', expect.any(Error), 'invalid json'); + }); + }); + + describe('updateFaviconIfComplete', () => { + test('should set favicon to neutral if no tests are running', () => { + store.isTestRunning.mockReturnValueOnce(false); + wsManager.updateFaviconIfComplete(); + expect(Utils.updateFavicon).toHaveBeenCalledWith('neutral'); + }); + + test('should not update favicon if tests are still running', () => { + store.isTestRunning.mockReturnValueOnce(true); + wsManager.updateFaviconIfComplete(); + expect(Utils.updateFavicon).not.toHaveBeenCalled(); + }); + }); + + describe('disconnect', () => { + test('should close the WebSocket connection if it exists', () => { + wsManager.ws = mockWebSocketInstance; + wsManager.disconnect(); + expect(mockWebSocketInstance.close).toHaveBeenCalledTimes(1); + expect(wsManager.ws).toBeNull(); + }); + + test('should do nothing if WebSocket connection does not exist', () => { + wsManager.ws = null; + wsManager.disconnect(); + expect(mockWebSocketInstance.close).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/public/js/utils.js b/assets/js/utils.js similarity index 90% rename from public/js/utils.js rename to assets/js/utils.js index 80d14b4..05f0e1a 100644 --- a/public/js/utils.js +++ b/assets/js/utils.js @@ -77,3 +77,14 @@ export function toggleTestDetails(store, testcase) { const id = testcase.id; store.setExpandedTest(state.expandedTestId === id ? null : id); } + +export function formatNanoseconds(nanoseconds) { + if (nanoseconds === undefined || nanoseconds === null) { + return '0.00ms'; + } + const seconds = nanoseconds / 1_000_000_000; + if (seconds >= 1) { + return `${seconds.toFixed(2)}s`; + } + return `${(nanoseconds / 1_000_000).toFixed(2)}ms`; +} diff --git a/public/js/websocket.js b/assets/js/websocket.js similarity index 67% rename from public/js/websocket.js rename to assets/js/websocket.js index 8db04e6..e2a8e51 100644 --- a/public/js/websocket.js +++ b/assets/js/websocket.js @@ -5,10 +5,10 @@ import { updateFavicon } from './utils.js'; export class WebSocketManager { - constructor(url = 'ws://127.0.0.1:8080/ws/status', store, app) { + constructor(url = 'ws://127.0.0.1:8080/ws/status', store, callbacks = {}) { this.url = url; this.store = store; - this.app = app; + this.callbacks = callbacks; // { fetchCoverageReport: Function } this.ws = null; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; @@ -76,10 +76,10 @@ export class WebSocketManager { this.handleRealtimeEvent(message); break; case 'exit': - this.handleTestExit(message); + this.handleTestExit(); break; case 'stopped': - this.handleTestStopped(message); + this.handleTestStopped(); break; default: console.warn('Unknown message type:', message.type); @@ -90,7 +90,7 @@ export class WebSocketManager { * Handle test start event */ handleTestStart(message) { - this.store.initializeTestRun(message.runId, message.contextId); + this.store.initializeTestRun(message.contextId); } /** @@ -99,7 +99,11 @@ export class WebSocketManager { handleRealtimeEvent(message) { try { const event = JSON.parse(message.data); - this.store.handleTestEvent(message.runId, event); + if (event.event === 'execution.ended') { + this.handleExecutionEnded(event); + } else { + this.store.handleTestEvent(event); + } if (event.event === 'execution.ended' && this.store.state.coverage) { this.store.setCoverageLoading(true); @@ -109,61 +113,33 @@ export class WebSocketManager { } } + handleExecutionEnded(eventData) { + this.store.handleExecutionEnded(eventData); + } + /** * Handle test exit event */ - handleTestExit(message) { - this.updateFaviconFromRun(message.runId); - if (this.store.state.coverage) { - this.app.fetchCoverageReport(message.runId); + handleTestExit() { + this.store.finishTestRun(); + if (this.store.state.coverage && this.callbacks.fetchCoverageReport) { + this.callbacks.fetchCoverageReport(); } } /** * Handle test stopped event */ - handleTestStopped(message) { - this.store.stopTestRun(message.runId); + handleTestStopped() { + this.store.stopTestRun(); this.updateFaviconIfComplete(); } - /** - * Update favicon based on test run results - */ - updateFaviconFromRun(runId) { - const run = this.store.getTestRun(runId); - if (!run || !run.summary) { - return; - } - - // In update mode, check all runs to determine overall status - if (this.store.state.options.resultUpdateMode === 'update') { - let hasFailures = false; - - for (const id in this.store.state.realtimeTestRuns) { - const r = this.store.state.realtimeTestRuns[id]; - if (r.summary && (r.summary.numberOfFailures > 0 || r.summary.numberOfErrors > 0)) { - hasFailures = true; - break; - } - } - - updateFavicon(hasFailures ? 'failure' : 'success'); - } else { - // In reset mode, only consider current run - if (run.summary.numberOfFailures > 0 || run.summary.numberOfErrors > 0) { - updateFavicon('failure'); - } else { - updateFavicon('success'); - } - } - } - /** * Update favicon if all tests are complete */ updateFaviconIfComplete() { - if (this.store.getRunningTestCount() === 0) { + if (!this.store.isTestRunning()) { updateFavicon('neutral'); } } diff --git a/castor.php b/castor.php index e0eb671..656cd0e 100644 --- a/castor.php +++ b/castor.php @@ -16,7 +16,7 @@ function install(): int #[\Castor\Attribute\AsTask] function phpunit(): int { - run('rm -f clover-*.xml'); + run('rm -f clover*.xml'); return exit_code(dockerize('vendor/bin/phpunit')); diff --git a/package-lock.json b/package-lock.json index 0884663..942e06e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,37 @@ { - "name": "PHPUnitGUI", + "name": "PHPUnitHub", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "PHPUnitGUI", + "name": "PHPUnitHub", "version": "1.0.0", "license": "ISC", "devDependencies": { "@babel/core": "^7.23.9", "@babel/preset-env": "^7.23.9", + "@tailwindcss/vite": "^4.1.17", + "@vitejs/plugin-vue": "^6.0.2", + "@vue/test-utils": "^2.4.6", "autoprefixer": "^10.4.17", - "babel-jest": "^29.7.0", - "jest": "^29.7.0", - "jest-environment-jsdom": "^30.2.0", + "jsdom": "^27.2.0", "postcss": "^8.4.35", - "tailwindcss": "^3.4.1" + "tailwindcss": "^3.4.18", + "vite": "^7.2.6", + "vitest": "^4.0.15" + }, + "engines": { + "node": ">=20" } }, + "node_modules/@acemir/cssom": { + "version": "0.9.26", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.26.tgz", + "integrity": "sha512-UMFbL3EnWH/eTvl21dz9s7Td4wYDMtxz/56zD8sL9IZGYyi48RxmdgPMiyT7R6Vn3rjMTwYZ42bqKa7ex74GEQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -33,25 +46,59 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.0.tgz", + "integrity": "sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "lru-cache": "^11.2.2" } }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.5.tgz", + "integrity": "sha512-Eks6dY8zau4m4wNRQjRVaKQRTalNcPcBvU1ZQ35w5kKRk1gUeNCkVLsRiATurjASTp3TKM4H10wsI50nx3NZdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.2" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.27.1", @@ -514,61 +561,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", - "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-import-assertions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", @@ -601,174 +593,6 @@ "@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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "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==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "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.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "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", @@ -1790,13 +1614,6 @@ "node": ">=6.9.0" } }, - "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, - "license": "MIT" - }, "node_modules/@csstools/color-helpers": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", @@ -1892,6 +1709,26 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.20.tgz", + "integrity": "sha512-8BHsjXfSciZxjmHQOuVdW2b8WLUPts9a+mfL13/PzEviufUEW2xnvQuOlKs9dRBHgRqJ53SF/DUoK9+MZk72oQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", @@ -1912,599 +1749,549 @@ "node": ">=18" } }, - "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==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "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==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "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, - "license": "MIT", - "dependencies": { - "@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": "^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, - "license": "MIT", - "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" - }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "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": ">=18" } }, - "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==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.2.0.tgz", - "integrity": "sha512-kazxw2L9IPuZpQ0mEt9lu9Z98SqR74xcagANmMBU16X0lS23yPc0+S6hGLUz8kVRlomZEs/5S/Zlpqwf5yu6OQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/jsdom": "^21.1.7", - "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", - "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/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==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "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==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "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==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "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==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "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" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/pattern/node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "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" - }, + "optional": true, + "os": [ + "win32" + ], "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": ">=18" } }, - "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "BSD-3-Clause", - "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" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@jest/reporters/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "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==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "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==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", - "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": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "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==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "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": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/@isaacs/cliui/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==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "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" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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==", + "node_modules/@isaacs/cliui/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==", "dev": true, "license": "MIT", "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" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/@jridgewell/gen-mapping": { @@ -2595,2560 +2382,2445 @@ "node": ">= 8" } }, - "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/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true, "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" } }, - "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==", + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.50", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", + "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } + "license": "MIT" }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "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==", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "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==", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" - }, - "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==", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "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==", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jsdom": { - "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "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==", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", "dev": true, "license": "MIT" }, - "node_modules/@types/yargs": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", - "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "node_modules/@tailwindcss/node": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", + "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==", "dev": true, "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.17" + } + }, + "node_modules/@tailwindcss/node/node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" } }, - "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/@tailwindcss/node/node_modules/tailwindcss": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", + "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", "dev": true, "license": "MIT" }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "node_modules/@tailwindcss/oxide": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz", + "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-arm64": "4.1.17", + "@tailwindcss/oxide-darwin-x64": "4.1.17", + "@tailwindcss/oxide-freebsd-x64": "4.1.17", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", + "@tailwindcss/oxide-linux-x64-musl": "4.1.17", + "@tailwindcss/oxide-wasm32-wasi": "4.1.17", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz", + "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" } }, - "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/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz", + "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10" } }, - "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/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz", + "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": ">= 10" } }, - "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/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz", + "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 10" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz", + "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } }, - "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==", + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz", + "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "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/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz", + "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz", + "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/autoprefixer": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", - "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", - "dev": true, - "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" - } + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz", + "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==", + "cpu": [ + "x64" ], + "dev": true, "license": "MIT", - "dependencies": { - "browserslist": "^4.27.0", - "caniuse-lite": "^1.0.30001754", - "fraction.js": "^5.3.4", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">= 10" } }, - "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==", + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz", + "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@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" + "@emnapi/core": "^1.6.0", + "@emnapi/runtime": "^1.6.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.7", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "node": ">=14.0.0" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz", + "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">= 10" } }, - "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==", + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz", + "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 10" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "node_modules/@tailwindcss/vite": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.17.tgz", + "integrity": "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", - "semver": "^6.3.1" + "@tailwindcss/node": "4.1.17", + "@tailwindcss/oxide": "4.1.17", + "tailwindcss": "4.1.17" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "node_modules/@tailwindcss/vite/node_modules/tailwindcss": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", + "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@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" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" + "undici-types": "~7.16.0" } }, - "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==", + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", + "integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "@rolldown/pluginutils": "1.0.0-beta.50" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" } }, - "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, - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.31", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", - "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", + "node_modules/@vitest/expect": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.15.tgz", + "integrity": "sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w==", "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.15", + "@vitest/utils": "4.0.15", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/mocker": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.15.tgz", + "integrity": "sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@vitest/spy": "4.0.15", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@vitest/mocker/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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@types/estree": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@vitest/pretty-format": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.15.tgz", + "integrity": "sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "node_modules/@vitest/runner": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.15.tgz", + "integrity": "sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw==", "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" - } - ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" - }, - "bin": { - "browserslist": "cli.js" + "@vitest/utils": "4.0.15", + "pathe": "^2.0.3" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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==", + "node_modules/@vitest/snapshot": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.15.tgz", + "integrity": "sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "node-int64": "^0.4.0" + "@vitest/pretty-format": "4.0.15", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "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, - "license": "MIT" - }, - "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/@vitest/spy": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.15.tgz", + "integrity": "sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@vitest/utils": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.15.tgz", + "integrity": "sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@vitest/pretty-format": "4.0.15", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "node_modules/@vue/compiler-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" + "peer": true, + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.25", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001757", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", - "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", - "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" - } - ], - "license": "CC-BY-4.0" - }, - "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/@vue/compiler-core/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, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "license": "BSD-2-Clause", + "peer": true, "engines": { - "node": ">=10" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/fb55/entities?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==", + "node_modules/@vue/compiler-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "peer": true, + "dependencies": { + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@vue/compiler-sfc": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" } }, - "node_modules/chokidar/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/@vue/compiler-ssr": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", "dev": true, - "license": "ISC", + "license": "MIT", + "peer": true, "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/@vue/reactivity": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", + "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", - "engines": { - "node": ">=8" + "peer": true, + "dependencies": { + "@vue/shared": "3.5.25" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, - "license": "MIT" - }, - "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==", + "node_modules/@vue/runtime-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", + "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", "dev": true, - "license": "ISC", + "license": "MIT", + "peer": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" + "@vue/reactivity": "3.5.25", + "@vue/shared": "3.5.25" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/@vue/runtime-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", + "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", "dev": true, "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "peer": true, + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/runtime-core": "3.5.25", + "@vue/shared": "3.5.25", + "csstype": "^3.1.3" } }, - "node_modules/collect-v8-coverage": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", - "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", - "dev": true, - "license": "MIT" - }, - "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/@vue/server-renderer": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", + "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "color-name": "~1.1.4" + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25" }, - "engines": { - "node": ">=7.0.0" + "peerDependencies": { + "vue": "3.5.25" } }, - "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/@vue/shared": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "node_modules/@vue/test-utils": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" + "dependencies": { + "js-beautify": "^1.14.9", + "vue-component-type-helpers": "^2.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, - "license": "MIT" - }, - "node_modules/convert-source-map": { + "node_modules/abbrev": { "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==", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, - "license": "MIT" - }, - "node_modules/core-js-compat": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", - "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "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, - "license": "MIT", - "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-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, + "license": "ISC", "engines": { - "node": ">=4" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" - }, "engines": { - "node": ">=18" + "node": ">= 14" } }, - "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==", + "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, "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "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, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6.0" + "node": ">=8" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true, "license": "MIT" }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "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, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": 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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "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, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "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, "license": "MIT" }, - "node_modules/electron-to-chromium": { - "version": "1.5.260", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.260.tgz", - "integrity": "sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==", - "dev": true, - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "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, - "license": "MIT" - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", "dev": true, + "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" + } + ], "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" }, - "engines": { - "node": ">=4" - } - }, - "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, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "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" + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || >=14" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "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" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", "dev": true, "license": "MIT", "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" + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "dev": true, "license": "MIT", "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.8" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" }, - "engines": { - "node": ">=8.6.0" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "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/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "@babel/helper-define-polyfill-provider": "^0.6.5" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.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/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, "license": "MIT" }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "node_modules/baseline-browser-mapping": { + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "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==", + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "require-from-string": "^2.0.2" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "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==", "dev": true, "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "node_modules/browserslist": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", "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" + } + ], "license": "MIT", - "engines": { - "node": "*" + "dependencies": { + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "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, - "license": "ISC" - }, - "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, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "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/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">= 6" } }, - "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==", + "node_modules/caniuse-lite": { + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "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" + } + ], + "license": "CC-BY-4.0" }, - "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==", + "node_modules/chai": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", + "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=18" } }, - "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==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", + "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": ">=10" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/chokidar/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, "license": "ISC", "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" + "is-glob": "^4.0.1" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 6" } }, - "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/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, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10.13.0" + "node": ">=7.0.0" } }, - "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, - "license": "ISC" - }, - "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/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, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 6" } }, - "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==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "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/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, "license": "MIT" }, - "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==", + "node_modules/core-js-compat": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "browserslist": "^4.28.0" }, - "engines": { - "node": ">= 14" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/https-proxy-agent": { + "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 14" - } - }, - "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, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" + "node": ">= 8" } }, - "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==", + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, "bin": { - "import-local-fixture": "fixtures/cli.js" + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/cssstyle": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.3.tgz", + "integrity": "sha512-OytmFH+13/QXONJcC75QNdMtKpceNk3u8ThBjyyYjkEcy/ekBwR1mMAuNvi3gdBPW3N5TlCzQ0WZw8H0lN/bDw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "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==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@asamuzakjp/css-color": "^4.0.3", + "@csstools/css-syntax-patches-for-csstree": "^1.0.14", + "css-tree": "^3.1.0" + }, + "engines": { + "node": ">=20" } }, - "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, - "license": "ISC" - }, - "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/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, - "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==", + "node_modules/data-urls": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz", + "integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.0.0" }, "engines": { - "node": ">=8" + "node": ">=20" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "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/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "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==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "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, - "license": "MIT", - "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==", + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "Apache-2.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/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } + "license": "MIT" }, - "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==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "license": "MIT" }, - "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/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "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==", + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14" } }, - "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==", + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, - "license": "BSD-3-Clause", + "license": "ISC", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/editorconfig/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "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==", + "node_modules/electron-to-chromium": { + "version": "1.5.260", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.260.tgz", + "integrity": "sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "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" + "esbuild": "bin/esbuild" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=18" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "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==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "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": ">=6" } }, - "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==", + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, "license": "MIT", - "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" - }, + "peer": true + }, + "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, + "license": "BSD-2-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.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==", + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", "dev": true, - "license": "MIT", - "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" - }, + "license": "Apache-2.0", "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": ">=12.0.0" } }, - "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==", + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "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" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "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": ">=8.6.0" } }, - "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==", + "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==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "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==", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "reusify": "^1.0.4" } }, - "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==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "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" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-environment-jsdom": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.2.0.tgz", - "integrity": "sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/environment-jsdom-abstract": "30.2.0", - "@types/jsdom": "^21.1.7", - "@types/node": "*", - "jsdom": "^26.1.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0" + "node": ">=14" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "node_modules/foreground-child/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, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0" - }, + "license": "ISC", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", - "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "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, "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "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==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "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, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/jest-environment-jsdom/node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "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, - "license": "BSD-3-Clause", + "license": "ISC", "dependencies": { - "@sinonjs/commons": "^3.0.1" + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/jest-environment-jsdom/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==", + "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, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/jest-environment-jsdom/node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "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, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 14" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 14" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "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, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-environment-jsdom/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "ISC" }, - "node_modules/jest-environment-jsdom/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "binary-extensions": "^2.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "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==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "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" + "hasown": "^2.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.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==", + "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, "license": "MIT", - "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": ">=8" } }, - "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==", + "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, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.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==", + "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, "license": "MIT", - "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": ">=0.12.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==", + "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, - "license": "MIT", - "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" - } + "license": "MIT" }, - "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==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "ISC" }, - "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==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" }, - "peerDependencies": { - "jest-resolve": "*" + "funding": { + "url": "https://github.com/sponsors/isaacs" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "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==", + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "jiti": "bin/jiti.js" } }, - "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==", + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", "dev": true, "license": "MIT", "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" + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14" } }, - "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==", + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.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==", + "node_modules/js-beautify/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, - "license": "MIT", + "license": "ISC", "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" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", "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" + "brace-expansion": "^2.0.1" }, "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, - "license": "MIT", - "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" + "node": ">=16 || 14 >=14.17" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14" } }, - "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==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.2.0.tgz", + "integrity": "sha512-454TI39PeRDW1LgpyLPyURtB4Zx1tklSr6+OFOipsxGUH1WMTvk6C65JQdrj455+DP2uJ1+veBEHTGFKWVLFoA==", "dev": true, "license": "MIT", "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" + "@acemir/cssom": "^0.9.23", + "@asamuzakjp/dom-selector": "^6.7.4", + "cssstyle": "^5.3.3", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "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==", + "node_modules/jsdom/node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", "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" + "entities": "^6.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "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==", + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "bin": { + "jsesc": "bin/jsesc" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "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==", + "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, "license": "MIT", - "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" + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "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==", + "node_modules/lightningcss": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "dev": true, - "license": "MIT", + "license": "MPL-2.0", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^3.0.0" + "node": ">= 12.0.0" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "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/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/lilconfig": { @@ -5171,19 +4843,6 @@ "dev": true, "license": "MIT" }, - "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, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -5201,51 +4860,22 @@ "yallist": "^3.0.2" } }, - "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==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "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/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "dev": true, - "license": "MIT" + "license": "CC0-1.0" }, "node_modules/merge2": { "version": "1.4.1", @@ -5271,27 +4901,14 @@ "node": ">=8.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, - "license": "MIT", - "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==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" } }, "node_modules/ms": { @@ -5304,247 +4921,114 @@ "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nwsapi": { - "version": "2.2.22", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.22.tgz", - "integrity": "sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "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, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" } }, - "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==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=8" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/p-locate/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==", + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", "dependencies": { - "p-try": "^2.0.0" + "abbrev": "^2.0.0" }, - "engines": { - "node": ">=6" + "bin": { + "nopt": "bin/nopt.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "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==", + "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, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "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/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "license": "MIT", - "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": ">=0.10.0" } }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "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==", "dev": true, "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "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==", + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/path-is-absolute": { + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/package-json-from-dist": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "BlueOak-1.0.0" }, "node_modules/path-key": { "version": "3.1.1", @@ -5563,6 +5047,37 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5603,19 +5118,6 @@ "node": ">= 6" } }, - "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, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -5779,47 +5281,12 @@ "dev": true, "license": "MIT" }, - "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, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", + "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==", "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } + "license": "ISC" }, "node_modules/punycode": { "version": "2.3.1", @@ -5831,23 +5298,6 @@ "node": ">=6" } }, - "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": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5869,13 +5319,6 @@ ], "license": "MIT" }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -5957,10 +5400,10 @@ "regjsparser": "bin/parser" } }, - "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==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", "engines": { @@ -5988,39 +5431,6 @@ "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, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -6032,12 +5442,47 @@ "node": ">=0.10.0" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } }, "node_modules/run-parallel": { "version": "1.2.0", @@ -6116,40 +5561,13 @@ "node": ">=8" } }, - "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/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6160,52 +5578,37 @@ "node": ">=0.10.0" } }, - "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, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "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/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, - "license": "BSD-3-Clause" + "license": "MIT" }, - "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==", + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "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==", + "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, "license": "MIT", "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/string-width": { + "node_modules/string-width-cjs": { + "name": "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==", @@ -6233,37 +5636,18 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "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==", + "node_modules/strip-ansi-cjs": { + "name": "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, "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sucrase": { @@ -6289,19 +5673,6 @@ "node": ">=16 || 14 >=14.17" } }, - "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, - "license": "MIT", - "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", @@ -6360,19 +5731,18 @@ "node": ">=14.0.0" } }, - "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==", + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/thenify": { @@ -6398,6 +5768,23 @@ "node": ">=0.8" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -6446,33 +5833,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "dev": true, "license": "MIT" }, - "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, - "license": "BSD-3-Clause" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6487,29 +5877,29 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "tldts": "^7.0.5" }, "engines": { "node": ">=16" } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/ts-interface-checker": { @@ -6519,35 +5909,14 @@ "dev": true, "license": "Apache-2.0" }, - "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, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "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, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", @@ -6631,21 +6000,233 @@ "dev": true, "license": "MIT" }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/vite": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.15.tgz", + "integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.15", + "@vitest/mocker": "4.0.15", + "@vitest/pretty-format": "4.0.15", + "@vitest/runner": "4.0.15", + "@vitest/snapshot": "4.0.15", + "@vitest/spy": "4.0.15", + "@vitest/utils": "4.0.15", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.15", + "@vitest/browser-preview": "4.0.15", + "@vitest/browser-webdriverio": "4.0.15", + "@vitest/ui": "4.0.15", + "happy-dom": "*", + "jsdom": "*" }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10.12.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", + "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-sfc": "3.5.25", + "@vue/runtime-dom": "3.5.25", + "@vue/server-renderer": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, + "node_modules/vue-component-type-helpers": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.12.tgz", + "integrity": "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==", + "dev": true, + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -6659,24 +6240,14 @@ "node": ">=18" } }, - "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, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, "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==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=20" } }, "node_modules/whatwg-encoding": { @@ -6703,17 +6274,17 @@ } }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/which": { @@ -6732,7 +6303,25 @@ "node": ">= 8" } }, - "node_modules/wrap-ansi": { + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -6750,27 +6339,6 @@ "url": "https://github.com/chalk/wrap-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==", - "dev": true, - "license": "ISC" - }, - "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, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -6810,64 +6378,12 @@ "dev": true, "license": "MIT" }, - "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, - "license": "ISC", - "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==", "dev": true, "license": "ISC" - }, - "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, - "license": "MIT", - "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, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index bbab078..e9da83a 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { - "name": "PHPUnitGUI", + "name": "PHPUnitHub", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { - "test": "jest", - "build:css": "tailwindcss -i ./public/css/input.css -o ./public/css/styles.css --minify", - "watch:css": "tailwindcss -i ./public/css/input.css -o ./public/css/styles.css --watch" + "test": "vitest", + "dev": "vite", + "build": "vite build" }, "engines": { - "node": ">=18" + "node": ">=20" }, "keywords": [], "author": "", @@ -17,20 +17,14 @@ "devDependencies": { "@babel/core": "^7.23.9", "@babel/preset-env": "^7.23.9", + "@vitejs/plugin-vue": "^6.0.2", + "@vue/test-utils": "^2.4.6", "autoprefixer": "^10.4.17", - "babel-jest": "^29.7.0", - "jest": "^29.7.0", - "jest-environment-jsdom": "^30.2.0", "postcss": "^8.4.35", - "tailwindcss": "^3.4.1" - }, - "jest": { - "transform": { - "^.+\\.js$": "babel-jest" - }, - "moduleNameMapper": { - "^https://cdn\\.jsdelivr\\.net/npm/vue@3/dist/vue\\.esm-browser\\.prod\\.js$": "/public/js/tests/mocks/vue.js" - }, - "testEnvironment": "jsdom" + "tailwindcss": "^3.4.18", + "vite": "^7.2.6", + "@tailwindcss/vite": "^4.1.17", + "jsdom": "^27.2.0", + "vitest": "^4.0.15" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..8567b4c --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/public/assets/favicon-failure.svg b/public/assets/favicon-failure.svg deleted file mode 100644 index 28bf253..0000000 --- a/public/assets/favicon-failure.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/public/assets/favicon-neutral.svg b/public/assets/favicon-neutral.svg deleted file mode 100644 index 1f8fd5b..0000000 --- a/public/assets/favicon-neutral.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/public/assets/favicon-success.svg b/public/assets/favicon-success.svg deleted file mode 100644 index ce61b13..0000000 --- a/public/assets/favicon-success.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/public/build/.vite/manifest.json b/public/build/.vite/manifest.json new file mode 100644 index 0000000..68c56aa --- /dev/null +++ b/public/build/.vite/manifest.json @@ -0,0 +1,11 @@ +{ + "assets/js/main.js": { + "file": "assets/main-Bz2SJcpk.js", + "name": "main", + "src": "assets/js/main.js", + "isEntry": true, + "css": [ + "assets/main-1B33L-JK.css" + ] + } +} \ No newline at end of file diff --git a/public/build/assets/main-1B33L-JK.css b/public/build/assets/main-1B33L-JK.css new file mode 100644 index 0000000..350bf3b --- /dev/null +++ b/public/build/assets/main-1B33L-JK.css @@ -0,0 +1 @@ +*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-success: #10B981;--color-failure: #EF4444;--color-warning: #F59E0B;--color-deprecation: #F59E0B;--color-neutral: #6b7280}.filter-panel-dropdown{position:absolute;top:100%;right:0;z-index:20;min-width:450px}.form-group{border-bottom:1px solid #4b5563;padding-bottom:1rem;margin-bottom:1rem}.form-group:last-of-type{border-bottom:none;padding-bottom:0;margin-bottom:0}input[type=radio],input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25rem;height:1.25rem;border:2px solid #6b7280;border-radius:.25rem;background-color:transparent;transition:background-color .2s,border-color .2s;cursor:pointer}input[type=radio]{border-radius:50%}input[type=radio]:checked,input[type=checkbox]:checked{background-color:#3b82f6;border-color:#3b82f6}input[type=radio]:focus,input[type=checkbox]:focus{outline:none;--tw-ring-color: rgba(59, 130, 246, .5);box-shadow:0 0 0 2px #1f2937,0 0 0 4px var(--tw-ring-color)}.suite-header{display:flex;justify-content:space-between;align-items:center;padding:8px 4px;border-radius:4px;transition:background-color .2s}.suite-header:hover{background-color:#374151}.suite-arrow{transition:transform .2s ease-in-out;margin-right:8px}.suite-arrow.rotated{transform:rotate(90deg)}.spinner{border-top:2px solid #3498db;border-radius:50%;width:10px;height:10px;animation:spin 1s linear infinite;margin-left:0}.spinner-big{border-top:4px solid #3498db}.spinner,.spinner-big{border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.test-item{display:flex;justify-content:space-between;align-items:center;padding:6px 4px;border-radius:4px;transition:background-color .2s}.test-item:hover{background-color:#374151}.test-item-left{display:flex;align-items:center}.status-icon{width:10px;height:10px;border-radius:50%;margin-right:8px;flex-shrink:0}.status-neutral,.status-skipped{background-color:#6b7280}.status-passed{background-color:#10b981}.status-failed,.status-errored{background-color:#ef4444}.status-running{background-color:#3498db}.test-name{color:#d1d5db}.sort-arrow.none{opacity:.7;transform:rotate(0) scale(1)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#1f2937}::-webkit-scrollbar-thumb{background:#4b5563;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#6b7280}#resizer{width:1.5px;cursor:col-resize;background-color:#374151;transition:background-color .2s}#resizer:hover{background-color:#3b82f6}@keyframes three-dots-loading{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}[v-cloak]{display:none}.token-keyword{color:#c586c0}.token-string{color:#ce9178}.token-comment{color:#6a9955}.token-variable{color:#9cdcfe}.token-default{color:#d4d4d4}.line-covered{background-color:#10b9811a}.line-uncovered{background-color:#f871711a}.static{position:static}.relative{position:relative}.z-10{z-index:10}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!h-4{height:1rem!important}.h-2{height:.5rem}.h-24{height:6rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-full{height:100%}.h-screen{height:100vh}.\!w-4{width:1rem!important}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-28{width:7rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-80{width:20rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(55 65 81 / var(--tw-divide-opacity, 1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-amber-500{--tw-border-opacity: 1;border-color:rgb(245 158 11 / var(--tw-border-opacity, 1))}.border-gray-600{--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.border-purple-500{--tw-border-opacity: 1;border-color:rgb(168 85 247 / var(--tw-border-opacity, 1))}.border-sky-500{--tw-border-opacity: 1;border-color:rgb(14 165 233 / var(--tw-border-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-500\/0{background-color:#f59e0b00}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/100{background-color:#f59e0b}.bg-amber-500\/15{background-color:#f59e0b26}.bg-amber-500\/20{background-color:#f59e0b33}.bg-amber-500\/25{background-color:#f59e0b40}.bg-amber-500\/30{background-color:#f59e0b4d}.bg-amber-500\/35{background-color:#f59e0b59}.bg-amber-500\/40{background-color:#f59e0b66}.bg-amber-500\/45{background-color:#f59e0b73}.bg-amber-500\/5{background-color:#f59e0b0d}.bg-amber-500\/50{background-color:#f59e0b80}.bg-amber-500\/55{background-color:#f59e0b8c}.bg-amber-500\/60{background-color:#f59e0b99}.bg-amber-500\/65{background-color:#f59e0ba6}.bg-amber-500\/70{background-color:#f59e0bb3}.bg-amber-500\/75{background-color:#f59e0bbf}.bg-amber-500\/80{background-color:#f59e0bcc}.bg-amber-500\/85{background-color:#f59e0bd9}.bg-amber-500\/90{background-color:#f59e0be6}.bg-amber-500\/95{background-color:#f59e0bf2}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-amber-600\/0{background-color:#d9770600}.bg-amber-600\/10{background-color:#d977061a}.bg-amber-600\/100{background-color:#d97706}.bg-amber-600\/15{background-color:#d9770626}.bg-amber-600\/20{background-color:#d9770633}.bg-amber-600\/25{background-color:#d9770640}.bg-amber-600\/30{background-color:#d977064d}.bg-amber-600\/35{background-color:#d9770659}.bg-amber-600\/40{background-color:#d9770666}.bg-amber-600\/45{background-color:#d9770673}.bg-amber-600\/5{background-color:#d977060d}.bg-amber-600\/50{background-color:#d9770680}.bg-amber-600\/55{background-color:#d977068c}.bg-amber-600\/60{background-color:#d9770699}.bg-amber-600\/65{background-color:#d97706a6}.bg-amber-600\/70{background-color:#d97706b3}.bg-amber-600\/75{background-color:#d97706bf}.bg-amber-600\/80{background-color:#d97706cc}.bg-amber-600\/85{background-color:#d97706d9}.bg-amber-600\/90{background-color:#d97706e6}.bg-amber-600\/95{background-color:#d97706f2}.bg-amber-700{--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.bg-amber-700\/0{background-color:#b4530900}.bg-amber-700\/10{background-color:#b453091a}.bg-amber-700\/100{background-color:#b45309}.bg-amber-700\/15{background-color:#b4530926}.bg-amber-700\/20{background-color:#b4530933}.bg-amber-700\/25{background-color:#b4530940}.bg-amber-700\/30{background-color:#b453094d}.bg-amber-700\/35{background-color:#b4530959}.bg-amber-700\/40{background-color:#b4530966}.bg-amber-700\/45{background-color:#b4530973}.bg-amber-700\/5{background-color:#b453090d}.bg-amber-700\/50{background-color:#b4530980}.bg-amber-700\/55{background-color:#b453098c}.bg-amber-700\/60{background-color:#b4530999}.bg-amber-700\/65{background-color:#b45309a6}.bg-amber-700\/70{background-color:#b45309b3}.bg-amber-700\/75{background-color:#b45309bf}.bg-amber-700\/80{background-color:#b45309cc}.bg-amber-700\/85{background-color:#b45309d9}.bg-amber-700\/90{background-color:#b45309e6}.bg-amber-700\/95{background-color:#b45309f2}.bg-amber-800{--tw-bg-opacity: 1;background-color:rgb(146 64 14 / var(--tw-bg-opacity, 1))}.bg-amber-800\/0{background-color:#92400e00}.bg-amber-800\/10{background-color:#92400e1a}.bg-amber-800\/100{background-color:#92400e}.bg-amber-800\/15{background-color:#92400e26}.bg-amber-800\/20{background-color:#92400e33}.bg-amber-800\/25{background-color:#92400e40}.bg-amber-800\/30{background-color:#92400e4d}.bg-amber-800\/35{background-color:#92400e59}.bg-amber-800\/40{background-color:#92400e66}.bg-amber-800\/45{background-color:#92400e73}.bg-amber-800\/5{background-color:#92400e0d}.bg-amber-800\/50{background-color:#92400e80}.bg-amber-800\/55{background-color:#92400e8c}.bg-amber-800\/60{background-color:#92400e99}.bg-amber-800\/65{background-color:#92400ea6}.bg-amber-800\/70{background-color:#92400eb3}.bg-amber-800\/75{background-color:#92400ebf}.bg-amber-800\/80{background-color:#92400ecc}.bg-amber-800\/85{background-color:#92400ed9}.bg-amber-800\/90{background-color:#92400ee6}.bg-amber-800\/95{background-color:#92400ef2}.bg-amber-900{--tw-bg-opacity: 1;background-color:rgb(120 53 15 / var(--tw-bg-opacity, 1))}.bg-amber-900\/0{background-color:#78350f00}.bg-amber-900\/10{background-color:#78350f1a}.bg-amber-900\/100{background-color:#78350f}.bg-amber-900\/15{background-color:#78350f26}.bg-amber-900\/20{background-color:#78350f33}.bg-amber-900\/25{background-color:#78350f40}.bg-amber-900\/30{background-color:#78350f4d}.bg-amber-900\/35{background-color:#78350f59}.bg-amber-900\/40{background-color:#78350f66}.bg-amber-900\/45{background-color:#78350f73}.bg-amber-900\/5{background-color:#78350f0d}.bg-amber-900\/50{background-color:#78350f80}.bg-amber-900\/55{background-color:#78350f8c}.bg-amber-900\/60{background-color:#78350f99}.bg-amber-900\/65{background-color:#78350fa6}.bg-amber-900\/70{background-color:#78350fb3}.bg-amber-900\/75{background-color:#78350fbf}.bg-amber-900\/80{background-color:#78350fcc}.bg-amber-900\/85{background-color:#78350fd9}.bg-amber-900\/90{background-color:#78350fe6}.bg-amber-900\/95{background-color:#78350ff2}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-500{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.bg-gray-500\/0{background-color:#6b728000}.bg-gray-500\/10{background-color:#6b72801a}.bg-gray-500\/100{background-color:#6b7280}.bg-gray-500\/15{background-color:#6b728026}.bg-gray-500\/20{background-color:#6b728033}.bg-gray-500\/25{background-color:#6b728040}.bg-gray-500\/30{background-color:#6b72804d}.bg-gray-500\/35{background-color:#6b728059}.bg-gray-500\/40{background-color:#6b728066}.bg-gray-500\/45{background-color:#6b728073}.bg-gray-500\/5{background-color:#6b72800d}.bg-gray-500\/50{background-color:#6b728080}.bg-gray-500\/55{background-color:#6b72808c}.bg-gray-500\/60{background-color:#6b728099}.bg-gray-500\/65{background-color:#6b7280a6}.bg-gray-500\/70{background-color:#6b7280b3}.bg-gray-500\/75{background-color:#6b7280bf}.bg-gray-500\/80{background-color:#6b7280cc}.bg-gray-500\/85{background-color:#6b7280d9}.bg-gray-500\/90{background-color:#6b7280e6}.bg-gray-500\/95{background-color:#6b7280f2}.bg-gray-600{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.bg-gray-600\/0{background-color:#4b556300}.bg-gray-600\/10{background-color:#4b55631a}.bg-gray-600\/100{background-color:#4b5563}.bg-gray-600\/15{background-color:#4b556326}.bg-gray-600\/20{background-color:#4b556333}.bg-gray-600\/25{background-color:#4b556340}.bg-gray-600\/30{background-color:#4b55634d}.bg-gray-600\/35{background-color:#4b556359}.bg-gray-600\/40{background-color:#4b556366}.bg-gray-600\/45{background-color:#4b556373}.bg-gray-600\/5{background-color:#4b55630d}.bg-gray-600\/50{background-color:#4b556380}.bg-gray-600\/55{background-color:#4b55638c}.bg-gray-600\/60{background-color:#4b556399}.bg-gray-600\/65{background-color:#4b5563a6}.bg-gray-600\/70{background-color:#4b5563b3}.bg-gray-600\/75{background-color:#4b5563bf}.bg-gray-600\/80{background-color:#4b5563cc}.bg-gray-600\/85{background-color:#4b5563d9}.bg-gray-600\/90{background-color:#4b5563e6}.bg-gray-600\/95{background-color:#4b5563f2}.bg-gray-700{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.bg-gray-700\/0{background-color:#37415100}.bg-gray-700\/10{background-color:#3741511a}.bg-gray-700\/100{background-color:#374151}.bg-gray-700\/15{background-color:#37415126}.bg-gray-700\/20{background-color:#37415133}.bg-gray-700\/25{background-color:#37415140}.bg-gray-700\/30{background-color:#3741514d}.bg-gray-700\/35{background-color:#37415159}.bg-gray-700\/40{background-color:#37415166}.bg-gray-700\/45{background-color:#37415173}.bg-gray-700\/5{background-color:#3741510d}.bg-gray-700\/50{background-color:#37415180}.bg-gray-700\/55{background-color:#3741518c}.bg-gray-700\/60{background-color:#37415199}.bg-gray-700\/65{background-color:#374151a6}.bg-gray-700\/70{background-color:#374151b3}.bg-gray-700\/75{background-color:#374151bf}.bg-gray-700\/80{background-color:#374151cc}.bg-gray-700\/85{background-color:#374151d9}.bg-gray-700\/90{background-color:#374151e6}.bg-gray-700\/95{background-color:#374151f2}.bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-gray-800\/0{background-color:#1f293700}.bg-gray-800\/10{background-color:#1f29371a}.bg-gray-800\/100{background-color:#1f2937}.bg-gray-800\/15{background-color:#1f293726}.bg-gray-800\/20{background-color:#1f293733}.bg-gray-800\/25{background-color:#1f293740}.bg-gray-800\/30{background-color:#1f29374d}.bg-gray-800\/35{background-color:#1f293759}.bg-gray-800\/40{background-color:#1f293766}.bg-gray-800\/45{background-color:#1f293773}.bg-gray-800\/5{background-color:#1f29370d}.bg-gray-800\/50{background-color:#1f293780}.bg-gray-800\/55{background-color:#1f29378c}.bg-gray-800\/60{background-color:#1f293799}.bg-gray-800\/65{background-color:#1f2937a6}.bg-gray-800\/70{background-color:#1f2937b3}.bg-gray-800\/75{background-color:#1f2937bf}.bg-gray-800\/80{background-color:#1f2937cc}.bg-gray-800\/85{background-color:#1f2937d9}.bg-gray-800\/90{background-color:#1f2937e6}.bg-gray-800\/95{background-color:#1f2937f2}.bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.bg-gray-900\/0{background-color:#11182700}.bg-gray-900\/10{background-color:#1118271a}.bg-gray-900\/100{background-color:#111827}.bg-gray-900\/15{background-color:#11182726}.bg-gray-900\/20{background-color:#11182733}.bg-gray-900\/25{background-color:#11182740}.bg-gray-900\/30{background-color:#1118274d}.bg-gray-900\/35{background-color:#11182759}.bg-gray-900\/40{background-color:#11182766}.bg-gray-900\/45{background-color:#11182773}.bg-gray-900\/5{background-color:#1118270d}.bg-gray-900\/50{background-color:#11182780}.bg-gray-900\/55{background-color:#1118278c}.bg-gray-900\/60{background-color:#11182799}.bg-gray-900\/65{background-color:#111827a6}.bg-gray-900\/70{background-color:#111827b3}.bg-gray-900\/75{background-color:#111827bf}.bg-gray-900\/80{background-color:#111827cc}.bg-gray-900\/85{background-color:#111827d9}.bg-gray-900\/90{background-color:#111827e6}.bg-gray-900\/95{background-color:#111827f2}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/0{background-color:#22c55e00}.bg-green-500\/10{background-color:#22c55e1a}.bg-green-500\/100{background-color:#22c55e}.bg-green-500\/15{background-color:#22c55e26}.bg-green-500\/20{background-color:#22c55e33}.bg-green-500\/25{background-color:#22c55e40}.bg-green-500\/30{background-color:#22c55e4d}.bg-green-500\/35{background-color:#22c55e59}.bg-green-500\/40{background-color:#22c55e66}.bg-green-500\/45{background-color:#22c55e73}.bg-green-500\/5{background-color:#22c55e0d}.bg-green-500\/50{background-color:#22c55e80}.bg-green-500\/55{background-color:#22c55e8c}.bg-green-500\/60{background-color:#22c55e99}.bg-green-500\/65{background-color:#22c55ea6}.bg-green-500\/70{background-color:#22c55eb3}.bg-green-500\/75{background-color:#22c55ebf}.bg-green-500\/80{background-color:#22c55ecc}.bg-green-500\/85{background-color:#22c55ed9}.bg-green-500\/90{background-color:#22c55ee6}.bg-green-500\/95{background-color:#22c55ef2}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-green-600\/0{background-color:#16a34a00}.bg-green-600\/10{background-color:#16a34a1a}.bg-green-600\/100{background-color:#16a34a}.bg-green-600\/15{background-color:#16a34a26}.bg-green-600\/20{background-color:#16a34a33}.bg-green-600\/25{background-color:#16a34a40}.bg-green-600\/30{background-color:#16a34a4d}.bg-green-600\/35{background-color:#16a34a59}.bg-green-600\/40{background-color:#16a34a66}.bg-green-600\/45{background-color:#16a34a73}.bg-green-600\/5{background-color:#16a34a0d}.bg-green-600\/50{background-color:#16a34a80}.bg-green-600\/55{background-color:#16a34a8c}.bg-green-600\/60{background-color:#16a34a99}.bg-green-600\/65{background-color:#16a34aa6}.bg-green-600\/70{background-color:#16a34ab3}.bg-green-600\/75{background-color:#16a34abf}.bg-green-600\/80{background-color:#16a34acc}.bg-green-600\/85{background-color:#16a34ad9}.bg-green-600\/90{background-color:#16a34ae6}.bg-green-600\/95{background-color:#16a34af2}.bg-green-700{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.bg-green-700\/0{background-color:#15803d00}.bg-green-700\/10{background-color:#15803d1a}.bg-green-700\/100{background-color:#15803d}.bg-green-700\/15{background-color:#15803d26}.bg-green-700\/20{background-color:#15803d33}.bg-green-700\/25{background-color:#15803d40}.bg-green-700\/30{background-color:#15803d4d}.bg-green-700\/35{background-color:#15803d59}.bg-green-700\/40{background-color:#15803d66}.bg-green-700\/45{background-color:#15803d73}.bg-green-700\/5{background-color:#15803d0d}.bg-green-700\/50{background-color:#15803d80}.bg-green-700\/55{background-color:#15803d8c}.bg-green-700\/60{background-color:#15803d99}.bg-green-700\/65{background-color:#15803da6}.bg-green-700\/70{background-color:#15803db3}.bg-green-700\/75{background-color:#15803dbf}.bg-green-700\/80{background-color:#15803dcc}.bg-green-700\/85{background-color:#15803dd9}.bg-green-700\/90{background-color:#15803de6}.bg-green-700\/95{background-color:#15803df2}.bg-green-800{--tw-bg-opacity: 1;background-color:rgb(22 101 52 / var(--tw-bg-opacity, 1))}.bg-green-800\/0{background-color:#16653400}.bg-green-800\/10{background-color:#1665341a}.bg-green-800\/100{background-color:#166534}.bg-green-800\/15{background-color:#16653426}.bg-green-800\/20{background-color:#16653433}.bg-green-800\/25{background-color:#16653440}.bg-green-800\/30{background-color:#1665344d}.bg-green-800\/35{background-color:#16653459}.bg-green-800\/40{background-color:#16653466}.bg-green-800\/45{background-color:#16653473}.bg-green-800\/5{background-color:#1665340d}.bg-green-800\/50{background-color:#16653480}.bg-green-800\/55{background-color:#1665348c}.bg-green-800\/60{background-color:#16653499}.bg-green-800\/65{background-color:#166534a6}.bg-green-800\/70{background-color:#166534b3}.bg-green-800\/75{background-color:#166534bf}.bg-green-800\/80{background-color:#166534cc}.bg-green-800\/85{background-color:#166534d9}.bg-green-800\/90{background-color:#166534e6}.bg-green-800\/95{background-color:#166534f2}.bg-green-900{--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.bg-green-900\/0{background-color:#14532d00}.bg-green-900\/10{background-color:#14532d1a}.bg-green-900\/100{background-color:#14532d}.bg-green-900\/15{background-color:#14532d26}.bg-green-900\/20{background-color:#14532d33}.bg-green-900\/25{background-color:#14532d40}.bg-green-900\/30{background-color:#14532d4d}.bg-green-900\/35{background-color:#14532d59}.bg-green-900\/40{background-color:#14532d66}.bg-green-900\/45{background-color:#14532d73}.bg-green-900\/5{background-color:#14532d0d}.bg-green-900\/50{background-color:#14532d80}.bg-green-900\/55{background-color:#14532d8c}.bg-green-900\/60{background-color:#14532d99}.bg-green-900\/65{background-color:#14532da6}.bg-green-900\/70{background-color:#14532db3}.bg-green-900\/75{background-color:#14532dbf}.bg-green-900\/80{background-color:#14532dcc}.bg-green-900\/85{background-color:#14532dd9}.bg-green-900\/90{background-color:#14532de6}.bg-green-900\/95{background-color:#14532df2}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-orange-800{--tw-bg-opacity: 1;background-color:rgb(154 52 18 / var(--tw-bg-opacity, 1))}.bg-purple-500{--tw-bg-opacity: 1;background-color:rgb(168 85 247 / var(--tw-bg-opacity, 1))}.bg-purple-500\/0{background-color:#a855f700}.bg-purple-500\/10{background-color:#a855f71a}.bg-purple-500\/100{background-color:#a855f7}.bg-purple-500\/15{background-color:#a855f726}.bg-purple-500\/20{background-color:#a855f733}.bg-purple-500\/25{background-color:#a855f740}.bg-purple-500\/30{background-color:#a855f74d}.bg-purple-500\/35{background-color:#a855f759}.bg-purple-500\/40{background-color:#a855f766}.bg-purple-500\/45{background-color:#a855f773}.bg-purple-500\/5{background-color:#a855f70d}.bg-purple-500\/50{background-color:#a855f780}.bg-purple-500\/55{background-color:#a855f78c}.bg-purple-500\/60{background-color:#a855f799}.bg-purple-500\/65{background-color:#a855f7a6}.bg-purple-500\/70{background-color:#a855f7b3}.bg-purple-500\/75{background-color:#a855f7bf}.bg-purple-500\/80{background-color:#a855f7cc}.bg-purple-500\/85{background-color:#a855f7d9}.bg-purple-500\/90{background-color:#a855f7e6}.bg-purple-500\/95{background-color:#a855f7f2}.bg-purple-600{--tw-bg-opacity: 1;background-color:rgb(147 51 234 / var(--tw-bg-opacity, 1))}.bg-purple-600\/0{background-color:#9333ea00}.bg-purple-600\/10{background-color:#9333ea1a}.bg-purple-600\/100{background-color:#9333ea}.bg-purple-600\/15{background-color:#9333ea26}.bg-purple-600\/20{background-color:#9333ea33}.bg-purple-600\/25{background-color:#9333ea40}.bg-purple-600\/30{background-color:#9333ea4d}.bg-purple-600\/35{background-color:#9333ea59}.bg-purple-600\/40{background-color:#9333ea66}.bg-purple-600\/45{background-color:#9333ea73}.bg-purple-600\/5{background-color:#9333ea0d}.bg-purple-600\/50{background-color:#9333ea80}.bg-purple-600\/55{background-color:#9333ea8c}.bg-purple-600\/60{background-color:#9333ea99}.bg-purple-600\/65{background-color:#9333eaa6}.bg-purple-600\/70{background-color:#9333eab3}.bg-purple-600\/75{background-color:#9333eabf}.bg-purple-600\/80{background-color:#9333eacc}.bg-purple-600\/85{background-color:#9333ead9}.bg-purple-600\/90{background-color:#9333eae6}.bg-purple-600\/95{background-color:#9333eaf2}.bg-purple-700{--tw-bg-opacity: 1;background-color:rgb(126 34 206 / var(--tw-bg-opacity, 1))}.bg-purple-700\/0{background-color:#7e22ce00}.bg-purple-700\/10{background-color:#7e22ce1a}.bg-purple-700\/100{background-color:#7e22ce}.bg-purple-700\/15{background-color:#7e22ce26}.bg-purple-700\/20{background-color:#7e22ce33}.bg-purple-700\/25{background-color:#7e22ce40}.bg-purple-700\/30{background-color:#7e22ce4d}.bg-purple-700\/35{background-color:#7e22ce59}.bg-purple-700\/40{background-color:#7e22ce66}.bg-purple-700\/45{background-color:#7e22ce73}.bg-purple-700\/5{background-color:#7e22ce0d}.bg-purple-700\/50{background-color:#7e22ce80}.bg-purple-700\/55{background-color:#7e22ce8c}.bg-purple-700\/60{background-color:#7e22ce99}.bg-purple-700\/65{background-color:#7e22cea6}.bg-purple-700\/70{background-color:#7e22ceb3}.bg-purple-700\/75{background-color:#7e22cebf}.bg-purple-700\/80{background-color:#7e22cecc}.bg-purple-700\/85{background-color:#7e22ced9}.bg-purple-700\/90{background-color:#7e22cee6}.bg-purple-700\/95{background-color:#7e22cef2}.bg-purple-800{--tw-bg-opacity: 1;background-color:rgb(107 33 168 / var(--tw-bg-opacity, 1))}.bg-purple-800\/0{background-color:#6b21a800}.bg-purple-800\/10{background-color:#6b21a81a}.bg-purple-800\/100{background-color:#6b21a8}.bg-purple-800\/15{background-color:#6b21a826}.bg-purple-800\/20{background-color:#6b21a833}.bg-purple-800\/25{background-color:#6b21a840}.bg-purple-800\/30{background-color:#6b21a84d}.bg-purple-800\/35{background-color:#6b21a859}.bg-purple-800\/40{background-color:#6b21a866}.bg-purple-800\/45{background-color:#6b21a873}.bg-purple-800\/5{background-color:#6b21a80d}.bg-purple-800\/50{background-color:#6b21a880}.bg-purple-800\/55{background-color:#6b21a88c}.bg-purple-800\/60{background-color:#6b21a899}.bg-purple-800\/65{background-color:#6b21a8a6}.bg-purple-800\/70{background-color:#6b21a8b3}.bg-purple-800\/75{background-color:#6b21a8bf}.bg-purple-800\/80{background-color:#6b21a8cc}.bg-purple-800\/85{background-color:#6b21a8d9}.bg-purple-800\/90{background-color:#6b21a8e6}.bg-purple-800\/95{background-color:#6b21a8f2}.bg-purple-900{--tw-bg-opacity: 1;background-color:rgb(88 28 135 / var(--tw-bg-opacity, 1))}.bg-purple-900\/0{background-color:#581c8700}.bg-purple-900\/10{background-color:#581c871a}.bg-purple-900\/100{background-color:#581c87}.bg-purple-900\/15{background-color:#581c8726}.bg-purple-900\/20{background-color:#581c8733}.bg-purple-900\/25{background-color:#581c8740}.bg-purple-900\/30{background-color:#581c874d}.bg-purple-900\/35{background-color:#581c8759}.bg-purple-900\/40{background-color:#581c8766}.bg-purple-900\/45{background-color:#581c8773}.bg-purple-900\/5{background-color:#581c870d}.bg-purple-900\/50{background-color:#581c8780}.bg-purple-900\/55{background-color:#581c878c}.bg-purple-900\/60{background-color:#581c8799}.bg-purple-900\/65{background-color:#581c87a6}.bg-purple-900\/70{background-color:#581c87b3}.bg-purple-900\/75{background-color:#581c87bf}.bg-purple-900\/80{background-color:#581c87cc}.bg-purple-900\/85{background-color:#581c87d9}.bg-purple-900\/90{background-color:#581c87e6}.bg-purple-900\/95{background-color:#581c87f2}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/0{background-color:#ef444400}.bg-red-500\/10{background-color:#ef44441a}.bg-red-500\/100{background-color:#ef4444}.bg-red-500\/15{background-color:#ef444426}.bg-red-500\/20{background-color:#ef444433}.bg-red-500\/25{background-color:#ef444440}.bg-red-500\/30{background-color:#ef44444d}.bg-red-500\/35{background-color:#ef444459}.bg-red-500\/40{background-color:#ef444466}.bg-red-500\/45{background-color:#ef444473}.bg-red-500\/5{background-color:#ef44440d}.bg-red-500\/50{background-color:#ef444480}.bg-red-500\/55{background-color:#ef44448c}.bg-red-500\/60{background-color:#ef444499}.bg-red-500\/65{background-color:#ef4444a6}.bg-red-500\/70{background-color:#ef4444b3}.bg-red-500\/75{background-color:#ef4444bf}.bg-red-500\/80{background-color:#ef4444cc}.bg-red-500\/85{background-color:#ef4444d9}.bg-red-500\/90{background-color:#ef4444e6}.bg-red-500\/95{background-color:#ef4444f2}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-red-600\/0{background-color:#dc262600}.bg-red-600\/10{background-color:#dc26261a}.bg-red-600\/100{background-color:#dc2626}.bg-red-600\/15{background-color:#dc262626}.bg-red-600\/20{background-color:#dc262633}.bg-red-600\/25{background-color:#dc262640}.bg-red-600\/30{background-color:#dc26264d}.bg-red-600\/35{background-color:#dc262659}.bg-red-600\/40{background-color:#dc262666}.bg-red-600\/45{background-color:#dc262673}.bg-red-600\/5{background-color:#dc26260d}.bg-red-600\/50{background-color:#dc262680}.bg-red-600\/55{background-color:#dc26268c}.bg-red-600\/60{background-color:#dc262699}.bg-red-600\/65{background-color:#dc2626a6}.bg-red-600\/70{background-color:#dc2626b3}.bg-red-600\/75{background-color:#dc2626bf}.bg-red-600\/80{background-color:#dc2626cc}.bg-red-600\/85{background-color:#dc2626d9}.bg-red-600\/90{background-color:#dc2626e6}.bg-red-600\/95{background-color:#dc2626f2}.bg-red-700{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.bg-red-700\/0{background-color:#b91c1c00}.bg-red-700\/10{background-color:#b91c1c1a}.bg-red-700\/100{background-color:#b91c1c}.bg-red-700\/15{background-color:#b91c1c26}.bg-red-700\/20{background-color:#b91c1c33}.bg-red-700\/25{background-color:#b91c1c40}.bg-red-700\/30{background-color:#b91c1c4d}.bg-red-700\/35{background-color:#b91c1c59}.bg-red-700\/40{background-color:#b91c1c66}.bg-red-700\/45{background-color:#b91c1c73}.bg-red-700\/5{background-color:#b91c1c0d}.bg-red-700\/50{background-color:#b91c1c80}.bg-red-700\/55{background-color:#b91c1c8c}.bg-red-700\/60{background-color:#b91c1c99}.bg-red-700\/65{background-color:#b91c1ca6}.bg-red-700\/70{background-color:#b91c1cb3}.bg-red-700\/75{background-color:#b91c1cbf}.bg-red-700\/80{background-color:#b91c1ccc}.bg-red-700\/85{background-color:#b91c1cd9}.bg-red-700\/90{background-color:#b91c1ce6}.bg-red-700\/95{background-color:#b91c1cf2}.bg-red-800{--tw-bg-opacity: 1;background-color:rgb(153 27 27 / var(--tw-bg-opacity, 1))}.bg-red-800\/0{background-color:#991b1b00}.bg-red-800\/10{background-color:#991b1b1a}.bg-red-800\/100{background-color:#991b1b}.bg-red-800\/15{background-color:#991b1b26}.bg-red-800\/20{background-color:#991b1b33}.bg-red-800\/25{background-color:#991b1b40}.bg-red-800\/30{background-color:#991b1b4d}.bg-red-800\/35{background-color:#991b1b59}.bg-red-800\/40{background-color:#991b1b66}.bg-red-800\/45{background-color:#991b1b73}.bg-red-800\/5{background-color:#991b1b0d}.bg-red-800\/50{background-color:#991b1b80}.bg-red-800\/55{background-color:#991b1b8c}.bg-red-800\/60{background-color:#991b1b99}.bg-red-800\/65{background-color:#991b1ba6}.bg-red-800\/70{background-color:#991b1bb3}.bg-red-800\/75{background-color:#991b1bbf}.bg-red-800\/80{background-color:#991b1bcc}.bg-red-800\/85{background-color:#991b1bd9}.bg-red-800\/90{background-color:#991b1be6}.bg-red-800\/95{background-color:#991b1bf2}.bg-red-900{--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.bg-red-900\/0{background-color:#7f1d1d00}.bg-red-900\/10{background-color:#7f1d1d1a}.bg-red-900\/100{background-color:#7f1d1d}.bg-red-900\/15{background-color:#7f1d1d26}.bg-red-900\/20{background-color:#7f1d1d33}.bg-red-900\/25{background-color:#7f1d1d40}.bg-red-900\/30{background-color:#7f1d1d4d}.bg-red-900\/35{background-color:#7f1d1d59}.bg-red-900\/40{background-color:#7f1d1d66}.bg-red-900\/45{background-color:#7f1d1d73}.bg-red-900\/5{background-color:#7f1d1d0d}.bg-red-900\/50{background-color:#7f1d1d80}.bg-red-900\/55{background-color:#7f1d1d8c}.bg-red-900\/60{background-color:#7f1d1d99}.bg-red-900\/65{background-color:#7f1d1da6}.bg-red-900\/70{background-color:#7f1d1db3}.bg-red-900\/75{background-color:#7f1d1dbf}.bg-red-900\/80{background-color:#7f1d1dcc}.bg-red-900\/85{background-color:#7f1d1dd9}.bg-red-900\/90{background-color:#7f1d1de6}.bg-red-900\/95{background-color:#7f1d1df2}.bg-sky-500{--tw-bg-opacity: 1;background-color:rgb(14 165 233 / var(--tw-bg-opacity, 1))}.bg-sky-800{--tw-bg-opacity: 1;background-color:rgb(7 89 133 / var(--tw-bg-opacity, 1))}.bg-sky-900\/20{background-color:#0c4a6e33}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.bg-yellow-500\/0{background-color:#eab30800}.bg-yellow-500\/10{background-color:#eab3081a}.bg-yellow-500\/100{background-color:#eab308}.bg-yellow-500\/15{background-color:#eab30826}.bg-yellow-500\/20{background-color:#eab30833}.bg-yellow-500\/25{background-color:#eab30840}.bg-yellow-500\/30{background-color:#eab3084d}.bg-yellow-500\/35{background-color:#eab30859}.bg-yellow-500\/40{background-color:#eab30866}.bg-yellow-500\/45{background-color:#eab30873}.bg-yellow-500\/5{background-color:#eab3080d}.bg-yellow-500\/50{background-color:#eab30880}.bg-yellow-500\/55{background-color:#eab3088c}.bg-yellow-500\/60{background-color:#eab30899}.bg-yellow-500\/65{background-color:#eab308a6}.bg-yellow-500\/70{background-color:#eab308b3}.bg-yellow-500\/75{background-color:#eab308bf}.bg-yellow-500\/80{background-color:#eab308cc}.bg-yellow-500\/85{background-color:#eab308d9}.bg-yellow-500\/90{background-color:#eab308e6}.bg-yellow-500\/95{background-color:#eab308f2}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-yellow-600\/0{background-color:#ca8a0400}.bg-yellow-600\/10{background-color:#ca8a041a}.bg-yellow-600\/100{background-color:#ca8a04}.bg-yellow-600\/15{background-color:#ca8a0426}.bg-yellow-600\/20{background-color:#ca8a0433}.bg-yellow-600\/25{background-color:#ca8a0440}.bg-yellow-600\/30{background-color:#ca8a044d}.bg-yellow-600\/35{background-color:#ca8a0459}.bg-yellow-600\/40{background-color:#ca8a0466}.bg-yellow-600\/45{background-color:#ca8a0473}.bg-yellow-600\/5{background-color:#ca8a040d}.bg-yellow-600\/50{background-color:#ca8a0480}.bg-yellow-600\/55{background-color:#ca8a048c}.bg-yellow-600\/60{background-color:#ca8a0499}.bg-yellow-600\/65{background-color:#ca8a04a6}.bg-yellow-600\/70{background-color:#ca8a04b3}.bg-yellow-600\/75{background-color:#ca8a04bf}.bg-yellow-600\/80{background-color:#ca8a04cc}.bg-yellow-600\/85{background-color:#ca8a04d9}.bg-yellow-600\/90{background-color:#ca8a04e6}.bg-yellow-600\/95{background-color:#ca8a04f2}.bg-yellow-700{--tw-bg-opacity: 1;background-color:rgb(161 98 7 / var(--tw-bg-opacity, 1))}.bg-yellow-700\/0{background-color:#a1620700}.bg-yellow-700\/10{background-color:#a162071a}.bg-yellow-700\/100{background-color:#a16207}.bg-yellow-700\/15{background-color:#a1620726}.bg-yellow-700\/20{background-color:#a1620733}.bg-yellow-700\/25{background-color:#a1620740}.bg-yellow-700\/30{background-color:#a162074d}.bg-yellow-700\/35{background-color:#a1620759}.bg-yellow-700\/40{background-color:#a1620766}.bg-yellow-700\/45{background-color:#a1620773}.bg-yellow-700\/5{background-color:#a162070d}.bg-yellow-700\/50{background-color:#a1620780}.bg-yellow-700\/55{background-color:#a162078c}.bg-yellow-700\/60{background-color:#a1620799}.bg-yellow-700\/65{background-color:#a16207a6}.bg-yellow-700\/70{background-color:#a16207b3}.bg-yellow-700\/75{background-color:#a16207bf}.bg-yellow-700\/80{background-color:#a16207cc}.bg-yellow-700\/85{background-color:#a16207d9}.bg-yellow-700\/90{background-color:#a16207e6}.bg-yellow-700\/95{background-color:#a16207f2}.bg-yellow-800{--tw-bg-opacity: 1;background-color:rgb(133 77 14 / var(--tw-bg-opacity, 1))}.bg-yellow-800\/0{background-color:#854d0e00}.bg-yellow-800\/10{background-color:#854d0e1a}.bg-yellow-800\/100{background-color:#854d0e}.bg-yellow-800\/15{background-color:#854d0e26}.bg-yellow-800\/20{background-color:#854d0e33}.bg-yellow-800\/25{background-color:#854d0e40}.bg-yellow-800\/30{background-color:#854d0e4d}.bg-yellow-800\/35{background-color:#854d0e59}.bg-yellow-800\/40{background-color:#854d0e66}.bg-yellow-800\/45{background-color:#854d0e73}.bg-yellow-800\/5{background-color:#854d0e0d}.bg-yellow-800\/50{background-color:#854d0e80}.bg-yellow-800\/55{background-color:#854d0e8c}.bg-yellow-800\/60{background-color:#854d0e99}.bg-yellow-800\/65{background-color:#854d0ea6}.bg-yellow-800\/70{background-color:#854d0eb3}.bg-yellow-800\/75{background-color:#854d0ebf}.bg-yellow-800\/80{background-color:#854d0ecc}.bg-yellow-800\/85{background-color:#854d0ed9}.bg-yellow-800\/90{background-color:#854d0ee6}.bg-yellow-800\/95{background-color:#854d0ef2}.bg-yellow-900{--tw-bg-opacity: 1;background-color:rgb(113 63 18 / var(--tw-bg-opacity, 1))}.bg-yellow-900\/0{background-color:#713f1200}.bg-yellow-900\/10{background-color:#713f121a}.bg-yellow-900\/100{background-color:#713f12}.bg-yellow-900\/15{background-color:#713f1226}.bg-yellow-900\/20{background-color:#713f1233}.bg-yellow-900\/25{background-color:#713f1240}.bg-yellow-900\/30{background-color:#713f124d}.bg-yellow-900\/35{background-color:#713f1259}.bg-yellow-900\/40{background-color:#713f1266}.bg-yellow-900\/45{background-color:#713f1273}.bg-yellow-900\/5{background-color:#713f120d}.bg-yellow-900\/50{background-color:#713f1280}.bg-yellow-900\/55{background-color:#713f128c}.bg-yellow-900\/60{background-color:#713f1299}.bg-yellow-900\/65{background-color:#713f12a6}.bg-yellow-900\/70{background-color:#713f12b3}.bg-yellow-900\/75{background-color:#713f12bf}.bg-yellow-900\/80{background-color:#713f12cc}.bg-yellow-900\/85{background-color:#713f12d9}.bg-yellow-900\/90{background-color:#713f12e6}.bg-yellow-900\/95{background-color:#713f12f2}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-3{padding-right:.75rem}.pt-10{padding-top:2.5rem}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-5{line-height:1.25rem}.text-amber-200{--tw-text-opacity: 1;color:rgb(253 230 138 / var(--tw-text-opacity, 1))}.text-amber-200\/0{color:#fde68a00}.text-amber-200\/10{color:#fde68a1a}.text-amber-200\/100{color:#fde68a}.text-amber-200\/15{color:#fde68a26}.text-amber-200\/20{color:#fde68a33}.text-amber-200\/25{color:#fde68a40}.text-amber-200\/30{color:#fde68a4d}.text-amber-200\/35{color:#fde68a59}.text-amber-200\/40{color:#fde68a66}.text-amber-200\/45{color:#fde68a73}.text-amber-200\/5{color:#fde68a0d}.text-amber-200\/50{color:#fde68a80}.text-amber-200\/55{color:#fde68a8c}.text-amber-200\/60{color:#fde68a99}.text-amber-200\/65{color:#fde68aa6}.text-amber-200\/70{color:#fde68ab3}.text-amber-200\/75{color:#fde68abf}.text-amber-200\/80{color:#fde68acc}.text-amber-200\/85{color:#fde68ad9}.text-amber-200\/90{color:#fde68ae6}.text-amber-200\/95{color:#fde68af2}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-300\/0{color:#fcd34d00}.text-amber-300\/10{color:#fcd34d1a}.text-amber-300\/100{color:#fcd34d}.text-amber-300\/15{color:#fcd34d26}.text-amber-300\/20{color:#fcd34d33}.text-amber-300\/25{color:#fcd34d40}.text-amber-300\/30{color:#fcd34d4d}.text-amber-300\/35{color:#fcd34d59}.text-amber-300\/40{color:#fcd34d66}.text-amber-300\/45{color:#fcd34d73}.text-amber-300\/5{color:#fcd34d0d}.text-amber-300\/50{color:#fcd34d80}.text-amber-300\/55{color:#fcd34d8c}.text-amber-300\/60{color:#fcd34d99}.text-amber-300\/65{color:#fcd34da6}.text-amber-300\/70{color:#fcd34db3}.text-amber-300\/75{color:#fcd34dbf}.text-amber-300\/80{color:#fcd34dcc}.text-amber-300\/85{color:#fcd34dd9}.text-amber-300\/90{color:#fcd34de6}.text-amber-300\/95{color:#fcd34df2}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-400\/0{color:#fbbf2400}.text-amber-400\/10{color:#fbbf241a}.text-amber-400\/100{color:#fbbf24}.text-amber-400\/15{color:#fbbf2426}.text-amber-400\/20{color:#fbbf2433}.text-amber-400\/25{color:#fbbf2440}.text-amber-400\/30{color:#fbbf244d}.text-amber-400\/35{color:#fbbf2459}.text-amber-400\/40{color:#fbbf2466}.text-amber-400\/45{color:#fbbf2473}.text-amber-400\/5{color:#fbbf240d}.text-amber-400\/50{color:#fbbf2480}.text-amber-400\/55{color:#fbbf248c}.text-amber-400\/60{color:#fbbf2499}.text-amber-400\/65{color:#fbbf24a6}.text-amber-400\/70{color:#fbbf24b3}.text-amber-400\/75{color:#fbbf24bf}.text-amber-400\/80{color:#fbbf24cc}.text-amber-400\/85{color:#fbbf24d9}.text-amber-400\/90{color:#fbbf24e6}.text-amber-400\/95{color:#fbbf24f2}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.text-gray-200\/0{color:#e5e7eb00}.text-gray-200\/10{color:#e5e7eb1a}.text-gray-200\/100{color:#e5e7eb}.text-gray-200\/15{color:#e5e7eb26}.text-gray-200\/20{color:#e5e7eb33}.text-gray-200\/25{color:#e5e7eb40}.text-gray-200\/30{color:#e5e7eb4d}.text-gray-200\/35{color:#e5e7eb59}.text-gray-200\/40{color:#e5e7eb66}.text-gray-200\/45{color:#e5e7eb73}.text-gray-200\/5{color:#e5e7eb0d}.text-gray-200\/50{color:#e5e7eb80}.text-gray-200\/55{color:#e5e7eb8c}.text-gray-200\/60{color:#e5e7eb99}.text-gray-200\/65{color:#e5e7eba6}.text-gray-200\/70{color:#e5e7ebb3}.text-gray-200\/75{color:#e5e7ebbf}.text-gray-200\/80{color:#e5e7ebcc}.text-gray-200\/85{color:#e5e7ebd9}.text-gray-200\/90{color:#e5e7ebe6}.text-gray-200\/95{color:#e5e7ebf2}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-300\/0{color:#d1d5db00}.text-gray-300\/10{color:#d1d5db1a}.text-gray-300\/100{color:#d1d5db}.text-gray-300\/15{color:#d1d5db26}.text-gray-300\/20{color:#d1d5db33}.text-gray-300\/25{color:#d1d5db40}.text-gray-300\/30{color:#d1d5db4d}.text-gray-300\/35{color:#d1d5db59}.text-gray-300\/40{color:#d1d5db66}.text-gray-300\/45{color:#d1d5db73}.text-gray-300\/5{color:#d1d5db0d}.text-gray-300\/50{color:#d1d5db80}.text-gray-300\/55{color:#d1d5db8c}.text-gray-300\/60{color:#d1d5db99}.text-gray-300\/65{color:#d1d5dba6}.text-gray-300\/70{color:#d1d5dbb3}.text-gray-300\/75{color:#d1d5dbbf}.text-gray-300\/80{color:#d1d5dbcc}.text-gray-300\/85{color:#d1d5dbd9}.text-gray-300\/90{color:#d1d5dbe6}.text-gray-300\/95{color:#d1d5dbf2}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-400\/0{color:#9ca3af00}.text-gray-400\/10{color:#9ca3af1a}.text-gray-400\/100{color:#9ca3af}.text-gray-400\/15{color:#9ca3af26}.text-gray-400\/20{color:#9ca3af33}.text-gray-400\/25{color:#9ca3af40}.text-gray-400\/30{color:#9ca3af4d}.text-gray-400\/35{color:#9ca3af59}.text-gray-400\/40{color:#9ca3af66}.text-gray-400\/45{color:#9ca3af73}.text-gray-400\/5{color:#9ca3af0d}.text-gray-400\/50{color:#9ca3af80}.text-gray-400\/55{color:#9ca3af8c}.text-gray-400\/60{color:#9ca3af99}.text-gray-400\/65{color:#9ca3afa6}.text-gray-400\/70{color:#9ca3afb3}.text-gray-400\/75{color:#9ca3afbf}.text-gray-400\/80{color:#9ca3afcc}.text-gray-400\/85{color:#9ca3afd9}.text-gray-400\/90{color:#9ca3afe6}.text-gray-400\/95{color:#9ca3aff2}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-green-200{--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.text-green-200\/0{color:#bbf7d000}.text-green-200\/10{color:#bbf7d01a}.text-green-200\/100{color:#bbf7d0}.text-green-200\/15{color:#bbf7d026}.text-green-200\/20{color:#bbf7d033}.text-green-200\/25{color:#bbf7d040}.text-green-200\/30{color:#bbf7d04d}.text-green-200\/35{color:#bbf7d059}.text-green-200\/40{color:#bbf7d066}.text-green-200\/45{color:#bbf7d073}.text-green-200\/5{color:#bbf7d00d}.text-green-200\/50{color:#bbf7d080}.text-green-200\/55{color:#bbf7d08c}.text-green-200\/60{color:#bbf7d099}.text-green-200\/65{color:#bbf7d0a6}.text-green-200\/70{color:#bbf7d0b3}.text-green-200\/75{color:#bbf7d0bf}.text-green-200\/80{color:#bbf7d0cc}.text-green-200\/85{color:#bbf7d0d9}.text-green-200\/90{color:#bbf7d0e6}.text-green-200\/95{color:#bbf7d0f2}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-300\/0{color:#86efac00}.text-green-300\/10{color:#86efac1a}.text-green-300\/100{color:#86efac}.text-green-300\/15{color:#86efac26}.text-green-300\/20{color:#86efac33}.text-green-300\/25{color:#86efac40}.text-green-300\/30{color:#86efac4d}.text-green-300\/35{color:#86efac59}.text-green-300\/40{color:#86efac66}.text-green-300\/45{color:#86efac73}.text-green-300\/5{color:#86efac0d}.text-green-300\/50{color:#86efac80}.text-green-300\/55{color:#86efac8c}.text-green-300\/60{color:#86efac99}.text-green-300\/65{color:#86efaca6}.text-green-300\/70{color:#86efacb3}.text-green-300\/75{color:#86efacbf}.text-green-300\/80{color:#86efaccc}.text-green-300\/85{color:#86efacd9}.text-green-300\/90{color:#86eface6}.text-green-300\/95{color:#86efacf2}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-400\/0{color:#4ade8000}.text-green-400\/10{color:#4ade801a}.text-green-400\/100{color:#4ade80}.text-green-400\/15{color:#4ade8026}.text-green-400\/20{color:#4ade8033}.text-green-400\/25{color:#4ade8040}.text-green-400\/30{color:#4ade804d}.text-green-400\/35{color:#4ade8059}.text-green-400\/40{color:#4ade8066}.text-green-400\/45{color:#4ade8073}.text-green-400\/5{color:#4ade800d}.text-green-400\/50{color:#4ade8080}.text-green-400\/55{color:#4ade808c}.text-green-400\/60{color:#4ade8099}.text-green-400\/65{color:#4ade80a6}.text-green-400\/70{color:#4ade80b3}.text-green-400\/75{color:#4ade80bf}.text-green-400\/80{color:#4ade80cc}.text-green-400\/85{color:#4ade80d9}.text-green-400\/90{color:#4ade80e6}.text-green-400\/95{color:#4ade80f2}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-orange-200{--tw-text-opacity: 1;color:rgb(254 215 170 / var(--tw-text-opacity, 1))}.text-purple-200{--tw-text-opacity: 1;color:rgb(233 213 255 / var(--tw-text-opacity, 1))}.text-purple-200\/0{color:#e9d5ff00}.text-purple-200\/10{color:#e9d5ff1a}.text-purple-200\/100{color:#e9d5ff}.text-purple-200\/15{color:#e9d5ff26}.text-purple-200\/20{color:#e9d5ff33}.text-purple-200\/25{color:#e9d5ff40}.text-purple-200\/30{color:#e9d5ff4d}.text-purple-200\/35{color:#e9d5ff59}.text-purple-200\/40{color:#e9d5ff66}.text-purple-200\/45{color:#e9d5ff73}.text-purple-200\/5{color:#e9d5ff0d}.text-purple-200\/50{color:#e9d5ff80}.text-purple-200\/55{color:#e9d5ff8c}.text-purple-200\/60{color:#e9d5ff99}.text-purple-200\/65{color:#e9d5ffa6}.text-purple-200\/70{color:#e9d5ffb3}.text-purple-200\/75{color:#e9d5ffbf}.text-purple-200\/80{color:#e9d5ffcc}.text-purple-200\/85{color:#e9d5ffd9}.text-purple-200\/90{color:#e9d5ffe6}.text-purple-200\/95{color:#e9d5fff2}.text-purple-300{--tw-text-opacity: 1;color:rgb(216 180 254 / var(--tw-text-opacity, 1))}.text-purple-300\/0{color:#d8b4fe00}.text-purple-300\/10{color:#d8b4fe1a}.text-purple-300\/100{color:#d8b4fe}.text-purple-300\/15{color:#d8b4fe26}.text-purple-300\/20{color:#d8b4fe33}.text-purple-300\/25{color:#d8b4fe40}.text-purple-300\/30{color:#d8b4fe4d}.text-purple-300\/35{color:#d8b4fe59}.text-purple-300\/40{color:#d8b4fe66}.text-purple-300\/45{color:#d8b4fe73}.text-purple-300\/5{color:#d8b4fe0d}.text-purple-300\/50{color:#d8b4fe80}.text-purple-300\/55{color:#d8b4fe8c}.text-purple-300\/60{color:#d8b4fe99}.text-purple-300\/65{color:#d8b4fea6}.text-purple-300\/70{color:#d8b4feb3}.text-purple-300\/75{color:#d8b4febf}.text-purple-300\/80{color:#d8b4fecc}.text-purple-300\/85{color:#d8b4fed9}.text-purple-300\/90{color:#d8b4fee6}.text-purple-300\/95{color:#d8b4fef2}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-purple-400\/0{color:#c084fc00}.text-purple-400\/10{color:#c084fc1a}.text-purple-400\/100{color:#c084fc}.text-purple-400\/15{color:#c084fc26}.text-purple-400\/20{color:#c084fc33}.text-purple-400\/25{color:#c084fc40}.text-purple-400\/30{color:#c084fc4d}.text-purple-400\/35{color:#c084fc59}.text-purple-400\/40{color:#c084fc66}.text-purple-400\/45{color:#c084fc73}.text-purple-400\/5{color:#c084fc0d}.text-purple-400\/50{color:#c084fc80}.text-purple-400\/55{color:#c084fc8c}.text-purple-400\/60{color:#c084fc99}.text-purple-400\/65{color:#c084fca6}.text-purple-400\/70{color:#c084fcb3}.text-purple-400\/75{color:#c084fcbf}.text-purple-400\/80{color:#c084fccc}.text-purple-400\/85{color:#c084fcd9}.text-purple-400\/90{color:#c084fce6}.text-purple-400\/95{color:#c084fcf2}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-200\/0{color:#fecaca00}.text-red-200\/10{color:#fecaca1a}.text-red-200\/100{color:#fecaca}.text-red-200\/15{color:#fecaca26}.text-red-200\/20{color:#fecaca33}.text-red-200\/25{color:#fecaca40}.text-red-200\/30{color:#fecaca4d}.text-red-200\/35{color:#fecaca59}.text-red-200\/40{color:#fecaca66}.text-red-200\/45{color:#fecaca73}.text-red-200\/5{color:#fecaca0d}.text-red-200\/50{color:#fecaca80}.text-red-200\/55{color:#fecaca8c}.text-red-200\/60{color:#fecaca99}.text-red-200\/65{color:#fecacaa6}.text-red-200\/70{color:#fecacab3}.text-red-200\/75{color:#fecacabf}.text-red-200\/80{color:#fecacacc}.text-red-200\/85{color:#fecacad9}.text-red-200\/90{color:#fecacae6}.text-red-200\/95{color:#fecacaf2}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-300\/0{color:#fca5a500}.text-red-300\/10{color:#fca5a51a}.text-red-300\/100{color:#fca5a5}.text-red-300\/15{color:#fca5a526}.text-red-300\/20{color:#fca5a533}.text-red-300\/25{color:#fca5a540}.text-red-300\/30{color:#fca5a54d}.text-red-300\/35{color:#fca5a559}.text-red-300\/40{color:#fca5a566}.text-red-300\/45{color:#fca5a573}.text-red-300\/5{color:#fca5a50d}.text-red-300\/50{color:#fca5a580}.text-red-300\/55{color:#fca5a58c}.text-red-300\/60{color:#fca5a599}.text-red-300\/65{color:#fca5a5a6}.text-red-300\/70{color:#fca5a5b3}.text-red-300\/75{color:#fca5a5bf}.text-red-300\/80{color:#fca5a5cc}.text-red-300\/85{color:#fca5a5d9}.text-red-300\/90{color:#fca5a5e6}.text-red-300\/95{color:#fca5a5f2}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-400\/0{color:#f8717100}.text-red-400\/10{color:#f871711a}.text-red-400\/100{color:#f87171}.text-red-400\/15{color:#f8717126}.text-red-400\/20{color:#f8717133}.text-red-400\/25{color:#f8717140}.text-red-400\/30{color:#f871714d}.text-red-400\/35{color:#f8717159}.text-red-400\/40{color:#f8717166}.text-red-400\/45{color:#f8717173}.text-red-400\/5{color:#f871710d}.text-red-400\/50{color:#f8717180}.text-red-400\/55{color:#f871718c}.text-red-400\/60{color:#f8717199}.text-red-400\/65{color:#f87171a6}.text-red-400\/70{color:#f87171b3}.text-red-400\/75{color:#f87171bf}.text-red-400\/80{color:#f87171cc}.text-red-400\/85{color:#f87171d9}.text-red-400\/90{color:#f87171e6}.text-red-400\/95{color:#f87171f2}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-sky-200{--tw-text-opacity: 1;color:rgb(186 230 253 / var(--tw-text-opacity, 1))}.text-sky-400{--tw-text-opacity: 1;color:rgb(56 189 248 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-200{--tw-text-opacity: 1;color:rgb(254 240 138 / var(--tw-text-opacity, 1))}.text-yellow-200\/0{color:#fef08a00}.text-yellow-200\/10{color:#fef08a1a}.text-yellow-200\/100{color:#fef08a}.text-yellow-200\/15{color:#fef08a26}.text-yellow-200\/20{color:#fef08a33}.text-yellow-200\/25{color:#fef08a40}.text-yellow-200\/30{color:#fef08a4d}.text-yellow-200\/35{color:#fef08a59}.text-yellow-200\/40{color:#fef08a66}.text-yellow-200\/45{color:#fef08a73}.text-yellow-200\/5{color:#fef08a0d}.text-yellow-200\/50{color:#fef08a80}.text-yellow-200\/55{color:#fef08a8c}.text-yellow-200\/60{color:#fef08a99}.text-yellow-200\/65{color:#fef08aa6}.text-yellow-200\/70{color:#fef08ab3}.text-yellow-200\/75{color:#fef08abf}.text-yellow-200\/80{color:#fef08acc}.text-yellow-200\/85{color:#fef08ad9}.text-yellow-200\/90{color:#fef08ae6}.text-yellow-200\/95{color:#fef08af2}.text-yellow-300{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.text-yellow-300\/0{color:#fde04700}.text-yellow-300\/10{color:#fde0471a}.text-yellow-300\/100{color:#fde047}.text-yellow-300\/15{color:#fde04726}.text-yellow-300\/20{color:#fde04733}.text-yellow-300\/25{color:#fde04740}.text-yellow-300\/30{color:#fde0474d}.text-yellow-300\/35{color:#fde04759}.text-yellow-300\/40{color:#fde04766}.text-yellow-300\/45{color:#fde04773}.text-yellow-300\/5{color:#fde0470d}.text-yellow-300\/50{color:#fde04780}.text-yellow-300\/55{color:#fde0478c}.text-yellow-300\/60{color:#fde04799}.text-yellow-300\/65{color:#fde047a6}.text-yellow-300\/70{color:#fde047b3}.text-yellow-300\/75{color:#fde047bf}.text-yellow-300\/80{color:#fde047cc}.text-yellow-300\/85{color:#fde047d9}.text-yellow-300\/90{color:#fde047e6}.text-yellow-300\/95{color:#fde047f2}.text-yellow-400{--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.text-yellow-400\/0{color:#facc1500}.text-yellow-400\/10{color:#facc151a}.text-yellow-400\/100{color:#facc15}.text-yellow-400\/15{color:#facc1526}.text-yellow-400\/20{color:#facc1533}.text-yellow-400\/25{color:#facc1540}.text-yellow-400\/30{color:#facc154d}.text-yellow-400\/35{color:#facc1559}.text-yellow-400\/40{color:#facc1566}.text-yellow-400\/45{color:#facc1573}.text-yellow-400\/5{color:#facc150d}.text-yellow-400\/50{color:#facc1580}.text-yellow-400\/55{color:#facc158c}.text-yellow-400\/60{color:#facc1599}.text-yellow-400\/65{color:#facc15a6}.text-yellow-400\/70{color:#facc15b3}.text-yellow-400\/75{color:#facc15bf}.text-yellow-400\/80{color:#facc15cc}.text-yellow-400\/85{color:#facc15d9}.text-yellow-400\/90{color:#facc15e6}.text-yellow-400\/95{color:#facc15f2}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\:bg-blue-600:hover{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-700:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-600:hover{--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-700:hover{--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-700\/50:hover,.hover\:bg-gray-700\/\[\.5\]:hover{background-color:#37415180}.hover\:bg-red-700:hover{--tw-bg-opacity: 1;background-color:rgb(185 28 28 / var(--tw-bg-opacity, 1))}.hover\:text-blue-300:hover{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.hover\:text-green-400:hover{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.disabled\:bg-gray-500:disabled{--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.disabled\:opacity-60:disabled{opacity:.6} diff --git a/public/build/assets/main-Bz2SJcpk.js b/public/build/assets/main-Bz2SJcpk.js new file mode 100644 index 0000000..68895c0 --- /dev/null +++ b/public/build/assets/main-Bz2SJcpk.js @@ -0,0 +1,7 @@ +function ln(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const G={},xt=[],Ne=()=>{},mi=()=>!1,vs=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),an=e=>e.startsWith("onUpdate:"),he=Object.assign,cn=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},Nr=Object.prototype.hasOwnProperty,B=(e,t)=>Nr.call(e,t),M=Array.isArray,bt=e=>qt(e)==="[object Map]",Rt=e=>qt(e)==="[object Set]",Mn=e=>qt(e)==="[object Date]",L=e=>typeof e=="function",ie=e=>typeof e=="string",je=e=>typeof e=="symbol",X=e=>e!==null&&typeof e=="object",yi=e=>(X(e)||L(e))&&L(e.then)&&L(e.catch),_i=Object.prototype.toString,qt=e=>_i.call(e),jr=e=>qt(e).slice(8,-1),xi=e=>qt(e)==="[object Object]",ws=e=>ie(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Nt=ln(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Ss=e=>{const t=Object.create(null);return(s=>t[s]||(t[s]=e(s)))},Lr=/-\w/g,tt=Ss(e=>e.replace(Lr,t=>t.slice(1).toUpperCase())),Ur=/\B([A-Z])/g,gt=Ss(e=>e.replace(Ur,"-$1").toLowerCase()),bi=Ss(e=>e.charAt(0).toUpperCase()+e.slice(1)),js=Ss(e=>e?`on${bi(e)}`:""),et=(e,t)=>!Object.is(e,t),as=(e,...t)=>{for(let s=0;s{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},Ts=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let Dn;const ks=()=>Dn||(Dn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function un(e){if(M(e)){const t={};for(let s=0;s{if(s){const n=s.split(Hr);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function le(e){let t="";if(ie(e))t=e;else if(M(e))for(let s=0;spt(s,t))}const Si=e=>!!(e&&e.__v_isRef===!0),O=e=>ie(e)?e:e==null?"":M(e)||X(e)&&(e.toString===_i||!L(e.toString))?Si(e)?O(e.value):JSON.stringify(e,Ti,2):String(e),Ti=(e,t)=>Si(t)?Ti(e,t.value):bt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,i],r)=>(s[Ls(n,r)+" =>"]=i,s),{})}:Rt(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>Ls(s))}:je(t)?Ls(t):X(t)&&!M(t)&&!xi(t)?String(t):t,Ls=(e,t="")=>{var s;return je(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};let ye;class Jr{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ye,!t&&ye&&(this.index=(ye.scopes||(ye.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t0&&--this._on===0&&(ye=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s0)return;if(Lt){let t=Lt;for(Lt=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;jt;){let t=jt;for(jt=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function Ri(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Ei(e){let t,s=e.depsTail,n=s;for(;n;){const i=n.prevDep;n.version===-1?(n===s&&(s=i),hn(n),Yr(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=i}e.deps=t,e.depsTail=s}function Js(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Oi(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Oi(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Bt)||(e.globalVersion=Bt,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Js(e))))return;e.flags|=2;const t=e.dep,s=q,n=Ce;q=e,Ce=!0;try{Ri(e);const i=e.fn(e._value);(t.version===0||et(i,e._value))&&(e.flags|=128,e._value=i,t.version++)}catch(i){throw t.version++,i}finally{q=s,Ce=n,Ei(e),e.flags&=-3}}function hn(e,t=!1){const{dep:s,prevSub:n,nextSub:i}=e;if(n&&(n.nextSub=i,e.prevSub=void 0),i&&(i.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let r=s.computed.deps;r;r=r.nextDep)hn(r,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function Yr(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let Ce=!0;const Ii=[];function Ke(){Ii.push(Ce),Ce=!1}function Ge(){const e=Ii.pop();Ce=e===void 0?!0:e}function Nn(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=q;q=void 0;try{t()}finally{q=s}}}let Bt=0;class Xr{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class gn{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!q||!Ce||q===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==q)s=this.activeLink=new Xr(q,this),q.deps?(s.prevDep=q.depsTail,q.depsTail.nextDep=s,q.depsTail=s):q.deps=q.depsTail=s,Ai(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=q.depsTail,s.nextDep=void 0,q.depsTail.nextDep=s,q.depsTail=s,q.deps===s&&(q.deps=n)}return s}trigger(t){this.version++,Bt++,this.notify(t)}notify(t){dn();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{pn()}}}function Ai(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)Ai(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const ds=new WeakMap,ft=Symbol(""),qs=Symbol(""),Kt=Symbol("");function ce(e,t,s){if(Ce&&q){let n=ds.get(e);n||ds.set(e,n=new Map);let i=n.get(s);i||(n.set(s,i=new gn),i.map=n,i.key=s),i.track()}}function He(e,t,s,n,i,r){const o=ds.get(e);if(!o){Bt++;return}const l=a=>{a&&a.trigger()};if(dn(),t==="clear")o.forEach(l);else{const a=M(e),f=a&&ws(s);if(a&&s==="length"){const c=Number(n);o.forEach((d,x)=>{(x==="length"||x===Kt||!je(x)&&x>=c)&&l(d)})}else switch((s!==void 0||o.has(void 0))&&l(o.get(s)),f&&l(o.get(Kt)),t){case"add":a?f&&l(o.get("length")):(l(o.get(ft)),bt(e)&&l(o.get(qs)));break;case"delete":a||(l(o.get(ft)),bt(e)&&l(o.get(qs)));break;case"set":bt(e)&&l(o.get(ft));break}}pn()}function Qr(e,t){const s=ds.get(e);return s&&s.get(t)}function yt(e){const t=W(e);return t===e?t:(ce(t,"iterate",Kt),Se(e)?t:t.map(Re))}function $s(e){return ce(e=W(e),"iterate",Kt),e}function Xe(e,t){return ze(e)?dt(e)?Tt(Re(t)):Tt(t):Re(t)}const Zr={__proto__:null,[Symbol.iterator](){return Vs(this,Symbol.iterator,e=>Xe(this,e))},concat(...e){return yt(this).concat(...e.map(t=>M(t)?yt(t):t))},entries(){return Vs(this,"entries",e=>(e[1]=Xe(this,e[1]),e))},every(e,t){return Ue(this,"every",e,t,void 0,arguments)},filter(e,t){return Ue(this,"filter",e,t,s=>s.map(n=>Xe(this,n)),arguments)},find(e,t){return Ue(this,"find",e,t,s=>Xe(this,s),arguments)},findIndex(e,t){return Ue(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Ue(this,"findLast",e,t,s=>Xe(this,s),arguments)},findLastIndex(e,t){return Ue(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Ue(this,"forEach",e,t,void 0,arguments)},includes(...e){return Hs(this,"includes",e)},indexOf(...e){return Hs(this,"indexOf",e)},join(e){return yt(this).join(e)},lastIndexOf(...e){return Hs(this,"lastIndexOf",e)},map(e,t){return Ue(this,"map",e,t,void 0,arguments)},pop(){return Ft(this,"pop")},push(...e){return Ft(this,"push",e)},reduce(e,...t){return jn(this,"reduce",e,t)},reduceRight(e,...t){return jn(this,"reduceRight",e,t)},shift(){return Ft(this,"shift")},some(e,t){return Ue(this,"some",e,t,void 0,arguments)},splice(...e){return Ft(this,"splice",e)},toReversed(){return yt(this).toReversed()},toSorted(e){return yt(this).toSorted(e)},toSpliced(...e){return yt(this).toSpliced(...e)},unshift(...e){return Ft(this,"unshift",e)},values(){return Vs(this,"values",e=>Xe(this,e))}};function Vs(e,t,s){const n=$s(e),i=n[t]();return n!==e&&!Se(e)&&(i._next=i.next,i.next=()=>{const r=i._next();return r.done||(r.value=s(r.value)),r}),i}const eo=Array.prototype;function Ue(e,t,s,n,i,r){const o=$s(e),l=o!==e&&!Se(e),a=o[t];if(a!==eo[t]){const d=a.apply(e,r);return l?Re(d):d}let f=s;o!==e&&(l?f=function(d,x){return s.call(this,Xe(e,d),x,e)}:s.length>2&&(f=function(d,x){return s.call(this,d,x,e)}));const c=a.call(o,f,n);return l&&i?i(c):c}function jn(e,t,s,n){const i=$s(e);let r=s;return i!==e&&(Se(e)?s.length>3&&(r=function(o,l,a){return s.call(this,o,l,a,e)}):r=function(o,l,a){return s.call(this,o,Xe(e,l),a,e)}),i[t](r,...n)}function Hs(e,t,s){const n=W(e);ce(n,"iterate",Kt);const i=n[t](...s);return(i===-1||i===!1)&&Rs(s[0])?(s[0]=W(s[0]),n[t](...s)):i}function Ft(e,t,s=[]){Ke(),dn();const n=W(e)[t].apply(e,s);return pn(),Ge(),n}const to=ln("__proto__,__v_isRef,__isVue"),Fi=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(je));function so(e){je(e)||(e=String(e));const t=W(this);return ce(t,"has",e),t.hasOwnProperty(e)}class Pi{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const i=this._isReadonly,r=this._isShallow;if(s==="__v_isReactive")return!i;if(s==="__v_isReadonly")return i;if(s==="__v_isShallow")return r;if(s==="__v_raw")return n===(i?r?po:ji:r?Ni:Di).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const o=M(t);if(!i){let a;if(o&&(a=Zr[s]))return a;if(s==="hasOwnProperty")return so}const l=Reflect.get(t,s,ae(t)?t:n);if((je(s)?Fi.has(s):to(s))||(i||ce(t,"get",s),r))return l;if(ae(l)){const a=o&&ws(s)?l:l.value;return i&&X(a)?Xs(a):a}return X(l)?i?Xs(l):Cs(l):l}}class Mi extends Pi{constructor(t=!1){super(!1,t)}set(t,s,n,i){let r=t[s];const o=M(t)&&ws(s);if(!this._isShallow){const f=ze(r);if(!Se(n)&&!ze(n)&&(r=W(r),n=W(n)),!o&&ae(r)&&!ae(n))return f||(r.value=n),!0}const l=o?Number(s)e,rs=e=>Reflect.getPrototypeOf(e);function lo(e,t,s){return function(...n){const i=this.__v_raw,r=W(i),o=bt(r),l=e==="entries"||e===Symbol.iterator&&o,a=e==="keys"&&o,f=i[e](...n),c=s?Ys:t?Tt:Re;return!t&&ce(r,"iterate",a?qs:ft),{next(){const{value:d,done:x}=f.next();return x?{value:d,done:x}:{value:l?[c(d[0]),c(d[1])]:c(d),done:x}},[Symbol.iterator](){return this}}}}function os(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function ao(e,t){const s={get(i){const r=this.__v_raw,o=W(r),l=W(i);e||(et(i,l)&&ce(o,"get",i),ce(o,"get",l));const{has:a}=rs(o),f=t?Ys:e?Tt:Re;if(a.call(o,i))return f(r.get(i));if(a.call(o,l))return f(r.get(l));r!==o&&r.get(i)},get size(){const i=this.__v_raw;return!e&&ce(W(i),"iterate",ft),i.size},has(i){const r=this.__v_raw,o=W(r),l=W(i);return e||(et(i,l)&&ce(o,"has",i),ce(o,"has",l)),i===l?r.has(i):r.has(i)||r.has(l)},forEach(i,r){const o=this,l=o.__v_raw,a=W(l),f=t?Ys:e?Tt:Re;return!e&&ce(a,"iterate",ft),l.forEach((c,d)=>i.call(r,f(c),f(d),o))}};return he(s,e?{add:os("add"),set:os("set"),delete:os("delete"),clear:os("clear")}:{add(i){!t&&!Se(i)&&!ze(i)&&(i=W(i));const r=W(this);return rs(r).has.call(r,i)||(r.add(i),He(r,"add",i,i)),this},set(i,r){!t&&!Se(r)&&!ze(r)&&(r=W(r));const o=W(this),{has:l,get:a}=rs(o);let f=l.call(o,i);f||(i=W(i),f=l.call(o,i));const c=a.call(o,i);return o.set(i,r),f?et(r,c)&&He(o,"set",i,r):He(o,"add",i,r),this},delete(i){const r=W(this),{has:o,get:l}=rs(r);let a=o.call(r,i);a||(i=W(i),a=o.call(r,i)),l&&l.call(r,i);const f=r.delete(i);return a&&He(r,"delete",i,void 0),f},clear(){const i=W(this),r=i.size!==0,o=i.clear();return r&&He(i,"clear",void 0,void 0),o}}),["keys","values","entries",Symbol.iterator].forEach(i=>{s[i]=lo(i,e,t)}),s}function mn(e,t){const s=ao(e,t);return(n,i,r)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(B(s,i)&&i in n?s:n,i,r)}const co={get:mn(!1,!1)},uo={get:mn(!1,!0)},fo={get:mn(!0,!1)};const Di=new WeakMap,Ni=new WeakMap,ji=new WeakMap,po=new WeakMap;function ho(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function go(e){return e.__v_skip||!Object.isExtensible(e)?0:ho(jr(e))}function Cs(e){return ze(e)?e:yn(e,!1,io,co,Di)}function mo(e){return yn(e,!1,oo,uo,Ni)}function Xs(e){return yn(e,!0,ro,fo,ji)}function yn(e,t,s,n,i){if(!X(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=go(e);if(r===0)return e;const o=i.get(e);if(o)return o;const l=new Proxy(e,r===2?n:s);return i.set(e,l),l}function dt(e){return ze(e)?dt(e.__v_raw):!!(e&&e.__v_isReactive)}function ze(e){return!!(e&&e.__v_isReadonly)}function Se(e){return!!(e&&e.__v_isShallow)}function Rs(e){return e?!!e.__v_raw:!1}function W(e){const t=e&&e.__v_raw;return t?W(t):e}function yo(e){return!B(e,"__v_skip")&&Object.isExtensible(e)&&vi(e,"__v_skip",!0),e}const Re=e=>X(e)?Cs(e):e,Tt=e=>X(e)?Xs(e):e;function ae(e){return e?e.__v_isRef===!0:!1}function Li(e){return _o(e,!1)}function _o(e,t){return ae(e)?e:new xo(e,t)}class xo{constructor(t,s){this.dep=new gn,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:W(t),this._value=s?t:Re(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||Se(t)||ze(t);t=n?t:W(t),et(t,s)&&(this._rawValue=t,this._value=n?t:Re(t),this.dep.trigger())}}function g(e){return ae(e)?e.value:e}const bo={get:(e,t,s)=>t==="__v_raw"?e:g(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const i=e[t];return ae(i)&&!ae(s)?(i.value=s,!0):Reflect.set(e,t,s,n)}};function Ui(e){return dt(e)?e:new Proxy(e,bo)}function _n(e){const t=M(e)?new Array(e.length):{};for(const s in e)t[s]=wo(e,s);return t}class vo{constructor(t,s,n){this._object=t,this._key=s,this._defaultValue=n,this.__v_isRef=!0,this._value=void 0,this._raw=W(t);let i=!0,r=t;if(!M(t)||!ws(String(s)))do i=!Rs(r)||Se(r);while(i&&(r=r.__v_raw));this._shallow=i}get value(){let t=this._object[this._key];return this._shallow&&(t=g(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&ae(this._raw[this._key])){const s=this._object[this._key];if(ae(s)){s.value=t;return}}this._object[this._key]=t}get dep(){return Qr(this._raw,this._key)}}function wo(e,t,s){return new vo(e,t,s)}class So{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new gn(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Bt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&q!==this)return Ci(this,!0),!0}get value(){const t=this.dep.track();return Oi(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function To(e,t,s=!1){let n,i;return L(e)?n=e:(n=e.get,i=e.set),new So(n,i,s)}const ls={},ps=new WeakMap;let ut;function ko(e,t=!1,s=ut){if(s){let n=ps.get(s);n||ps.set(s,n=[]),n.push(e)}}function $o(e,t,s=G){const{immediate:n,deep:i,once:r,scheduler:o,augmentJob:l,call:a}=s,f=N=>i?N:Se(N)||i===!1||i===0?We(N,1):We(N);let c,d,x,$,F=!1,I=!1;if(ae(e)?(d=()=>e.value,F=Se(e)):dt(e)?(d=()=>f(e),F=!0):M(e)?(I=!0,F=e.some(N=>dt(N)||Se(N)),d=()=>e.map(N=>{if(ae(N))return N.value;if(dt(N))return f(N);if(L(N))return a?a(N,2):N()})):L(e)?t?d=a?()=>a(e,2):e:d=()=>{if(x){Ke();try{x()}finally{Ge()}}const N=ut;ut=c;try{return a?a(e,3,[$]):e($)}finally{ut=N}}:d=Ne,t&&i){const N=d,re=i===!0?1/0:i;d=()=>We(N(),re)}const oe=qr(),U=()=>{c.stop(),oe&&oe.active&&cn(oe.effects,c)};if(r&&t){const N=t;t=(...re)=>{N(...re),U()}}let Q=I?new Array(e.length).fill(ls):ls;const te=N=>{if(!(!(c.flags&1)||!c.dirty&&!N))if(t){const re=c.run();if(i||F||(I?re.some((qe,Ee)=>et(qe,Q[Ee])):et(re,Q))){x&&x();const qe=ut;ut=c;try{const Ee=[re,Q===ls?void 0:I&&Q[0]===ls?[]:Q,$];Q=re,a?a(t,3,Ee):t(...Ee)}finally{ut=qe}}}else c.run()};return l&&l(te),c=new ki(d),c.scheduler=o?()=>o(te,!1):te,$=N=>ko(N,!1,c),x=c.onStop=()=>{const N=ps.get(c);if(N){if(a)a(N,4);else for(const re of N)re();ps.delete(c)}},t?n?te(!0):Q=c.run():o?o(te.bind(null,!0),!0):c.run(),U.pause=c.pause.bind(c),U.resume=c.resume.bind(c),U.stop=U,U}function We(e,t=1/0,s){if(t<=0||!X(e)||e.__v_skip||(s=s||new Map,(s.get(e)||0)>=t))return e;if(s.set(e,t),t--,ae(e))We(e.value,t,s);else if(M(e))for(let n=0;n{We(n,t,s)});else if(xi(e)){for(const n in e)We(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&&We(e[n],t,s)}return e}function Yt(e,t,s,n){try{return n?e(...n):e()}catch(i){Es(i,t,s)}}function Le(e,t,s,n){if(L(e)){const i=Yt(e,t,s,n);return i&&yi(i)&&i.catch(r=>{Es(r,t,s)}),i}if(M(e)){const i=[];for(let r=0;r>>1,i=de[n],r=Gt(i);r=Gt(s)?de.push(e):de.splice(Ro(t),0,e),e.flags|=1,Wi()}}function Wi(){hs||(hs=Vi.then(Ki))}function Eo(e){M(e)?vt.push(...e):Qe&&e.id===-1?Qe.splice(_t+1,0,e):e.flags&1||(vt.push(e),e.flags|=1),Wi()}function Ln(e,t,s=Me+1){for(;sGt(s)-Gt(n));if(vt.length=0,Qe){Qe.push(...t);return}for(Qe=t,_t=0;_te.id==null?e.flags&2?-1:1/0:e.id;function Ki(e){try{for(Me=0;Me{n._d&&qn(-1);const r=gs(t);let o;try{o=e(...i)}finally{gs(r),n._d&&qn(1)}return o};return n._n=!0,n._c=!0,n._d=!0,n}function ne(e,t){if(ke===null)return e;const s=Ps(ke),n=e.dirs||(e.dirs=[]);for(let i=0;ie.__isTeleport,Fo=Symbol("_leaveCb");function bn(e,t){e.shapeFlag&6&&e.component?(e.transition=t,bn(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function zi(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}const ms=new WeakMap;function Ut(e,t,s,n,i=!1){if(M(e)){e.forEach((F,I)=>Ut(F,t&&(M(t)?t[I]:t),s,n,i));return}if(Vt(n)&&!i){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&Ut(e,t,s,n.component.subTree);return}const r=n.shapeFlag&4?Ps(n.component):n.el,o=i?null:r,{i:l,r:a}=e,f=t&&t.r,c=l.refs===G?l.refs={}:l.refs,d=l.setupState,x=W(d),$=d===G?mi:F=>B(x,F);if(f!=null&&f!==a){if(Un(t),ie(f))c[f]=null,$(f)&&(d[f]=null);else if(ae(f)){f.value=null;const F=t;F.k&&(c[F.k]=null)}}if(L(a))Yt(a,l,12,[o,c]);else{const F=ie(a),I=ae(a);if(F||I){const oe=()=>{if(e.f){const U=F?$(a)?d[a]:c[a]:a.value;if(i)M(U)&&cn(U,r);else if(M(U))U.includes(r)||U.push(r);else if(F)c[a]=[r],$(a)&&(d[a]=c[a]);else{const Q=[r];a.value=Q,e.k&&(c[e.k]=Q)}}else F?(c[a]=o,$(a)&&(d[a]=o)):I&&(a.value=o,e.k&&(c[e.k]=o))};if(o){const U=()=>{oe(),ms.delete(e)};U.id=-1,ms.set(e,U),ve(U,s)}else Un(e),oe()}}}function Un(e){const t=ms.get(e);t&&(t.flags|=8,ms.delete(e))}ks().requestIdleCallback;ks().cancelIdleCallback;const Vt=e=>!!e.type.__asyncLoader,Ji=e=>e.type.__isKeepAlive;function Po(e,t){qi(e,"a",t)}function Mo(e,t){qi(e,"da",t)}function qi(e,t,s=pe){const n=e.__wdc||(e.__wdc=()=>{let i=s;for(;i;){if(i.isDeactivated)return;i=i.parent}return e()});if(Os(t,n,s),s){let i=s.parent;for(;i&&i.parent;)Ji(i.parent.vnode)&&Do(n,t,s,i),i=i.parent}}function Do(e,t,s,n){const i=Os(t,e,n,!0);Yi(()=>{cn(n[t],i)},s)}function Os(e,t,s=pe,n=!1){if(s){const i=s[e]||(s[e]=[]),r=t.__weh||(t.__weh=(...o)=>{Ke();const l=Xt(s),a=Le(t,s,e,o);return l(),Ge(),a});return n?i.unshift(r):i.push(r),r}}const Je=e=>(t,s=pe)=>{(!Jt||e==="sp")&&Os(e,(...n)=>t(...n),s)},No=Je("bm"),Is=Je("m"),jo=Je("bu"),Lo=Je("u"),Uo=Je("bum"),Yi=Je("um"),Vo=Je("sp"),Ho=Je("rtg"),Wo=Je("rtc");function Bo(e,t=pe){Os("ec",e,t)}const Ko=Symbol.for("v-ndc");function xe(e,t,s,n){let i;const r=s,o=M(e);if(o||ie(e)){const l=o&&dt(e);let a=!1,f=!1;l&&(a=!Se(e),f=ze(e),e=$s(e)),i=new Array(e.length);for(let c=0,d=e.length;ct(l,a,void 0,r));else{const l=Object.keys(e);i=new Array(l.length);for(let a=0,f=l.length;ae?yr(e)?Ps(e):Qs(e.parent):null,Ht=he(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Qs(e.parent),$root:e=>Qs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Qi(e),$forceUpdate:e=>e.f||(e.f=()=>{xn(e.update)}),$nextTick:e=>e.n||(e.n=Hi.bind(e.proxy)),$watch:e=>nl.bind(e)}),Ws=(e,t)=>e!==G&&!e.__isScriptSetup&&B(e,t),Go={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:i,props:r,accessCache:o,type:l,appContext:a}=e;if(t[0]!=="$"){const x=o[t];if(x!==void 0)switch(x){case 1:return n[t];case 2:return i[t];case 4:return s[t];case 3:return r[t]}else{if(Ws(n,t))return o[t]=1,n[t];if(i!==G&&B(i,t))return o[t]=2,i[t];if(B(r,t))return o[t]=3,r[t];if(s!==G&&B(s,t))return o[t]=4,s[t];Zs&&(o[t]=0)}}const f=Ht[t];let c,d;if(f)return t==="$attrs"&&ce(e.attrs,"get",""),f(e);if((c=l.__cssModules)&&(c=c[t]))return c;if(s!==G&&B(s,t))return o[t]=4,s[t];if(d=a.config.globalProperties,B(d,t))return d[t]},set({_:e},t,s){const{data:n,setupState:i,ctx:r}=e;return Ws(i,t)?(i[t]=s,!0):n!==G&&B(n,t)?(n[t]=s,!0):B(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:i,props:r,type:o}},l){let a;return!!(s[l]||e!==G&&l[0]!=="$"&&B(e,l)||Ws(t,l)||B(r,l)||B(n,l)||B(Ht,l)||B(i.config.globalProperties,l)||(a=o.__cssModules)&&a[l])},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:B(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function Vn(e){return M(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let Zs=!0;function zo(e){const t=Qi(e),s=e.proxy,n=e.ctx;Zs=!1,t.beforeCreate&&Hn(t.beforeCreate,e,"bc");const{data:i,computed:r,methods:o,watch:l,provide:a,inject:f,created:c,beforeMount:d,mounted:x,beforeUpdate:$,updated:F,activated:I,deactivated:oe,beforeDestroy:U,beforeUnmount:Q,destroyed:te,unmounted:N,render:re,renderTracked:qe,renderTriggered:Ee,errorCaptured:Ye,serverPrefetch:es,expose:rt,inheritAttrs:Et,components:ts,directives:ss,filters:Ds}=t;if(f&&Jo(f,n,null),o)for(const ee in o){const z=o[ee];L(z)&&(n[ee]=z.bind(s))}if(i){const ee=i.call(s,s);X(ee)&&(e.data=Cs(ee))}if(Zs=!0,r)for(const ee in r){const z=r[ee],ot=L(z)?z.bind(s,s):L(z.get)?z.get.bind(s,s):Ne,ns=!L(z)&&L(z.set)?z.set.bind(s):Ne,lt=_e({get:ot,set:ns});Object.defineProperty(n,ee,{enumerable:!0,configurable:!0,get:()=>lt.value,set:Oe=>lt.value=Oe})}if(l)for(const ee in l)Xi(l[ee],n,s,ee);if(a){const ee=L(a)?a.call(s):a;Reflect.ownKeys(ee).forEach(z=>{el(z,ee[z])})}c&&Hn(c,e,"c");function ue(ee,z){M(z)?z.forEach(ot=>ee(ot.bind(s))):z&&ee(z.bind(s))}if(ue(No,d),ue(Is,x),ue(jo,$),ue(Lo,F),ue(Po,I),ue(Mo,oe),ue(Bo,Ye),ue(Wo,qe),ue(Ho,Ee),ue(Uo,Q),ue(Yi,N),ue(Vo,es),M(rt))if(rt.length){const ee=e.exposed||(e.exposed={});rt.forEach(z=>{Object.defineProperty(ee,z,{get:()=>s[z],set:ot=>s[z]=ot,enumerable:!0})})}else e.exposed||(e.exposed={});re&&e.render===Ne&&(e.render=re),Et!=null&&(e.inheritAttrs=Et),ts&&(e.components=ts),ss&&(e.directives=ss),es&&zi(e)}function Jo(e,t,s=Ne){M(e)&&(e=en(e));for(const n in e){const i=e[n];let r;X(i)?"default"in i?r=cs(i.from||n,i.default,!0):r=cs(i.from||n):r=cs(i),ae(r)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>r.value,set:o=>r.value=o}):t[n]=r}}function Hn(e,t,s){Le(M(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function Xi(e,t,s,n){let i=n.includes(".")?tr(s,n):()=>s[n];if(ie(e)){const r=t[e];L(r)&&St(i,r)}else if(L(e))St(i,e.bind(s));else if(X(e))if(M(e))e.forEach(r=>Xi(r,t,s,n));else{const r=L(e.handler)?e.handler.bind(s):t[e.handler];L(r)&&St(i,r,e)}}function Qi(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:i,optionsCache:r,config:{optionMergeStrategies:o}}=e.appContext,l=r.get(t);let a;return l?a=l:!i.length&&!s&&!n?a=t:(a={},i.length&&i.forEach(f=>ys(a,f,o,!0)),ys(a,t,o)),X(t)&&r.set(t,a),a}function ys(e,t,s,n=!1){const{mixins:i,extends:r}=t;r&&ys(e,r,s,!0),i&&i.forEach(o=>ys(e,o,s,!0));for(const o in t)if(!(n&&o==="expose")){const l=qo[o]||s&&s[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const qo={data:Wn,props:Bn,emits:Bn,methods:Dt,computed:Dt,beforeCreate:fe,created:fe,beforeMount:fe,mounted:fe,beforeUpdate:fe,updated:fe,beforeDestroy:fe,beforeUnmount:fe,destroyed:fe,unmounted:fe,activated:fe,deactivated:fe,errorCaptured:fe,serverPrefetch:fe,components:Dt,directives:Dt,watch:Xo,provide:Wn,inject:Yo};function Wn(e,t){return t?e?function(){return he(L(e)?e.call(this,this):e,L(t)?t.call(this,this):t)}:t:e}function Yo(e,t){return Dt(en(e),en(t))}function en(e){if(M(e)){const t={};for(let s=0;s1)return s&&L(t)?t.call(n&&n.proxy):t}}const tl=Symbol.for("v-scx"),sl=()=>cs(tl);function St(e,t,s){return er(e,t,s)}function er(e,t,s=G){const{immediate:n,deep:i,flush:r,once:o}=s,l=he({},s),a=t&&n||!t&&r!=="post";let f;if(Jt){if(r==="sync"){const $=sl();f=$.__watcherHandles||($.__watcherHandles=[])}else if(!a){const $=()=>{};return $.stop=Ne,$.resume=Ne,$.pause=Ne,$}}const c=pe;l.call=($,F,I)=>Le($,c,F,I);let d=!1;r==="post"?l.scheduler=$=>{ve($,c&&c.suspense)}:r!=="sync"&&(d=!0,l.scheduler=($,F)=>{F?$():xn($)}),l.augmentJob=$=>{t&&($.flags|=4),d&&($.flags|=2,c&&($.id=c.uid,$.i=c))};const x=$o(e,t,l);return Jt&&(f?f.push(x):a&&x()),x}function nl(e,t,s){const n=this.proxy,i=ie(e)?e.includes(".")?tr(n,e):()=>n[e]:e.bind(n,n);let r;L(t)?r=t:(r=t.handler,s=t);const o=Xt(this),l=er(i,r.bind(n),s);return o(),l}function tr(e,t){const s=t.split(".");return()=>{let n=e;for(let i=0;it==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${tt(t)}Modifiers`]||e[`${gt(t)}Modifiers`];function rl(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||G;let i=s;const r=t.startsWith("update:"),o=r&&il(n,t.slice(7));o&&(o.trim&&(i=s.map(c=>ie(c)?c.trim():c)),o.number&&(i=s.map(Ts)));let l,a=n[l=js(t)]||n[l=js(tt(t))];!a&&r&&(a=n[l=js(gt(t))]),a&&Le(a,e,6,i);const f=n[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Le(f,e,6,i)}}const ol=new WeakMap;function sr(e,t,s=!1){const n=s?ol:t.emitsCache,i=n.get(e);if(i!==void 0)return i;const r=e.emits;let o={},l=!1;if(!L(e)){const a=f=>{const c=sr(f,t,!0);c&&(l=!0,he(o,c))};!s&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!r&&!l?(X(e)&&n.set(e,null),null):(M(r)?r.forEach(a=>o[a]=null):he(o,r),X(e)&&n.set(e,o),o)}function As(e,t){return!e||!vs(t)?!1:(t=t.slice(2).replace(/Once$/,""),B(e,t[0].toLowerCase()+t.slice(1))||B(e,gt(t))||B(e,t))}function Kn(e){const{type:t,vnode:s,proxy:n,withProxy:i,propsOptions:[r],slots:o,attrs:l,emit:a,render:f,renderCache:c,props:d,data:x,setupState:$,ctx:F,inheritAttrs:I}=e,oe=gs(e);let U,Q;try{if(s.shapeFlag&4){const N=i||n,re=N;U=De(f.call(re,N,c,d,$,x,F)),Q=l}else{const N=t;U=De(N.length>1?N(d,{attrs:l,slots:o,emit:a}):N(d,null)),Q=t.props?l:ll(l)}}catch(N){Wt.length=0,Es(N,e,1),U=Y(st)}let te=U;if(Q&&I!==!1){const N=Object.keys(Q),{shapeFlag:re}=te;N.length&&re&7&&(r&&N.some(an)&&(Q=al(Q,r)),te=kt(te,Q,!1,!0))}return s.dirs&&(te=kt(te,null,!1,!0),te.dirs=te.dirs?te.dirs.concat(s.dirs):s.dirs),s.transition&&bn(te,s.transition),U=te,gs(oe),U}const ll=e=>{let t;for(const s in e)(s==="class"||s==="style"||vs(s))&&((t||(t={}))[s]=e[s]);return t},al=(e,t)=>{const s={};for(const n in e)(!an(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function cl(e,t,s){const{props:n,children:i,component:r}=e,{props:o,children:l,patchFlag:a}=t,f=r.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&a>=0){if(a&1024)return!0;if(a&16)return n?Gn(n,o,f):!!o;if(a&8){const c=t.dynamicProps;for(let d=0;dObject.create(nr),rr=e=>Object.getPrototypeOf(e)===nr;function fl(e,t,s,n=!1){const i={},r=ir();e.propsDefaults=Object.create(null),or(e,t,i,r);for(const o in e.propsOptions[0])o in i||(i[o]=void 0);s?e.props=n?i:mo(i):e.type.props?e.props=i:e.props=r,e.attrs=r}function dl(e,t,s,n){const{props:i,attrs:r,vnode:{patchFlag:o}}=e,l=W(i),[a]=e.propsOptions;let f=!1;if((n||o>0)&&!(o&16)){if(o&8){const c=e.vnode.dynamicProps;for(let d=0;d{a=!0;const[x,$]=lr(d,t,!0);he(o,x),$&&l.push(...$)};!s&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}if(!r&&!a)return X(e)&&n.set(e,xt),xt;if(M(r))for(let c=0;ce==="_"||e==="_ctx"||e==="$stable",wn=e=>M(e)?e.map(De):[De(e)],hl=(e,t,s)=>{if(t._n)return t;const n=Oo((...i)=>wn(t(...i)),s);return n._c=!1,n},ar=(e,t,s)=>{const n=e._ctx;for(const i in e){if(vn(i))continue;const r=e[i];if(L(r))t[i]=hl(i,r,n);else if(r!=null){const o=wn(r);t[i]=()=>o}}},cr=(e,t)=>{const s=wn(t);e.slots.default=()=>s},ur=(e,t,s)=>{for(const n in t)(s||!vn(n))&&(e[n]=t[n])},gl=(e,t,s)=>{const n=e.slots=ir();if(e.vnode.shapeFlag&32){const i=t._;i?(ur(n,t,s),s&&vi(n,"_",i,!0)):ar(t,n)}else t&&cr(e,t)},ml=(e,t,s)=>{const{vnode:n,slots:i}=e;let r=!0,o=G;if(n.shapeFlag&32){const l=t._;l?s&&l===1?r=!1:ur(i,t,s):(r=!t.$stable,ar(t,i)),o=t}else t&&(cr(e,t),o={default:1});if(r)for(const l in i)!vn(l)&&o[l]==null&&delete i[l]},ve=vl;function yl(e){return _l(e)}function _l(e,t){const s=ks();s.__VUE__=!0;const{insert:n,remove:i,patchProp:r,createElement:o,createText:l,createComment:a,setText:f,setElementText:c,parentNode:d,nextSibling:x,setScopeId:$=Ne,insertStaticContent:F}=e,I=(u,p,m,S=null,b=null,v=null,C=void 0,k=null,T=!!p.dynamicChildren)=>{if(u===p)return;u&&!Pt(u,p)&&(S=is(u),Oe(u,b,v,!0),u=null),p.patchFlag===-2&&(T=!1,p.dynamicChildren=null);const{type:w,ref:P,shapeFlag:E}=p;switch(w){case Fs:oe(u,p,m,S);break;case st:U(u,p,m,S);break;case Ks:u==null&&Q(p,m,S,C);break;case Z:ts(u,p,m,S,b,v,C,k,T);break;default:E&1?re(u,p,m,S,b,v,C,k,T):E&6?ss(u,p,m,S,b,v,C,k,T):(E&64||E&128)&&w.process(u,p,m,S,b,v,C,k,T,It)}P!=null&&b?Ut(P,u&&u.ref,v,p||u,!p):P==null&&u&&u.ref!=null&&Ut(u.ref,null,v,u,!0)},oe=(u,p,m,S)=>{if(u==null)n(p.el=l(p.children),m,S);else{const b=p.el=u.el;p.children!==u.children&&f(b,p.children)}},U=(u,p,m,S)=>{u==null?n(p.el=a(p.children||""),m,S):p.el=u.el},Q=(u,p,m,S)=>{[u.el,u.anchor]=F(u.children,p,m,S,u.el,u.anchor)},te=({el:u,anchor:p},m,S)=>{let b;for(;u&&u!==p;)b=x(u),n(u,m,S),u=b;n(p,m,S)},N=({el:u,anchor:p})=>{let m;for(;u&&u!==p;)m=x(u),i(u),u=m;i(p)},re=(u,p,m,S,b,v,C,k,T)=>{if(p.type==="svg"?C="svg":p.type==="math"&&(C="mathml"),u==null)qe(p,m,S,b,v,C,k,T);else{const w=u.el&&u.el._isVueCE?u.el:null;try{w&&w._beginPatch(),es(u,p,b,v,C,k,T)}finally{w&&w._endPatch()}}},qe=(u,p,m,S,b,v,C,k)=>{let T,w;const{props:P,shapeFlag:E,transition:A,dirs:j}=u;if(T=u.el=o(u.type,v,P&&P.is,P),E&8?c(T,u.children):E&16&&Ye(u.children,T,null,S,b,Bs(u,v),C,k),j&&at(u,null,S,"created"),Ee(T,u,u.scopeId,C,S),P){for(const J in P)J!=="value"&&!Nt(J)&&r(T,J,null,P[J],v,S);"value"in P&&r(T,"value",null,P.value,v),(w=P.onVnodeBeforeMount)&&Pe(w,S,u)}j&&at(u,null,S,"beforeMount");const V=xl(b,A);V&&A.beforeEnter(T),n(T,p,m),((w=P&&P.onVnodeMounted)||V||j)&&ve(()=>{w&&Pe(w,S,u),V&&A.enter(T),j&&at(u,null,S,"mounted")},b)},Ee=(u,p,m,S,b)=>{if(m&&$(u,m),S)for(let v=0;v{for(let w=T;w{const k=p.el=u.el;let{patchFlag:T,dynamicChildren:w,dirs:P}=p;T|=u.patchFlag&16;const E=u.props||G,A=p.props||G;let j;if(m&&ct(m,!1),(j=A.onVnodeBeforeUpdate)&&Pe(j,m,p,u),P&&at(p,u,m,"beforeUpdate"),m&&ct(m,!0),(E.innerHTML&&A.innerHTML==null||E.textContent&&A.textContent==null)&&c(k,""),w?rt(u.dynamicChildren,w,k,m,S,Bs(p,b),v):C||z(u,p,k,null,m,S,Bs(p,b),v,!1),T>0){if(T&16)Et(k,E,A,m,b);else if(T&2&&E.class!==A.class&&r(k,"class",null,A.class,b),T&4&&r(k,"style",E.style,A.style,b),T&8){const V=p.dynamicProps;for(let J=0;J{j&&Pe(j,m,p,u),P&&at(p,u,m,"updated")},S)},rt=(u,p,m,S,b,v,C)=>{for(let k=0;k{if(p!==m){if(p!==G)for(const v in p)!Nt(v)&&!(v in m)&&r(u,v,p[v],null,b,S);for(const v in m){if(Nt(v))continue;const C=m[v],k=p[v];C!==k&&v!=="value"&&r(u,v,k,C,b,S)}"value"in m&&r(u,"value",p.value,m.value,b)}},ts=(u,p,m,S,b,v,C,k,T)=>{const w=p.el=u?u.el:l(""),P=p.anchor=u?u.anchor:l("");let{patchFlag:E,dynamicChildren:A,slotScopeIds:j}=p;j&&(k=k?k.concat(j):j),u==null?(n(w,m,S),n(P,m,S),Ye(p.children||[],m,P,b,v,C,k,T)):E>0&&E&64&&A&&u.dynamicChildren?(rt(u.dynamicChildren,A,m,b,v,C,k),(p.key!=null||b&&p===b.subTree)&&fr(u,p,!0)):z(u,p,m,P,b,v,C,k,T)},ss=(u,p,m,S,b,v,C,k,T)=>{p.slotScopeIds=k,u==null?p.shapeFlag&512?b.ctx.activate(p,m,S,C,T):Ds(p,m,S,b,v,C,T):En(u,p,T)},Ds=(u,p,m,S,b,v,C)=>{const k=u.component=Rl(u,S,b);if(Ji(u)&&(k.ctx.renderer=It),Ol(k,!1,C),k.asyncDep){if(b&&b.registerDep(k,ue,C),!u.el){const T=k.subTree=Y(st);U(null,T,p,m),u.placeholder=T.el}}else ue(k,u,p,m,b,v,C)},En=(u,p,m)=>{const S=p.component=u.component;if(cl(u,p,m))if(S.asyncDep&&!S.asyncResolved){ee(S,p,m);return}else S.next=p,S.update();else p.el=u.el,S.vnode=p},ue=(u,p,m,S,b,v,C)=>{const k=()=>{if(u.isMounted){let{next:E,bu:A,u:j,parent:V,vnode:J}=u;{const Ae=dr(u);if(Ae){E&&(E.el=J.el,ee(u,E,C)),Ae.asyncDep.then(()=>{u.isUnmounted||k()});return}}let K=E,ge;ct(u,!1),E?(E.el=J.el,ee(u,E,C)):E=J,A&&as(A),(ge=E.props&&E.props.onVnodeBeforeUpdate)&&Pe(ge,V,E,J),ct(u,!0);const me=Kn(u),Ie=u.subTree;u.subTree=me,I(Ie,me,d(Ie.el),is(Ie),u,b,v),E.el=me.el,K===null&&ul(u,me.el),j&&ve(j,b),(ge=E.props&&E.props.onVnodeUpdated)&&ve(()=>Pe(ge,V,E,J),b)}else{let E;const{el:A,props:j}=p,{bm:V,m:J,parent:K,root:ge,type:me}=u,Ie=Vt(p);ct(u,!1),V&&as(V),!Ie&&(E=j&&j.onVnodeBeforeMount)&&Pe(E,K,p),ct(u,!0);{ge.ce&&ge.ce._def.shadowRoot!==!1&&ge.ce._injectChildStyle(me);const Ae=u.subTree=Kn(u);I(null,Ae,m,S,u,b,v),p.el=Ae.el}if(J&&ve(J,b),!Ie&&(E=j&&j.onVnodeMounted)){const Ae=p;ve(()=>Pe(E,K,Ae),b)}(p.shapeFlag&256||K&&Vt(K.vnode)&&K.vnode.shapeFlag&256)&&u.a&&ve(u.a,b),u.isMounted=!0,p=m=S=null}};u.scope.on();const T=u.effect=new ki(k);u.scope.off();const w=u.update=T.run.bind(T),P=u.job=T.runIfDirty.bind(T);P.i=u,P.id=u.uid,T.scheduler=()=>xn(P),ct(u,!0),w()},ee=(u,p,m)=>{p.component=u;const S=u.vnode.props;u.vnode=p,u.next=null,dl(u,p.props,S,m),ml(u,p.children,m),Ke(),Ln(u),Ge()},z=(u,p,m,S,b,v,C,k,T=!1)=>{const w=u&&u.children,P=u?u.shapeFlag:0,E=p.children,{patchFlag:A,shapeFlag:j}=p;if(A>0){if(A&128){ns(w,E,m,S,b,v,C,k,T);return}else if(A&256){ot(w,E,m,S,b,v,C,k,T);return}}j&8?(P&16&&Ot(w,b,v),E!==w&&c(m,E)):P&16?j&16?ns(w,E,m,S,b,v,C,k,T):Ot(w,b,v,!0):(P&8&&c(m,""),j&16&&Ye(E,m,S,b,v,C,k,T))},ot=(u,p,m,S,b,v,C,k,T)=>{u=u||xt,p=p||xt;const w=u.length,P=p.length,E=Math.min(w,P);let A;for(A=0;AP?Ot(u,b,v,!0,!1,E):Ye(p,m,S,b,v,C,k,T,E)},ns=(u,p,m,S,b,v,C,k,T)=>{let w=0;const P=p.length;let E=u.length-1,A=P-1;for(;w<=E&&w<=A;){const j=u[w],V=p[w]=T?Ze(p[w]):De(p[w]);if(Pt(j,V))I(j,V,m,null,b,v,C,k,T);else break;w++}for(;w<=E&&w<=A;){const j=u[E],V=p[A]=T?Ze(p[A]):De(p[A]);if(Pt(j,V))I(j,V,m,null,b,v,C,k,T);else break;E--,A--}if(w>E){if(w<=A){const j=A+1,V=jA)for(;w<=E;)Oe(u[w],b,v,!0),w++;else{const j=w,V=w,J=new Map;for(w=V;w<=A;w++){const be=p[w]=T?Ze(p[w]):De(p[w]);be.key!=null&&J.set(be.key,w)}let K,ge=0;const me=A-V+1;let Ie=!1,Ae=0;const At=new Array(me);for(w=0;w=me){Oe(be,b,v,!0);continue}let Fe;if(be.key!=null)Fe=J.get(be.key);else for(K=V;K<=A;K++)if(At[K-V]===0&&Pt(be,p[K])){Fe=K;break}Fe===void 0?Oe(be,b,v,!0):(At[Fe-V]=w+1,Fe>=Ae?Ae=Fe:Ie=!0,I(be,p[Fe],m,null,b,v,C,k,T),ge++)}const An=Ie?bl(At):xt;for(K=An.length-1,w=me-1;w>=0;w--){const be=V+w,Fe=p[be],Fn=p[be+1],Pn=be+1{const{el:v,type:C,transition:k,children:T,shapeFlag:w}=u;if(w&6){lt(u.component.subTree,p,m,S);return}if(w&128){u.suspense.move(p,m,S);return}if(w&64){C.move(u,p,m,It);return}if(C===Z){n(v,p,m);for(let E=0;Ek.enter(v),b);else{const{leave:E,delayLeave:A,afterLeave:j}=k,V=()=>{u.ctx.isUnmounted?i(v):n(v,p,m)},J=()=>{v._isLeaving&&v[Fo](!0),E(v,()=>{V(),j&&j()})};A?A(v,V,J):J()}else n(v,p,m)},Oe=(u,p,m,S=!1,b=!1)=>{const{type:v,props:C,ref:k,children:T,dynamicChildren:w,shapeFlag:P,patchFlag:E,dirs:A,cacheIndex:j}=u;if(E===-2&&(b=!1),k!=null&&(Ke(),Ut(k,null,m,u,!0),Ge()),j!=null&&(p.renderCache[j]=void 0),P&256){p.ctx.deactivate(u);return}const V=P&1&&A,J=!Vt(u);let K;if(J&&(K=C&&C.onVnodeBeforeUnmount)&&Pe(K,p,u),P&6)Dr(u.component,m,S);else{if(P&128){u.suspense.unmount(m,S);return}V&&at(u,null,p,"beforeUnmount"),P&64?u.type.remove(u,p,m,It,S):w&&!w.hasOnce&&(v!==Z||E>0&&E&64)?Ot(w,p,m,!1,!0):(v===Z&&E&384||!b&&P&16)&&Ot(T,p,m),S&&On(u)}(J&&(K=C&&C.onVnodeUnmounted)||V)&&ve(()=>{K&&Pe(K,p,u),V&&at(u,null,p,"unmounted")},m)},On=u=>{const{type:p,el:m,anchor:S,transition:b}=u;if(p===Z){Mr(m,S);return}if(p===Ks){N(u);return}const v=()=>{i(m),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(u.shapeFlag&1&&b&&!b.persisted){const{leave:C,delayLeave:k}=b,T=()=>C(m,v);k?k(u.el,v,T):T()}else v()},Mr=(u,p)=>{let m;for(;u!==p;)m=x(u),i(u),u=m;i(p)},Dr=(u,p,m)=>{const{bum:S,scope:b,job:v,subTree:C,um:k,m:T,a:w}=u;Jn(T),Jn(w),S&&as(S),b.stop(),v&&(v.flags|=8,Oe(C,u,p,m)),k&&ve(k,p),ve(()=>{u.isUnmounted=!0},p)},Ot=(u,p,m,S=!1,b=!1,v=0)=>{for(let C=v;C{if(u.shapeFlag&6)return is(u.component.subTree);if(u.shapeFlag&128)return u.suspense.next();const p=x(u.anchor||u.el),m=p&&p[Io];return m?x(m):p};let Ns=!1;const In=(u,p,m)=>{u==null?p._vnode&&Oe(p._vnode,null,null,!0):I(p._vnode||null,u,p,null,null,null,m),p._vnode=u,Ns||(Ns=!0,Ln(),Bi(),Ns=!1)},It={p:I,um:Oe,m:lt,r:On,mt:Ds,mc:Ye,pc:z,pbc:rt,n:is,o:e};return{render:In,hydrate:void 0,createApp:Zo(In)}}function Bs({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function ct({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function xl(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function fr(e,t,s=!1){const n=e.children,i=t.children;if(M(n)&&M(i))for(let r=0;r>1,e[s[l]]0&&(t[n]=s[r-1]),s[r]=n)}}for(r=s.length,o=s[r-1];r-- >0;)s[r]=o,o=t[o];return s}function dr(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:dr(t)}function Jn(e){if(e)for(let t=0;te.__isSuspense;function vl(e,t){t&&t.pendingBranch?M(e)?t.effects.push(...e):t.effects.push(e):Eo(e)}const Z=Symbol.for("v-fgt"),Fs=Symbol.for("v-txt"),st=Symbol.for("v-cmt"),Ks=Symbol.for("v-stc"),Wt=[];let we=null;function y(e=!1){Wt.push(we=e?null:[])}function wl(){Wt.pop(),we=Wt[Wt.length-1]||null}let zt=1;function qn(e,t=!1){zt+=e,e<0&&we&&t&&(we.hasOnce=!0)}function hr(e){return e.dynamicChildren=zt>0?we||xt:null,wl(),zt>0&&we&&we.push(e),e}function _(e,t,s,n,i,r){return hr(h(e,t,s,n,i,r,!0))}function nt(e,t,s,n,i){return hr(Y(e,t,s,n,i,!0))}function gr(e){return e?e.__v_isVNode===!0:!1}function Pt(e,t){return e.type===t.type&&e.key===t.key}const mr=({key:e})=>e??null,us=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?ie(e)||ae(e)||L(e)?{i:ke,r:e,k:t,f:!!s}:e:null);function h(e,t=null,s=null,n=0,i=null,r=e===Z?0:1,o=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&mr(t),ref:t&&us(t),scopeId:Gi,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:n,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:ke};return l?(Sn(a,s),r&128&&e.normalize(a)):s&&(a.shapeFlag|=ie(s)?8:16),zt>0&&!o&&we&&(a.patchFlag>0||r&6)&&a.patchFlag!==32&&we.push(a),a}const Y=Sl;function Sl(e,t=null,s=null,n=0,i=null,r=!1){if((!e||e===Ko)&&(e=st),gr(e)){const l=kt(e,t,!0);return s&&Sn(l,s),zt>0&&!r&&we&&(l.shapeFlag&6?we[we.indexOf(e)]=l:we.push(l)),l.patchFlag=-2,l}if(Pl(e)&&(e=e.__vccOpts),t){t=Tl(t);let{class:l,style:a}=t;l&&!ie(l)&&(t.class=le(l)),X(a)&&(Rs(a)&&!M(a)&&(a=he({},a)),t.style=un(a))}const o=ie(e)?1:pr(e)?128:Ao(e)?64:X(e)?4:L(e)?2:0;return h(e,t,s,n,i,o,r,!0)}function Tl(e){return e?Rs(e)||rr(e)?he({},e):e:null}function kt(e,t,s=!1,n=!1){const{props:i,ref:r,patchFlag:o,children:l,transition:a}=e,f=t?kl(i||{},t):i,c={__v_isVNode:!0,__v_skip:!0,type:e.type,props:f,key:f&&mr(f),ref:t&&t.ref?s&&r?M(r)?r.concat(us(t)):[r,us(t)]:us(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Z?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:a,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&kt(e.ssContent),ssFallback:e.ssFallback&&kt(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return a&&n&&bn(c,a.clone(c)),c}function H(e=" ",t=0){return Y(Fs,null,e,t)}function D(e="",t=!1){return t?(y(),nt(st,null,e)):Y(st,null,e)}function De(e){return e==null||typeof e=="boolean"?Y(st):M(e)?Y(Z,null,e.slice()):gr(e)?Ze(e):Y(Fs,null,String(e))}function Ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:kt(e)}function Sn(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(M(t))s=16;else if(typeof t=="object")if(n&65){const i=t.default;i&&(i._c&&(i._d=!1),Sn(e,i()),i._c&&(i._d=!0));return}else{s=32;const i=t._;!i&&!rr(t)?t._ctx=ke:i===3&&ke&&(ke.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else L(t)?(t={default:t,_ctx:ke},s=32):(t=String(t),n&64?(s=16,t=[H(t)]):s=8);e.children=t,e.shapeFlag|=s}function kl(...e){const t={};for(let s=0;spe||ke;let _s,sn;{const e=ks(),t=(s,n)=>{let i;return(i=e[s])||(i=e[s]=[]),i.push(n),r=>{i.length>1?i.forEach(o=>o(r)):i[0](r)}};_s=t("__VUE_INSTANCE_SETTERS__",s=>pe=s),sn=t("__VUE_SSR_SETTERS__",s=>Jt=s)}const Xt=e=>{const t=pe;return _s(e),e.scope.on(),()=>{e.scope.off(),_s(t)}},Yn=()=>{pe&&pe.scope.off(),_s(null)};function yr(e){return e.vnode.shapeFlag&4}let Jt=!1;function Ol(e,t=!1,s=!1){t&&sn(t);const{props:n,children:i}=e.vnode,r=yr(e);fl(e,n,r,t),gl(e,i,s||t);const o=r?Il(e,t):void 0;return t&&sn(!1),o}function Il(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Go);const{setup:n}=s;if(n){Ke();const i=e.setupContext=n.length>1?Fl(e):null,r=Xt(e),o=Yt(n,e,0,[e.props,i]),l=yi(o);if(Ge(),r(),(l||e.sp)&&!Vt(e)&&zi(e),l){if(o.then(Yn,Yn),t)return o.then(a=>{Xn(e,a)}).catch(a=>{Es(a,e,0)});e.asyncDep=o}else Xn(e,o)}else _r(e)}function Xn(e,t,s){L(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:X(t)&&(e.setupState=Ui(t)),_r(e)}function _r(e,t,s){const n=e.type;e.render||(e.render=n.render||Ne);{const i=Xt(e);Ke();try{zo(e)}finally{Ge(),i()}}}const Al={get(e,t){return ce(e,"get",""),e[t]}};function Fl(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,Al),slots:e.slots,emit:e.emit,expose:t}}function Ps(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ui(yo(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in Ht)return Ht[s](e)},has(t,s){return s in t||s in Ht}})):e.proxy}function Pl(e){return L(e)&&"__vccOpts"in e}const _e=(e,t)=>To(e,t,Jt),Ml="3.5.25";let nn;const Qn=typeof window<"u"&&window.trustedTypes;if(Qn)try{nn=Qn.createPolicy("vue",{createHTML:e=>e})}catch{}const xr=nn?e=>nn.createHTML(e):e=>e,Dl="http://www.w3.org/2000/svg",Nl="http://www.w3.org/1998/Math/MathML",Ve=typeof document<"u"?document:null,Zn=Ve&&Ve.createElement("template"),jl={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const i=t==="svg"?Ve.createElementNS(Dl,e):t==="mathml"?Ve.createElementNS(Nl,e):s?Ve.createElement(e,{is:s}):Ve.createElement(e);return e==="select"&&n&&n.multiple!=null&&i.setAttribute("multiple",n.multiple),i},createText:e=>Ve.createTextNode(e),createComment:e=>Ve.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ve.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,i,r){const o=s?s.previousSibling:t.lastChild;if(i&&(i===r||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),s),!(i===r||!(i=i.nextSibling)););else{Zn.innerHTML=xr(n==="svg"?`${e}`:n==="mathml"?`${e}`:e);const l=Zn.content;if(n==="svg"||n==="mathml"){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,s)}return[o?o.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},Ll=Symbol("_vtc");function Ul(e,t,s){const n=e[Ll];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const xs=Symbol("_vod"),br=Symbol("_vsh"),Tn={name:"show",beforeMount(e,{value:t},{transition:s}){e[xs]=e.style.display==="none"?"":e.style.display,s&&t?s.beforeEnter(e):Mt(e,t)},mounted(e,{value:t},{transition:s}){s&&t&&s.enter(e)},updated(e,{value:t,oldValue:s},{transition:n}){!t!=!s&&(n?t?(n.beforeEnter(e),Mt(e,!0),n.enter(e)):n.leave(e,()=>{Mt(e,!1)}):Mt(e,t))},beforeUnmount(e,{value:t}){Mt(e,t)}};function Mt(e,t){e.style.display=t?e[xs]:"none",e[br]=!t}const Vl=Symbol(""),Hl=/(?:^|;)\s*display\s*:/;function Wl(e,t,s){const n=e.style,i=ie(s);let r=!1;if(s&&!i){if(t)if(ie(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();s[l]==null&&fs(n,l,"")}else for(const o in t)s[o]==null&&fs(n,o,"");for(const o in s)o==="display"&&(r=!0),fs(n,o,s[o])}else if(i){if(t!==s){const o=n[Vl];o&&(s+=";"+o),n.cssText=s,r=Hl.test(s)}}else t&&e.removeAttribute("style");xs in e&&(e[xs]=r?n.display:"",e[br]&&(n.display="none"))}const ei=/\s*!important$/;function fs(e,t,s){if(M(s))s.forEach(n=>fs(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=Bl(e,t);ei.test(s)?e.setProperty(gt(n),s.replace(ei,""),"important"):e[n]=s}}const ti=["Webkit","Moz","ms"],Gs={};function Bl(e,t){const s=Gs[t];if(s)return s;let n=tt(t);if(n!=="filter"&&n in e)return Gs[t]=n;n=bi(n);for(let i=0;izs||(Jl.then(()=>zs=0),zs=Date.now());function Yl(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;Le(Xl(n,s.value),t,5,[n])};return s.value=e,s.attached=ql(),s}function Xl(e,t){if(M(t)){const s=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{s.call(e),e._stopped=!0},t.map(n=>i=>!i._stopped&&n&&n(i))}else return t}const li=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Ql=(e,t,s,n,i,r)=>{const o=i==="svg";t==="class"?Ul(e,n,o):t==="style"?Wl(e,s,n):vs(t)?an(t)||Gl(e,t,s,n,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Zl(e,t,n,o))?(ii(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&ni(e,t,n,o,r,t!=="value")):e._isVueCE&&(/[A-Z]/.test(t)||!ie(n))?ii(e,tt(t),n,r,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),ni(e,t,n,o))};function Zl(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&li(t)&&L(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return li(t)&&ie(s)?!1:t in e}const it=e=>{const t=e.props["onUpdate:modelValue"]||!1;return M(t)?s=>as(t,s):t};function ea(e){e.target.composing=!0}function ai(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const $e=Symbol("_assign");function ci(e,t,s){return t&&(e=e.trim()),s&&(e=Ts(e)),e}const ta={created(e,{modifiers:{lazy:t,trim:s,number:n}},i){e[$e]=it(i);const r=n||i.props&&i.props.type==="number";Be(e,t?"change":"input",o=>{o.target.composing||e[$e](ci(e.value,s,r))}),(s||r)&&Be(e,"change",()=>{e.value=ci(e.value,s,r)}),t||(Be(e,"compositionstart",ea),Be(e,"compositionend",ai),Be(e,"change",ai))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:i,number:r}},o){if(e[$e]=it(o),e.composing)return;const l=(r||e.type==="number")&&!/^0\d/.test(e.value)?Ts(e.value):e.value,a=t??"";l!==a&&(document.activeElement===e&&e.type!=="range"&&(n&&t===s||i&&e.value.trim()===a)||(e.value=a))}},Te={deep:!0,created(e,t,s){e[$e]=it(s),Be(e,"change",()=>{const n=e._modelValue,i=$t(e),r=e.checked,o=e[$e];if(M(n)){const l=fn(n,i),a=l!==-1;if(r&&!a)o(n.concat(i));else if(!r&&a){const f=[...n];f.splice(l,1),o(f)}}else if(Rt(n)){const l=new Set(n);r?l.add(i):l.delete(i),o(l)}else o(vr(e,r))})},mounted:ui,beforeUpdate(e,t,s){e[$e]=it(s),ui(e,t,s)}};function ui(e,{value:t,oldValue:s},n){e._modelValue=t;let i;if(M(t))i=fn(t,n.props.value)>-1;else if(Rt(t))i=t.has(n.props.value);else{if(t===s)return;i=pt(t,vr(e,!0))}e.checked!==i&&(e.checked=i)}const fi={created(e,{value:t},s){e.checked=pt(t,s.props.value),e[$e]=it(s),Be(e,"change",()=>{e[$e]($t(e))})},beforeUpdate(e,{value:t,oldValue:s},n){e[$e]=it(n),t!==s&&(e.checked=pt(t,n.props.value))}},di={deep:!0,created(e,{value:t,modifiers:{number:s}},n){const i=Rt(t);Be(e,"change",()=>{const r=Array.prototype.filter.call(e.options,o=>o.selected).map(o=>s?Ts($t(o)):$t(o));e[$e](e.multiple?i?new Set(r):r:r[0]),e._assigning=!0,Hi(()=>{e._assigning=!1})}),e[$e]=it(n)},mounted(e,{value:t}){pi(e,t)},beforeUpdate(e,t,s){e[$e]=it(s)},updated(e,{value:t}){e._assigning||pi(e,t)}};function pi(e,t){const s=e.multiple,n=M(t);if(!(s&&!n&&!Rt(t))){for(let i=0,r=e.options.length;iString(f)===String(l)):o.selected=fn(t,l)>-1}else o.selected=t.has(l);else if(pt($t(o),t)){e.selectedIndex!==i&&(e.selectedIndex=i);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function $t(e){return"_value"in e?e._value:e.value}function vr(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const sa=["ctrl","shift","alt","meta"],na={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>sa.some(s=>e[`${s}Key`]&&!t.includes(s))},ht=(e,t)=>{const s=e._withMods||(e._withMods={}),n=t.join(".");return s[n]||(s[n]=((i,...r)=>{for(let o=0;o{const t=ra().createApp(...e),{mount:s}=t;return t.mount=n=>{const i=aa(n);if(!i)return;const r=t._component;!L(r)&&!r.render&&!r.template&&(r.template=i.innerHTML),i.nodeType===1&&(i.textContent="");const o=s(i,!1,la(i));return i instanceof Element&&(i.removeAttribute("v-cloak"),i.setAttribute("data-v-app","")),o},t});function la(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function aa(e){return ie(e)?document.querySelector(e):e}const gi={neutral:'',success:'',failure:''};function Ct(e="neutral"){const t=document.getElementById("favicon");if(t){const s=gi[e]||gi.neutral;t.href=`data:image/svg+xml;base64,${btoa(s)}`}}function Qt(e){const t=e.indexOf("::");return t===-1?{suiteName:e,testName:void 0,fullId:e}:{suiteName:e.substring(0,t),testName:e.substring(t+2),fullId:e}}function bs(e){if(e==null)return"0.00ms";const t=e/1e9;return t>=1?`${t.toFixed(2)}s`:`${(e/1e6).toFixed(2)}ms`}class mt{constructor(t=""){this.baseUrl=t}async retry(t,s=3,n=1e3){for(let i=0;i<=s;i++)try{return await t()}catch(r){const o=r instanceof TypeError&&r.message==="Failed to fetch";if(o&&isetTimeout(l,n));else if(o){const l="Network error: Could not connect to the server after multiple attempts. Please check your connection or try again.";throw new Error(l)}else throw r}}async fetchTests(){try{return await this.retry(async()=>{const t=await fetch(`${this.baseUrl}/api/tests`);if(!t.ok){const s=await t.json();throw new Error(s.error||"Failed to fetch tests")}return await t.json()})}catch(t){throw console.error("Failed to fetch tests:",t),t}}async runTests(t){try{return await this.retry(async()=>{const s=await fetch(`${this.baseUrl}/api/run`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!s.ok){const n=await s.json();throw new Error(n.error||"Failed to run tests")}return await s.json()})}catch(s){throw console.error("Failed to run tests:",s),s}}async stopAllTests(){try{await this.retry(async()=>{if(!(await fetch(`${this.baseUrl}/api/stop`,{method:"POST"})).ok)throw new Error("Failed to stop tests")})}catch(t){throw console.error("Failed to stop tests:",t),t}}async stopSingleTest(){try{await this.retry(async()=>{if(!(await fetch(`${this.baseUrl}/api/stop-single-test`,{method:"POST"})).ok)throw new Error("Failed to stop test run")})}catch(t){throw console.error("Failed to stop test run:",t),t}}async fetchCoverage(){try{return await this.retry(async()=>{const t=await fetch(`${this.baseUrl}/api/coverage`);if(!t.ok){let s="Unknown error";try{const n=await t.json();s=n.error||JSON.stringify(n)}catch{s=t.statusText}throw new Error(`Failed to fetch coverage report: ${s}`)}return await t.json()})}catch(t){throw console.error("Failed to fetch coverage report:",t),t}}async fetchFileCoverage(t){try{return await this.retry(async()=>{const s=await fetch(`${this.baseUrl}/api/file-coverage?path=${encodeURIComponent(t)}`);if(!s.ok){const n=await s.json();throw new Error(n.error||"Failed to fetch file coverage")}return await s.json()})}catch(s){throw console.error("Failed to fetch file coverage:",s),s}}async fetchFileContent(t){try{return await this.retry(async()=>{const s=await fetch(`${this.baseUrl}/api/file-content?path=${encodeURIComponent(t)}`);if(!s.ok){const n=await s.text();try{const i=JSON.parse(n);throw new Error(i.error||"Failed to fetch file content")}catch{throw new Error(n||"Failed to fetch file content")}}return await s.text()})}catch(s){throw console.error("Failed to fetch file content:",s),s}}}const rn="phpunit-hub-settings",wr={displayWarnings:!0,displayDeprecations:!0,displaySkipped:!0,displayIncomplete:!0,displayRisky:!0,displayNotices:!0,stopOnDefect:!1,stopOnError:!1,stopOnFailure:!1,stopOnWarning:!1,stopOnRisky:!1,displayMode:"default"},R=Cs({testSuites:[],availableSuites:[],availableGroups:[],isLoading:!1,isStarting:!1,expandedSuites:new Set,expandedTestcaseGroups:new Set,expandedTestId:null,showFilterPanel:!1,activeTab:"results",sortBy:"default",sortDirection:"desc",selectedSuites:[],selectedGroups:[],options:{...wr},coverage:!1,testRun:null,isRunning:!1,isStopping:!1,coverageReport:null,isCoverageLoading:!1,fileCoverage:null,coverageDriverMissing:!1});async function ca(e={}){if(R.isStarting)return;R.isStarting=!0,R.activeTab="results";const t=new mt(""),{displayMode:s,...n}=R.options,i={filters:e.filters||[],groups:R.selectedGroups,suites:R.selectedSuites,options:{...n,colors:!0},coverage:!!R.coverage,contextId:e.contextId||"global"};try{await t.runTests(i)}catch(r){console.error("Failed to run tests:",r),Ct("failure"),R.isStarting=!1}}function ua(){const e=localStorage.getItem(rn);if(e)try{const t=JSON.parse(e);if(t.options){const{resultUpdateMode:s,...n}=t.options;R.options={...R.options,...n}}Array.isArray(t.selectedSuites)&&(R.selectedSuites=t.selectedSuites),Array.isArray(t.selectedGroups)&&(R.selectedGroups=t.selectedGroups),t.coverage&&(R.coverage=t.coverage)}catch(t){console.error("Failed to load state from localStorage",t),localStorage.removeItem(rn)}}function fa(){const e={options:R.options,selectedSuites:R.selectedSuites,selectedGroups:R.selectedGroups,coverage:R.coverage};localStorage.setItem(rn,JSON.stringify(e))}function Zt(e={}){ca(e)}function da(){Zt({contextId:"global"})}function pa(){const e=Or();if(e.length===0){console.log("No failed tests to run.");return}Zt({filters:e,contextId:"failed"})}function ha(e){Zt({filters:[e],contextId:e})}function ga(e){Zt({filters:[e],contextId:e})}async function ma(){const e=new mt("");try{Cn(),await e.stopAllTests()}catch(t){console.error("Failed to stop tests:",t),Rn()}}async function ya(){const e=new mt("");try{Cn(),await e.stopSingleTest()}catch(t){console.error("Failed to stop test run:",t),Rn()}}function _a(e){R.sortBy===e?R.sortDirection==="desc"?R.sortDirection="asc":(R.sortBy="default",R.sortDirection="desc"):(R.sortBy=e,R.sortDirection="desc")}function xa(e){R.options.displayMode=e}function ba(e){R.isStarting=e}function va(e){R.isStarting=!1,R.isRunning=!0,R.isStopping=!1,R.testRun={status:"running",contextId:e,suites:{},summary:null,failedTestIds:new Set,executionEnded:!1,sumOfDurations:0},R.expandedTestId=null,R.expandedTestcaseGroups=new Set,Er(),R.testSuites.forEach(t=>{t.id===e&&(t.isRunning=!0)}),R.activeTab="results"}function wa(e){const t=R.testRun;if(!t){console.warn("Received event for unknown run");return}switch(e.event){case"suite.started":Sr(t,e);break;case"test.prepared":Tr(t,e);break;case"test.warning":case"test.deprecation":kr(t,e);break;case"test.notice":$r(t,e);break;case"test.passed":case"test.failed":case"test.errored":case"test.skipped":case"test.incomplete":case"test.risky":Cr(t,e);break;case"test.finished":Rr(t,e);break}}function Sr(e,t){e.suites[t.data.name]={name:t.data.name,count:t.data.count,tests:{},passed:0,failed:0,errored:0,skipped:0,incomplete:0,warning:0,deprecation:0,notice:0,risky:0,hasIssues:!1}}function Tr(e,t){const{suiteName:s,testName:n}=Qt(t.data.testId);e.suites[s]||(e.suites[s]={name:s,count:0,tests:{},passed:0,failed:0,errored:0,skipped:0,incomplete:0,warning:0,deprecation:0,notice:0,risky:0,hasIssues:!1}),e.suites[s].tests[t.data.testId]={id:t.data.testId,name:n,class:s,status:"running",duration:null,assertions:0,message:null,trace:null,warnings:[],deprecations:[],notices:[]},kn(s,t.data.testId,"running")}function kr(e,t){const{suiteName:s}=Qt(t.data.testId),n=t.data.testId;if(e.suites[s]&&e.suites[s].tests[n]){const i=e.suites[s].tests[n],r=e.suites[s];t.event==="test.warning"?(i.warnings.push(t.data.message||"Some warning triggered"),r.warning++):t.event==="test.deprecation"&&(i.deprecations.push(t.data.message||"Some deprecation triggered"),r.deprecation++),r.hasIssues=!0}}function $r(e,t){const{suiteName:s}=Qt(t.data.testId),n=t.data.testId;if(e.suites[s]&&e.suites[s].tests[n]){const i=e.suites[s].tests[n],r=e.suites[s];i.notices.push(t.data.message||"Some notice triggered"),r.notice++,r.hasIssues=!0}}function Cr(e,t){const{suiteName:s,testName:n}=Qt(t.data.testId),i=t.data.testId;if(e.suites[s]&&e.suites[s].tests[i]){const r=e.suites[s].tests[i],o=t.event.replace("test.","");r.status=o,r.message=t.data.message||null,r.trace=t.data.trace||null;const l=e.suites[s];l[o]!==void 0&&l[o]++,o==="failed"||o==="errored"?(e.failedTestIds.add(i),l.hasIssues=!0):o==="passed"?e.failedTestIds.delete(i):o!=="passed"&&(l.hasIssues=!0),kn(s,i,o,r.duration)}}function Rr(e,t){const{suiteName:s}=Qt(t.data.testId),n=t.data.testId;if(e.suites[s]&&e.suites[s].tests[n]){const i=e.suites[s].tests[n];i.duration=t.data.duration,i.assertions=t.data.assertions,e.sumOfDurations+=i.duration,i.status&&kn(s,n,i.status,i.duration)}}function Sa(e){const t=R.testRun;t&&(t.summary=e.data.summary,t.executionEnded=!0,Ct(t.summary.status==="passed"?"success":"failure"))}function Ta(){const e=R.testRun;e&&(e.status="finished"),R.isRunning=!1,R.isStopping=!1,R.isStarting=!1,$n()}function kn(e,t,s,n=null){R.testSuites.forEach(i=>{i.id===e&&i.methods?.forEach(r=>{r.id===t&&(r.status=s,n!==null&&(r.duration=n))})})}function Er(){R.testSuites.forEach(e=>{e.isRunning=!1,e.methods?.forEach(t=>{t.status=null,t.duration=null})})}function ka(){const e=R.testRun;e&&(e.status="stopped"),R.isRunning=!1,R.isStopping=!1,R.isStarting=!1,$n()}function $n(){R.testSuites.forEach(e=>{e.isRunning=!1})}function $a(){return R.testRun}function Ca(){return R.isRunning}function Ra(){R.isRunning=!1,R.isStopping=!1}function Cn(){R.isStopping=!0}function Rn(){R.isStopping=!1}function Ea(e){R.expandedSuites.has(e)?R.expandedSuites.delete(e):R.expandedSuites.add(e)}function Oa(e){R.expandedTestcaseGroups.has(e)?R.expandedTestcaseGroups.delete(e):R.expandedTestcaseGroups.add(e)}function Ia(e){R.expandedTestId=e}function Aa(){R.showFilterPanel=!R.showFilterPanel}function Or(){const e=R.testRun;return e?Array.from(e.failedTestIds):[]}function Fa(){const e=R.testRun;return e?e.failedTestIds.size>0:!1}function Pa(){R.selectedSuites=[],R.selectedGroups=[],R.coverage=!1,R.options={...wr}}function Ma(e){R.activeTab=e}function Ir(e){R.coverageReport=e}function Ar(e){R.isCoverageLoading=e}function Da(e){R.fileCoverage=e}async function Na(){const e=new mt("");try{const t=await e.fetchCoverage();Ir(t)}catch(t){console.error("Failed to fetch coverage report:",t)}finally{Ar(!1)}}ua();function se(){return{state:R,saveState:fa,runTests:Zt,runAllTests:da,runFailedTests:pa,runSingleTest:ha,runSuiteTests:ga,stopAllTests:ma,stopSingleTest:ya,setSortBy:_a,setDisplayMode:xa,setStarting:ba,initializeTestRun:va,handleTestEvent:wa,handleSuiteStarted:Sr,handleTestPrepared:Tr,handleTestWarningOrDeprecation:kr,handleTestNotice:$r,handleTestCompleted:Cr,handleTestFinished:Rr,handleExecutionEnded:Sa,finishTestRun:Ta,stopTestRun:ka,getTestRun:$a,isTestRunning:Ca,clearRunningTests:Ra,markStopPending:Cn,clearStopPending:Rn,toggleSuiteExpansion:Ea,toggleTestcaseGroupExpansion:Oa,setExpandedTest:Ia,toggleFilterPanel:Aa,getFailedTestIds:Or,hasFailedTests:Fa,clearAllResults(){this.state.testRun=null,this.state.expandedTestId=null,this.state.expandedTestcaseGroups=new Set,this.state.coverageReport=null,this.state.fileCoverage=null,this.resetSidebarTestStatuses(),Ct("neutral")},clearFilters:Pa,setActiveTab:Ma,setCoverageReport:Ir,setCoverageLoading:Ar,setFileCoverage:Da,fetchCoverageReport:Na,resetSidebarTestStatuses:Er,updateSidebarAfterRun:$n}}class ja{constructor(t="ws://127.0.0.1:8080/ws/status",s,n={}){this.url=t,this.store=s,this.callbacks=n,this.ws=null,this.reconnectAttempts=0,this.maxReconnectAttempts=5,this.reconnectDelay=2e3}connect(){return new Promise((t,s)=>{try{this.ws=new WebSocket(this.url),this.ws.onopen=()=>{console.log("WebSocket connected"),this.reconnectAttempts=0,t()},this.ws.onmessage=n=>{this.handleMessage(JSON.parse(n.data))},this.ws.onerror=n=>{console.error("WebSocket error:",n),s(n)},this.ws.onclose=()=>{console.log("WebSocket disconnected"),this.handleDisconnect()}}catch(n){s(n)}})}handleDisconnect(){if(this.store.clearRunningTests(),Ct("neutral"),this.reconnectAttemptsthis.connect().catch(()=>{}),t)}}handleMessage(t){switch(t.type){case"start":this.handleTestStart(t);break;case"realtime":this.handleRealtimeEvent(t);break;case"exit":this.handleTestExit();break;case"stopped":this.handleTestStopped();break;default:console.warn("Unknown message type:",t.type)}}handleTestStart(t){this.store.initializeTestRun(t.contextId)}handleRealtimeEvent(t){try{const s=JSON.parse(t.data);s.event==="execution.ended"?this.handleExecutionEnded(s):this.store.handleTestEvent(s),s.event==="execution.ended"&&this.store.state.coverage&&this.store.setCoverageLoading(!0)}catch(s){console.error("Failed to parse realtime event:",s,t.data)}}handleExecutionEnded(t){this.store.handleExecutionEnded(t)}handleTestExit(){this.store.finishTestRun(),this.store.state.coverage&&this.callbacks.fetchCoverageReport&&this.callbacks.fetchCoverageReport()}handleTestStopped(){this.store.stopTestRun(),this.updateFaviconIfComplete()}updateFaviconIfComplete(){this.store.isTestRunning()||Ct("neutral")}disconnect(){this.ws&&(this.ws.close(),this.ws=null)}}function La(e,t){Is(()=>{const s=document.getElementById(e),n=document.getElementById(t);if(!s||!n)return;let i=!1;const r=a=>{a.preventDefault(),i=!0,document.body.style.cursor="col-resize",document.body.style.userSelect="none",document.addEventListener("mousemove",o),document.addEventListener("mouseup",l)},o=a=>{if(i){const f=a.clientX;f>200&&f{i=!1,document.body.style.cursor="",document.body.style.userSelect="",document.removeEventListener("mousemove",o),document.removeEventListener("mouseup",l)};s.addEventListener("mousedown",r)})}const Fr=(e,t)=>{const s=e.__vccOpts||e;for(const[n,i]of t)s[n]=i;return s},Ua={},Va={class:"text-2xl font-bold text-white"};function Ha(e,t){return y(),_("h1",Va,"PHPUnit Hub")}const Wa=Fr(Ua,[["render",Ha]]),Ba={};function Ka(e,t){return y(),_("button",{onClick:t[0]||(t[0]=ht(s=>e.$emit("toggle"),["stop"])),class:"bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out"}," Filters / Settings ")}const Ga=Fr(Ba,[["render",Ka]]),za={class:"form-group"},Ja=["value"],qa={class:"form-group"},Ya=["value"],Xa={class:"form-group"},Qa={class:"space-y-2"},Za={class:"flex items-center text-sm"},ec={class:"flex items-center text-sm"},tc={class:"form-group"},sc={class:"grid grid-cols-2 gap-2"},nc={class:"flex items-center text-sm"},ic={class:"flex items-center text-sm"},rc={class:"flex items-center text-sm"},oc={class:"flex items-center text-sm"},lc={class:"flex items-center text-sm"},ac={class:"flex items-center text-sm"},cc={class:"form-group"},uc={class:"grid grid-cols-2 gap-2"},fc={class:"flex items-center text-sm"},dc={class:"flex items-center text-sm"},pc={class:"flex items-center text-sm"},hc={class:"flex items-center text-sm"},gc={class:"flex items-center text-sm"},mc={class:"form-group"},yc={class:"grid grid-cols-2 gap-2"},_c={class:"flex items-center text-sm"},xc={__name:"FilterPanelContent",setup(e){const t=se();function s(){t.clearFilters()}return(n,i)=>(y(),_("div",{onClick:i[16]||(i[16]=ht(()=>{},["stop"])),class:"filter-panel-dropdown bg-gray-800 p-4 rounded-lg shadow-lg border border-gray-700"},[h("div",{class:"flex justify-between items-center mb-4"},[i[17]||(i[17]=h("h3",{class:"text-lg font-semibold text-white"},"Filters & Settings",-1)),h("button",{onClick:s,class:"text-sm text-blue-400 hover:text-blue-300"},"Clear Filters")]),h("div",za,[i[18]||(i[18]=h("label",{for:"group-filter",class:"block text-sm font-medium text-gray-300 mb-1"},"Test Groups",-1)),ne(h("select",{id:"group-filter","onUpdate:modelValue":i[0]||(i[0]=r=>g(t).state.selectedGroups=r),multiple:"",class:"w-full bg-gray-700 border border-gray-600 rounded py-2 px-3 text-white h-24"},[(y(!0),_(Z,null,xe(g(t).state.availableGroups,(r,o)=>(y(),_("option",{value:o},O(r),9,Ja))),256))],512),[[di,g(t).state.selectedGroups]])]),h("div",qa,[i[19]||(i[19]=h("label",{for:"filter-suite",class:"block text-sm font-medium text-gray-300 mb-1"},"Test Suites",-1)),ne(h("select",{id:"filter-suite","onUpdate:modelValue":i[1]||(i[1]=r=>g(t).state.selectedSuites=r),multiple:"",class:"w-full bg-gray-700 border border-gray-600 rounded py-2 px-3 text-white h-24"},[(y(!0),_(Z,null,xe(g(t).state.availableSuites,(r,o)=>(y(),_("option",{value:o},O(r),9,Ya))),256))],512),[[di,g(t).state.selectedSuites]])]),h("div",Xa,[i[22]||(i[22]=h("label",{class:"block text-sm font-medium text-gray-300 mb-2"},"Display Mode",-1)),h("div",Qa,[h("label",Za,[ne(h("input",{type:"radio","onUpdate:modelValue":i[2]||(i[2]=r=>g(t).state.options.displayMode=r),value:"default",class:"mr-2"},null,512),[[fi,g(t).state.options.displayMode]]),i[20]||(i[20]=H(" Grouped (default) ",-1))]),h("label",ec,[ne(h("input",{type:"radio","onUpdate:modelValue":i[3]||(i[3]=r=>g(t).state.options.displayMode=r),value:"individual",class:"mr-2"},null,512),[[fi,g(t).state.options.displayMode]]),i[21]||(i[21]=H(" Individual tests ",-1))])])]),h("div",tc,[i[29]||(i[29]=h("label",{class:"block text-sm font-medium text-gray-300 mb-2"},"Output Options",-1)),h("div",sc,[h("label",nc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[4]||(i[4]=r=>g(t).state.options.displayWarnings=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displayWarnings]]),i[23]||(i[23]=H(" Show Warnings ",-1))]),h("label",ic,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[5]||(i[5]=r=>g(t).state.options.displayDeprecations=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displayDeprecations]]),i[24]||(i[24]=H(" Show Deprecations ",-1))]),h("label",rc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[6]||(i[6]=r=>g(t).state.options.displayNotices=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displayNotices]]),i[25]||(i[25]=H(" Show Notices ",-1))]),h("label",oc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[7]||(i[7]=r=>g(t).state.options.displaySkipped=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displaySkipped]]),i[26]||(i[26]=H(" Show Skipped ",-1))]),h("label",lc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[8]||(i[8]=r=>g(t).state.options.displayIncomplete=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displayIncomplete]]),i[27]||(i[27]=H(" Show Incomplete ",-1))]),h("label",ac,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[9]||(i[9]=r=>g(t).state.options.displayRisky=r),class:"mr-2"},null,512),[[Te,g(t).state.options.displayRisky]]),i[28]||(i[28]=H(" Show Risky ",-1))])])]),h("div",cc,[i[35]||(i[35]=h("label",{class:"block text-sm font-medium text-gray-300 mb-2"},"Stop On Options",-1)),h("div",uc,[h("label",fc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[10]||(i[10]=r=>g(t).state.options.stopOnDefect=r),class:"mr-2"},null,512),[[Te,g(t).state.options.stopOnDefect]]),i[30]||(i[30]=H(" Defect ",-1))]),h("label",dc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[11]||(i[11]=r=>g(t).state.options.stopOnError=r),class:"mr-2"},null,512),[[Te,g(t).state.options.stopOnError]]),i[31]||(i[31]=H(" Error ",-1))]),h("label",pc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[12]||(i[12]=r=>g(t).state.options.stopOnFailure=r),class:"mr-2"},null,512),[[Te,g(t).state.options.stopOnFailure]]),i[32]||(i[32]=H(" Failure ",-1))]),h("label",hc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[13]||(i[13]=r=>g(t).state.options.stopOnWarning=r),class:"mr-2"},null,512),[[Te,g(t).state.options.stopOnWarning]]),i[33]||(i[33]=H(" Warning ",-1))]),h("label",gc,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[14]||(i[14]=r=>g(t).state.options.stopOnRisky=r),class:"mr-2"},null,512),[[Te,g(t).state.options.stopOnRisky]]),i[34]||(i[34]=H(" Risky ",-1))])])]),h("div",mc,[i[37]||(i[37]=h("label",{class:"block text-sm font-medium text-gray-300 mb-2"},"Coverage",-1)),h("div",yc,[h("label",_c,[ne(h("input",{type:"checkbox","onUpdate:modelValue":i[15]||(i[15]=r=>g(t).state.coverage=r),class:"mr-2"},null,512),[[Te,g(t).state.coverage]]),i[36]||(i[36]=H(" Run with Code Coverage ",-1))])])])]))}},bc={class:"relative"},vc={__name:"FilterPanel",setup(e){const t=se();function s(){t.toggleFilterPanel()}return(n,i)=>(y(),_("div",bc,[Y(Ga,{onToggle:s}),ne(Y(xc,null,null,512),[[Tn,g(t).state.showFilterPanel]])]))}},wc=["disabled"],Sc={__name:"ClearResultsButton",setup(e){const t=se();function s(){t.clearAllResults()}const n=_e(()=>t.state.isStarting||t.state.isRunning||i.value),i=_e(()=>t.state.isStopping);return(r,o)=>(y(),_("button",{onClick:s,disabled:n.value,class:"bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out disabled:bg-gray-500",title:"Clear all test results"}," Clear Results ",8,wc))}},Tc=["disabled"],kc={__name:"RunFailedButton",setup(e){const t=_e(()=>s.hasFailedTests()),s=se();function n(){s.runFailedTests()}const i=_e(()=>s.state.isStopping),r=_e(()=>s.state.isStarting||s.state.isRunning||i.value);return(o,l)=>(y(),_("button",{onClick:n,disabled:r.value||!t.value,class:"bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out disabled:bg-gray-500"}," Run Failed ",8,Tc))}},$c=["title","disabled"],Cc={key:0},Rc={key:0},Ec={key:1},Oc={__name:"RunStopAllButton",setup(e){const t=se();function s(){t.state.isRunning?t.stopAllTests():t.runAllTests()}const n=_e(()=>t.state.isStarting||t.state.isRunning||i.value),i=_e(()=>t.state.isStopping);return(r,o)=>(y(),_("button",{onClick:s,title:n.value?"Stop all test runs":"Run all tests",disabled:i.value,class:"bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out disabled:opacity-60"},[i.value?(y(),_("span",Cc,"Stopping...")):(y(),_(Z,{key:1},[n.value?(y(),_("span",Ec,[...o[1]||(o[1]=[h("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",class:"w-5 h-5 inline-block"},[h("path",{d:"M6 6h8v8H6z"})],-1),h("span",{class:"ml-2 align-middle"},"Stop All",-1)])])):(y(),_("span",Rc,[...o[0]||(o[0]=[h("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",class:"w-5 h-5 inline-block"},[h("path",{d:"M6.3 2.841A1.5 1.5 0 004 4.11V15.89a1.5 1.5 0 002.3 1.269l9.344-5.89a1.5 1.5 0 000-2.538L6.3 2.84z"})],-1),h("span",{class:"ml-2 align-middle"},"Run All",-1)])]))],64))],8,$c))}},Ic={class:"bg-gray-800 shadow-md p-4 flex justify-between items-center z-10 relative"},Ac={class:"flex items-center space-x-4"},Fc={__name:"Header",props:["isAnyStopPending","results"],setup(e){return(t,s)=>(y(),_("header",Ic,[Y(Wa),h("div",Ac,[Y(vc),Y(Sc,{results:e.results},null,8,["results"]),Y(kc),Y(Oc)])]))}},Pc={__name:"TestSearchBar",emits:["update:filtered-suites"],setup(e,{emit:t}){const s=se(),n=t,i=Li(""),r=o=>{if(!o){n("update:filtered-suites",s.state.testSuites);return}const l=o.toLowerCase(),a=s.state.testSuites.map(f=>{const c=f.methods.filter(d=>d.name.toLowerCase().includes(l));return f.name.toLowerCase().includes(l)?{...f,methods:f.methods}:c.length>0?{...f,methods:c}:null}).filter(Boolean);n("update:filtered-suites",a)};return St(i,o=>{r(o)},{immediate:!0}),St(()=>s.state.testSuites,o=>{i.value="",n("update:filtered-suites",o)}),(o,l)=>ne((y(),_("input",{type:"text","onUpdate:modelValue":l[0]||(l[0]=a=>i.value=a),placeholder:"Search tests...",class:"w-full bg-gray-800 border border-gray-600 rounded py-2 px-3 mb-4 text-white focus:outline-none focus:ring-2 focus:ring-blue-500"},null,512)),[[ta,i.value]])}},Mc={class:"suite-header text-md text-gray-200"},Dc={class:"font-bold"},Nc={class:"flex items-center"},jc={key:0,class:"spinner !w-4 !h-4"},Lc=["title"],Uc={__name:"TestSuiteHeader",props:["suite"],emits:["toggle-suite","runSuiteTests"],setup(e,{emit:t}){const s=new mt(""),n=se(),i=t;async function r(){try{n.markStopPending(),await s.stopSingleTest()}catch(f){console.error("Failed to stop test run:",f),n.clearStopPending()}}function o(f){l()||i("runSuiteTests",f)}function l(){return n.state.isRunning}function a(){return n.state.isStopping}return(f,c)=>(y(),_("div",Mc,[h("div",{onClick:c[0]||(c[0]=d=>f.$emit("toggle-suite",e.suite.id)),class:"flex items-center flex-grow cursor-pointer"},[(y(),_("svg",{class:le(["suite-arrow w-4 h-4 text-gray-400",{rotated:g(n).state.expandedSuites.has(e.suite.id)}]),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg"},[...c[2]||(c[2]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 5l7 7-7 7"},null,-1)])],2)),h("span",Dc,O(e.suite.name),1)]),h("div",Nc,[e.suite.isRunning?(y(),_("div",jc)):D("",!0),e.suite.isRunning?(y(),_("span",{key:1,onClick:ht(r,["stop"]),class:"cursor-pointer text-red-500 hover:text-red-400 ml-2",title:"Stop this suite"},[...c[3]||(c[3]=[h("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",class:"w-5 h-5"},[h("path",{d:"M6 6h8v8H6z"})],-1)])])):(y(),_("span",{key:2,onClick:c[1]||(c[1]=ht(d=>o(e.suite.id),["stop"])),class:le({"cursor-pointer text-green-500 hover:text-green-400":!a(),"text-gray-500":a()}),title:a()?"Stopping...":"Run all tests in this suite"},[...c[4]||(c[4]=[h("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",class:"w-5 h-5"},[h("path",{d:"M6.3 2.841A1.5 1.5 0 004 4.11V15.89a1.5 1.5 0 002.3 1.269l9.344-5.89a1.5 1.5 0 000-2.538L6.3 2.84z"})],-1)])],10,Lc))])]))}},Vc={class:"test-item-left w-full"},Hc={class:"flex items-center"},Wc={key:0,class:"status-icon spinner"},Bc={class:"flex items-center space-x-2 justify-between w-full"},Kc={class:"test-name"},Gc={__name:"TestItem",props:["method"],emits:["runSingleTest"],setup(e,{emit:t}){const s=t,n=se();function i(o){s("runSingleTest",o)}function r(){return n.state.isRunning}return(o,l)=>(y(),_("li",{class:"test-item cursor-pointer",onClick:l[0]||(l[0]=ht(a=>i(e.method.id),["stop"]))},[h("div",Vc,[h("div",Hc,[e.method.runId&&r(e.method.runId)?(y(),_("span",Wc)):(y(),_("span",{key:1,class:le(["status-icon",e.method.status?"status-"+e.method.status:"status-neutral"])},null,2))]),h("div",Bc,[h("span",Kc,O(e.method.name),1)])])]))}},zc={class:"ml-2 mt-2 space-y-1"},Jc={__name:"TestList",props:["suite"],emits:["runSingleTest"],setup(e,{emit:t}){const s=t;function n(i){s("runSingleTest",i)}return(i,r)=>(y(),_("ul",zc,[(y(!0),_(Z,null,xe(e.suite.methods,o=>(y(),nt(Gc,{key:o.id,method:o,onRunSingleTest:n},null,8,["method"]))),128))]))}},qc={class:"mb-4"},Yc={__name:"TestSuite",props:["suite"],setup(e){const t=se();function s(r){t.runSuiteTests(r)}function n(r){t.runSingleTest(r)}function i(r){t.toggleSuiteExpansion(r)}return(r,o)=>(y(),_("div",qc,[Y(Uc,{suite:e.suite,onToggleSuite:i,onRunSuiteTests:s},null,8,["suite"]),ne(Y(Jc,{suite:e.suite,onRunSingleTest:n},null,8,["suite"]),[[Tn,g(t).state.expandedSuites.has(e.suite.id)]])]))}},Xc={id:"test-sidebar",class:"bg-gray-800 p-4 overflow-y-auto border-r border-gray-700 w-80"},Qc={key:0,class:"flex justify-center h-full mt-4"},Zc={key:1,class:"text-gray-500"},eu={__name:"TestSidebar",setup(e){const t=new mt(""),s=se(),n=Li(s.state.testSuites||[]),i={};Is(async()=>{try{await r()}catch(l){console.error("Failed to initialize sidebar:",l)}});async function r(){s.state.isLoading=!0;try{const l=await t.fetchTests();s.state.testSuites=l.suites,s.state.availableSuites=l.availableSuites||[],s.state.availableGroups=l.availableGroups||[],s.state.coverageDriverMissing=!l.coverageDriver,o()}catch(l){throw console.error("Failed to fetch tests:",l),l}finally{s.state.isLoading=!1}}function o(){s.state.testSuites.forEach(l=>{l.methods&&l.methods.forEach(a=>{i[a.id]={suite:l,method:a}})})}return(l,a)=>(y(),_("aside",Xc,[Y(Pc,{"onUpdate:filteredSuites":a[0]||(a[0]=f=>n.value=f)}),g(s).state.isLoading?(y(),_("div",Qc,[...a[1]||(a[1]=[h("div",{class:"spinner-big"},null,-1)])])):D("",!0),!g(s).state.isLoading&&n.value.length===0?(y(),_("div",Zc," No tests found. ")):D("",!0),g(s).state.isLoading?D("",!0):(y(!0),_(Z,{key:2},xe(n.value,f=>(y(),nt(Yc,{key:f.id,suite:f},null,8,["suite"]))),128))]))}},tu={class:"mb-4"},su={class:"flex space-x-2"},nu={__name:"TabNavigation",setup(e){const t=se();function s(n){t.setActiveTab(n)}return(n,i)=>(y(),_("div",tu,[h("nav",su,[h("a",{href:"#",onClick:i[0]||(i[0]=ht(r=>s("results"),["prevent"])),class:le(["px-4 py-2 rounded-md text-sm font-medium",g(t).state.activeTab==="results"?"bg-blue-600 text-white":"bg-gray-700 text-gray-300 hover:bg-gray-600"])}," Results ",2),h("a",{href:"#",onClick:i[1]||(i[1]=ht(r=>s("coverage"),["prevent"])),class:le(["px-4 py-2 rounded-md text-sm font-medium",g(t).state.activeTab==="coverage"?"bg-blue-600 text-white":"bg-gray-700 text-gray-300 hover:bg-gray-600"])}," Coverage ",2)])]))}};function Ms(e){const t=se(),s=_e(()=>{const l=t.state.testRun;if(!l)return null;const f={...{numberOfTests:0,numberOfAssertions:0,duration:0,numberOfFailures:0,numberOfErrors:0,numberOfWarnings:0,numberOfSkipped:0,numberOfDeprecations:0,numberOfIncomplete:0,numberOfRisky:0,numberOfNotices:0},...l.summary||{}};if(l&&!l.summary){const d=n(l);f.numberOfTests=d.tests,f.numberOfAssertions=d.assertions,f.numberOfFailures=d.failures,f.numberOfErrors=d.errors,f.numberOfWarnings=d.warnings,f.numberOfSkipped=d.skipped,f.numberOfDeprecations=d.deprecations,f.numberOfIncomplete=d.incomplete,f.numberOfRisky=d.risky,f.notices=d.notices}const c=[];for(const d in l.suites){const x=l.suites[d],$=[];for(const F in x.tests){const I=x.tests[F];$.push({name:I.name,class:I.class,id:I.id,duration:I.duration||0,assertions:I.assertions||0,status:I.status,message:I.message,trace:I.trace,warnings:I.warnings||[],deprecations:I.deprecations||[],notices:I.notices||[]})}c.push({name:x.name,testcases:$})}return{summary:{tests:f.numberOfTests,assertions:f.numberOfAssertions,time:l.sumOfDurations>0?l.sumOfDurations:f.duration,failures:f.numberOfFailures,errors:f.numberOfErrors,warnings:f.numberOfWarnings,skipped:f.numberOfSkipped,deprecations:f.numberOfDeprecations,incomplete:f.numberOfIncomplete,risky:f.numberOfRisky,notices:f.notices},suites:c}}),n=l=>{const a={tests:0,assertions:0,failures:0,errors:0,warnings:0,skipped:0,deprecations:0,incomplete:0,risky:0,notices:0};if(!l||!l.suites)return a;for(const f in l.suites)for(const c in l.suites[f].tests){const d=l.suites[f].tests[c];switch(a.tests++,a.assertions+=d.assertions||0,a.warnings+=d.warnings?.length||0,a.deprecations+=d.deprecations?.length||0,a.notices+=d.notices?.length||0,d.status){case"failed":a.failures++;break;case"errored":a.errors++;break;case"skipped":a.skipped++;break;case"incomplete":a.incomplete++;break;case"risky":a.risky++;break}}return a},i=_e(()=>{const l=e.value;if(!l)return{passed:0,failed:0,error:0,warnings:0,skipped:0,deprecations:0,incomplete:0,risky:0,notices:0};const a=l.summary,f={passed:0,failed:a.failures||0,error:a.errors||0,warnings:a.warnings||0,skipped:a.skipped||0,deprecations:a.deprecations||0,incomplete:a.incomplete||0,risky:a.risky||0,notices:a.notices||0},c=f.failed+f.error+f.skipped+f.incomplete+f.risky;return f.passed=(a.tests||0)-c,f}),r=_e(()=>{const l=e.value;if(!l)return[];let a=[];return l.suites.forEach(f=>{a.push(...f.testcases)}),a=a.filter(f=>!(f.status==="skipped"&&!t.state.options.displaySkipped||f.status==="incomplete"&&!t.state.options.displayIncomplete||f.status==="risky"&&!t.state.options.displayRisky||f.warnings?.length>0&&!t.state.options.displayWarnings&&f.status==="passed"||f.deprecations?.length>0&&!t.state.options.displayDeprecations&&f.status==="passed"||f.notices?.length>0&&!t.state.options.displayNotices&&f.status==="passed")),a.sort((f,c)=>{const d=f.duration||0,x=c.duration||0;if(t.state.sortBy==="duration")return t.state.sortDirection==="asc"?d-x:x-d;const $={errored:1,failed:2,incomplete:3,risky:4,skipped:5,warning:6,deprecation:7,notice:8,passed:9},F=$[f.status||"passed"]||99,I=$[c.status||"passed"]||99;return F!==I?F-I:x-d}),a}),o=_e(()=>{const l=e.value;if(!l)return[];const a={};l.suites.forEach(d=>{d.testcases.forEach(x=>{a[x.class]||(a[x.class]={className:x.class,testcases:[],passed:0,failed:0,errored:0,skipped:0,warning:0,deprecation:0,incomplete:0,risky:0,notice:0,hasIssues:!1});const $=a[x.class];$.testcases.push(x);const F=x.status||"passed";$[F]!==void 0&&$[F]++,x.warnings?.length>0&&($.warning+=x.warnings.length),x.deprecations?.length>0&&($.deprecation+=x.deprecations.length),x.notices?.length>0&&($.notice+=x.notices.length),(x.warnings?.length>0||x.deprecations?.length>0||x.notices?.length>0||F!=="passed")&&($.hasIssues=!0)})});const f={errored:1,failed:2,incomplete:3,risky:4,skipped:5,warning:6,deprecation:7,notice:8,passed:9};Object.values(a).forEach(d=>{let x=f.passed;d.testcases.forEach($=>{const F=$.status||"passed",I=f[F];I&&Id.suiteStatus!==x.suiteStatus?d.suiteStatus-x.suiteStatus:d.className.localeCompare(x.className));return c.forEach(d=>{d.testcases.sort((x,$)=>{const F=x.duration||0,I=$.duration||0;if(t.state.sortBy==="duration"&&F!==I)return t.state.sortDirection==="asc"?F-I:I-F;const oe=f[x.status||"passed"]||99,U=f[$.status||"passed"]||99;return oe!==U?oe-U:I-F})}),c});return{getResults:s,getStatusCounts:i,getIndividualResults:r,getGroupedResults:o}}const iu={class:"bg-gray-800 rounded-lg shadow-lg p-4"},ru={class:"grid grid-cols-3 gap-4 text-center mb-4 border-b border-gray-700 pb-4"},ou={class:"text-2xl font-bold"},lu={class:"text-2xl font-bold"},au={class:"text-2xl font-bold"},cu={class:"flex justify-center flex-wrap gap-x-4 gap-y-2 text-sm"},uu={class:"flex items-center"},fu={key:0,class:"flex items-center"},du={key:1,class:"flex items-center"},pu={key:2,class:"flex items-center"},hu={key:3,class:"flex items-center"},gu={key:4,class:"flex items-center"},mu={key:5,class:"flex items-center"},yu={key:6,class:"flex items-center"},_u={key:7,class:"flex items-center"},xu={__name:"ResultsSummary",props:["results"],setup(e){const t=se(),s=e,{results:n}=_n(s),{getStatusCounts:i}=Ms(n),r=i;return(o,l)=>(y(),_("div",iu,[h("div",ru,[h("div",null,[l[0]||(l[0]=h("div",{class:"text-sm text-gray-400"},"Total Tests",-1)),h("div",ou,O(g(n)?.summary.tests??0),1)]),h("div",null,[l[1]||(l[1]=h("div",{class:"text-sm text-gray-400"},"Total Assertions",-1)),h("div",lu,O(g(n)?.summary.assertions??0),1)]),h("div",null,[l[2]||(l[2]=h("div",{class:"text-sm text-gray-400"},"Duration",-1)),h("div",au,O(g(bs)(g(n)?.summary.time)),1)])]),h("div",cu,[h("span",uu,[l[3]||(l[3]=h("span",{class:"w-2 h-2 rounded-full bg-green-500 mr-2"},null,-1)),H(" "+O(g(r).passed)+" Passed ",1)]),g(n)?.summary.failures>0?(y(),_("span",fu,[l[4]||(l[4]=h("span",{class:"w-2 h-2 rounded-full bg-red-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.failures)+" Failed ",1)])):D("",!0),g(n)?.summary.errors>0?(y(),_("span",du,[l[5]||(l[5]=h("span",{class:"w-2 h-2 rounded-full bg-red-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.errors)+" Errors ",1)])):D("",!0),g(n)?.summary.warnings>0&&g(t).state.options.displayWarnings?(y(),_("span",pu,[l[6]||(l[6]=h("span",{class:"w-2 h-2 rounded-full bg-amber-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.warnings)+" Warnings ",1)])):D("",!0),g(n)?.summary.skipped>0&&g(t).state.options.displaySkipped?(y(),_("span",hu,[l[7]||(l[7]=h("span",{class:"w-2 h-2 rounded-full bg-gray-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.skipped)+" Skipped ",1)])):D("",!0),g(n)?.summary.deprecations>0&&g(t).state.options.displayDeprecations?(y(),_("span",gu,[l[8]||(l[8]=h("span",{class:"w-2 h-2 rounded-full bg-purple-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.deprecations)+" Deprecations ",1)])):D("",!0),g(n)?.summary.notices>0&&g(t).state.options.displayNotices?(y(),_("span",mu,[l[9]||(l[9]=h("span",{class:"w-2 h-2 rounded-full bg-sky-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.notices)+" Notices ",1)])):D("",!0),g(n)?.summary.incomplete>0&&g(t).state.options.displayIncomplete?(y(),_("span",yu,[l[10]||(l[10]=h("span",{class:"w-2 h-2 rounded-full bg-yellow-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.incomplete)+" Incomplete ",1)])):D("",!0),g(n)?.summary.risky>0&&g(t).state.options.displayRisky?(y(),_("span",_u,[l[11]||(l[11]=h("span",{class:"w-2 h-2 rounded-full bg-orange-500 mr-2"},null,-1)),H(" "+O(g(n)?.summary.risky)+" Risky ",1)])):D("",!0)])]))}},bu={class:"bg-gray-900 p-4 space-y-3"},vu={key:0},wu={key:0,class:"font-mono text-sm text-white whitespace-pre-wrap bg-black p-3 rounded overflow-x-auto"},Su={key:1},Tu={class:"font-bold text-sm text-amber-400 mb-2"},ku={class:"font-mono text-xs text-gray-300 whitespace-pre-wrap"},$u={key:2},Cu={class:"font-bold text-sm text-purple-400 mb-2"},Ru={class:"font-mono text-xs text-gray-300 whitespace-pre-wrap"},Eu={key:3},Ou={class:"font-bold text-sm text-sky-400 mb-2"},Iu={class:"font-mono text-xs text-gray-300 whitespace-pre-wrap"},on={__name:"TestDetails",props:["testcase"],setup(e){const t=se();return(s,n)=>(y(),_("div",bu,[e.testcase.message?(y(),_("div",vu,[h("h4",{class:le([{"text-red-400":e.testcase.status==="failed"||e.testcase.status==="errored"},"font-bold text-md mb-2"])},O(e.testcase.message),3),e.testcase.trace?(y(),_("pre",wu,O(e.testcase.trace),1)):D("",!0)])):D("",!0),g(t).state.options.displayWarnings&&e.testcase.warnings?.length>0?(y(),_("div",Su,[h("h5",Tu,"Warnings ("+O(e.testcase.warnings.length)+")",1),(y(!0),_(Z,null,xe(e.testcase.warnings,(i,r)=>(y(),_("div",{key:"w-"+r,class:"bg-amber-900/20 border-l-4 border-amber-500 p-2 mb-2"},[h("pre",ku,O(i),1)]))),128))])):D("",!0),g(t).state.options.displayDeprecations&&e.testcase.deprecations?.length>0?(y(),_("div",$u,[h("h5",Cu,"Deprecations ("+O(e.testcase.deprecations.length)+")",1),(y(!0),_(Z,null,xe(e.testcase.deprecations,(i,r)=>(y(),_("div",{key:"d-"+r,class:"bg-purple-900/20 border-l-4 border-purple-500 p-2 mb-2"},[h("pre",Ru,O(i),1)]))),128))])):D("",!0),g(t).state.options.displayNotices&&e.testcase.notices?.length>0?(y(),_("div",Eu,[h("h5",Ou,"Notices ("+O(e.testcase.notices.length)+")",1),(y(!0),_(Z,null,xe(e.testcase.notices,(i,r)=>(y(),_("div",{key:"n-"+r,class:"bg-sky-900/20 border-l-4 border-sky-500 p-2 mb-2"},[h("pre",Iu,O(i),1)]))),128))])):D("",!0)]))}};function Pr(){const e=se();function t(s){e.state.expandedTestId===s.id?e.setExpandedTest(null):e.setExpandedTest(s.id)}return{toggleTestDetails:t}}const Au={class:"bg-gray-800 rounded-lg shadow-lg overflow-hidden"},Fu={class:"flex items-center p-3 bg-gray-700/50 text-xs text-gray-400 uppercase font-semibold"},Pu={key:0},Mu={key:0},Du={key:1},Nu={class:"divide-y divide-gray-700"},ju=["onClick"],Lu={class:"w-28 flex-shrink-0 pl-3"},Uu={class:"flex-grow"},Vu={class:"text-sm text-white"},Hu={class:"text-xs text-gray-400 mt-1"},Wu={class:"text-xs text-gray-400 mt-1"},Bu={key:0,class:"text-amber-400"},Ku={key:1,class:"text-purple-400 ml-2"},Gu={key:2,class:"text-sky-400 ml-2"},zu={class:"w-28 text-right flex-shrink-0 pr-3"},Ju={__name:"IndividualTestResults",props:["results"],setup(e){const t=se(),s=e,{results:n}=_n(s),{toggleTestDetails:i}=Pr(),{getIndividualResults:r}=Ms(n),o=r;function l(a){t.setSortBy(a)}return(a,f)=>(y(),_("div",Au,[h("div",Fu,[f[2]||(f[2]=h("div",{class:"w-28 flex-shrink-0 pl-3"},"Status",-1)),f[3]||(f[3]=h("div",{class:"flex-grow"},"Test Case",-1)),h("div",{class:"w-28 text-right flex-shrink-0 pr-3 cursor-pointer",onClick:f[0]||(f[0]=c=>l("duration"))},[f[1]||(f[1]=H(" Duration ",-1)),g(t).state.sortBy==="duration"?(y(),_("span",Pu,[g(t).state.sortDirection==="asc"?(y(),_("span",Mu,"▲")):(y(),_("span",Du,"▼"))])):D("",!0)])]),h("div",Nu,[(y(!0),_(Z,null,xe(g(o),c=>(y(),_("div",{key:"individual-test-"+c.id,class:"hover:bg-gray-700/50"},[h("div",{class:"flex items-center p-3 cursor-pointer",onClick:d=>g(i)(c)},[h("div",Lu,[h("span",{class:le(["px-2 inline-flex text-xs leading-5 font-semibold rounded-full",{"bg-green-900 text-green-300":c.status==="passed","bg-red-900 text-red-300":c.status==="failed"||c.status==="errored","bg-gray-700 text-gray-300":c.status==="skipped","bg-yellow-800 text-yellow-200":c.status==="incomplete","bg-orange-800 text-orange-200":c.status==="risky"}])},O(c.status),3)]),h("div",Uu,[h("div",Vu,O(c.name),1),h("div",Hu,O(c.class),1)]),h("div",Wu,[g(t).state.options.displayWarnings&&c.warnings?.length>0?(y(),_("span",Bu,"⚠ "+O(c.warnings.length)+" warning(s)",1)):D("",!0),g(t).state.options.displayDeprecations&&c.deprecations?.length>0?(y(),_("span",Ku,"⚠ "+O(c.deprecations.length)+" deprecation(s)",1)):D("",!0),g(t).state.options.displayNotices&&c.notices?.length>0?(y(),_("span",Gu,"⚠ "+O(c.notices.length)+" notice(s)",1)):D("",!0)]),h("div",zu,[h("span",{class:le(["text-sm",{"text-yellow-400":c.duration/1e9>.5}])},O(g(bs)(c.duration)),3)])],8,ju),g(t).state.expandedTestId===c.id&&(g(t).state.options.displayWarnings&&c.warnings?.length>0||g(t).state.options.displayDeprecations&&c.deprecations?.length>0||g(t).state.options.displayNotices&&c.notices?.length>0)?(y(),nt(on,{key:0,testcase:c},null,8,["testcase"])):D("",!0)]))),128))])]))}},qu=["onClick"],Yu={class:"flex items-center"},Xu={class:"font-bold text-white"},Qu={class:"flex items-center space-x-4 text-sm"},Zu={key:0,class:"px-2 py-0.5 rounded-full bg-red-900 text-red-300"},ef={key:1,class:"px-2 py-0.5 rounded-full bg-red-900 text-red-300"},tf={key:2,class:"px-2 py-0.5 rounded-full bg-amber-800 text-amber-200"},sf={key:3,class:"px-2 py-0.5 rounded-full bg-purple-800 text-purple-200"},nf={key:4,class:"px-2 py-0.5 rounded-full bg-sky-800 text-sky-200"},rf={key:5,class:"px-2 py-0.5 rounded-full bg-gray-700 text-gray-300"},of={key:6,class:"px-2 py-0.5 rounded-full bg-yellow-800 text-yellow-200"},lf={key:7,class:"px-2 py-0.5 rounded-full bg-orange-800 text-orange-200"},af={key:8,class:"px-2 py-0.5 rounded-full bg-green-900 text-green-300"},cf={class:"divide-y divide-gray-700"},uf=["onClick"],ff={class:"w-28 flex-shrink-0 pl-3"},df={class:"flex-grow"},pf={class:"text-sm text-white"},hf={class:"text-xs text-gray-400 mt-1"},gf={key:0,class:"text-amber-400"},mf={key:1,class:"text-purple-400 ml-2"},yf={key:2,class:"text-sky-400 ml-2"},_f={class:"w-28 text-right flex-shrink-0 pr-3"},xf=["onClick"],bf={class:"flex-grow"},vf={class:"text-sm text-white"},wf={class:"text-xs text-gray-400 mt-1"},Sf={key:0,class:"text-amber-400"},Tf={key:1,class:"text-purple-400 ml-2"},kf={key:2,class:"text-sky-400 ml-2"},$f={class:"w-28 text-right flex-shrink-0 pr-3"},Cf={key:0,class:"flex items-center p-3"},Rf={class:"flex-grow"},Ef={class:"text-sm text-gray-400"},Of={__name:"GroupedTestResults",props:["results"],setup(e){const t=se(),s=e,{results:n}=_n(s),{toggleTestDetails:i}=Pr(),{getGroupedResults:r}=Ms(n),o=r;function l(a){t.toggleTestcaseGroupExpansion(a)}return(a,f)=>(y(!0),_(Z,null,xe(g(o),c=>(y(),_("div",{key:c.className,class:"bg-gray-800 rounded-lg shadow-lg overflow-hidden"},[h("div",{class:"flex items-center justify-between bg-gray-700 px-4 py-3 cursor-pointer hover:bg-gray-600",onClick:d=>l(c.className)},[h("div",Yu,[(y(),_("svg",{class:le(["w-5 h-5 mr-2 text-gray-400 transition-transform",{"rotate-90":g(t).state.expandedTestcaseGroups.has(c.className)}]),viewBox:"0 0 20 20",fill:"currentColor"},[...f[0]||(f[0]=[h("path",{"fill-rule":"evenodd",d:"M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z","clip-rule":"evenodd"},null,-1)])],2)),h("span",Xu,O(c.className),1)]),h("div",Qu,[c.failed>0?(y(),_("span",Zu,O(c.failed)+" Failed",1)):D("",!0),c.errored>0?(y(),_("span",ef,O(c.errored)+" Error",1)):D("",!0),c.warning>0&&g(t).state.options.displayWarnings?(y(),_("span",tf,O(c.warning)+" Warnings",1)):D("",!0),c.deprecation>0&&g(t).state.options.displayDeprecations?(y(),_("span",sf,O(c.deprecation)+" Deprecations",1)):D("",!0),c.notice>0&&g(t).state.options.displayNotices?(y(),_("span",nf,O(c.notice)+" Notices",1)):D("",!0),c.skipped>0&&g(t).state.options.displaySkipped?(y(),_("span",rf,O(c.skipped)+" Skipped",1)):D("",!0),c.incomplete>0&&g(t).state.options.displayIncomplete?(y(),_("span",of,O(c.incomplete)+" Incomplete",1)):D("",!0),c.risky>0&&g(t).state.options.displayRisky?(y(),_("span",lf,O(c.risky)+" Risky",1)):D("",!0),c.passed>0?(y(),_("span",af,O(c.passed)+" Passed",1)):D("",!0)])],8,qu),ne(h("div",cf,[(y(!0),_(Z,null,xe(c.testcases.filter(d=>!(d.status==="passed"||d.status==="skipped"&&!g(t).state.options.displaySkipped||d.status==="incomplete"&&!g(t).state.options.displayIncomplete||d.status==="risky"&&!g(t).state.options.displayRisky)),d=>(y(),_("div",{key:"test-"+d.id,class:"hover:bg-gray-700/50"},[h("div",{class:"flex items-center p-3 cursor-pointer",onClick:x=>g(i)(d)},[h("div",ff,[h("span",{class:le(["px-2 inline-flex text-xs leading-5 font-semibold rounded-full",{"bg-red-900 text-red-300":d.status==="failed"||d.status==="errored","bg-gray-700 text-gray-300":d.status==="skipped","bg-yellow-800 text-yellow-200":d.status==="incomplete","bg-orange-800 text-orange-200":d.status==="risky"}])},O(d.status),3)]),h("div",df,[h("div",pf,O(d.name),1),h("div",hf,[g(t).state.options.displayWarnings&&d.warnings?.length>0?(y(),_("span",gf,"⚠ "+O(d.warnings.length)+" warning(s)",1)):D("",!0),g(t).state.options.displayDeprecations&&d.deprecations?.length>0?(y(),_("span",mf,"⚠ "+O(d.deprecations.length)+" deprecation(s)",1)):D("",!0),g(t).state.options.displayNotices&&d.notices?.length>0?(y(),_("span",yf,"⚠ "+O(d.notices.length)+" notice(s)",1)):D("",!0)])]),h("div",_f,[h("span",{class:le(["text-sm",{"text-yellow-400":d.duration/1e9>.5}])},O(g(bs)(d.duration)),3)])],8,uf),g(t).state.expandedTestId===d.id?(y(),nt(on,{key:0,testcase:d},null,8,["testcase"])):D("",!0)]))),128)),(y(!0),_(Z,null,xe(c.testcases.filter(d=>d.status==="passed"&&(g(t).state.options.displayWarnings&&d.warnings?.length>0||g(t).state.options.displayDeprecations&&d.deprecations?.length>0||g(t).state.options.displayNotices&&d.notices?.length>0)),d=>(y(),_("div",null,[h("div",{onClick:x=>g(i)(d),class:"flex items-center p-3 cursor-pointer hover:bg-gray-700/[.5]"},[f[1]||(f[1]=h("div",{class:"w-28 flex-shrink-0 pl-3"},[h("span",{class:"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-900 text-green-300"},"passed")],-1)),h("div",bf,[h("div",vf,O(d.name),1),h("div",wf,[g(t).state.options.displayWarnings&&d.warnings?.length>0?(y(),_("span",Sf,"⚠ "+O(d.warnings.length)+" warning(s)",1)):D("",!0),g(t).state.options.displayDeprecations&&d.deprecations?.length>0?(y(),_("span",Tf,"⚠ "+O(d.deprecations.length)+" deprecation(s)",1)):D("",!0),g(t).state.options.displayNotices&&d.notices?.length>0?(y(),_("span",kf,"⚠ "+O(d.notices.length)+" notice(s)",1)):D("",!0)])]),h("div",$f,[h("span",{class:le(["text-sm",{"text-yellow-400":d.duration/1e9>.5}])},O(g(bs)(d.duration)),3)])],8,xf),g(t).state.expandedTestId===d.id?(y(),nt(on,{key:0,testcase:d},null,8,["testcase"])):D("",!0)]))),256)),c.passed>0?(y(),_("div",Cf,[f[2]||(f[2]=h("div",{class:"w-28 flex-shrink-0 pl-3"},[h("span",{class:"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-900 text-green-300"},"passed")],-1)),h("div",Rf,[h("div",Ef,O(c.passed)+" test(s) passed",1)])])):D("",!0)],512),[[Tn,g(t).state.expandedTestcaseGroups.has(c.className)]])]))),128))}},If={class:"bg-gray-800 rounded-lg shadow-lg p-4 mb-4"},Af={class:"text-lg font-semibold text-white mb-2"},Ff={class:"bg-gray-900 p-4 rounded-lg overflow-x-auto text-sm font-mono"},Pf={class:"text-gray-500 flex-shrink-0 text-right pr-3",style:{"user-select":"none"}},Mf={style:{flex:"1","white-space":"pre"}},Df={__name:"FileCoverageDetail",setup(e){const t=se();function s(i){const r="token-";if(!i.startsWith("T_"))return r+"default";const o=i.substring(2).toLowerCase();return["encapsed_and_whitespace","constant_encapsed_string"].includes(o)?r+"string":["comment","doc_comment"].includes(o)?r+"comment":o.includes("variable")?r+"variable":["class","function","public","private","protected","readonly","new","echo","return","if","else","elseif","while","do","for","foreach","switch","case","break","continue","declare","const","enddeclare","endfor","endforeach","endif","endswitch","endwhile","use","namespace","try","catch","finally","throw","extends","implements","interface","trait","abstract","final","static","instanceof","insteadof","global","goto","include","include_once","require","require_once","unset","isset","empty"].includes(o)?r+"keyword":r+"default"}function n(){t.setFileCoverage(null)}return(i,r)=>(y(),_("div",If,[h("button",{onClick:n,class:"bg-gray-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded transition duration-150 ease-in-out mb-4"}," ← Back to Coverage Report "),h("h3",Af,O(g(t).state.fileCoverage.path),1),h("pre",Ff,[r[5]||(r[5]=H(" ",-1)),(y(!0),_(Z,null,xe(g(t).state.fileCoverage.lines,o=>(y(),_("div",{class:le([o.coverage==="covered"?"line-covered":"",o.coverage==="uncovered"?"line-uncovered":""]),style:{display:"flex","align-items":"center","line-height":"1.4","max-height":"20px"}},[r[2]||(r[2]=H(` + `,-1)),h("span",Pf,O(o.number),1),r[3]||(r[3]=H(` + `,-1)),h("span",Mf,[r[0]||(r[0]=H(` + `,-1)),(y(!0),_(Z,null,xe(o.tokens,l=>(y(),_("span",{key:l.value,class:le(s(l.type))},O(l.value),3))),128)),r[1]||(r[1]=H(` + `,-1))]),r[4]||(r[4]=H(` + `,-1))],2))),256)),r[6]||(r[6]=H(` + `,-1))])]))}},Nf={key:0,class:"flex flex-col justify-center items-center pt-10"},jf={key:1,class:"text-gray-500 text-center pt-10"},Lf={key:0},Uf={key:1},Vf={key:2},Hf={key:3},Wf={class:"bg-gray-800 rounded-lg shadow-lg p-4 mb-4"},Bf={class:"text-center"},Kf={class:"text-2xl font-bold"},Gf={class:"bg-gray-800 rounded-lg shadow-lg overflow-hidden"},zf={class:"divide-y divide-gray-700"},Jf=["onClick"],qf={class:"flex items-center p-3"},Yf={class:"flex-grow text-sm text-white"},Xf={class:"w-28 text-right flex-shrink-0 pr-3"},Qf={__name:"CoverageReport",setup(e){const t=se(),s=new mt("");async function n(i){try{const r=await s.fetchFileCoverage(i);t.setFileCoverage({...r,path:i})}catch(r){console.error("Failed to fetch file coverage:",r)}}return(i,r)=>g(t).state.isCoverageLoading?(y(),_("div",Nf,[...r[0]||(r[0]=[h("div",{class:"spinner-big"},null,-1),h("div",{class:"mt-4 text-gray-400"},"Generating coverage report...",-1)])])):!g(t).state.coverageReport||g(t).state.coverageReport.files.length===0?(y(),_("div",jf,[g(t).state.coverageDriverMissing?(y(),_("div",Lf," No coverage driver (Xdebug, pcov) is enabled. ")):(y(),_("div",Uf," Run tests with coverage enabled to see the report. "))])):g(t).state.fileCoverage?(y(),_("div",Vf,[Y(Df)])):(y(),_("div",Hf,[h("div",Wf,[h("div",Bf,[r[1]||(r[1]=h("div",{class:"text-sm text-gray-400"},"Total Coverage",-1)),h("div",Kf,O(g(t).state.coverageReport.total_coverage_percent.toFixed(2))+"%",1)])]),h("div",Gf,[r[2]||(r[2]=h("div",{class:"flex items-center p-3 bg-gray-700/50 text-xs text-gray-400 uppercase font-semibold"},[h("div",{class:"flex-grow"},"File"),h("div",{class:"w-28 text-right flex-shrink-0 pr-3"},"Coverage")],-1)),h("div",zf,[(y(!0),_(Z,null,xe(g(t).state.coverageReport.files,o=>(y(),_("div",{key:o.path,class:"hover:bg-gray-700/50 cursor-pointer",onClick:l=>n(o.path)},[h("div",qf,[h("div",Yf,O(o.path),1),h("div",Xf,[h("span",{class:le(["text-sm",{"text-green-400":o.coverage_percent>80,"text-yellow-400":o.coverage_percent>50&&o.coverage_percent<=80,"text-red-400":o.coverage_percent<=50}])},O(o.coverage_percent.toFixed(2))+"%",3)])])],8,Jf))),128))])])]))}},Zf={id:"main-content",class:"flex-1 p-4 flex flex-col"},ed={class:"flex-grow overflow-y-auto"},td={key:0},sd={key:0,class:"text-gray-500 text-center pt-10"},nd={key:1,class:"space-y-2 mt-4"},id={key:0,class:"flex justify-center items-center pt-10"},rd={key:1},od={__name:"MainContent",setup(e){const t=se(),{getResults:s}=Ms(),n=s,i=_e(()=>t.state.isStarting||t.state.isRunning||r.value),r=_e(()=>t.state.isStopping);return(o,l)=>(y(),_("main",Zf,[Y(nu),h("div",ed,[g(t).state.activeTab==="results"?(y(),_("div",td,[Y(xu,{results:g(n)},null,8,["results"]),g(n)?D("",!0):(y(),_("div",sd," Run tests to see the results. ")),g(n)?(y(),_("div",nd,[i.value?(y(),_("div",id,[...l[0]||(l[0]=[h("div",{class:"spinner-big"},null,-1)])])):D("",!0),!i.value&&g(t).state.options.displayMode==="individual"?(y(),nt(Ju,{key:1,results:g(n)},null,8,["results"])):D("",!0),!i.value&&g(t).state.options.displayMode==="default"?(y(),nt(Of,{key:2,results:g(n)},null,8,["results"])):D("",!0)])):D("",!0)])):D("",!0),g(t).state.activeTab==="coverage"?(y(),_("div",rd,[Y(Qf)])):D("",!0)])]))}},ld={id:"app",class:"flex flex-col h-screen"},ad={class:"flex flex-grow overflow-hidden"},cd={__name:"App",setup(e){const t=se();let s=null;return La("resizer","test-sidebar"),Is(async()=>{try{const n=window.WS_HOST||"127.0.0.1",i=window.WS_PORT||"8080";s=new ja(`ws://${n}:${i}/ws/status`,t,{fetchCoverageReport:t.fetchCoverageReport}),await s.connect(),Ct("neutral")}catch(n){console.error("Failed to initialize app:",n)}}),St(()=>[t.state.options,t.state.selectedSuites,t.state.selectedGroups,t.state.coverage],()=>{t.saveState()},{deep:!0}),(n,i)=>(y(),_("div",ld,[Y(Fc),h("div",ad,[Y(eu),i[0]||(i[0]=h("div",{id:"resizer",class:"w-1.5 cursor-col-resize bg-gray-700 hover:bg-blue-600 transition-colors duration-200"},null,-1)),Y(od)])]))}};oa(cd).mount("#app"); diff --git a/public/css/styles.css b/public/css/styles.css deleted file mode 100644 index 82f1f27..0000000 --- a/public/css/styles.css +++ /dev/null @@ -1 +0,0 @@ -*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.18 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-success:#10b981;--color-failure:#ef4444;--color-warning:#f59e0b;--color-deprecation:#f59e0b;--color-neutral:#6b7280}.filter-panel-dropdown{position:absolute;top:100%;right:0;z-index:20;min-width:450px}.form-group{border-bottom:1px solid #4b5563;padding-bottom:1rem;margin-bottom:1rem}.form-group:last-of-type{border-bottom:none;padding-bottom:0;margin-bottom:0}input[type=checkbox],input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25rem;height:1.25rem;border:2px solid #6b7280;border-radius:.25rem;background-color:transparent;transition:background-color .2s,border-color .2s;cursor:pointer}input[type=radio]{border-radius:50%}input[type=checkbox]:checked,input[type=radio]:checked{background-color:#3b82f6;border-color:#3b82f6}input[type=checkbox]:focus,input[type=radio]:focus{outline:none;--tw-ring-color:rgba(59,130,246,.5);box-shadow:0 0 0 2px #1f2937,0 0 0 4px var(--tw-ring-color)}.suite-header{display:flex;justify-content:space-between;align-items:center;padding:8px 4px;border-radius:4px;transition:background-color .2s}.suite-header:hover{background-color:#374151}.suite-arrow{transition:transform .2s ease-in-out;margin-right:8px}.suite-arrow.rotated{transform:rotate(90deg)}.spinner{border-top:2px solid #3498db;border-radius:50%;width:10px;height:10px;animation:spin 1s linear infinite;margin-left:0}.spinner-big{border-top:4px solid #3498db}.spinner,.spinner-big{border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.test-item{display:flex;justify-content:space-between;align-items:center;padding:6px 4px;border-radius:4px;transition:background-color .2s}.test-item:hover{background-color:#374151}.test-item-left{display:flex;align-items:center}.status-icon{width:10px;height:10px;border-radius:50%;margin-right:8px;flex-shrink:0}.status-neutral,.status-skipped{background-color:#6b7280}.status-passed{background-color:#10b981}.status-errored,.status-failed{background-color:#ef4444}.status-running{background-color:#3498db}.test-name{color:#d1d5db}.sort-arrow.none{opacity:.7;transform:rotate(0deg) scale(1)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#1f2937}::-webkit-scrollbar-thumb{background:#4b5563;border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#6b7280}#resizer{width:1.5px;cursor:col-resize;background-color:#374151;transition:background-color .2s}#resizer:hover{background-color:#3b82f6}.flex-grow{flex-grow:1}.flex-shrink-0{flex-shrink:0}.w-2{width:.5rem}.h-2{height:.5rem}.rounded-full{border-radius:9999px}.mr-2{margin-right:.5rem}@keyframes three-dots-loading{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}.static{position:static}.relative{position:relative}.z-10{z-index:10}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!h-4{height:1rem!important}.h-2{height:.5rem}.h-24{height:6rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-full{height:100%}.h-screen{height:100vh}.\!w-4{width:1rem!important}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-28{width:7rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-80{width:20rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-700>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(55 65 81/var(--tw-divide-opacity,1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-pre-wrap{white-space:pre-wrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-amber-500{--tw-border-opacity:1;border-color:rgb(245 158 11/var(--tw-border-opacity,1))}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity,1))}.border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.border-purple-500{--tw-border-opacity:1;border-color:rgb(168 85 247/var(--tw-border-opacity,1))}.border-sky-500{--tw-border-opacity:1;border-color:rgb(14 165 233/var(--tw-border-opacity,1))}.bg-amber-500{--tw-bg-opacity:1;background-color:rgb(245 158 11/var(--tw-bg-opacity,1))}.bg-amber-500\/0{background-color:rgba(245,158,11,0)}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-amber-500\/100{background-color:#f59e0b}.bg-amber-500\/15{background-color:rgba(245,158,11,.15)}.bg-amber-500\/20{background-color:rgba(245,158,11,.2)}.bg-amber-500\/25{background-color:rgba(245,158,11,.25)}.bg-amber-500\/30{background-color:rgba(245,158,11,.3)}.bg-amber-500\/35{background-color:rgba(245,158,11,.35)}.bg-amber-500\/40{background-color:rgba(245,158,11,.4)}.bg-amber-500\/45{background-color:rgba(245,158,11,.45)}.bg-amber-500\/5{background-color:rgba(245,158,11,.05)}.bg-amber-500\/50{background-color:rgba(245,158,11,.5)}.bg-amber-500\/55{background-color:rgba(245,158,11,.55)}.bg-amber-500\/60{background-color:rgba(245,158,11,.6)}.bg-amber-500\/65{background-color:rgba(245,158,11,.65)}.bg-amber-500\/70{background-color:rgba(245,158,11,.7)}.bg-amber-500\/75{background-color:rgba(245,158,11,.75)}.bg-amber-500\/80{background-color:rgba(245,158,11,.8)}.bg-amber-500\/85{background-color:rgba(245,158,11,.85)}.bg-amber-500\/90{background-color:rgba(245,158,11,.9)}.bg-amber-500\/95{background-color:rgba(245,158,11,.95)}.bg-amber-600{--tw-bg-opacity:1;background-color:rgb(217 119 6/var(--tw-bg-opacity,1))}.bg-amber-600\/0{background-color:rgba(217,119,6,0)}.bg-amber-600\/10{background-color:rgba(217,119,6,.1)}.bg-amber-600\/100{background-color:#d97706}.bg-amber-600\/15{background-color:rgba(217,119,6,.15)}.bg-amber-600\/20{background-color:rgba(217,119,6,.2)}.bg-amber-600\/25{background-color:rgba(217,119,6,.25)}.bg-amber-600\/30{background-color:rgba(217,119,6,.3)}.bg-amber-600\/35{background-color:rgba(217,119,6,.35)}.bg-amber-600\/40{background-color:rgba(217,119,6,.4)}.bg-amber-600\/45{background-color:rgba(217,119,6,.45)}.bg-amber-600\/5{background-color:rgba(217,119,6,.05)}.bg-amber-600\/50{background-color:rgba(217,119,6,.5)}.bg-amber-600\/55{background-color:rgba(217,119,6,.55)}.bg-amber-600\/60{background-color:rgba(217,119,6,.6)}.bg-amber-600\/65{background-color:rgba(217,119,6,.65)}.bg-amber-600\/70{background-color:rgba(217,119,6,.7)}.bg-amber-600\/75{background-color:rgba(217,119,6,.75)}.bg-amber-600\/80{background-color:rgba(217,119,6,.8)}.bg-amber-600\/85{background-color:rgba(217,119,6,.85)}.bg-amber-600\/90{background-color:rgba(217,119,6,.9)}.bg-amber-600\/95{background-color:rgba(217,119,6,.95)}.bg-amber-700{--tw-bg-opacity:1;background-color:rgb(180 83 9/var(--tw-bg-opacity,1))}.bg-amber-700\/0{background-color:rgba(180,83,9,0)}.bg-amber-700\/10{background-color:rgba(180,83,9,.1)}.bg-amber-700\/100{background-color:#b45309}.bg-amber-700\/15{background-color:rgba(180,83,9,.15)}.bg-amber-700\/20{background-color:rgba(180,83,9,.2)}.bg-amber-700\/25{background-color:rgba(180,83,9,.25)}.bg-amber-700\/30{background-color:rgba(180,83,9,.3)}.bg-amber-700\/35{background-color:rgba(180,83,9,.35)}.bg-amber-700\/40{background-color:rgba(180,83,9,.4)}.bg-amber-700\/45{background-color:rgba(180,83,9,.45)}.bg-amber-700\/5{background-color:rgba(180,83,9,.05)}.bg-amber-700\/50{background-color:rgba(180,83,9,.5)}.bg-amber-700\/55{background-color:rgba(180,83,9,.55)}.bg-amber-700\/60{background-color:rgba(180,83,9,.6)}.bg-amber-700\/65{background-color:rgba(180,83,9,.65)}.bg-amber-700\/70{background-color:rgba(180,83,9,.7)}.bg-amber-700\/75{background-color:rgba(180,83,9,.75)}.bg-amber-700\/80{background-color:rgba(180,83,9,.8)}.bg-amber-700\/85{background-color:rgba(180,83,9,.85)}.bg-amber-700\/90{background-color:rgba(180,83,9,.9)}.bg-amber-700\/95{background-color:rgba(180,83,9,.95)}.bg-amber-800{--tw-bg-opacity:1;background-color:rgb(146 64 14/var(--tw-bg-opacity,1))}.bg-amber-800\/0{background-color:rgba(146,64,14,0)}.bg-amber-800\/10{background-color:rgba(146,64,14,.1)}.bg-amber-800\/100{background-color:#92400e}.bg-amber-800\/15{background-color:rgba(146,64,14,.15)}.bg-amber-800\/20{background-color:rgba(146,64,14,.2)}.bg-amber-800\/25{background-color:rgba(146,64,14,.25)}.bg-amber-800\/30{background-color:rgba(146,64,14,.3)}.bg-amber-800\/35{background-color:rgba(146,64,14,.35)}.bg-amber-800\/40{background-color:rgba(146,64,14,.4)}.bg-amber-800\/45{background-color:rgba(146,64,14,.45)}.bg-amber-800\/5{background-color:rgba(146,64,14,.05)}.bg-amber-800\/50{background-color:rgba(146,64,14,.5)}.bg-amber-800\/55{background-color:rgba(146,64,14,.55)}.bg-amber-800\/60{background-color:rgba(146,64,14,.6)}.bg-amber-800\/65{background-color:rgba(146,64,14,.65)}.bg-amber-800\/70{background-color:rgba(146,64,14,.7)}.bg-amber-800\/75{background-color:rgba(146,64,14,.75)}.bg-amber-800\/80{background-color:rgba(146,64,14,.8)}.bg-amber-800\/85{background-color:rgba(146,64,14,.85)}.bg-amber-800\/90{background-color:rgba(146,64,14,.9)}.bg-amber-800\/95{background-color:rgba(146,64,14,.95)}.bg-amber-900{--tw-bg-opacity:1;background-color:rgb(120 53 15/var(--tw-bg-opacity,1))}.bg-amber-900\/0{background-color:rgba(120,53,15,0)}.bg-amber-900\/10{background-color:rgba(120,53,15,.1)}.bg-amber-900\/100{background-color:#78350f}.bg-amber-900\/15{background-color:rgba(120,53,15,.15)}.bg-amber-900\/20{background-color:rgba(120,53,15,.2)}.bg-amber-900\/25{background-color:rgba(120,53,15,.25)}.bg-amber-900\/30{background-color:rgba(120,53,15,.3)}.bg-amber-900\/35{background-color:rgba(120,53,15,.35)}.bg-amber-900\/40{background-color:rgba(120,53,15,.4)}.bg-amber-900\/45{background-color:rgba(120,53,15,.45)}.bg-amber-900\/5{background-color:rgba(120,53,15,.05)}.bg-amber-900\/50{background-color:rgba(120,53,15,.5)}.bg-amber-900\/55{background-color:rgba(120,53,15,.55)}.bg-amber-900\/60{background-color:rgba(120,53,15,.6)}.bg-amber-900\/65{background-color:rgba(120,53,15,.65)}.bg-amber-900\/70{background-color:rgba(120,53,15,.7)}.bg-amber-900\/75{background-color:rgba(120,53,15,.75)}.bg-amber-900\/80{background-color:rgba(120,53,15,.8)}.bg-amber-900\/85{background-color:rgba(120,53,15,.85)}.bg-amber-900\/90{background-color:rgba(120,53,15,.9)}.bg-amber-900\/95{background-color:rgba(120,53,15,.95)}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.bg-gray-500\/0{background-color:hsla(220,9%,46%,0)}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/100{background-color:#6b7280}.bg-gray-500\/15{background-color:hsla(220,9%,46%,.15)}.bg-gray-500\/20{background-color:hsla(220,9%,46%,.2)}.bg-gray-500\/25{background-color:hsla(220,9%,46%,.25)}.bg-gray-500\/30{background-color:hsla(220,9%,46%,.3)}.bg-gray-500\/35{background-color:hsla(220,9%,46%,.35)}.bg-gray-500\/40{background-color:hsla(220,9%,46%,.4)}.bg-gray-500\/45{background-color:hsla(220,9%,46%,.45)}.bg-gray-500\/5{background-color:hsla(220,9%,46%,.05)}.bg-gray-500\/50{background-color:hsla(220,9%,46%,.5)}.bg-gray-500\/55{background-color:hsla(220,9%,46%,.55)}.bg-gray-500\/60{background-color:hsla(220,9%,46%,.6)}.bg-gray-500\/65{background-color:hsla(220,9%,46%,.65)}.bg-gray-500\/70{background-color:hsla(220,9%,46%,.7)}.bg-gray-500\/75{background-color:hsla(220,9%,46%,.75)}.bg-gray-500\/80{background-color:hsla(220,9%,46%,.8)}.bg-gray-500\/85{background-color:hsla(220,9%,46%,.85)}.bg-gray-500\/90{background-color:hsla(220,9%,46%,.9)}.bg-gray-500\/95{background-color:hsla(220,9%,46%,.95)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-gray-600\/0{background-color:rgba(75,85,99,0)}.bg-gray-600\/10{background-color:rgba(75,85,99,.1)}.bg-gray-600\/100{background-color:#4b5563}.bg-gray-600\/15{background-color:rgba(75,85,99,.15)}.bg-gray-600\/20{background-color:rgba(75,85,99,.2)}.bg-gray-600\/25{background-color:rgba(75,85,99,.25)}.bg-gray-600\/30{background-color:rgba(75,85,99,.3)}.bg-gray-600\/35{background-color:rgba(75,85,99,.35)}.bg-gray-600\/40{background-color:rgba(75,85,99,.4)}.bg-gray-600\/45{background-color:rgba(75,85,99,.45)}.bg-gray-600\/5{background-color:rgba(75,85,99,.05)}.bg-gray-600\/50{background-color:rgba(75,85,99,.5)}.bg-gray-600\/55{background-color:rgba(75,85,99,.55)}.bg-gray-600\/60{background-color:rgba(75,85,99,.6)}.bg-gray-600\/65{background-color:rgba(75,85,99,.65)}.bg-gray-600\/70{background-color:rgba(75,85,99,.7)}.bg-gray-600\/75{background-color:rgba(75,85,99,.75)}.bg-gray-600\/80{background-color:rgba(75,85,99,.8)}.bg-gray-600\/85{background-color:rgba(75,85,99,.85)}.bg-gray-600\/90{background-color:rgba(75,85,99,.9)}.bg-gray-600\/95{background-color:rgba(75,85,99,.95)}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.bg-gray-700\/0{background-color:rgba(55,65,81,0)}.bg-gray-700\/10{background-color:rgba(55,65,81,.1)}.bg-gray-700\/100{background-color:#374151}.bg-gray-700\/15{background-color:rgba(55,65,81,.15)}.bg-gray-700\/20{background-color:rgba(55,65,81,.2)}.bg-gray-700\/25{background-color:rgba(55,65,81,.25)}.bg-gray-700\/30{background-color:rgba(55,65,81,.3)}.bg-gray-700\/35{background-color:rgba(55,65,81,.35)}.bg-gray-700\/40{background-color:rgba(55,65,81,.4)}.bg-gray-700\/45{background-color:rgba(55,65,81,.45)}.bg-gray-700\/5{background-color:rgba(55,65,81,.05)}.bg-gray-700\/50{background-color:rgba(55,65,81,.5)}.bg-gray-700\/55{background-color:rgba(55,65,81,.55)}.bg-gray-700\/60{background-color:rgba(55,65,81,.6)}.bg-gray-700\/65{background-color:rgba(55,65,81,.65)}.bg-gray-700\/70{background-color:rgba(55,65,81,.7)}.bg-gray-700\/75{background-color:rgba(55,65,81,.75)}.bg-gray-700\/80{background-color:rgba(55,65,81,.8)}.bg-gray-700\/85{background-color:rgba(55,65,81,.85)}.bg-gray-700\/90{background-color:rgba(55,65,81,.9)}.bg-gray-700\/95{background-color:rgba(55,65,81,.95)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/0{background-color:rgba(31,41,55,0)}.bg-gray-800\/10{background-color:rgba(31,41,55,.1)}.bg-gray-800\/100{background-color:#1f2937}.bg-gray-800\/15{background-color:rgba(31,41,55,.15)}.bg-gray-800\/20{background-color:rgba(31,41,55,.2)}.bg-gray-800\/25{background-color:rgba(31,41,55,.25)}.bg-gray-800\/30{background-color:rgba(31,41,55,.3)}.bg-gray-800\/35{background-color:rgba(31,41,55,.35)}.bg-gray-800\/40{background-color:rgba(31,41,55,.4)}.bg-gray-800\/45{background-color:rgba(31,41,55,.45)}.bg-gray-800\/5{background-color:rgba(31,41,55,.05)}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-800\/55{background-color:rgba(31,41,55,.55)}.bg-gray-800\/60{background-color:rgba(31,41,55,.6)}.bg-gray-800\/65{background-color:rgba(31,41,55,.65)}.bg-gray-800\/70{background-color:rgba(31,41,55,.7)}.bg-gray-800\/75{background-color:rgba(31,41,55,.75)}.bg-gray-800\/80{background-color:rgba(31,41,55,.8)}.bg-gray-800\/85{background-color:rgba(31,41,55,.85)}.bg-gray-800\/90{background-color:rgba(31,41,55,.9)}.bg-gray-800\/95{background-color:rgba(31,41,55,.95)}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-gray-900\/0{background-color:rgba(17,24,39,0)}.bg-gray-900\/10{background-color:rgba(17,24,39,.1)}.bg-gray-900\/100{background-color:#111827}.bg-gray-900\/15{background-color:rgba(17,24,39,.15)}.bg-gray-900\/20{background-color:rgba(17,24,39,.2)}.bg-gray-900\/25{background-color:rgba(17,24,39,.25)}.bg-gray-900\/30{background-color:rgba(17,24,39,.3)}.bg-gray-900\/35{background-color:rgba(17,24,39,.35)}.bg-gray-900\/40{background-color:rgba(17,24,39,.4)}.bg-gray-900\/45{background-color:rgba(17,24,39,.45)}.bg-gray-900\/5{background-color:rgba(17,24,39,.05)}.bg-gray-900\/50{background-color:rgba(17,24,39,.5)}.bg-gray-900\/55{background-color:rgba(17,24,39,.55)}.bg-gray-900\/60{background-color:rgba(17,24,39,.6)}.bg-gray-900\/65{background-color:rgba(17,24,39,.65)}.bg-gray-900\/70{background-color:rgba(17,24,39,.7)}.bg-gray-900\/75{background-color:rgba(17,24,39,.75)}.bg-gray-900\/80{background-color:rgba(17,24,39,.8)}.bg-gray-900\/85{background-color:rgba(17,24,39,.85)}.bg-gray-900\/90{background-color:rgba(17,24,39,.9)}.bg-gray-900\/95{background-color:rgba(17,24,39,.95)}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/0{background-color:rgba(34,197,94,0)}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/100{background-color:#22c55e}.bg-green-500\/15{background-color:rgba(34,197,94,.15)}.bg-green-500\/20{background-color:rgba(34,197,94,.2)}.bg-green-500\/25{background-color:rgba(34,197,94,.25)}.bg-green-500\/30{background-color:rgba(34,197,94,.3)}.bg-green-500\/35{background-color:rgba(34,197,94,.35)}.bg-green-500\/40{background-color:rgba(34,197,94,.4)}.bg-green-500\/45{background-color:rgba(34,197,94,.45)}.bg-green-500\/5{background-color:rgba(34,197,94,.05)}.bg-green-500\/50{background-color:rgba(34,197,94,.5)}.bg-green-500\/55{background-color:rgba(34,197,94,.55)}.bg-green-500\/60{background-color:rgba(34,197,94,.6)}.bg-green-500\/65{background-color:rgba(34,197,94,.65)}.bg-green-500\/70{background-color:rgba(34,197,94,.7)}.bg-green-500\/75{background-color:rgba(34,197,94,.75)}.bg-green-500\/80{background-color:rgba(34,197,94,.8)}.bg-green-500\/85{background-color:rgba(34,197,94,.85)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-green-500\/95{background-color:rgba(34,197,94,.95)}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity,1))}.bg-green-600\/0{background-color:rgba(22,163,74,0)}.bg-green-600\/10{background-color:rgba(22,163,74,.1)}.bg-green-600\/100{background-color:#16a34a}.bg-green-600\/15{background-color:rgba(22,163,74,.15)}.bg-green-600\/20{background-color:rgba(22,163,74,.2)}.bg-green-600\/25{background-color:rgba(22,163,74,.25)}.bg-green-600\/30{background-color:rgba(22,163,74,.3)}.bg-green-600\/35{background-color:rgba(22,163,74,.35)}.bg-green-600\/40{background-color:rgba(22,163,74,.4)}.bg-green-600\/45{background-color:rgba(22,163,74,.45)}.bg-green-600\/5{background-color:rgba(22,163,74,.05)}.bg-green-600\/50{background-color:rgba(22,163,74,.5)}.bg-green-600\/55{background-color:rgba(22,163,74,.55)}.bg-green-600\/60{background-color:rgba(22,163,74,.6)}.bg-green-600\/65{background-color:rgba(22,163,74,.65)}.bg-green-600\/70{background-color:rgba(22,163,74,.7)}.bg-green-600\/75{background-color:rgba(22,163,74,.75)}.bg-green-600\/80{background-color:rgba(22,163,74,.8)}.bg-green-600\/85{background-color:rgba(22,163,74,.85)}.bg-green-600\/90{background-color:rgba(22,163,74,.9)}.bg-green-600\/95{background-color:rgba(22,163,74,.95)}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(21 128 61/var(--tw-bg-opacity,1))}.bg-green-700\/0{background-color:rgba(21,128,61,0)}.bg-green-700\/10{background-color:rgba(21,128,61,.1)}.bg-green-700\/100{background-color:#15803d}.bg-green-700\/15{background-color:rgba(21,128,61,.15)}.bg-green-700\/20{background-color:rgba(21,128,61,.2)}.bg-green-700\/25{background-color:rgba(21,128,61,.25)}.bg-green-700\/30{background-color:rgba(21,128,61,.3)}.bg-green-700\/35{background-color:rgba(21,128,61,.35)}.bg-green-700\/40{background-color:rgba(21,128,61,.4)}.bg-green-700\/45{background-color:rgba(21,128,61,.45)}.bg-green-700\/5{background-color:rgba(21,128,61,.05)}.bg-green-700\/50{background-color:rgba(21,128,61,.5)}.bg-green-700\/55{background-color:rgba(21,128,61,.55)}.bg-green-700\/60{background-color:rgba(21,128,61,.6)}.bg-green-700\/65{background-color:rgba(21,128,61,.65)}.bg-green-700\/70{background-color:rgba(21,128,61,.7)}.bg-green-700\/75{background-color:rgba(21,128,61,.75)}.bg-green-700\/80{background-color:rgba(21,128,61,.8)}.bg-green-700\/85{background-color:rgba(21,128,61,.85)}.bg-green-700\/90{background-color:rgba(21,128,61,.9)}.bg-green-700\/95{background-color:rgba(21,128,61,.95)}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(22 101 52/var(--tw-bg-opacity,1))}.bg-green-800\/0{background-color:rgba(22,101,52,0)}.bg-green-800\/10{background-color:rgba(22,101,52,.1)}.bg-green-800\/100{background-color:#166534}.bg-green-800\/15{background-color:rgba(22,101,52,.15)}.bg-green-800\/20{background-color:rgba(22,101,52,.2)}.bg-green-800\/25{background-color:rgba(22,101,52,.25)}.bg-green-800\/30{background-color:rgba(22,101,52,.3)}.bg-green-800\/35{background-color:rgba(22,101,52,.35)}.bg-green-800\/40{background-color:rgba(22,101,52,.4)}.bg-green-800\/45{background-color:rgba(22,101,52,.45)}.bg-green-800\/5{background-color:rgba(22,101,52,.05)}.bg-green-800\/50{background-color:rgba(22,101,52,.5)}.bg-green-800\/55{background-color:rgba(22,101,52,.55)}.bg-green-800\/60{background-color:rgba(22,101,52,.6)}.bg-green-800\/65{background-color:rgba(22,101,52,.65)}.bg-green-800\/70{background-color:rgba(22,101,52,.7)}.bg-green-800\/75{background-color:rgba(22,101,52,.75)}.bg-green-800\/80{background-color:rgba(22,101,52,.8)}.bg-green-800\/85{background-color:rgba(22,101,52,.85)}.bg-green-800\/90{background-color:rgba(22,101,52,.9)}.bg-green-800\/95{background-color:rgba(22,101,52,.95)}.bg-green-900{--tw-bg-opacity:1;background-color:rgb(20 83 45/var(--tw-bg-opacity,1))}.bg-green-900\/0{background-color:rgba(20,83,45,0)}.bg-green-900\/10{background-color:rgba(20,83,45,.1)}.bg-green-900\/100{background-color:#14532d}.bg-green-900\/15{background-color:rgba(20,83,45,.15)}.bg-green-900\/20{background-color:rgba(20,83,45,.2)}.bg-green-900\/25{background-color:rgba(20,83,45,.25)}.bg-green-900\/30{background-color:rgba(20,83,45,.3)}.bg-green-900\/35{background-color:rgba(20,83,45,.35)}.bg-green-900\/40{background-color:rgba(20,83,45,.4)}.bg-green-900\/45{background-color:rgba(20,83,45,.45)}.bg-green-900\/5{background-color:rgba(20,83,45,.05)}.bg-green-900\/50{background-color:rgba(20,83,45,.5)}.bg-green-900\/55{background-color:rgba(20,83,45,.55)}.bg-green-900\/60{background-color:rgba(20,83,45,.6)}.bg-green-900\/65{background-color:rgba(20,83,45,.65)}.bg-green-900\/70{background-color:rgba(20,83,45,.7)}.bg-green-900\/75{background-color:rgba(20,83,45,.75)}.bg-green-900\/80{background-color:rgba(20,83,45,.8)}.bg-green-900\/85{background-color:rgba(20,83,45,.85)}.bg-green-900\/90{background-color:rgba(20,83,45,.9)}.bg-green-900\/95{background-color:rgba(20,83,45,.95)}.bg-orange-500{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity,1))}.bg-orange-800{--tw-bg-opacity:1;background-color:rgb(154 52 18/var(--tw-bg-opacity,1))}.bg-purple-500{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.bg-purple-500\/0{background-color:rgba(168,85,247,0)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-purple-500\/100{background-color:#a855f7}.bg-purple-500\/15{background-color:rgba(168,85,247,.15)}.bg-purple-500\/20{background-color:rgba(168,85,247,.2)}.bg-purple-500\/25{background-color:rgba(168,85,247,.25)}.bg-purple-500\/30{background-color:rgba(168,85,247,.3)}.bg-purple-500\/35{background-color:rgba(168,85,247,.35)}.bg-purple-500\/40{background-color:rgba(168,85,247,.4)}.bg-purple-500\/45{background-color:rgba(168,85,247,.45)}.bg-purple-500\/5{background-color:rgba(168,85,247,.05)}.bg-purple-500\/50{background-color:rgba(168,85,247,.5)}.bg-purple-500\/55{background-color:rgba(168,85,247,.55)}.bg-purple-500\/60{background-color:rgba(168,85,247,.6)}.bg-purple-500\/65{background-color:rgba(168,85,247,.65)}.bg-purple-500\/70{background-color:rgba(168,85,247,.7)}.bg-purple-500\/75{background-color:rgba(168,85,247,.75)}.bg-purple-500\/80{background-color:rgba(168,85,247,.8)}.bg-purple-500\/85{background-color:rgba(168,85,247,.85)}.bg-purple-500\/90{background-color:rgba(168,85,247,.9)}.bg-purple-500\/95{background-color:rgba(168,85,247,.95)}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234/var(--tw-bg-opacity,1))}.bg-purple-600\/0{background-color:rgba(147,51,234,0)}.bg-purple-600\/10{background-color:rgba(147,51,234,.1)}.bg-purple-600\/100{background-color:#9333ea}.bg-purple-600\/15{background-color:rgba(147,51,234,.15)}.bg-purple-600\/20{background-color:rgba(147,51,234,.2)}.bg-purple-600\/25{background-color:rgba(147,51,234,.25)}.bg-purple-600\/30{background-color:rgba(147,51,234,.3)}.bg-purple-600\/35{background-color:rgba(147,51,234,.35)}.bg-purple-600\/40{background-color:rgba(147,51,234,.4)}.bg-purple-600\/45{background-color:rgba(147,51,234,.45)}.bg-purple-600\/5{background-color:rgba(147,51,234,.05)}.bg-purple-600\/50{background-color:rgba(147,51,234,.5)}.bg-purple-600\/55{background-color:rgba(147,51,234,.55)}.bg-purple-600\/60{background-color:rgba(147,51,234,.6)}.bg-purple-600\/65{background-color:rgba(147,51,234,.65)}.bg-purple-600\/70{background-color:rgba(147,51,234,.7)}.bg-purple-600\/75{background-color:rgba(147,51,234,.75)}.bg-purple-600\/80{background-color:rgba(147,51,234,.8)}.bg-purple-600\/85{background-color:rgba(147,51,234,.85)}.bg-purple-600\/90{background-color:rgba(147,51,234,.9)}.bg-purple-600\/95{background-color:rgba(147,51,234,.95)}.bg-purple-700{--tw-bg-opacity:1;background-color:rgb(126 34 206/var(--tw-bg-opacity,1))}.bg-purple-700\/0{background-color:rgba(126,34,206,0)}.bg-purple-700\/10{background-color:rgba(126,34,206,.1)}.bg-purple-700\/100{background-color:#7e22ce}.bg-purple-700\/15{background-color:rgba(126,34,206,.15)}.bg-purple-700\/20{background-color:rgba(126,34,206,.2)}.bg-purple-700\/25{background-color:rgba(126,34,206,.25)}.bg-purple-700\/30{background-color:rgba(126,34,206,.3)}.bg-purple-700\/35{background-color:rgba(126,34,206,.35)}.bg-purple-700\/40{background-color:rgba(126,34,206,.4)}.bg-purple-700\/45{background-color:rgba(126,34,206,.45)}.bg-purple-700\/5{background-color:rgba(126,34,206,.05)}.bg-purple-700\/50{background-color:rgba(126,34,206,.5)}.bg-purple-700\/55{background-color:rgba(126,34,206,.55)}.bg-purple-700\/60{background-color:rgba(126,34,206,.6)}.bg-purple-700\/65{background-color:rgba(126,34,206,.65)}.bg-purple-700\/70{background-color:rgba(126,34,206,.7)}.bg-purple-700\/75{background-color:rgba(126,34,206,.75)}.bg-purple-700\/80{background-color:rgba(126,34,206,.8)}.bg-purple-700\/85{background-color:rgba(126,34,206,.85)}.bg-purple-700\/90{background-color:rgba(126,34,206,.9)}.bg-purple-700\/95{background-color:rgba(126,34,206,.95)}.bg-purple-800{--tw-bg-opacity:1;background-color:rgb(107 33 168/var(--tw-bg-opacity,1))}.bg-purple-800\/0{background-color:rgba(107,33,168,0)}.bg-purple-800\/10{background-color:rgba(107,33,168,.1)}.bg-purple-800\/100{background-color:#6b21a8}.bg-purple-800\/15{background-color:rgba(107,33,168,.15)}.bg-purple-800\/20{background-color:rgba(107,33,168,.2)}.bg-purple-800\/25{background-color:rgba(107,33,168,.25)}.bg-purple-800\/30{background-color:rgba(107,33,168,.3)}.bg-purple-800\/35{background-color:rgba(107,33,168,.35)}.bg-purple-800\/40{background-color:rgba(107,33,168,.4)}.bg-purple-800\/45{background-color:rgba(107,33,168,.45)}.bg-purple-800\/5{background-color:rgba(107,33,168,.05)}.bg-purple-800\/50{background-color:rgba(107,33,168,.5)}.bg-purple-800\/55{background-color:rgba(107,33,168,.55)}.bg-purple-800\/60{background-color:rgba(107,33,168,.6)}.bg-purple-800\/65{background-color:rgba(107,33,168,.65)}.bg-purple-800\/70{background-color:rgba(107,33,168,.7)}.bg-purple-800\/75{background-color:rgba(107,33,168,.75)}.bg-purple-800\/80{background-color:rgba(107,33,168,.8)}.bg-purple-800\/85{background-color:rgba(107,33,168,.85)}.bg-purple-800\/90{background-color:rgba(107,33,168,.9)}.bg-purple-800\/95{background-color:rgba(107,33,168,.95)}.bg-purple-900{--tw-bg-opacity:1;background-color:rgb(88 28 135/var(--tw-bg-opacity,1))}.bg-purple-900\/0{background-color:rgba(88,28,135,0)}.bg-purple-900\/10{background-color:rgba(88,28,135,.1)}.bg-purple-900\/100{background-color:#581c87}.bg-purple-900\/15{background-color:rgba(88,28,135,.15)}.bg-purple-900\/20{background-color:rgba(88,28,135,.2)}.bg-purple-900\/25{background-color:rgba(88,28,135,.25)}.bg-purple-900\/30{background-color:rgba(88,28,135,.3)}.bg-purple-900\/35{background-color:rgba(88,28,135,.35)}.bg-purple-900\/40{background-color:rgba(88,28,135,.4)}.bg-purple-900\/45{background-color:rgba(88,28,135,.45)}.bg-purple-900\/5{background-color:rgba(88,28,135,.05)}.bg-purple-900\/50{background-color:rgba(88,28,135,.5)}.bg-purple-900\/55{background-color:rgba(88,28,135,.55)}.bg-purple-900\/60{background-color:rgba(88,28,135,.6)}.bg-purple-900\/65{background-color:rgba(88,28,135,.65)}.bg-purple-900\/70{background-color:rgba(88,28,135,.7)}.bg-purple-900\/75{background-color:rgba(88,28,135,.75)}.bg-purple-900\/80{background-color:rgba(88,28,135,.8)}.bg-purple-900\/85{background-color:rgba(88,28,135,.85)}.bg-purple-900\/90{background-color:rgba(88,28,135,.9)}.bg-purple-900\/95{background-color:rgba(88,28,135,.95)}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/0{background-color:rgba(239,68,68,0)}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/100{background-color:#ef4444}.bg-red-500\/15{background-color:rgba(239,68,68,.15)}.bg-red-500\/20{background-color:rgba(239,68,68,.2)}.bg-red-500\/25{background-color:rgba(239,68,68,.25)}.bg-red-500\/30{background-color:rgba(239,68,68,.3)}.bg-red-500\/35{background-color:rgba(239,68,68,.35)}.bg-red-500\/40{background-color:rgba(239,68,68,.4)}.bg-red-500\/45{background-color:rgba(239,68,68,.45)}.bg-red-500\/5{background-color:rgba(239,68,68,.05)}.bg-red-500\/50{background-color:rgba(239,68,68,.5)}.bg-red-500\/55{background-color:rgba(239,68,68,.55)}.bg-red-500\/60{background-color:rgba(239,68,68,.6)}.bg-red-500\/65{background-color:rgba(239,68,68,.65)}.bg-red-500\/70{background-color:rgba(239,68,68,.7)}.bg-red-500\/75{background-color:rgba(239,68,68,.75)}.bg-red-500\/80{background-color:rgba(239,68,68,.8)}.bg-red-500\/85{background-color:rgba(239,68,68,.85)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-red-500\/95{background-color:rgba(239,68,68,.95)}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/0{background-color:rgba(220,38,38,0)}.bg-red-600\/10{background-color:rgba(220,38,38,.1)}.bg-red-600\/100{background-color:#dc2626}.bg-red-600\/15{background-color:rgba(220,38,38,.15)}.bg-red-600\/20{background-color:rgba(220,38,38,.2)}.bg-red-600\/25{background-color:rgba(220,38,38,.25)}.bg-red-600\/30{background-color:rgba(220,38,38,.3)}.bg-red-600\/35{background-color:rgba(220,38,38,.35)}.bg-red-600\/40{background-color:rgba(220,38,38,.4)}.bg-red-600\/45{background-color:rgba(220,38,38,.45)}.bg-red-600\/5{background-color:rgba(220,38,38,.05)}.bg-red-600\/50{background-color:rgba(220,38,38,.5)}.bg-red-600\/55{background-color:rgba(220,38,38,.55)}.bg-red-600\/60{background-color:rgba(220,38,38,.6)}.bg-red-600\/65{background-color:rgba(220,38,38,.65)}.bg-red-600\/70{background-color:rgba(220,38,38,.7)}.bg-red-600\/75{background-color:rgba(220,38,38,.75)}.bg-red-600\/80{background-color:rgba(220,38,38,.8)}.bg-red-600\/85{background-color:rgba(220,38,38,.85)}.bg-red-600\/90{background-color:rgba(220,38,38,.9)}.bg-red-600\/95{background-color:rgba(220,38,38,.95)}.bg-red-700{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.bg-red-700\/0{background-color:rgba(185,28,28,0)}.bg-red-700\/10{background-color:rgba(185,28,28,.1)}.bg-red-700\/100{background-color:#b91c1c}.bg-red-700\/15{background-color:rgba(185,28,28,.15)}.bg-red-700\/20{background-color:rgba(185,28,28,.2)}.bg-red-700\/25{background-color:rgba(185,28,28,.25)}.bg-red-700\/30{background-color:rgba(185,28,28,.3)}.bg-red-700\/35{background-color:rgba(185,28,28,.35)}.bg-red-700\/40{background-color:rgba(185,28,28,.4)}.bg-red-700\/45{background-color:rgba(185,28,28,.45)}.bg-red-700\/5{background-color:rgba(185,28,28,.05)}.bg-red-700\/50{background-color:rgba(185,28,28,.5)}.bg-red-700\/55{background-color:rgba(185,28,28,.55)}.bg-red-700\/60{background-color:rgba(185,28,28,.6)}.bg-red-700\/65{background-color:rgba(185,28,28,.65)}.bg-red-700\/70{background-color:rgba(185,28,28,.7)}.bg-red-700\/75{background-color:rgba(185,28,28,.75)}.bg-red-700\/80{background-color:rgba(185,28,28,.8)}.bg-red-700\/85{background-color:rgba(185,28,28,.85)}.bg-red-700\/90{background-color:rgba(185,28,28,.9)}.bg-red-700\/95{background-color:rgba(185,28,28,.95)}.bg-red-800{--tw-bg-opacity:1;background-color:rgb(153 27 27/var(--tw-bg-opacity,1))}.bg-red-800\/0{background-color:rgba(153,27,27,0)}.bg-red-800\/10{background-color:rgba(153,27,27,.1)}.bg-red-800\/100{background-color:#991b1b}.bg-red-800\/15{background-color:rgba(153,27,27,.15)}.bg-red-800\/20{background-color:rgba(153,27,27,.2)}.bg-red-800\/25{background-color:rgba(153,27,27,.25)}.bg-red-800\/30{background-color:rgba(153,27,27,.3)}.bg-red-800\/35{background-color:rgba(153,27,27,.35)}.bg-red-800\/40{background-color:rgba(153,27,27,.4)}.bg-red-800\/45{background-color:rgba(153,27,27,.45)}.bg-red-800\/5{background-color:rgba(153,27,27,.05)}.bg-red-800\/50{background-color:rgba(153,27,27,.5)}.bg-red-800\/55{background-color:rgba(153,27,27,.55)}.bg-red-800\/60{background-color:rgba(153,27,27,.6)}.bg-red-800\/65{background-color:rgba(153,27,27,.65)}.bg-red-800\/70{background-color:rgba(153,27,27,.7)}.bg-red-800\/75{background-color:rgba(153,27,27,.75)}.bg-red-800\/80{background-color:rgba(153,27,27,.8)}.bg-red-800\/85{background-color:rgba(153,27,27,.85)}.bg-red-800\/90{background-color:rgba(153,27,27,.9)}.bg-red-800\/95{background-color:rgba(153,27,27,.95)}.bg-red-900{--tw-bg-opacity:1;background-color:rgb(127 29 29/var(--tw-bg-opacity,1))}.bg-red-900\/0{background-color:rgba(127,29,29,0)}.bg-red-900\/10{background-color:rgba(127,29,29,.1)}.bg-red-900\/100{background-color:#7f1d1d}.bg-red-900\/15{background-color:rgba(127,29,29,.15)}.bg-red-900\/20{background-color:rgba(127,29,29,.2)}.bg-red-900\/25{background-color:rgba(127,29,29,.25)}.bg-red-900\/30{background-color:rgba(127,29,29,.3)}.bg-red-900\/35{background-color:rgba(127,29,29,.35)}.bg-red-900\/40{background-color:rgba(127,29,29,.4)}.bg-red-900\/45{background-color:rgba(127,29,29,.45)}.bg-red-900\/5{background-color:rgba(127,29,29,.05)}.bg-red-900\/50{background-color:rgba(127,29,29,.5)}.bg-red-900\/55{background-color:rgba(127,29,29,.55)}.bg-red-900\/60{background-color:rgba(127,29,29,.6)}.bg-red-900\/65{background-color:rgba(127,29,29,.65)}.bg-red-900\/70{background-color:rgba(127,29,29,.7)}.bg-red-900\/75{background-color:rgba(127,29,29,.75)}.bg-red-900\/80{background-color:rgba(127,29,29,.8)}.bg-red-900\/85{background-color:rgba(127,29,29,.85)}.bg-red-900\/90{background-color:rgba(127,29,29,.9)}.bg-red-900\/95{background-color:rgba(127,29,29,.95)}.bg-sky-500{--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity,1))}.bg-sky-800{--tw-bg-opacity:1;background-color:rgb(7 89 133/var(--tw-bg-opacity,1))}.bg-sky-900\/20{background-color:rgba(12,74,110,.2)}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/0{background-color:rgba(234,179,8,0)}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.bg-yellow-500\/100{background-color:#eab308}.bg-yellow-500\/15{background-color:rgba(234,179,8,.15)}.bg-yellow-500\/20{background-color:rgba(234,179,8,.2)}.bg-yellow-500\/25{background-color:rgba(234,179,8,.25)}.bg-yellow-500\/30{background-color:rgba(234,179,8,.3)}.bg-yellow-500\/35{background-color:rgba(234,179,8,.35)}.bg-yellow-500\/40{background-color:rgba(234,179,8,.4)}.bg-yellow-500\/45{background-color:rgba(234,179,8,.45)}.bg-yellow-500\/5{background-color:rgba(234,179,8,.05)}.bg-yellow-500\/50{background-color:rgba(234,179,8,.5)}.bg-yellow-500\/55{background-color:rgba(234,179,8,.55)}.bg-yellow-500\/60{background-color:rgba(234,179,8,.6)}.bg-yellow-500\/65{background-color:rgba(234,179,8,.65)}.bg-yellow-500\/70{background-color:rgba(234,179,8,.7)}.bg-yellow-500\/75{background-color:rgba(234,179,8,.75)}.bg-yellow-500\/80{background-color:rgba(234,179,8,.8)}.bg-yellow-500\/85{background-color:rgba(234,179,8,.85)}.bg-yellow-500\/90{background-color:rgba(234,179,8,.9)}.bg-yellow-500\/95{background-color:rgba(234,179,8,.95)}.bg-yellow-600{--tw-bg-opacity:1;background-color:rgb(202 138 4/var(--tw-bg-opacity,1))}.bg-yellow-600\/0{background-color:rgba(202,138,4,0)}.bg-yellow-600\/10{background-color:rgba(202,138,4,.1)}.bg-yellow-600\/100{background-color:#ca8a04}.bg-yellow-600\/15{background-color:rgba(202,138,4,.15)}.bg-yellow-600\/20{background-color:rgba(202,138,4,.2)}.bg-yellow-600\/25{background-color:rgba(202,138,4,.25)}.bg-yellow-600\/30{background-color:rgba(202,138,4,.3)}.bg-yellow-600\/35{background-color:rgba(202,138,4,.35)}.bg-yellow-600\/40{background-color:rgba(202,138,4,.4)}.bg-yellow-600\/45{background-color:rgba(202,138,4,.45)}.bg-yellow-600\/5{background-color:rgba(202,138,4,.05)}.bg-yellow-600\/50{background-color:rgba(202,138,4,.5)}.bg-yellow-600\/55{background-color:rgba(202,138,4,.55)}.bg-yellow-600\/60{background-color:rgba(202,138,4,.6)}.bg-yellow-600\/65{background-color:rgba(202,138,4,.65)}.bg-yellow-600\/70{background-color:rgba(202,138,4,.7)}.bg-yellow-600\/75{background-color:rgba(202,138,4,.75)}.bg-yellow-600\/80{background-color:rgba(202,138,4,.8)}.bg-yellow-600\/85{background-color:rgba(202,138,4,.85)}.bg-yellow-600\/90{background-color:rgba(202,138,4,.9)}.bg-yellow-600\/95{background-color:rgba(202,138,4,.95)}.bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity,1))}.bg-yellow-700\/0{background-color:rgba(161,98,7,0)}.bg-yellow-700\/10{background-color:rgba(161,98,7,.1)}.bg-yellow-700\/100{background-color:#a16207}.bg-yellow-700\/15{background-color:rgba(161,98,7,.15)}.bg-yellow-700\/20{background-color:rgba(161,98,7,.2)}.bg-yellow-700\/25{background-color:rgba(161,98,7,.25)}.bg-yellow-700\/30{background-color:rgba(161,98,7,.3)}.bg-yellow-700\/35{background-color:rgba(161,98,7,.35)}.bg-yellow-700\/40{background-color:rgba(161,98,7,.4)}.bg-yellow-700\/45{background-color:rgba(161,98,7,.45)}.bg-yellow-700\/5{background-color:rgba(161,98,7,.05)}.bg-yellow-700\/50{background-color:rgba(161,98,7,.5)}.bg-yellow-700\/55{background-color:rgba(161,98,7,.55)}.bg-yellow-700\/60{background-color:rgba(161,98,7,.6)}.bg-yellow-700\/65{background-color:rgba(161,98,7,.65)}.bg-yellow-700\/70{background-color:rgba(161,98,7,.7)}.bg-yellow-700\/75{background-color:rgba(161,98,7,.75)}.bg-yellow-700\/80{background-color:rgba(161,98,7,.8)}.bg-yellow-700\/85{background-color:rgba(161,98,7,.85)}.bg-yellow-700\/90{background-color:rgba(161,98,7,.9)}.bg-yellow-700\/95{background-color:rgba(161,98,7,.95)}.bg-yellow-800{--tw-bg-opacity:1;background-color:rgb(133 77 14/var(--tw-bg-opacity,1))}.bg-yellow-800\/0{background-color:rgba(133,77,14,0)}.bg-yellow-800\/10{background-color:rgba(133,77,14,.1)}.bg-yellow-800\/100{background-color:#854d0e}.bg-yellow-800\/15{background-color:rgba(133,77,14,.15)}.bg-yellow-800\/20{background-color:rgba(133,77,14,.2)}.bg-yellow-800\/25{background-color:rgba(133,77,14,.25)}.bg-yellow-800\/30{background-color:rgba(133,77,14,.3)}.bg-yellow-800\/35{background-color:rgba(133,77,14,.35)}.bg-yellow-800\/40{background-color:rgba(133,77,14,.4)}.bg-yellow-800\/45{background-color:rgba(133,77,14,.45)}.bg-yellow-800\/5{background-color:rgba(133,77,14,.05)}.bg-yellow-800\/50{background-color:rgba(133,77,14,.5)}.bg-yellow-800\/55{background-color:rgba(133,77,14,.55)}.bg-yellow-800\/60{background-color:rgba(133,77,14,.6)}.bg-yellow-800\/65{background-color:rgba(133,77,14,.65)}.bg-yellow-800\/70{background-color:rgba(133,77,14,.7)}.bg-yellow-800\/75{background-color:rgba(133,77,14,.75)}.bg-yellow-800\/80{background-color:rgba(133,77,14,.8)}.bg-yellow-800\/85{background-color:rgba(133,77,14,.85)}.bg-yellow-800\/90{background-color:rgba(133,77,14,.9)}.bg-yellow-800\/95{background-color:rgba(133,77,14,.95)}.bg-yellow-900{--tw-bg-opacity:1;background-color:rgb(113 63 18/var(--tw-bg-opacity,1))}.bg-yellow-900\/0{background-color:rgba(113,63,18,0)}.bg-yellow-900\/10{background-color:rgba(113,63,18,.1)}.bg-yellow-900\/100{background-color:#713f12}.bg-yellow-900\/15{background-color:rgba(113,63,18,.15)}.bg-yellow-900\/20{background-color:rgba(113,63,18,.2)}.bg-yellow-900\/25{background-color:rgba(113,63,18,.25)}.bg-yellow-900\/30{background-color:rgba(113,63,18,.3)}.bg-yellow-900\/35{background-color:rgba(113,63,18,.35)}.bg-yellow-900\/40{background-color:rgba(113,63,18,.4)}.bg-yellow-900\/45{background-color:rgba(113,63,18,.45)}.bg-yellow-900\/5{background-color:rgba(113,63,18,.05)}.bg-yellow-900\/50{background-color:rgba(113,63,18,.5)}.bg-yellow-900\/55{background-color:rgba(113,63,18,.55)}.bg-yellow-900\/60{background-color:rgba(113,63,18,.6)}.bg-yellow-900\/65{background-color:rgba(113,63,18,.65)}.bg-yellow-900\/70{background-color:rgba(113,63,18,.7)}.bg-yellow-900\/75{background-color:rgba(113,63,18,.75)}.bg-yellow-900\/80{background-color:rgba(113,63,18,.8)}.bg-yellow-900\/85{background-color:rgba(113,63,18,.85)}.bg-yellow-900\/90{background-color:rgba(113,63,18,.9)}.bg-yellow-900\/95{background-color:rgba(113,63,18,.95)}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-3{padding-right:.75rem}.pt-10{padding-top:2.5rem}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-5{line-height:1.25rem}.text-amber-200{--tw-text-opacity:1;color:rgb(253 230 138/var(--tw-text-opacity,1))}.text-amber-200\/0{color:hsla(48,97%,77%,0)}.text-amber-200\/10{color:hsla(48,97%,77%,.1)}.text-amber-200\/100{color:#fde68a}.text-amber-200\/15{color:hsla(48,97%,77%,.15)}.text-amber-200\/20{color:hsla(48,97%,77%,.2)}.text-amber-200\/25{color:hsla(48,97%,77%,.25)}.text-amber-200\/30{color:hsla(48,97%,77%,.3)}.text-amber-200\/35{color:hsla(48,97%,77%,.35)}.text-amber-200\/40{color:hsla(48,97%,77%,.4)}.text-amber-200\/45{color:hsla(48,97%,77%,.45)}.text-amber-200\/5{color:hsla(48,97%,77%,.05)}.text-amber-200\/50{color:hsla(48,97%,77%,.5)}.text-amber-200\/55{color:hsla(48,97%,77%,.55)}.text-amber-200\/60{color:hsla(48,97%,77%,.6)}.text-amber-200\/65{color:hsla(48,97%,77%,.65)}.text-amber-200\/70{color:hsla(48,97%,77%,.7)}.text-amber-200\/75{color:hsla(48,97%,77%,.75)}.text-amber-200\/80{color:hsla(48,97%,77%,.8)}.text-amber-200\/85{color:hsla(48,97%,77%,.85)}.text-amber-200\/90{color:hsla(48,97%,77%,.9)}.text-amber-200\/95{color:hsla(48,97%,77%,.95)}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-300\/0{color:rgba(252,211,77,0)}.text-amber-300\/10{color:rgba(252,211,77,.1)}.text-amber-300\/100{color:#fcd34d}.text-amber-300\/15{color:rgba(252,211,77,.15)}.text-amber-300\/20{color:rgba(252,211,77,.2)}.text-amber-300\/25{color:rgba(252,211,77,.25)}.text-amber-300\/30{color:rgba(252,211,77,.3)}.text-amber-300\/35{color:rgba(252,211,77,.35)}.text-amber-300\/40{color:rgba(252,211,77,.4)}.text-amber-300\/45{color:rgba(252,211,77,.45)}.text-amber-300\/5{color:rgba(252,211,77,.05)}.text-amber-300\/50{color:rgba(252,211,77,.5)}.text-amber-300\/55{color:rgba(252,211,77,.55)}.text-amber-300\/60{color:rgba(252,211,77,.6)}.text-amber-300\/65{color:rgba(252,211,77,.65)}.text-amber-300\/70{color:rgba(252,211,77,.7)}.text-amber-300\/75{color:rgba(252,211,77,.75)}.text-amber-300\/80{color:rgba(252,211,77,.8)}.text-amber-300\/85{color:rgba(252,211,77,.85)}.text-amber-300\/90{color:rgba(252,211,77,.9)}.text-amber-300\/95{color:rgba(252,211,77,.95)}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/0{color:rgba(251,191,36,0)}.text-amber-400\/10{color:rgba(251,191,36,.1)}.text-amber-400\/100{color:#fbbf24}.text-amber-400\/15{color:rgba(251,191,36,.15)}.text-amber-400\/20{color:rgba(251,191,36,.2)}.text-amber-400\/25{color:rgba(251,191,36,.25)}.text-amber-400\/30{color:rgba(251,191,36,.3)}.text-amber-400\/35{color:rgba(251,191,36,.35)}.text-amber-400\/40{color:rgba(251,191,36,.4)}.text-amber-400\/45{color:rgba(251,191,36,.45)}.text-amber-400\/5{color:rgba(251,191,36,.05)}.text-amber-400\/50{color:rgba(251,191,36,.5)}.text-amber-400\/55{color:rgba(251,191,36,.55)}.text-amber-400\/60{color:rgba(251,191,36,.6)}.text-amber-400\/65{color:rgba(251,191,36,.65)}.text-amber-400\/70{color:rgba(251,191,36,.7)}.text-amber-400\/75{color:rgba(251,191,36,.75)}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-400\/85{color:rgba(251,191,36,.85)}.text-amber-400\/90{color:rgba(251,191,36,.9)}.text-amber-400\/95{color:rgba(251,191,36,.95)}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity,1))}.text-gray-200\/0{color:rgba(229,231,235,0)}.text-gray-200\/10{color:rgba(229,231,235,.1)}.text-gray-200\/100{color:#e5e7eb}.text-gray-200\/15{color:rgba(229,231,235,.15)}.text-gray-200\/20{color:rgba(229,231,235,.2)}.text-gray-200\/25{color:rgba(229,231,235,.25)}.text-gray-200\/30{color:rgba(229,231,235,.3)}.text-gray-200\/35{color:rgba(229,231,235,.35)}.text-gray-200\/40{color:rgba(229,231,235,.4)}.text-gray-200\/45{color:rgba(229,231,235,.45)}.text-gray-200\/5{color:rgba(229,231,235,.05)}.text-gray-200\/50{color:rgba(229,231,235,.5)}.text-gray-200\/55{color:rgba(229,231,235,.55)}.text-gray-200\/60{color:rgba(229,231,235,.6)}.text-gray-200\/65{color:rgba(229,231,235,.65)}.text-gray-200\/70{color:rgba(229,231,235,.7)}.text-gray-200\/75{color:rgba(229,231,235,.75)}.text-gray-200\/80{color:rgba(229,231,235,.8)}.text-gray-200\/85{color:rgba(229,231,235,.85)}.text-gray-200\/90{color:rgba(229,231,235,.9)}.text-gray-200\/95{color:rgba(229,231,235,.95)}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-300\/0{color:rgba(209,213,219,0)}.text-gray-300\/10{color:rgba(209,213,219,.1)}.text-gray-300\/100{color:#d1d5db}.text-gray-300\/15{color:rgba(209,213,219,.15)}.text-gray-300\/20{color:rgba(209,213,219,.2)}.text-gray-300\/25{color:rgba(209,213,219,.25)}.text-gray-300\/30{color:rgba(209,213,219,.3)}.text-gray-300\/35{color:rgba(209,213,219,.35)}.text-gray-300\/40{color:rgba(209,213,219,.4)}.text-gray-300\/45{color:rgba(209,213,219,.45)}.text-gray-300\/5{color:rgba(209,213,219,.05)}.text-gray-300\/50{color:rgba(209,213,219,.5)}.text-gray-300\/55{color:rgba(209,213,219,.55)}.text-gray-300\/60{color:rgba(209,213,219,.6)}.text-gray-300\/65{color:rgba(209,213,219,.65)}.text-gray-300\/70{color:rgba(209,213,219,.7)}.text-gray-300\/75{color:rgba(209,213,219,.75)}.text-gray-300\/80{color:rgba(209,213,219,.8)}.text-gray-300\/85{color:rgba(209,213,219,.85)}.text-gray-300\/90{color:rgba(209,213,219,.9)}.text-gray-300\/95{color:rgba(209,213,219,.95)}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-400\/0{color:rgba(156,163,175,0)}.text-gray-400\/10{color:rgba(156,163,175,.1)}.text-gray-400\/100{color:#9ca3af}.text-gray-400\/15{color:rgba(156,163,175,.15)}.text-gray-400\/20{color:rgba(156,163,175,.2)}.text-gray-400\/25{color:rgba(156,163,175,.25)}.text-gray-400\/30{color:rgba(156,163,175,.3)}.text-gray-400\/35{color:rgba(156,163,175,.35)}.text-gray-400\/40{color:rgba(156,163,175,.4)}.text-gray-400\/45{color:rgba(156,163,175,.45)}.text-gray-400\/5{color:rgba(156,163,175,.05)}.text-gray-400\/50{color:rgba(156,163,175,.5)}.text-gray-400\/55{color:rgba(156,163,175,.55)}.text-gray-400\/60{color:rgba(156,163,175,.6)}.text-gray-400\/65{color:rgba(156,163,175,.65)}.text-gray-400\/70{color:rgba(156,163,175,.7)}.text-gray-400\/75{color:rgba(156,163,175,.75)}.text-gray-400\/80{color:rgba(156,163,175,.8)}.text-gray-400\/85{color:rgba(156,163,175,.85)}.text-gray-400\/90{color:rgba(156,163,175,.9)}.text-gray-400\/95{color:rgba(156,163,175,.95)}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-green-200{--tw-text-opacity:1;color:rgb(187 247 208/var(--tw-text-opacity,1))}.text-green-200\/0{color:rgba(187,247,208,0)}.text-green-200\/10{color:rgba(187,247,208,.1)}.text-green-200\/100{color:#bbf7d0}.text-green-200\/15{color:rgba(187,247,208,.15)}.text-green-200\/20{color:rgba(187,247,208,.2)}.text-green-200\/25{color:rgba(187,247,208,.25)}.text-green-200\/30{color:rgba(187,247,208,.3)}.text-green-200\/35{color:rgba(187,247,208,.35)}.text-green-200\/40{color:rgba(187,247,208,.4)}.text-green-200\/45{color:rgba(187,247,208,.45)}.text-green-200\/5{color:rgba(187,247,208,.05)}.text-green-200\/50{color:rgba(187,247,208,.5)}.text-green-200\/55{color:rgba(187,247,208,.55)}.text-green-200\/60{color:rgba(187,247,208,.6)}.text-green-200\/65{color:rgba(187,247,208,.65)}.text-green-200\/70{color:rgba(187,247,208,.7)}.text-green-200\/75{color:rgba(187,247,208,.75)}.text-green-200\/80{color:rgba(187,247,208,.8)}.text-green-200\/85{color:rgba(187,247,208,.85)}.text-green-200\/90{color:rgba(187,247,208,.9)}.text-green-200\/95{color:rgba(187,247,208,.95)}.text-green-300{--tw-text-opacity:1;color:rgb(134 239 172/var(--tw-text-opacity,1))}.text-green-300\/0{color:rgba(134,239,172,0)}.text-green-300\/10{color:rgba(134,239,172,.1)}.text-green-300\/100{color:#86efac}.text-green-300\/15{color:rgba(134,239,172,.15)}.text-green-300\/20{color:rgba(134,239,172,.2)}.text-green-300\/25{color:rgba(134,239,172,.25)}.text-green-300\/30{color:rgba(134,239,172,.3)}.text-green-300\/35{color:rgba(134,239,172,.35)}.text-green-300\/40{color:rgba(134,239,172,.4)}.text-green-300\/45{color:rgba(134,239,172,.45)}.text-green-300\/5{color:rgba(134,239,172,.05)}.text-green-300\/50{color:rgba(134,239,172,.5)}.text-green-300\/55{color:rgba(134,239,172,.55)}.text-green-300\/60{color:rgba(134,239,172,.6)}.text-green-300\/65{color:rgba(134,239,172,.65)}.text-green-300\/70{color:rgba(134,239,172,.7)}.text-green-300\/75{color:rgba(134,239,172,.75)}.text-green-300\/80{color:rgba(134,239,172,.8)}.text-green-300\/85{color:rgba(134,239,172,.85)}.text-green-300\/90{color:rgba(134,239,172,.9)}.text-green-300\/95{color:rgba(134,239,172,.95)}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-green-400\/0{color:rgba(74,222,128,0)}.text-green-400\/10{color:rgba(74,222,128,.1)}.text-green-400\/100{color:#4ade80}.text-green-400\/15{color:rgba(74,222,128,.15)}.text-green-400\/20{color:rgba(74,222,128,.2)}.text-green-400\/25{color:rgba(74,222,128,.25)}.text-green-400\/30{color:rgba(74,222,128,.3)}.text-green-400\/35{color:rgba(74,222,128,.35)}.text-green-400\/40{color:rgba(74,222,128,.4)}.text-green-400\/45{color:rgba(74,222,128,.45)}.text-green-400\/5{color:rgba(74,222,128,.05)}.text-green-400\/50{color:rgba(74,222,128,.5)}.text-green-400\/55{color:rgba(74,222,128,.55)}.text-green-400\/60{color:rgba(74,222,128,.6)}.text-green-400\/65{color:rgba(74,222,128,.65)}.text-green-400\/70{color:rgba(74,222,128,.7)}.text-green-400\/75{color:rgba(74,222,128,.75)}.text-green-400\/80{color:rgba(74,222,128,.8)}.text-green-400\/85{color:rgba(74,222,128,.85)}.text-green-400\/90{color:rgba(74,222,128,.9)}.text-green-400\/95{color:rgba(74,222,128,.95)}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-orange-200{--tw-text-opacity:1;color:rgb(254 215 170/var(--tw-text-opacity,1))}.text-purple-200{--tw-text-opacity:1;color:rgb(233 213 255/var(--tw-text-opacity,1))}.text-purple-200\/0{color:rgba(233,213,255,0)}.text-purple-200\/10{color:rgba(233,213,255,.1)}.text-purple-200\/100{color:#e9d5ff}.text-purple-200\/15{color:rgba(233,213,255,.15)}.text-purple-200\/20{color:rgba(233,213,255,.2)}.text-purple-200\/25{color:rgba(233,213,255,.25)}.text-purple-200\/30{color:rgba(233,213,255,.3)}.text-purple-200\/35{color:rgba(233,213,255,.35)}.text-purple-200\/40{color:rgba(233,213,255,.4)}.text-purple-200\/45{color:rgba(233,213,255,.45)}.text-purple-200\/5{color:rgba(233,213,255,.05)}.text-purple-200\/50{color:rgba(233,213,255,.5)}.text-purple-200\/55{color:rgba(233,213,255,.55)}.text-purple-200\/60{color:rgba(233,213,255,.6)}.text-purple-200\/65{color:rgba(233,213,255,.65)}.text-purple-200\/70{color:rgba(233,213,255,.7)}.text-purple-200\/75{color:rgba(233,213,255,.75)}.text-purple-200\/80{color:rgba(233,213,255,.8)}.text-purple-200\/85{color:rgba(233,213,255,.85)}.text-purple-200\/90{color:rgba(233,213,255,.9)}.text-purple-200\/95{color:rgba(233,213,255,.95)}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-300\/0{color:rgba(216,180,254,0)}.text-purple-300\/10{color:rgba(216,180,254,.1)}.text-purple-300\/100{color:#d8b4fe}.text-purple-300\/15{color:rgba(216,180,254,.15)}.text-purple-300\/20{color:rgba(216,180,254,.2)}.text-purple-300\/25{color:rgba(216,180,254,.25)}.text-purple-300\/30{color:rgba(216,180,254,.3)}.text-purple-300\/35{color:rgba(216,180,254,.35)}.text-purple-300\/40{color:rgba(216,180,254,.4)}.text-purple-300\/45{color:rgba(216,180,254,.45)}.text-purple-300\/5{color:rgba(216,180,254,.05)}.text-purple-300\/50{color:rgba(216,180,254,.5)}.text-purple-300\/55{color:rgba(216,180,254,.55)}.text-purple-300\/60{color:rgba(216,180,254,.6)}.text-purple-300\/65{color:rgba(216,180,254,.65)}.text-purple-300\/70{color:rgba(216,180,254,.7)}.text-purple-300\/75{color:rgba(216,180,254,.75)}.text-purple-300\/80{color:rgba(216,180,254,.8)}.text-purple-300\/85{color:rgba(216,180,254,.85)}.text-purple-300\/90{color:rgba(216,180,254,.9)}.text-purple-300\/95{color:rgba(216,180,254,.95)}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-purple-400\/0{color:rgba(192,132,252,0)}.text-purple-400\/10{color:rgba(192,132,252,.1)}.text-purple-400\/100{color:#c084fc}.text-purple-400\/15{color:rgba(192,132,252,.15)}.text-purple-400\/20{color:rgba(192,132,252,.2)}.text-purple-400\/25{color:rgba(192,132,252,.25)}.text-purple-400\/30{color:rgba(192,132,252,.3)}.text-purple-400\/35{color:rgba(192,132,252,.35)}.text-purple-400\/40{color:rgba(192,132,252,.4)}.text-purple-400\/45{color:rgba(192,132,252,.45)}.text-purple-400\/5{color:rgba(192,132,252,.05)}.text-purple-400\/50{color:rgba(192,132,252,.5)}.text-purple-400\/55{color:rgba(192,132,252,.55)}.text-purple-400\/60{color:rgba(192,132,252,.6)}.text-purple-400\/65{color:rgba(192,132,252,.65)}.text-purple-400\/70{color:rgba(192,132,252,.7)}.text-purple-400\/75{color:rgba(192,132,252,.75)}.text-purple-400\/80{color:rgba(192,132,252,.8)}.text-purple-400\/85{color:rgba(192,132,252,.85)}.text-purple-400\/90{color:rgba(192,132,252,.9)}.text-purple-400\/95{color:rgba(192,132,252,.95)}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-red-200\/0{color:hsla(0,96%,89%,0)}.text-red-200\/10{color:hsla(0,96%,89%,.1)}.text-red-200\/100{color:#fecaca}.text-red-200\/15{color:hsla(0,96%,89%,.15)}.text-red-200\/20{color:hsla(0,96%,89%,.2)}.text-red-200\/25{color:hsla(0,96%,89%,.25)}.text-red-200\/30{color:hsla(0,96%,89%,.3)}.text-red-200\/35{color:hsla(0,96%,89%,.35)}.text-red-200\/40{color:hsla(0,96%,89%,.4)}.text-red-200\/45{color:hsla(0,96%,89%,.45)}.text-red-200\/5{color:hsla(0,96%,89%,.05)}.text-red-200\/50{color:hsla(0,96%,89%,.5)}.text-red-200\/55{color:hsla(0,96%,89%,.55)}.text-red-200\/60{color:hsla(0,96%,89%,.6)}.text-red-200\/65{color:hsla(0,96%,89%,.65)}.text-red-200\/70{color:hsla(0,96%,89%,.7)}.text-red-200\/75{color:hsla(0,96%,89%,.75)}.text-red-200\/80{color:hsla(0,96%,89%,.8)}.text-red-200\/85{color:hsla(0,96%,89%,.85)}.text-red-200\/90{color:hsla(0,96%,89%,.9)}.text-red-200\/95{color:hsla(0,96%,89%,.95)}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-300\/0{color:hsla(0,94%,82%,0)}.text-red-300\/10{color:hsla(0,94%,82%,.1)}.text-red-300\/100{color:#fca5a5}.text-red-300\/15{color:hsla(0,94%,82%,.15)}.text-red-300\/20{color:hsla(0,94%,82%,.2)}.text-red-300\/25{color:hsla(0,94%,82%,.25)}.text-red-300\/30{color:hsla(0,94%,82%,.3)}.text-red-300\/35{color:hsla(0,94%,82%,.35)}.text-red-300\/40{color:hsla(0,94%,82%,.4)}.text-red-300\/45{color:hsla(0,94%,82%,.45)}.text-red-300\/5{color:hsla(0,94%,82%,.05)}.text-red-300\/50{color:hsla(0,94%,82%,.5)}.text-red-300\/55{color:hsla(0,94%,82%,.55)}.text-red-300\/60{color:hsla(0,94%,82%,.6)}.text-red-300\/65{color:hsla(0,94%,82%,.65)}.text-red-300\/70{color:hsla(0,94%,82%,.7)}.text-red-300\/75{color:hsla(0,94%,82%,.75)}.text-red-300\/80{color:hsla(0,94%,82%,.8)}.text-red-300\/85{color:hsla(0,94%,82%,.85)}.text-red-300\/90{color:hsla(0,94%,82%,.9)}.text-red-300\/95{color:hsla(0,94%,82%,.95)}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-red-400\/0{color:hsla(0,91%,71%,0)}.text-red-400\/10{color:hsla(0,91%,71%,.1)}.text-red-400\/100{color:#f87171}.text-red-400\/15{color:hsla(0,91%,71%,.15)}.text-red-400\/20{color:hsla(0,91%,71%,.2)}.text-red-400\/25{color:hsla(0,91%,71%,.25)}.text-red-400\/30{color:hsla(0,91%,71%,.3)}.text-red-400\/35{color:hsla(0,91%,71%,.35)}.text-red-400\/40{color:hsla(0,91%,71%,.4)}.text-red-400\/45{color:hsla(0,91%,71%,.45)}.text-red-400\/5{color:hsla(0,91%,71%,.05)}.text-red-400\/50{color:hsla(0,91%,71%,.5)}.text-red-400\/55{color:hsla(0,91%,71%,.55)}.text-red-400\/60{color:hsla(0,91%,71%,.6)}.text-red-400\/65{color:hsla(0,91%,71%,.65)}.text-red-400\/70{color:hsla(0,91%,71%,.7)}.text-red-400\/75{color:hsla(0,91%,71%,.75)}.text-red-400\/80{color:hsla(0,91%,71%,.8)}.text-red-400\/85{color:hsla(0,91%,71%,.85)}.text-red-400\/90{color:hsla(0,91%,71%,.9)}.text-red-400\/95{color:hsla(0,91%,71%,.95)}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-sky-200{--tw-text-opacity:1;color:rgb(186 230 253/var(--tw-text-opacity,1))}.text-sky-400{--tw-text-opacity:1;color:rgb(56 189 248/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity,1))}.text-yellow-200\/0{color:hsla(53,98%,77%,0)}.text-yellow-200\/10{color:hsla(53,98%,77%,.1)}.text-yellow-200\/100{color:#fef08a}.text-yellow-200\/15{color:hsla(53,98%,77%,.15)}.text-yellow-200\/20{color:hsla(53,98%,77%,.2)}.text-yellow-200\/25{color:hsla(53,98%,77%,.25)}.text-yellow-200\/30{color:hsla(53,98%,77%,.3)}.text-yellow-200\/35{color:hsla(53,98%,77%,.35)}.text-yellow-200\/40{color:hsla(53,98%,77%,.4)}.text-yellow-200\/45{color:hsla(53,98%,77%,.45)}.text-yellow-200\/5{color:hsla(53,98%,77%,.05)}.text-yellow-200\/50{color:hsla(53,98%,77%,.5)}.text-yellow-200\/55{color:hsla(53,98%,77%,.55)}.text-yellow-200\/60{color:hsla(53,98%,77%,.6)}.text-yellow-200\/65{color:hsla(53,98%,77%,.65)}.text-yellow-200\/70{color:hsla(53,98%,77%,.7)}.text-yellow-200\/75{color:hsla(53,98%,77%,.75)}.text-yellow-200\/80{color:hsla(53,98%,77%,.8)}.text-yellow-200\/85{color:hsla(53,98%,77%,.85)}.text-yellow-200\/90{color:hsla(53,98%,77%,.9)}.text-yellow-200\/95{color:hsla(53,98%,77%,.95)}.text-yellow-300{--tw-text-opacity:1;color:rgb(253 224 71/var(--tw-text-opacity,1))}.text-yellow-300\/0{color:rgba(253,224,71,0)}.text-yellow-300\/10{color:rgba(253,224,71,.1)}.text-yellow-300\/100{color:#fde047}.text-yellow-300\/15{color:rgba(253,224,71,.15)}.text-yellow-300\/20{color:rgba(253,224,71,.2)}.text-yellow-300\/25{color:rgba(253,224,71,.25)}.text-yellow-300\/30{color:rgba(253,224,71,.3)}.text-yellow-300\/35{color:rgba(253,224,71,.35)}.text-yellow-300\/40{color:rgba(253,224,71,.4)}.text-yellow-300\/45{color:rgba(253,224,71,.45)}.text-yellow-300\/5{color:rgba(253,224,71,.05)}.text-yellow-300\/50{color:rgba(253,224,71,.5)}.text-yellow-300\/55{color:rgba(253,224,71,.55)}.text-yellow-300\/60{color:rgba(253,224,71,.6)}.text-yellow-300\/65{color:rgba(253,224,71,.65)}.text-yellow-300\/70{color:rgba(253,224,71,.7)}.text-yellow-300\/75{color:rgba(253,224,71,.75)}.text-yellow-300\/80{color:rgba(253,224,71,.8)}.text-yellow-300\/85{color:rgba(253,224,71,.85)}.text-yellow-300\/90{color:rgba(253,224,71,.9)}.text-yellow-300\/95{color:rgba(253,224,71,.95)}.text-yellow-400{--tw-text-opacity:1;color:rgb(250 204 21/var(--tw-text-opacity,1))}.text-yellow-400\/0{color:rgba(250,204,21,0)}.text-yellow-400\/10{color:rgba(250,204,21,.1)}.text-yellow-400\/100{color:#facc15}.text-yellow-400\/15{color:rgba(250,204,21,.15)}.text-yellow-400\/20{color:rgba(250,204,21,.2)}.text-yellow-400\/25{color:rgba(250,204,21,.25)}.text-yellow-400\/30{color:rgba(250,204,21,.3)}.text-yellow-400\/35{color:rgba(250,204,21,.35)}.text-yellow-400\/40{color:rgba(250,204,21,.4)}.text-yellow-400\/45{color:rgba(250,204,21,.45)}.text-yellow-400\/5{color:rgba(250,204,21,.05)}.text-yellow-400\/50{color:rgba(250,204,21,.5)}.text-yellow-400\/55{color:rgba(250,204,21,.55)}.text-yellow-400\/60{color:rgba(250,204,21,.6)}.text-yellow-400\/65{color:rgba(250,204,21,.65)}.text-yellow-400\/70{color:rgba(250,204,21,.7)}.text-yellow-400\/75{color:rgba(250,204,21,.75)}.text-yellow-400\/80{color:rgba(250,204,21,.8)}.text-yellow-400\/85{color:rgba(250,204,21,.85)}.text-yellow-400\/90{color:rgba(250,204,21,.9)}.text-yellow-400\/95{color:rgba(250,204,21,.95)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-gray-600:hover{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity,1))}.hover\:bg-gray-700\/50:hover,.hover\:bg-gray-700\/\[\.5\]:hover{background-color:rgba(55,65,81,.5)}.hover\:bg-red-700:hover{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\:text-green-400:hover{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.disabled\:bg-gray-500:disabled{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.disabled\:opacity-60:disabled{opacity:.6} \ No newline at end of file diff --git a/public/index.html b/public/index.html index b958a5b..1f654af 100644 --- a/public/index.html +++ b/public/index.html @@ -9,677 +9,16 @@ window.WS_HOST = '{{ws_host}}'; window.WS_PORT = '{{ws_port}}'; - + - + +
- -
-

PHPUnit Hub

-
-
- -
-
-

Filters & Settings

- -
- -
- - -
- -
- - -
- - - -
- -
- - -
-
- -
- -
- - - - - - -
-
- -
- -
- - - - - -
-
- -
- -
- -
-
-
-
- - - - - - -
-
- - -
- - - - -
- - -
- - -
-
- -
-
-
-
Total Tests
-
{{ results?.summary.tests ?? 0 }}
-
-
-
Total Assertions
-
{{ results?.summary.assertions ?? 0 }}
-
-
-
Duration
-
{{ formatNanoseconds(results?.summary.time) }}
-
-
-
- - - {{ statusCounts.passed }} Passed - - - - {{ results?.summary.failures }} Failed - - - - {{ results?.summary.errors }} Errors - - - - {{ results?.summary.warnings }} Warnings - - - - {{ results?.summary.skipped }} Skipped - - - - {{ results?.summary.deprecations }} Deprecations - - - - {{ results?.summary.notices }} Notices - - - - {{ results?.summary.incomplete }} Incomplete - - - - {{ results?.summary.risky }} Risky - -
-
- - -
- Run tests to see the results. -
- - -
- -
-
-
- - - - - - -
-
-
-
-
-
Generating coverage report...
-
-
-
- No coverage driver (Xdebug, pcov) is enabled. -
-
- Run tests with coverage enabled to see the report. -
-
-
-
- -

{{ store.state.fileCoverage.path }}

-
{{ line.number }}{{ token.value }}
-
-
-
-
-
-
Total Coverage
-
{{ store.state.coverageReport.total_coverage_percent.toFixed(2) }}%
-
-
-
-
-
File
-
Coverage
-
-
-
-
-
{{ file.path }}
-
- {{ file.coverage_percent.toFixed(2) }}% -
-
-
-
-
-
-
-
-
-
+
- - + + \ No newline at end of file diff --git a/public/js/api.js b/public/js/api.js deleted file mode 100644 index b372746..0000000 --- a/public/js/api.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * API client for PHPUnit Hub - */ - -export class ApiClient { - constructor(baseUrl = '') { - this.baseUrl = baseUrl; - } - - /** - * Fetch available tests - */ - async fetchTests() { - try { - const response = await fetch(`${this.baseUrl}/api/tests`); - return await response.json(); - } catch (error) { - console.error('Failed to fetch tests:', error); - throw error; - } - } - - /** - * Run tests with specified options - */ - async runTests(payload) { - try { - const response = await fetch(`${this.baseUrl}/api/run`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(payload) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to run tests'); - } - - return await response.json(); - } catch (error) { - console.error('Failed to run tests:', error); - throw error; - } - } - - /** - * Stop all tests - */ - async stopAllTests() { - try { - const response = await fetch(`${this.baseUrl}/api/stop`, { - method: 'POST' - }); - - if (!response.ok) { - throw new Error('Failed to stop tests'); - } - } catch (error) { - console.error('Failed to stop tests:', error); - throw error; - } - } - - /** - * Stop a single test run - */ - async stopSingleTest(runId) { - try { - const response = await fetch(`${this.baseUrl}/api/stop-single-test/${runId}`, { - method: 'POST' - }); - - if (!response.ok) { - throw new Error(`Failed to stop test run ${runId}`); - } - } catch (error) { - console.error(`Failed to stop test run ${runId}:`, error); - throw error; - } - } - - /** - * Fetch coverage report - */ - async fetchCoverage(runId) { - try { - const response = await fetch(`${this.baseUrl}/api/coverage/${runId}`); - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to fetch coverage report'); - } - return await response.json(); - } catch (error) { - console.error('Failed to fetch coverage report:', error); - throw error; - } - } - - /** - * Fetch file coverage - */ - async fetchFileCoverage(runId, filePath) { - try { - const response = await fetch(`${this.baseUrl}/api/file-coverage?runId=${runId}&path=${encodeURIComponent(filePath)}`); - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to fetch file coverage'); - } - return await response.json(); - } catch (error) { - console.error('Failed to fetch file coverage:', error); - throw error; - } - } - - /** - * Fetch file content - */ - async fetchFileContent(filePath) { - try { - const response = await fetch(`${this.baseUrl}/api/file-content?path=${encodeURIComponent(filePath)}`); - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to fetch file content'); - } - return await response.text(); - } catch (error) { - console.error('Failed to fetch file content:', error); - throw error; - } - } -} diff --git a/public/js/app.js b/public/js/app.js deleted file mode 100644 index 9091d34..0000000 --- a/public/js/app.js +++ /dev/null @@ -1,667 +0,0 @@ -/** - * Main Application Logic for PHPUnit Hub - */ - -import {computed} from 'https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.prod.js'; -import {Store} from './store.js'; -import {ApiClient} from './api.js'; -import {WebSocketManager} from './websocket.js'; -import {updateFavicon} from './utils.js'; - -export class App { - constructor() { - this.store = new Store(); - this.api = new ApiClient(''); - this.wsManager = null; - this.testIndex = {}; - } - - /** - * Initialize the app - */ - async initialize() { - try { - // Fetch tests - await this.fetchTests(); - - // Connect WebSocket - const wsHost = window.WS_HOST || '127.0.0.1'; - const wsPort = window.WS_PORT || '8080'; - this.wsManager = new WebSocketManager(`ws://${wsHost}:${wsPort}/ws/status`, this.store, this); - await this.wsManager.connect(); - - // Setup resizer - this.setupResizer(); - - // Update favicon - updateFavicon('neutral'); - } catch (error) { - console.error('Failed to initialize app:', error); - } - } - - /** - * Fetch available tests - */ - async fetchTests() { - this.store.state.isLoading = true; - try { - const data = await this.api.fetchTests(); - this.store.state.testSuites = data.suites; - this.store.state.availableSuites = data.availableSuites || []; - this.store.state.availableGroups = data.availableGroups || []; - this.store.state.coverageDriverMissing = !data.coverageDriver; - - // Build test index - this.buildTestIndex(); - } catch (error) { - console.error('Failed to fetch tests:', error); - throw error; // Re-throw the error - } finally { - this.store.state.isLoading = false; - } - } - - /** - * Build test index for quick lookup - */ - buildTestIndex() { - this.testIndex = {}; - this.store.state.testSuites.forEach(suite => { - if (suite.methods) { - suite.methods.forEach(method => { - this.testIndex[method.id] = { - suite, - method - }; - }); - } - }); - } - - /** - * Internal method to run tests. - * Use runTests for public API. - * @private - */ - async _runTests(runOptions = {}) { - this.store.setStarting(true); - this.store.state.activeTab = 'results'; - - // Filter out frontend-only options that PHPUnit doesn't understand - const { displayMode, ...phpunitOptions } = this.store.state.options; - - const payload = { - filters: runOptions.filters || [], - groups: this.store.state.selectedGroups, - suites: this.store.state.selectedSuites, - options: { ...phpunitOptions, colors: true }, - coverage: !!this.store.state.coverage, - contextId: runOptions.contextId || 'global', - }; - - try { - await this.api.runTests(payload); - } catch (error) { - console.error('Failed to run tests:', error); - updateFavicon('failure'); - } finally { - this.store.setStarting(false); - } - } - - /** - * Run tests with options. This is the main entry point for running tests. - */ - runTests(runOptions = {}) { - this._runTests(runOptions); - } - - /** - * Run all tests - */ - runAllTests() { - this.runTests({ contextId: 'global' }); - } - - /** - * Run failed tests - */ - runFailedTests() { - const failedTestIds = this.store.getFailedTestIds(); - if (failedTestIds.length === 0) { - console.log('No failed tests to run.'); - return; - } - this.runTests({ filters: failedTestIds, contextId: 'failed' }); - } - - /** - * Run single test - */ - runSingleTest(testId) { - this.runTests({ filters: [testId], contextId: testId }); - } - - /** - * Run suite tests - */ - runSuiteTests(suiteId) { - this.runTests({ filters: [suiteId], contextId: suiteId }); - } - - /** - * Stop all tests - */ - async stopAllTests() { - try { - Object.keys(this.store.state.runningTestIds).forEach(runId => { - this.store.markStopPending(runId); - }); - await this.api.stopAllTests(); - } catch (error) { - console.error('Failed to stop tests:', error); - Object.keys(this.store.state.runningTestIds).forEach(runId => { - this.store.clearStopPending(runId); - }); - } - } - - /** - * Stop single test - */ - async stopSingleTest(runId) { - try { - this.store.markStopPending(runId); - await this.api.stopSingleTest(runId); - } catch (error) { - console.error(`Failed to stop test run ${runId}:`, error); - this.store.clearStopPending(runId); - } - } - - /** - * Toggle play/stop state - */ - togglePlayStop() { - if (Object.keys(this.store.state.runningTestIds).length > 0) { - this.stopAllTests(); - } else { - this.runAllTests(); - } - } - - /** - * Setup sidebar resizer - */ - setupResizer() { - const resizer = document.getElementById('resizer'); - const sidebar = document.getElementById('test-sidebar'); - - if (!resizer || !sidebar) return; - - let isResizing = false; - - resizer.addEventListener('mousedown', (e) => { - e.preventDefault(); - isResizing = true; - document.body.style.cursor = 'col-resize'; - document.body.style.userSelect = 'none'; - - const mouseMoveHandler = (e) => { - if (!isResizing) return; - const sidebarWidth = e.clientX; - if (sidebarWidth > 200 && sidebarWidth < window.innerWidth - 200) { - sidebar.style.width = `${sidebarWidth}px`; - } - }; - - const mouseUpHandler = () => { - isResizing = false; - document.body.style.cursor = ''; - document.body.style.userSelect = ''; - document.removeEventListener('mousemove', mouseMoveHandler); - document.removeEventListener('mouseup', mouseUpHandler); - }; - - document.addEventListener('mousemove', mouseMoveHandler); - document.addEventListener('mouseup', mouseUpHandler); - }); - } - - /** - * Get computed values for Vue - */ - getComputedValues() { - return { - isAnyTestRunning: computed(() => { - if (this.store.state.isStarting) return true; - // Check if there are any tests running - const runningCount = Object.keys(this.store.state.runningTestIds).length; - if (runningCount === 0) return false; - - // Check if any running test hasn't received execution.ended yet - for (const runId in this.store.state.runningTestIds) { - const run = this.store.state.realtimeTestRuns[runId]; - if (!run || !run.executionEnded) { - return true; - } - } - - return false; - }), - isAnyStopPending: computed(() => Object.keys(this.store.state.stopPending).length > 0), - hasFailedTests: computed(() => this.store.hasFailedTests()), - results: computed(() => this.getResults()), - groupedResults: computed(() => this.getGroupedResults()), - individualResults: computed(() => this.getIndividualResults()), - statusCounts: computed(() => this.getStatusCounts()), - filteredTestSuites: computed(() => this.getFilteredTestSuites()), - }; - } - - /** - * Get results from current test run (always reset mode) - */ - getResults() { - const runs = this.store.state.realtimeTestRuns; - const runIds = Object.keys(runs); - - if (runIds.length === 0) { - return null; - } - - // Always show only the last completed run - let runId = this.store.state.lastCompletedRunId; - if (!runId) { - runId = runIds[runIds.length - 1]; - } - return this.getSingleRunResults(runs[runId]); - } - - /** - * Calculate summary statistics from test data in real-time - */ - calculateRealtimeSummary(run) { - const summary = { - tests: 0, - assertions: 0, - failures: 0, - errors: 0, - warnings: 0, - skipped: 0, - deprecations: 0, - incomplete: 0, - risky: 0, - notices: 0, - }; - - if (!run || !run.suites) return summary; - - for (const suiteName in run.suites) { - for (const testId in run.suites[suiteName].tests) { - const testData = run.suites[suiteName].tests[testId]; - summary.tests++; - summary.assertions += testData.assertions || 0; - summary.warnings += testData.warnings?.length || 0; - summary.deprecations += testData.deprecations?.length || 0; - summary.notices += testData.notices?.length || 0; - - switch (testData.status) { - case 'failed': summary.failures++; break; - case 'errored': summary.errors++; break; - case 'skipped': summary.skipped++; break; - case 'incomplete': summary.incomplete++; break; - case 'risky': summary.risky++; break; - } - } - } - return summary; - } - - /** - * Get results from a single run - */ - getSingleRunResults(run) { - if (!run) return null; - - const defaultSummary = { - numberOfTests: 0, - numberOfAssertions: 0, - duration: 0, - numberOfFailures: 0, - numberOfErrors: 0, - numberOfWarnings: 0, - numberOfSkipped: 0, - numberOfDeprecations: 0, - numberOfIncomplete: 0, - numberOfRisky: 0, - numberOfNotices: 0, - }; - const summary = { ...defaultSummary, ...(run.summary || {}) }; - - // If the run is in progress, calculate totals in real-time - // We check for `!run.summary` because the final summary from PHPUnit is the source of truth. - // We only calculate in real-time if that final summary hasn't arrived yet. - if (run && !run.summary) { - const realtimeSummary = this.calculateRealtimeSummary(run); - summary.numberOfTests = realtimeSummary.tests; - summary.numberOfAssertions = realtimeSummary.assertions; - summary.numberOfFailures = realtimeSummary.failures; - summary.numberOfErrors = realtimeSummary.errors; - summary.numberOfWarnings = realtimeSummary.warnings; - summary.numberOfSkipped = realtimeSummary.skipped; - summary.numberOfDeprecations = realtimeSummary.deprecations; - summary.numberOfIncomplete = realtimeSummary.incomplete; - summary.numberOfRisky = realtimeSummary.risky; - summary.numberOfNotices = realtimeSummary.notices; - } - - // Transform suites data - const transformedSuites = []; - for (const suiteName in run.suites) { - const suiteData = run.suites[suiteName]; - const testcases = []; - for (const testId in suiteData.tests) { - const testData = suiteData.tests[testId]; - testcases.push({ - name: testData.name, - class: testData.class, - id: testData.id, - duration: testData.duration || 0, - assertions: testData.assertions || 0, - status: testData.status, - message: testData.message, - trace: testData.trace, - warnings: testData.warnings || [], - deprecations: testData.deprecations || [], - notices: testData.notices || [], - }); - } - transformedSuites.push({ - name: suiteData.name, - testcases, - }); - } - - return { - summary: { - tests: summary.numberOfTests, - assertions: summary.numberOfAssertions, - time: run.sumOfDurations > 0 ? run.sumOfDurations : summary.duration, - failures: summary.numberOfFailures, - errors: summary.numberOfErrors, - warnings: summary.numberOfWarnings, - skipped: summary.numberOfSkipped, - deprecations: summary.numberOfDeprecations, - incomplete: summary.numberOfIncomplete, - risky: summary.numberOfRisky, - notices: summary.numberOfNotices, - }, - suites: transformedSuites, - }; - } - - /** - * Calculate summary statistics from test data - */ - calculateSummaryFromTests(suites) { - const summary = { - tests: 0, - assertions: 0, - time: 0, - failures: 0, - errors: 0, - warnings: 0, - skipped: 0, - deprecations: 0, - incomplete: 0, - risky: 0, - notices: 0, - }; - - suites.forEach(suite => { - suite.testcases.forEach(tc => { - summary.tests++; - summary.time += tc.duration || 0; - summary.assertions += tc.assertions || 0; - - if (tc.status === 'failed') summary.failures++; - else if (tc.status === 'errored') summary.errors++; - else if (tc.status === 'skipped') summary.skipped++; - else if (tc.status === 'incomplete') summary.incomplete++; - else if (tc.status === 'risky') summary.risky++; - - summary.warnings += tc.warnings?.length || 0; - summary.deprecations += tc.deprecations?.length || 0; - summary.notices += tc.notices?.length || 0; - }); - }); - - return summary; - } - - /** - * Get grouped results - */ - getGroupedResults() { - const results = this.getResults(); - if (!results) return []; - - const groups = {}; - results.suites.forEach(suite => { - suite.testcases.forEach(tc => { - if (!groups[tc.class]) { - groups[tc.class] = { - className: tc.class, - testcases: [], - passed: 0, - failed: 0, - errored: 0, - skipped: 0, - warning: 0, - deprecation: 0, - incomplete: 0, - risky: 0, - notice: 0, - hasIssues: false - }; - } - - const group = groups[tc.class]; - group.testcases.push(tc); - const status = tc.status || 'passed'; - if (group[status] !== undefined) { - group[status]++; - } - - // Count warnings and deprecations - if (tc.warnings?.length > 0) { - group.warning += tc.warnings.length; - } - if (tc.deprecations?.length > 0) { - group.deprecation += tc.deprecations.length; - } - if (tc.notices?.length > 0) { - group.notice += tc.notices.length; - } - - // Set hasIssues if any issues are present (warnings array, deprecations array, or non-passed status) - if (tc.warnings?.length > 0 || tc.deprecations?.length > 0 || tc.notices?.length > 0 || status !== 'passed') { - group.hasIssues = true; - } - }); - }); - - const statusOrder = { 'errored': 1, 'failed': 2, 'incomplete': 3, 'risky': 4, 'skipped': 5, 'warning': 6, 'deprecation': 7, 'notice': 8, 'passed': 9 }; - - // Determine suite status - Object.values(groups).forEach(group => { - let highestPriorityStatus = statusOrder['passed']; // Start with the lowest priority - group.testcases.forEach(tc => { - const tcStatus = tc.status || 'passed'; - const priority = statusOrder[tcStatus]; - if (priority && priority < highestPriorityStatus) { - highestPriorityStatus = priority; - } - }); - group.suiteStatus = highestPriorityStatus; - }); - - const sortedGroups = Object.values(groups).sort((a, b) => { - if (a.suiteStatus !== b.suiteStatus) { - return a.suiteStatus - b.suiteStatus; - } - return a.className.localeCompare(b.className); - }); - - sortedGroups.forEach(group => { - group.testcases.sort((a, b) => { - const durationA = a.duration || 0; - const durationB = b.duration || 0; - if (this.store.state.sortBy === 'duration') { - if (durationA !== durationB) { - return this.store.state.sortDirection === 'asc' ? durationA - durationB : durationB - durationA; - } - } - - const statusA = statusOrder[a.status || 'passed'] || 99; - const statusB = statusOrder[b.status || 'passed'] || 99; - if (statusA !== statusB) { - return statusA - statusB; - } - return durationB - durationA; - }); - }); - - return sortedGroups; - } - - /** - * Get individual results, sorted by time - */ - getIndividualResults() { - const results = this.getResults(); - if (!results) return []; - - let allTests = []; - results.suites.forEach(suite => { - allTests.push(...suite.testcases); - }); - - // Filter based on options - allTests = allTests.filter(t => { - if (t.status === 'skipped' && !this.store.state.options.displaySkipped) return false; - if (t.status === 'incomplete' && !this.store.state.options.displayIncomplete) return false; - if (t.status === 'risky' && !this.store.state.options.displayRisky) return false; - if (t.warnings?.length > 0 && !this.store.state.options.displayWarnings) { - // if it's just a warning and we hide them, don't show if it passed - if (t.status === 'passed') return false; - } - if (t.deprecations?.length > 0 && !this.store.state.options.displayDeprecations) { - if (t.status === 'passed') return false; - } - if (t.notices?.length > 0 && !this.store.state.options.displayNotices) { - if (t.status === 'passed') return false; - } - return true; - }); - - // Sort by duration, descending - allTests.sort((a, b) => { - const durationA = a.duration || 0; - const durationB = b.duration || 0; - - if (this.store.state.sortBy === 'duration') { - return this.store.state.sortDirection === 'asc' ? durationA - durationB : durationB - durationA; - } - - const statusOrder = { 'errored': 1, 'failed': 2, 'incomplete': 3, 'risky': 4, 'skipped': 5, 'warning': 6, 'deprecation': 7, 'notice': 8, 'passed': 9 }; - const statusA = statusOrder[a.status || 'passed'] || 99; - const statusB = statusOrder[b.status || 'passed'] || 99; - if (statusA !== statusB) { - return statusA - statusB; - } - - return durationB - durationA; // Default to duration descending if statuses are equal - }); - - return allTests; - } - - /** - * Get status counts - */ - getStatusCounts() { - const results = this.getResults(); - - if (!results) { - return { passed: 0, failed: 0, error: 0, warnings: 0, skipped: 0, deprecations: 0, incomplete: 0, risky: 0, notices: 0 }; - } - - const s = results.summary; - const counts = { - passed: 0, - failed: s.failures || 0, - error: s.errors || 0, - warnings: s.warnings || 0, - skipped: s.skipped || 0, - deprecations: s.deprecations || 0, - incomplete: s.incomplete || 0, - risky: s.risky || 0, - notices: s.notices || 0, - }; - - // Only subtract actual failures (failed, error, skipped, incomplete) from total - // Warnings and deprecations don't prevent a test from being "passed" - const actualFailures = counts.failed + counts.error + counts.skipped + counts.incomplete + counts.risky; - counts.passed = (s.tests || 0) - actualFailures; - - return counts; - } - - /** - * Get filtered test suites based on search query - */ - getFilteredTestSuites() { - const query = this.store.state.searchQuery; - if (!query) return this.store.state.testSuites; - - const lower = query.toLowerCase(); - return this.store.state.testSuites.map(suite => { - const methods = suite.methods.filter(m => m.name.toLowerCase().includes(lower)); - if (suite.name.toLowerCase().includes(lower)) { - return { ...suite, methods: suite.methods }; - } - if (methods.length > 0) { - return { ...suite, methods }; - } - return null; - }).filter(Boolean); - } - - async fetchCoverageReport(runId) { - try { - const report = await this.api.fetchCoverage(runId); - this.store.setCoverageReport(report); - } catch (error) { - console.error('Failed to fetch coverage report:', error); - } finally { - this.store.setCoverageLoading(false); - } - } - - async showFileCoverage(filePath) { - try { - const runId = this.store.state.lastCompletedRunId; - if (!runId) { - console.error('No completed run ID found for file coverage.'); - return; - } - const coverage = await this.api.fetchFileCoverage(runId, filePath); - this.store.setFileCoverage({ ...coverage, path: filePath }); - } catch (error) { - console.error('Failed to fetch file coverage:', error); - } - } -} \ No newline at end of file diff --git a/public/js/store.js b/public/js/store.js deleted file mode 100644 index d5bfa27..0000000 --- a/public/js/store.js +++ /dev/null @@ -1,566 +0,0 @@ -/** - * Store/State management for PHPUnit Hub - */ - -import { reactive } from 'https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.prod.js'; -import {parseTestId, updateFavicon} from './utils.js'; - -const STORAGE_KEY = 'phpunit-hub-settings'; - -export class Store { - static defaultOptions = { - displayWarnings: true, - displayDeprecations: true, - displaySkipped: true, - displayIncomplete: true, - displayRisky: true, - displayNotices: true, - stopOnDefect: false, - stopOnError: false, - stopOnFailure: false, - stopOnWarning: false, - stopOnRisky: false, - displayMode: 'default', // 'default' or 'individual' - }; - - constructor() { - this.state = reactive({ - // Test suites - testSuites: [], - availableSuites: [], - availableGroups: [], - - // UI state - isLoading: false, - isStarting: false, - searchQuery: '', - expandedSuites: new Set(), - expandedTestcaseGroups: new Set(), - expandedTestId: null, - showFilterPanel: false, - activeTab: 'results', - sortBy: 'default', // 'default' or 'duration' - sortDirection: 'desc', // 'asc' or 'desc' - - // Filter options - selectedSuites: [], - selectedGroups: [], - options: { ...Store.defaultOptions }, - coverage: false, - - // Test runs - runningTestIds: {}, - stopPending: {}, - realtimeTestRuns: {}, - lastCompletedRunId: null, - - // Coverage - coverageReport: null, - isCoverageLoading: false, - fileCoverage: null, - coverageDriverMissing: false, - }); - - this.loadState(); - } - - /** - * Load state from localStorage - */ - loadState() { - const savedState = localStorage.getItem(STORAGE_KEY); - if (savedState) { - try { - const parsedState = JSON.parse(savedState); - if (parsedState.options) { - // Ensure resultUpdateMode is not loaded from old state - const { resultUpdateMode, ...restOptions } = parsedState.options; - this.state.options = { ...this.state.options, ...restOptions }; - } - if (Array.isArray(parsedState.selectedSuites)) { - this.state.selectedSuites = parsedState.selectedSuites; - } - if (Array.isArray(parsedState.selectedGroups)) { - this.state.selectedGroups = parsedState.selectedGroups; - } - if(parsedState.coverage) { - this.state.coverage = parsedState.coverage; - } - } catch (e) { - console.error('Failed to load state from localStorage', e); - localStorage.removeItem(STORAGE_KEY); - } - } - } - - /** - * Save state to localStorage - */ - saveState() { - const stateToSave = { - options: this.state.options, - selectedSuites: this.state.selectedSuites, - selectedGroups: this.state.selectedGroups, - coverage: this.state.coverage, - }; - localStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave)); - } - - setSortBy(sortBy) { - if (this.state.sortBy === sortBy) { - if (this.state.sortDirection === 'desc') { - this.state.sortDirection = 'asc'; - } else { - this.state.sortBy = 'default'; - this.state.sortDirection = 'desc'; - } - } else { - this.state.sortBy = sortBy; - this.state.sortDirection = 'desc'; - } - } - - setDisplayMode(mode) { - this.state.options.displayMode = mode; - } - - setStarting(isStarting) { - this.state.isStarting = isStarting; - } - - /** - * Initialize a new test run - */ - initializeTestRun(runId, contextId) { - this.state.isStarting = false; - // Always reset for 'global' runs or for 'failed' runs (to show only re-run tests) - const shouldReset = contextId === 'global' || contextId === 'failed'; - - this.state.realtimeTestRuns[runId] = { - status: 'running', - contextId, - suites: {}, - summary: null, - failedTestIds: new Set(), - executionEnded: false, - sumOfDurations: 0, - }; - this.state.runningTestIds[runId] = true; - delete this.state.stopPending[runId]; - - // Clear previous results in reset mode or for failed test runs - if (shouldReset) { - this.state.realtimeTestRuns = { [runId]: this.state.realtimeTestRuns[runId] }; - this.state.lastCompletedRunId = null; - this.state.expandedTestId = null; - this.state.expandedTestcaseGroups = new Set(); - this.resetSidebarTestStatuses(); - } - - // Assign runId to suite if this is a suite-level run - this.state.testSuites.forEach(suite => { - if (suite.id === contextId) { - suite.runId = runId; - } - }); - - this.state.activeTab = 'results'; - } - - /** - * Handle incoming test event - */ - handleTestEvent(runId, eventData) { - const run = this.state.realtimeTestRuns[runId]; - - if (!run) { - console.warn(`Received event for unknown runId: ${runId}`); - return; - } - - switch (eventData.event) { - case 'suite.started': - this.handleSuiteStarted(run, eventData); - break; - case 'test.prepared': - this.handleTestPrepared(run, eventData, runId); - break; - case 'test.warning': - case 'test.deprecation': - this.handleTestWarningOrDeprecation(run, eventData); - break; - case 'test.notice': - this.handleTestNotice(run, eventData); - break; - case 'test.passed': - case 'test.failed': - case 'test.errored': - case 'test.skipped': - case 'test.incomplete': - case 'test.risky': - this.handleTestCompleted(run, eventData, runId); - break; - case 'test.finished': - this.handleTestFinished(run, eventData, runId); - break; - case 'execution.ended': - this.handleExecutionEnded(run, eventData, runId); - break; - } - } - - /** - * Handle suite.started event - */ - handleSuiteStarted(run, eventData) { - run.suites[eventData.data.name] = { - name: eventData.data.name, - count: eventData.data.count, - tests: {}, - passed: 0, - failed: 0, - errored: 0, - skipped: 0, - incomplete: 0, - warning: 0, - deprecation: 0, - notice: 0, - risky: 0, - hasIssues: false, - }; - } - - /** - * Handle test.prepared event - */ - handleTestPrepared(run, eventData, runId) { - const { suiteName, testName } = parseTestId(eventData.data.testId); - - if (!run.suites[suiteName]) { - run.suites[suiteName] = { - name: suiteName, - count: 0, - tests: {}, - passed: 0, - failed: 0, - errored: 0, - skipped: 0, - incomplete: 0, - warning: 0, - deprecation: 0, - notice: 0, - risky: 0, - hasIssues: false, - }; - } - - run.suites[suiteName].tests[eventData.data.testId] = { - id: eventData.data.testId, - name: testName, - class: suiteName, - status: 'running', - duration: null, - assertions: 0, - message: null, - trace: null, - warnings: [], - deprecations: [], - notices: [], - }; - - // Update sidebar - this.updateSidebarTestStatus(suiteName, eventData.data.testId, 'running', null, runId); - } - - /** - * Handle test warning/deprecation event - */ - handleTestWarningOrDeprecation(run, eventData) { - const { suiteName } = parseTestId(eventData.data.testId); - const testId = eventData.data.testId; - - if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { - const test = run.suites[suiteName].tests[testId]; - const suite = run.suites[suiteName]; - - if (eventData.event === 'test.warning') { - test.warnings.push(eventData.data.message || 'Warning triggered'); - suite.warning++; - } else if (eventData.event === 'test.deprecation') { - test.deprecations.push(eventData.data.message || 'Deprecation triggered'); - suite.deprecation++; - } - - suite.hasIssues = true; - } - } - - handleTestNotice(run, eventData) { - const { suiteName } = parseTestId(eventData.data.testId); - const testId = eventData.data.testId; - - if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { - const test = run.suites[suiteName].tests[testId]; - const suite = run.suites[suiteName]; - - test.notices.push(eventData.data.message || 'Notice triggered'); - suite.notice++; - suite.hasIssues = true; - } - } - - /** - * Handle test completion event - */ - handleTestCompleted(run, eventData, runId) { - const { suiteName, testName } = parseTestId(eventData.data.testId); - const testId = eventData.data.testId; - - if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { - const test = run.suites[suiteName].tests[testId]; - const status = eventData.event.replace('test.', ''); - - test.status = status; - test.message = eventData.data.message || null; - test.trace = eventData.data.trace || null; - - // Update suite counts - const suite = run.suites[suiteName]; - if (suite[status] !== undefined) { - suite[status]++; - } - - // Track failed tests - if (status === 'failed' || status === 'errored') { - run.failedTestIds.add(testId); - suite.hasIssues = true; - } else if (status === 'passed') { - // Remove from current run - run.failedTestIds.delete(testId); - } else if (status !== 'passed') { - suite.hasIssues = true; - } - - // Update sidebar - this.updateSidebarTestStatus(suiteName, testId, status, test.duration, runId); - } - } - - handleTestFinished(run, eventData, runId) { - const { suiteName } = parseTestId(eventData.data.testId); - const testId = eventData.data.testId; - - if (run.suites[suiteName] && run.suites[suiteName].tests[testId]) { - const test = run.suites[suiteName].tests[testId]; - test.duration = eventData.data.duration; - test.assertions = eventData.data.assertions; - run.sumOfDurations += test.duration; - - // Also update the sidebar with the final duration. - // The status might have already been set by handleTestCompleted. - if (test.status) { - this.updateSidebarTestStatus(suiteName, testId, test.status, test.duration, runId); - } - } - } - - /** - * Handle execution.ended event - */ - handleExecutionEnded(run, eventData, runId) { - run.summary = eventData.data.summary; - run.executionEnded = true; - run.status = 'finished'; - this.state.lastCompletedRunId = runId; - delete this.state.runningTestIds[runId]; - delete this.state.stopPending[runId]; - this.state.isStarting = false; - this.updateSidebarAfterRun(runId); - updateFavicon(run.summary.status === 'passed' ? 'success' : 'failure'); - } - - /** - * Update sidebar test status - */ - updateSidebarTestStatus(suiteName, testId, status, time = null, runId = null) { - this.state.testSuites.forEach(suite => { - if (suite.id === suiteName) { - suite.methods?.forEach(method => { - if (method.id === testId) { - method.status = status; - if (time !== null) method.duration = time; - if (runId) method.runId = runId; - if (status !== 'running') { - method.runId = null; - } - } - }); - } - }); - } - - /** - * Reset all sidebar test statuses - */ - resetSidebarTestStatuses() { - this.state.testSuites.forEach(suite => { - suite.methods?.forEach(method => { - method.status = null; - method.duration = null; - method.runId = null; - }); - }); - } - - /** - * Stop a test run - */ - stopTestRun(runId) { - const run = this.state.realtimeTestRuns[runId]; - if (run) { - run.status = 'stopped'; - } - delete this.state.runningTestIds[runId]; - delete this.state.stopPending[runId]; - this.state.isStarting = false; - this.updateSidebarAfterRun(runId); - } - - /** - * Update sidebar after run completion - */ - updateSidebarAfterRun(runId) { - this.state.testSuites.forEach(suite => { - if (suite.runId === runId) suite.runId = null; - suite.methods?.forEach(method => { - if (method.runId === runId) method.runId = null; - }); - }); - } - - /** - * Get a specific test run - */ - getTestRun(runId) { - return this.state.realtimeTestRuns[runId]; - } - - /** - * Get count of running tests - */ - getRunningTestCount() { - return Object.keys(this.state.runningTestIds).length; - } - - /** - * Clear all running tests - */ - clearRunningTests() { - this.state.runningTestIds = {}; - this.state.stopPending = {}; - } - - /** - * Mark a test run as pending stop - */ - markStopPending(runId) { - this.state.stopPending[runId] = true; - } - - /** - * Clear stop pending status - */ - clearStopPending(runId) { - delete this.state.stopPending[runId]; - } - - /** - * Toggle suite expansion - */ - toggleSuiteExpansion(suiteId) { - if (this.state.expandedSuites.has(suiteId)) { - this.state.expandedSuites.delete(suiteId); - } else { - this.state.expandedSuites.add(suiteId); - } - } - - /** - * Toggle testcase group expansion - */ - toggleTestcaseGroupExpansion(className) { - if (this.state.expandedTestcaseGroups.has(className)) { - this.state.expandedTestcaseGroups.delete(className); - } else { - this.state.expandedTestcaseGroups.add(className); - } - } - - /** - * Set expanded test details - */ - setExpandedTest(testId) { - this.state.expandedTestId = testId; - } - - /** - * Toggle filter panel visibility - */ - toggleFilterPanel() { - this.state.showFilterPanel = !this.state.showFilterPanel; - } - - /** - * Get failed test IDs from last run - */ - getFailedTestIds() { - const run = this.state.realtimeTestRuns[this.state.lastCompletedRunId]; - return run ? Array.from(run.failedTestIds) : []; - } - - /** - * Check if there are failed tests - */ - hasFailedTests() { - const run = this.state.realtimeTestRuns[this.state.lastCompletedRunId]; - return run ? run.failedTestIds.size > 0 : false; - } - - /** - * Clear all test results manually - */ - clearAllResults() { - this.state.realtimeTestRuns = {}; - this.state.lastCompletedRunId = null; - this.state.expandedTestId = null; - this.state.expandedTestcaseGroups = new Set(); - this.resetSidebarTestStatuses(); - updateFavicon('neutral'); - } - - /** - * Clear all filters - */ - clearFilters() { - this.state.selectedSuites = []; - this.state.selectedGroups = []; - this.state.coverage = false; - this.state.options = { ...Store.defaultOptions }; - } - -setActiveTab(tab) { - this.state.activeTab = tab; - } - - setCoverageReport(report) { - this.state.coverageReport = report; - } - - setCoverageLoading(isLoading) { - this.state.isCoverageLoading = isLoading; - } - - setFileCoverage(coverage) { - this.state.fileCoverage = coverage; - } -} diff --git a/public/js/tests/api.test.js b/public/js/tests/api.test.js deleted file mode 100644 index a8aa3ba..0000000 --- a/public/js/tests/api.test.js +++ /dev/null @@ -1,155 +0,0 @@ -// Mock the global fetch function -const mockFetch = jest.fn(); -global.fetch = mockFetch; - -import { ApiClient } from '../api.js'; - -describe('ApiClient', () => { - let api; - const baseUrl = 'http://localhost:8000'; - - beforeEach(() => { - api = new ApiClient(baseUrl); - mockFetch.mockClear(); - jest.spyOn(console, 'error').mockImplementation(() => {}); // Suppress console.error during tests - }); - - afterEach(() => { - jest.restoreAllMocks(); // Restore console.error - }); - - describe('fetchTests', () => { - test('should fetch tests successfully', async () => { - const mockResponseData = { suites: [], availableSuites: [], availableGroups: [] }; - mockFetch.mockResolvedValueOnce({ - ok: true, - json: () => Promise.resolve(mockResponseData), - }); - - const result = await api.fetchTests(); - - expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/tests`); - expect(result).toEqual(mockResponseData); - }); - - test('should throw an error if fetch fails', async () => { - const error = new Error('Network error'); - mockFetch.mockRejectedValueOnce(error); - - await expect(api.fetchTests()).rejects.toThrow('Network error'); - expect(console.error).toHaveBeenCalledWith('Failed to fetch tests:', error); - }); - }); - - describe('runTests', () => { - const payload = { filters: ['test1'], groups: [], suites: [], options: {} }; - - test('should run tests successfully', async () => { - const mockResponseData = { status: 'running', runId: '123' }; - mockFetch.mockResolvedValueOnce({ - ok: true, - json: () => Promise.resolve(mockResponseData), - }); - - const result = await api.runTests(payload); - - expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/run`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(payload), - }); - expect(result).toEqual(mockResponseData); - }); - - test('should throw an error if API returns non-ok response', async () => { - const errorData = { error: 'Invalid payload' }; - mockFetch.mockResolvedValueOnce({ - ok: false, - json: () => Promise.resolve(errorData), - }); - - await expect(api.runTests(payload)).rejects.toThrow('Invalid payload'); - expect(console.error).toHaveBeenCalledWith('Failed to run tests:', expect.any(Error)); - }); - - test('should throw a generic error if API returns non-ok response without specific error message', async () => { - mockFetch.mockResolvedValueOnce({ - ok: false, - json: () => Promise.resolve({}), - }); - - await expect(api.runTests(payload)).rejects.toThrow('Failed to run tests'); - expect(console.error).toHaveBeenCalledWith('Failed to run tests:', expect.any(Error)); - }); - - test('should throw an error if fetch fails', async () => { - const error = new Error('Network error'); - mockFetch.mockRejectedValueOnce(error); - - await expect(api.runTests(payload)).rejects.toThrow('Network error'); - expect(console.error).toHaveBeenCalledWith('Failed to run tests:', error); - }); - }); - - describe('stopAllTests', () => { - test('should stop all tests successfully', async () => { - mockFetch.mockResolvedValueOnce({ - ok: true, - }); - - await expect(api.stopAllTests()).resolves.toBeUndefined(); - expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/stop`, { - method: 'POST', - }); - }); - - test('should throw an error if API returns non-ok response', async () => { - mockFetch.mockResolvedValueOnce({ - ok: false, - }); - - await expect(api.stopAllTests()).rejects.toThrow('Failed to stop tests'); - expect(console.error).toHaveBeenCalledWith('Failed to stop tests:', expect.any(Error)); - }); - - test('should throw an error if fetch fails', async () => { - const error = new Error('Network error'); - mockFetch.mockRejectedValueOnce(error); - - await expect(api.stopAllTests()).rejects.toThrow('Network error'); - expect(console.error).toHaveBeenCalledWith('Failed to stop tests:', error); - }); - }); - - describe('stopSingleTest', () => { - const runId = 'testRun123'; - - test('should stop a single test successfully', async () => { - mockFetch.mockResolvedValueOnce({ - ok: true, - }); - - await expect(api.stopSingleTest(runId)).resolves.toBeUndefined(); - expect(mockFetch).toHaveBeenCalledWith(`${baseUrl}/api/stop-single-test/${runId}`, { - method: 'POST', - }); - }); - - test('should throw an error if API returns non-ok response', async () => { - mockFetch.mockResolvedValueOnce({ - ok: false, - }); - - await expect(api.stopSingleTest(runId)).rejects.toThrow(`Failed to stop test run ${runId}`); - expect(console.error).toHaveBeenCalledWith(`Failed to stop test run ${runId}:`, expect.any(Error)); - }); - - test('should throw an error if fetch fails', async () => { - const error = new Error('Network error'); - mockFetch.mockRejectedValueOnce(error); - - await expect(api.stopSingleTest(runId)).rejects.toThrow('Network error'); - expect(console.error).toHaveBeenCalledWith(`Failed to stop test run ${runId}:`, error); - }); - }); -}); diff --git a/public/js/tests/app.test.js b/public/js/tests/app.test.js deleted file mode 100644 index b8cb02d..0000000 --- a/public/js/tests/app.test.js +++ /dev/null @@ -1,581 +0,0 @@ -// Mock utils.js functions - MUST BE BEFORE OTHER IMPORTS TO MOCK CORRECTLY -jest.mock('../utils.js', () => ({ - ...jest.requireActual('../utils.js'), // Keep original functions if not mocking them - updateFavicon: jest.fn(), // Mock this specific function -})); - -// Import the mocked function -import { updateFavicon } from '../utils.js'; - -// Mock dependencies -class MockStore { - constructor() { - this.state = { - testSuites: [], - availableSuites: [], - availableGroups: [], - selectedGroups: [], - selectedSuites: [], - options: {}, - runningTestIds: {}, - stopPending: {}, - lastCompletedRunId: null, - realtimeTestRuns: {}, - searchQuery: '', - isStarting: false, - coverage: false - }; - } - getFailedTestIds() { return []; } - hasFailedTests() { return false; } - markStopPending(runId) { this.state.stopPending[runId] = true; } - clearStopPending(runId) { delete this.state.stopPending[runId]; } - setStarting(value) { this.state.isStarting = value; } - clearAllResults() { - this.state.realtimeTestRuns = {}; - this.state.lastCompletedRunId = null; - } -} - -class MockApiClient { - constructor() { - this.fetchTests = jest.fn(() => Promise.resolve({ suites: [], availableSuites: [], availableGroups: [] })); - this.runTests = jest.fn(() => Promise.resolve({})); - this.stopAllTests = jest.fn(() => Promise.resolve()); - this.stopSingleTest = jest.fn(() => Promise.resolve()); - } -} - -// Define the mock class directly inside the jest.mock factory -jest.mock('../websocket.js', () => { - const MockWebSocketManager = jest.fn(() => ({ - connect: jest.fn(() => Promise.resolve()), - })); - return { - WebSocketManager: MockWebSocketManager, - }; -}); - -// Import the mocked WebSocketManager -import { WebSocketManager as MockWebSocketManager } from '../websocket.js'; - -import { App } from '../app.js'; - -describe('App', () => { - let app; - let store; - let api; - - beforeEach(() => { - // Reset mocks before each test - jest.clearAllMocks(); - - // Create new instances of mocks and App - store = new MockStore(); - api = new MockApiClient(); - - app = new App(); - app.store = store; - app.api = api; - - // Mock setupResizer as it interacts with the DOM - app.setupResizer = jest.fn(); - }); - - describe('initialize', () => { - test('should fetch tests, connect websocket, and setup resizer', async () => { - await app.initialize(); - - expect(api.fetchTests).toHaveBeenCalledTimes(1); - expect(app.setupResizer).toHaveBeenCalledTimes(1); - expect(updateFavicon).toHaveBeenCalledWith('neutral'); - }); - - test('should log an error if initialization fails', async () => { - const error = new Error('Failed to fetch tests'); - api.fetchTests.mockRejectedValueOnce(error); - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - - // Wrap in try-catch to handle the re-thrown error from fetchTests - try { - await app.initialize(); - } catch (e) { - // This will not be reached because the error is caught inside initialize - } - - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to initialize app:', error); - consoleErrorSpy.mockRestore(); - }); - }); - - describe('fetchTests', () => { - test('should fetch tests and update store', async () => { - const mockTestData = { - suites: [{ name: 'Suite1', methods: [{ id: 'test1', name: 'testMethod1' }] }], - availableSuites: ['Suite1'], - availableGroups: ['Group1'], - }; - api.fetchTests.mockResolvedValueOnce(mockTestData); - - await app.fetchTests(); - - expect(api.fetchTests).toHaveBeenCalledTimes(1); - expect(store.state.testSuites).toEqual(mockTestData.suites); - expect(store.state.availableSuites).toEqual(mockTestData.availableSuites); - expect(store.state.availableGroups).toEqual(mockTestData.availableGroups); - expect(app.testIndex).toEqual({ - 'test1': { suite: mockTestData.suites[0], method: mockTestData.suites[0].methods[0] } - }); - }); - - test('should log an error if fetching tests fails', async () => { - const error = new Error('API error'); - api.fetchTests.mockRejectedValueOnce(error); - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - - // Wrap in try-catch to handle the re-thrown error - try { - await app.fetchTests(); - fail('fetchTests should have thrown an error'); - } catch (e) { - expect(e).toBe(error); // Assert that the correct error was re-thrown - } - - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to fetch tests:', error); - consoleErrorSpy.mockRestore(); - }); - }); - - describe('buildTestIndex', () => { - test('should build test index correctly', () => { - store.state.testSuites = [ - { - name: 'SuiteA', - methods: [ - { id: 'suiteA_test1', name: 'test1' }, - { id: 'suiteA_test2', name: 'test2' }, - ], - }, - { - name: 'SuiteB', - methods: [ - { id: 'suiteB_test1', name: 'test3' }, - ], - }, - ]; - - app.buildTestIndex(); - - expect(app.testIndex).toEqual({ - 'suiteA_test1': { suite: store.state.testSuites[0], method: store.state.testSuites[0].methods[0] }, - 'suiteA_test2': { suite: store.state.testSuites[0], method: store.state.testSuites[0].methods[1] }, - 'suiteB_test1': { suite: store.state.testSuites[1], method: store.state.testSuites[1].methods[0] }, - }); - }); - - test('should handle suites with no methods', () => { - store.state.testSuites = [ - { name: 'SuiteC', methods: [] }, - { name: 'SuiteD' }, - ]; - - app.buildTestIndex(); - - expect(app.testIndex).toEqual({}); - }); - }); - - describe('runTests', () => { - test('should call api.runTests with correct payload and set starting state', async () => { - store.state.selectedGroups = ['GroupA']; - store.state.selectedSuites = ['SuiteX']; - store.state.options = { stopOnFailure: true }; - const setStartingSpy = jest.spyOn(store, 'setStarting'); - - await app.runTests({ filters: ['testId1'], contextId: 'specificTest' }); - - expect(setStartingSpy).toHaveBeenCalledWith(true); - expect(store.state.activeTab).toBe('results'); - expect(api.runTests).toHaveBeenCalledWith({ - filters: ['testId1'], - groups: ['GroupA'], - suites: ['SuiteX'], - options: { stopOnFailure: true, colors: true }, - contextId: 'specificTest', - coverage: false - }); - }); - - test('should log an error, update favicon, and reset starting state if running tests fails', async () => { - const error = new Error('Run error'); - api.runTests.mockRejectedValueOnce(error); - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const setStartingSpy = jest.spyOn(store, 'setStarting'); - - await app.runTests(); - - expect(setStartingSpy).toHaveBeenCalledWith(true); - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to run tests:', error); - expect(updateFavicon).toHaveBeenCalledWith('failure'); - expect(setStartingSpy).toHaveBeenCalledWith(false); - consoleErrorSpy.mockRestore(); - }); - }); - - describe('runAllTests', () => { - test('should call runTests with global contextId', async () => { - const runTestsSpy = jest.spyOn(app, 'runTests'); - await app.runAllTests(); - expect(runTestsSpy).toHaveBeenCalledWith({ contextId: 'global' }); - runTestsSpy.mockRestore(); - }); - }); - - describe('runFailedTests', () => { - test('should call runTests with failed test IDs', async () => { - jest.spyOn(store, 'getFailedTestIds').mockReturnValueOnce(['failedTest1', 'failedTest2']); - const runTestsSpy = jest.spyOn(app, 'runTests'); - - await app.runFailedTests(); - - expect(runTestsSpy).toHaveBeenCalledWith({ filters: ['failedTest1', 'failedTest2'], contextId: 'failed' }); - runTestsSpy.mockRestore(); - }); - - test('should not run tests if no failed tests', async () => { - jest.spyOn(store, 'getFailedTestIds').mockReturnValueOnce([]); - const runTestsSpy = jest.spyOn(app, 'runTests'); - const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); - - await app.runFailedTests(); - - expect(runTestsSpy).not.toHaveBeenCalled(); - expect(consoleLogSpy).toHaveBeenCalledWith('No failed tests to run.'); - consoleLogSpy.mockRestore(); - runTestsSpy.mockRestore(); - }); - }); - - describe('runSingleTest', () => { - test('should call runTests with the given testId', async () => { - const runTestsSpy = jest.spyOn(app, 'runTests'); - await app.runSingleTest('test1234'); - expect(runTestsSpy).toHaveBeenCalledWith({ filters: ['test1234'], contextId: 'test1234' }); - runTestsSpy.mockRestore(); - }); - }); - - describe('runSuiteTests', () => { - test('should call runTests with the given suiteId', async () => { - const runTestsSpy = jest.spyOn(app, 'runTests'); - await app.runSuiteTests('suiteABC'); - expect(runTestsSpy).toHaveBeenCalledWith({ filters: ['suiteABC'], contextId: 'suiteABC' }); - runTestsSpy.mockRestore(); - }); - }); - - describe('stopAllTests', () => { - test('should mark all running tests as stop pending and call api.stopAllTests', async () => { - store.state.runningTestIds = { 'run1': true, 'run2': true }; - const markStopPendingSpy = jest.spyOn(store, 'markStopPending'); - - await app.stopAllTests(); - - expect(markStopPendingSpy).toHaveBeenCalledWith('run1'); - expect(markStopPendingSpy).toHaveBeenCalledWith('run2'); - expect(api.stopAllTests).toHaveBeenCalledTimes(1); - markStopPendingSpy.mockRestore(); - }); - - test('should clear stop pending if stopping all tests fails', async () => { - const error = new Error('Stop error'); - api.stopAllTests.mockRejectedValueOnce(error); - store.state.runningTestIds = { 'run1': true }; - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const clearStopPendingSpy = jest.spyOn(store, 'clearStopPending'); - - await app.stopAllTests(); - - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to stop tests:', error); - expect(clearStopPendingSpy).toHaveBeenCalledWith('run1'); - consoleErrorSpy.mockRestore(); - clearStopPendingSpy.mockRestore(); - }); - }); - - describe('stopSingleTest', () => { - test('should mark single test as stop pending and call api.stopSingleTest', async () => { - const markStopPendingSpy = jest.spyOn(store, 'markStopPending'); - - await app.stopSingleTest('runId123'); - - expect(markStopPendingSpy).toHaveBeenCalledWith('runId123'); - expect(api.stopSingleTest).toHaveBeenCalledWith('runId123'); - markStopPendingSpy.mockRestore(); - }); - - test('should clear stop pending if stopping single test fails', async () => { - const error = new Error('Stop single error'); - api.stopSingleTest.mockRejectedValueOnce(error); - const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const clearStopPendingSpy = jest.spyOn(store, 'clearStopPending'); - - await app.stopSingleTest('runId123'); - - expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to stop test run runId123:', error); - expect(clearStopPendingSpy).toHaveBeenCalledWith('runId123'); - consoleErrorSpy.mockRestore(); - clearStopPendingSpy.mockRestore(); - }); - }); - - describe('togglePlayStop', () => { - test('should call stopAllTests if any test is running', async () => { - store.state.runningTestIds = { 'run1': true }; - const stopAllTestsSpy = jest.spyOn(app, 'stopAllTests'); - const runAllTestsSpy = jest.spyOn(app, 'runAllTests'); - - await app.togglePlayStop(); - - expect(stopAllTestsSpy).toHaveBeenCalledTimes(1); - expect(runAllTestsSpy).not.toHaveBeenCalled(); - stopAllTestsSpy.mockRestore(); - runAllTestsSpy.mockRestore(); - }); - - test('should call runAllTests if no tests are running', async () => { - store.state.runningTestIds = {}; - const stopAllTestsSpy = jest.spyOn(app, 'stopAllTests'); - const runAllTestsSpy = jest.spyOn(app, 'runAllTests'); - - await app.togglePlayStop(); - - expect(stopAllTestsSpy).not.toHaveBeenCalled(); - expect(runAllTestsSpy).toHaveBeenCalledTimes(1); - stopAllTestsSpy.mockRestore(); - runAllTestsSpy.mockRestore(); - }); - }); - - describe('getResults', () => { - test('should return null if no test runs', () => { - store.state.realtimeTestRuns = {}; - expect(app.getResults()).toBeNull(); - }); - - test('should return results for the last completed run', () => { - store.state.lastCompletedRunId = 'run1'; - store.state.realtimeTestRuns = { - 'run1': { - summary: { - numberOfTests: 1, numberOfAssertions: 1, duration: 0.1, - numberOfFailures: 0, numberOfErrors: 0, numberOfWarnings: 0, - numberOfSkipped: 0, numberOfDeprecations: 0, numberOfIncomplete: 0, - }, - suites: { - 'SuiteA': { - name: 'SuiteA', - tests: { - 'test1': { id: 'test1', name: 'testMethod', class: 'ClassA', status: 'passed' } - } - } - } - } - }; - - const results = app.getResults(); - expect(results).toEqual({ - summary: { - tests: 1, assertions: 1, time: 0.1, - failures: 0, errors: 0, warnings: 0, - skipped: 0, deprecations: 0, incomplete: 0, - notices: 0, - risky: 0, - }, - suites: [ - { - name: 'SuiteA', - testcases: [ - { id: 'test1', name: 'testMethod', assertions: 0, class: 'ClassA', duration: 0, status: 'passed', message: undefined, trace: undefined, warnings: [], deprecations: [], notices: [] } - ] - } - ] - }); - }); - - test('should return results for the most recent run if no completed run', () => { - store.state.lastCompletedRunId = null; - store.state.realtimeTestRuns = { - 'run1': { /* older run */ }, - 'run2': { - summary: { numberOfTests: 2, numberOfFailures: 1 }, - suites: { - 'SuiteB': { - name: 'SuiteB', - tests: { - 'test2': { id: 'test2', name: 'testMethod2', class: 'ClassB', status: 'failed' } - } - } - } - } - }; - - const results = app.getResults(); - // The original test expected results.summary.numberOfTests to be 2, - // but the mock data for run2 only specifies numberOfTests: 2 in summary, - // and the getResults method transforms it to 'tests'. - // Also, the suites transformation sets duration to 0 if not present. - expect(results.summary.tests).toBe(2); - expect(results.suites[0].name).toBe('SuiteB'); - }); - }); - - describe('getGroupedResults', () => { - test('should return empty array if no results', () => { - jest.spyOn(app, 'getResults').mockReturnValueOnce(null); - expect(app.getGroupedResults()).toEqual([]); - }); - - test('should group test cases by class and sort them', () => { - jest.spyOn(app, 'getResults').mockReturnValueOnce({ - suites: [ - { - name: 'Suite1', - testcases: [ - { id: 't1', name: 'testA', class: 'ClassB', status: 'passed' }, - { id: 't2', name: 'testB', class: 'ClassA', status: 'failed' }, - { id: 't3', name: 'testC', class: 'ClassB', status: 'warning', warnings: ['warn'] }, - ] - } - ] - }); - - const grouped = app.getGroupedResults(); - expect(grouped.length).toBe(2); - expect(grouped[0].className).toBe('ClassA'); // ClassA has failed test, so it comes first - expect(grouped[0].testcases[0].name).toBe('testB'); - expect(grouped[1].className).toBe('ClassB'); - expect(grouped[1].testcases[0].name).toBe('testC'); // Warning comes before passed - expect(grouped[1].testcases[1].name).toBe('testA'); - }); - - test('should correctly count statuses and issues', () => { - jest.spyOn(app, 'getResults').mockReturnValueOnce({ - suites: [ - { - name: 'Suite1', - testcases: [ - { id: 't1', name: 'testA', class: 'ClassA', status: 'passed' }, - { id: 't2', name: 'testB', class: 'ClassA', status: 'failed' }, - { id: 't3', name: 'testC', class: 'ClassA', status: 'errored' }, - { id: 't4', name: 'testD', class: 'ClassA', status: 'skipped' }, - { id: 't5', name: 'testE', class: 'ClassA', status: 'passed', warnings: ['w1', 'w2'] }, - { id: 't6', name: 'testF', class: 'ClassA', status: 'passed', deprecations: ['d1'] }, - { id: 't7', name: 'testG', class: 'ClassA', status: 'incomplete' }, - ] - } - ] - }); - - const grouped = app.getGroupedResults(); - const classA = grouped[0]; - expect(classA.passed).toBe(3); // testA, testE, testF are passed - expect(classA.failed).toBe(1); - expect(classA.errored).toBe(1); - expect(classA.skipped).toBe(1); - expect(classA.warning).toBe(2); // 2 warnings in testE - expect(classA.deprecation).toBe(1); // 1 deprecation in testF - expect(classA.incomplete).toBe(1); - expect(classA.hasIssues).toBe(true); - }); - }); - - describe('getStatusCounts', () => { - test('should return zero counts if no results', () => { - jest.spyOn(app, 'getResults').mockReturnValueOnce(null); - expect(app.getStatusCounts()).toEqual({ - passed: 0, failed: 0, error: 0, warnings: 0, skipped: 0, deprecations: 0, incomplete: 0, risky: 0, notices: 0, - }); - }); - - test('should correctly calculate status counts', () => { - jest.spyOn(app, 'getResults').mockReturnValueOnce({ - summary: { - tests: 10, - failures: 2, - errors: 1, - warnings: 3, - skipped: 1, - deprecations: 1, - incomplete: 1, - notices: 0, - risky: 0, - } - }); - - const counts = app.getStatusCounts(); - expect(counts).toEqual({ - passed: 5, // 10 total - (2f + 1e + 1s + 1i) = 5 (warnings and deprecations don't affect passed count) - failed: 2, - error: 1, - warnings: 3, - skipped: 1, - deprecations: 1, - incomplete: 1, - notices: 0, - risky: 0, - }); - }); - }); - - describe('getFilteredTestSuites', () => { - beforeEach(() => { - store.state.testSuites = [ - { name: 'SuiteA', methods: [{ id: 't1', name: 'testMethodOne' }] }, - { name: 'SuiteB', methods: [{ id: 't2', name: 'anotherTest' }] }, - { name: 'SuiteC', methods: [{ id: 't3', name: 'testMethodTwo' }] }, - ]; - }); - - test('should return all suites if search query is empty', () => { - store.state.searchQuery = ''; - expect(app.getFilteredTestSuites()).toEqual(store.state.testSuites); - }); - - test('should filter by suite name', () => { - store.state.searchQuery = 'suitea'; - const filtered = app.getFilteredTestSuites(); - expect(filtered.length).toBe(1); - expect(filtered[0].name).toBe('SuiteA'); - }); - - test('should filter by method name', () => { - store.state.searchQuery = 'anothertest'; - const filtered = app.getFilteredTestSuites(); - expect(filtered.length).toBe(1); - expect(filtered[0].name).toBe('SuiteB'); - expect(filtered[0].methods.length).toBe(1); - expect(filtered[0].methods[0].name).toBe('anotherTest'); - }); - - test('should return suites where either name or method matches', () => { - store.state.searchQuery = 'testmethod'; - const filtered = app.getFilteredTestSuites(); - expect(filtered.length).toBe(2); - expect(filtered[0].name).toBe('SuiteA'); - expect(filtered[1].name).toBe('SuiteC'); - }); - - test('should be case-insensitive', () => { - store.state.searchQuery = 'suiteb'; - const filtered = app.getFilteredTestSuites(); - expect(filtered.length).toBe(1); - expect(filtered[0].name).toBe('SuiteB'); - }); - - test('should return empty array if no matches', () => { - store.state.searchQuery = 'nomatch'; - expect(app.getFilteredTestSuites()).toEqual([]); - }); - }); -}); diff --git a/public/js/tests/websocket.test.js b/public/js/tests/websocket.test.js deleted file mode 100644 index e5f4764..0000000 --- a/public/js/tests/websocket.test.js +++ /dev/null @@ -1,247 +0,0 @@ -// Mock the global WebSocket object -const mockWebSocketInstance = { - onopen: null, - onmessage: null, - onerror: null, - onclose: null, - close: jest.fn(), - send: jest.fn(), -}; -const MockWebSocket = jest.fn(() => mockWebSocketInstance); -global.WebSocket = MockWebSocket; - -// Mock dependencies -import * as Utils from '../utils.js'; // Import the module -jest.mock('../utils.js'); // Mock the module - -class MockStore { - constructor() { - this.state = { - realtimeTestRuns: {}, - runningTestIds: {}, // Initialize runningTestIds - options: { - resultUpdateMode: 'update', // Default to update mode - }, - }; - this.initializeTestRun = jest.fn(); - this.handleTestEvent = jest.fn(); - this.stopTestRun = jest.fn(); - this.clearRunningTests = jest.fn(); - this.getTestRun = jest.fn((runId) => this.state.realtimeTestRuns[runId]); - this.getRunningTestCount = jest.fn(() => Object.keys(this.state.runningTestIds || {}).length); // Corrected property and added safety - } -} - -import { WebSocketManager } from '../websocket.js'; - -describe('WebSocketManager', () => { - let wsManager; - let store; - const wsUrl = 'ws://localhost:8080/ws'; - - beforeEach(() => { - store = new MockStore(); - wsManager = new WebSocketManager(wsUrl, store); - - jest.clearAllMocks(); - Utils.updateFavicon.mockClear(); // Clear the mock here - jest.spyOn(console, 'log').mockImplementation(() => {}); - jest.spyOn(console, 'error').mockImplementation(() => {}); - jest.spyOn(console, 'warn').mockImplementation(() => {}); - jest.useFakeTimers(); // Mock timers for setTimeout - }); - - afterEach(() => { - jest.restoreAllMocks(); - jest.useRealTimers(); // Restore real timers - }); - - describe('connect', () => { - test('should create a new WebSocket instance', async () => { - const connectPromise = wsManager.connect(); - mockWebSocketInstance.onopen(); // Simulate connection open - await connectPromise; - - expect(MockWebSocket).toHaveBeenCalledWith(wsUrl); - expect(console.log).toHaveBeenCalledWith('WebSocket connected'); - expect(wsManager.reconnectAttempts).toBe(0); - }); - - test('should reject if WebSocket connection fails', async () => { - const connectPromise = wsManager.connect(); - const error = new Error('Connection failed'); - mockWebSocketInstance.onerror(error); // Simulate connection error - await expect(connectPromise).rejects.toThrow('Connection failed'); - expect(console.error).toHaveBeenCalledWith('WebSocket error:', error); - }); - - test('should reject if WebSocket constructor throws an error', async () => { - MockWebSocket.mockImplementationOnce(() => { throw new Error('Invalid URL'); }); - await expect(wsManager.connect()).rejects.toThrow('Invalid URL'); - }); - }); - - describe('handleDisconnect', () => { - test('should clear running tests and update favicon to neutral', () => { - wsManager.handleDisconnect(); - expect(store.clearRunningTests).toHaveBeenCalledTimes(1); - expect(Utils.updateFavicon).toHaveBeenCalledWith('neutral'); // Use Utils.updateFavicon - }); - - test('should attempt to reconnect if reconnect attempts are less than max', () => { - wsManager.reconnectAttempts = 0; - wsManager.maxReconnectAttempts = 1; - const connectSpy = jest.spyOn(wsManager, 'connect').mockResolvedValueOnce(); - - wsManager.handleDisconnect(); - expect(wsManager.reconnectAttempts).toBe(1); - expect(console.log).toHaveBeenCalledWith('Attempting to reconnect in 2000ms...'); - - jest.advanceTimersByTime(2000); - expect(connectSpy).toHaveBeenCalledTimes(1); - }); - - test('should not attempt to reconnect if reconnect attempts exceed max', () => { - wsManager.reconnectAttempts = wsManager.maxReconnectAttempts; - const connectSpy = jest.spyOn(wsManager, 'connect'); - - wsManager.handleDisconnect(); - expect(connectSpy).not.toHaveBeenCalled(); - expect(console.log).not.toHaveBeenCalledWith(expect.stringContaining('Attempting to reconnect')); - }); - }); - - describe('handleMessage', () => { - test('should call handleTestStart for "start" message type', () => { - const message = { type: 'start', runId: '123', contextId: 'global' }; - wsManager.handleMessage(message); - expect(store.initializeTestRun).toHaveBeenCalledWith('123', 'global'); - }); - - test('should call handleRealtimeEvent for "realtime" message type', () => { - const message = { type: 'realtime', runId: '123', data: JSON.stringify({ event: 'test.prepared' }) }; - wsManager.handleMessage(message); - expect(store.handleTestEvent).toHaveBeenCalledWith('123', { event: 'test.prepared' }); - }); - - test('should call handleTestExit for "exit" message type', () => { - const message = { type: 'exit', runId: '123' }; - const updateFaviconSpy = jest.spyOn(wsManager, 'updateFaviconFromRun'); - wsManager.handleMessage(message); - expect(updateFaviconSpy).toHaveBeenCalledWith('123'); - }); - - test('should call handleTestStopped for "stopped" message type', () => { - const message = { type: 'stopped', runId: '123' }; - const updateFaviconSpy = jest.spyOn(wsManager, 'updateFaviconIfComplete'); - wsManager.handleMessage(message); - expect(store.stopTestRun).toHaveBeenCalledWith('123'); - expect(updateFaviconSpy).toHaveBeenCalledTimes(1); - }); - - test('should warn for unknown message type', () => { - const message = { type: 'unknown' }; - wsManager.handleMessage(message); - expect(console.warn).toHaveBeenCalledWith('Unknown message type:', 'unknown'); - }); - }); - - describe('handleRealtimeEvent', () => { - test('should parse message data and call store.handleTestEvent', () => { - const message = { runId: 'run456', data: JSON.stringify({ event: 'test.passed', data: { test: 'Suite::test' } }) }; - wsManager.handleRealtimeEvent(message); - expect(store.handleTestEvent).toHaveBeenCalledWith('run456', { event: 'test.passed', data: { test: 'Suite::test' } }); - }); - - test('should log an error if message data is invalid JSON', () => { - const message = { runId: 'run456', data: 'invalid json' }; - wsManager.handleRealtimeEvent(message); - expect(console.error).toHaveBeenCalledWith('Failed to parse realtime event:', expect.any(Error), 'invalid json'); - }); - }); - - describe('updateFaviconFromRun', () => { - test('should set favicon to failure if run has failures in reset mode', () => { - store.state.options.resultUpdateMode = 'reset'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 1, numberOfErrors: 0 } }; - wsManager.updateFaviconFromRun('run1'); - expect(Utils.updateFavicon).toHaveBeenCalledWith('failure'); - }); - - test('should set favicon to failure if run has errors in reset mode', () => { - store.state.options.resultUpdateMode = 'reset'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 0, numberOfErrors: 1 } }; - wsManager.updateFaviconFromRun('run1'); - expect(Utils.updateFavicon).toHaveBeenCalledWith('failure'); - }); - - test('should set favicon to success if run has no failures or errors in reset mode', () => { - store.state.options.resultUpdateMode = 'reset'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 0, numberOfErrors: 0 } }; - wsManager.updateFaviconFromRun('run1'); - expect(Utils.updateFavicon).toHaveBeenCalledWith('success'); - }); - - test('should set favicon to failure if any run has failures in update mode', () => { - store.state.options.resultUpdateMode = 'update'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 1, numberOfErrors: 0 } }; - store.state.realtimeTestRuns['run2'] = { summary: { numberOfFailures: 0, numberOfErrors: 0 } }; - wsManager.updateFaviconFromRun('run2'); // Calling on run2 which has no failures - expect(Utils.updateFavicon).toHaveBeenCalledWith('failure'); // But should show failure because run1 has failures - }); - - test('should set favicon to failure if any run has errors in update mode', () => { - store.state.options.resultUpdateMode = 'update'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 0, numberOfErrors: 0 } }; - store.state.realtimeTestRuns['run2'] = { summary: { numberOfFailures: 0, numberOfErrors: 1 } }; - wsManager.updateFaviconFromRun('run1'); // Calling on run1 which has no errors - expect(Utils.updateFavicon).toHaveBeenCalledWith('failure'); // But should show failure because run2 has errors - }); - - test('should set favicon to success if all runs pass in update mode', () => { - store.state.options.resultUpdateMode = 'update'; - store.state.realtimeTestRuns['run1'] = { summary: { numberOfFailures: 0, numberOfErrors: 0 } }; - store.state.realtimeTestRuns['run2'] = { summary: { numberOfFailures: 0, numberOfErrors: 0 } }; - wsManager.updateFaviconFromRun('run2'); - expect(Utils.updateFavicon).toHaveBeenCalledWith('success'); - }); - - test('should do nothing if run or summary is missing', () => { - wsManager.updateFaviconFromRun('nonExistentRun'); - expect(Utils.updateFavicon).not.toHaveBeenCalled(); - - store.state.realtimeTestRuns['run2'] = { summary: null }; - wsManager.updateFaviconFromRun('run2'); - expect(Utils.updateFavicon).not.toHaveBeenCalled(); - }); - }); - - describe('updateFaviconIfComplete', () => { - test('should set favicon to neutral if no tests are running', () => { - store.getRunningTestCount.mockReturnValueOnce(0); - wsManager.updateFaviconIfComplete(); - expect(Utils.updateFavicon).toHaveBeenCalledWith('neutral'); - }); - - test('should not update favicon if tests are still running', () => { - store.getRunningTestCount.mockReturnValueOnce(1); - wsManager.updateFaviconIfComplete(); - expect(Utils.updateFavicon).not.toHaveBeenCalled(); - }); - }); - - describe('disconnect', () => { - test('should close the WebSocket connection if it exists', () => { - wsManager.ws = mockWebSocketInstance; - wsManager.disconnect(); - expect(mockWebSocketInstance.close).toHaveBeenCalledTimes(1); - expect(wsManager.ws).toBeNull(); - }); - - test('should do nothing if WebSocket connection does not exist', () => { - wsManager.ws = null; - wsManager.disconnect(); - expect(mockWebSocketInstance.close).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/src/Command/Router.php b/src/Command/Router.php index 1305be7..993e650 100644 --- a/src/Command/Router.php +++ b/src/Command/Router.php @@ -10,7 +10,6 @@ use PhpUnitHub\TestRunner\TestRunner; use PhpUnitHub\WebSocket\StatusHandler; use Psr\Http\Message\RequestInterface; -use Ramsey\Uuid\Uuid; use Ratchet\ConnectionInterface; use Ratchet\Http\HttpServerInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -31,19 +30,21 @@ use function realpath; use function sprintf; use function str_replace; +use function str_starts_with; + +// Aggiunto per chiarezza, anche se probabilmente già presente class Router implements RouterInterface { private readonly string $publicPath; - /** @var array */ - private array $runningProcesses = []; + private ?Process $runningProcess = null; - /** @var array> */ // Mappa runId a lastFilters, lastSuites, lastGroups, lastOptions - private array $runContexts = []; + /** @var array|null */ + private ?array $runContext = null; - /** @var array> */ // Mappa runId a summary - private array $lastRunSummaries = []; + /** @var array|null */ + private ?array $lastRunSummary = null; /** @var string[] */ private array $failedTests = []; @@ -78,7 +79,7 @@ public function __construct( public function onOpen(ConnectionInterface $conn, ?RequestInterface $request = null): void { $path = $request?->getUri()->getPath(); - $this->output->writeln('Request for ' . $path, OutputInterface::VERBOSITY_VERBOSE); + $request?->getMethod(); if ($path === '/ws/status') { $this->httpServer->onOpen($conn, $request); @@ -137,26 +138,24 @@ private function handleHttpRequest(ConnectionInterface $connection, ?RequestInte $contextId = $payload['contextId'] ?? 'failed'; } - $runId = $this->runTests($filters, $suites, $groups, $options, $isRerun, $contextId, $coverage); - $jsonResponse = json_encode(['message' => 'Test run started.', 'runId' => $runId], JSON_THROW_ON_ERROR); + $this->runTests($filters, $suites, $groups, $options, $isRerun, $contextId, $coverage); + $jsonResponse = json_encode(['message' => 'Test run started.'], JSON_THROW_ON_ERROR); $response = new GuzzleResponse(202, ['Content-Type' => 'application/json'], $jsonResponse); } elseif ($path === '/api/stop' && $method === 'POST') { // Handle stop requests for all running tests $response = $this->stopAllTests(); - } elseif (str_starts_with((string) $path, '/api/stop-single-test/') && $method === 'POST') { - $parts = explode('/', (string) $path); - $runId = end($parts); - $response = $this->stopSingleTest($runId); - } elseif (str_starts_with((string) $path, '/api/coverage/') && $method === 'GET') { - $parts = explode('/', (string) $path); - $runId = end($parts); - $response = $this->getCoverage($runId); + } elseif (($path === '/api/stop-single-test' || str_starts_with((string) $path, '/api/stop-single-test/')) && $method === 'POST') { + // The path might still contain a runId from older frontends, but we ignore it now. + $response = $this->stopSingleTest(); + } elseif (($path === '/api/coverage' || str_starts_with((string) $path, '/api/coverage/')) && $method === 'GET') { + // The path might still contain a runId from older frontends, but we ignore it now. + $response = $this->getCoverage(); } elseif ($path === '/api/file-coverage' && $method === 'GET') { $queryParams = []; parse_str((string) $request?->getUri()->getQuery(), $queryParams); $filePath = $queryParams['path'] ?? null; - $runId = $queryParams['runId'] ?? null; - $response = $this->getFileCoverage($runId, $filePath); + + $response = $this->getFileCoverage($filePath); } elseif ($path === '/api/file-content' && $method === 'GET') { $queryParams = []; parse_str((string) $request?->getUri()->getQuery(), $queryParams); @@ -170,14 +169,39 @@ private function handleHttpRequest(ConnectionInterface $connection, ?RequestInte if (file_exists($filePath) && is_file($filePath) && str_starts_with(realpath($filePath), $this->publicPath)) { $content = file_get_contents($filePath); + if ($path === '/' || $path === '/index.html') { + $manifestPath = $this->publicPath . '/build/.vite/manifest.json'; + $viteScriptTag = ''; // Fallback per lo sviluppo + $viteCssTags = ''; // Conterrà i tag CSS generati da Vite + + // Tag CSS di fallback (per lo sviluppo o se Vite non genera CSS) $cssPath = $this->publicPath . '/css/styles.css'; $cssVersion = file_exists($cssPath) ? hash_file('md5', $cssPath) : 'dev'; - $content = str_replace( - ['{{ws_host}}', '{{ws_port}}', '{{css_version}}'], - [$this->host, $this->port, $cssVersion], - $content - ); + $fallbackCssTag = ''; + + if (file_exists($manifestPath)) { + $manifest = json_decode(file_get_contents($manifestPath), true); + $mainEntry = $manifest['assets/js/main.js'] ?? null; + + if ($mainEntry) { + $viteScriptTag = ''; + + if (!empty($mainEntry['css'])) { + foreach ($mainEntry['css'] as $cssFile) { + $viteCssTags .= ''; + } + } + } + } + + // Sostituisci il vecchio tag script con quello di Vite o il fallback + $content = str_replace('', $viteScriptTag, $content); + + // Rimuovi il vecchio link al manifest di Vite (non è per il browser) + // Sostituisci il vecchio link CSS. Se Vite ha generato CSS, usa quello. Altrimenti, usa il fallback. + // Sostituisci i placeholder di host/port + $content = str_replace(['', '', '{{ws_host}}', '{{ws_port}}'], ['', $viteCssTags === '' || $viteCssTags === '0' ? $fallbackCssTag : $viteCssTags, $this->host, $this->port], $content); } $response = new GuzzleResponse(200, ['Content-Type' => $this->getMimeType($filePath)], $content); @@ -197,13 +221,15 @@ private function handleHttpRequest(ConnectionInterface $connection, ?RequestInte * @param string[] $groups * @param array $options * @param string|null $contextId An identifier from the frontend to associate this run with a specific UI element. - * @return string The runId of the started test process. */ - public function runTests(array $filters, array $suites = [], array $groups = [], array $options = [], bool $isRerun = false, ?string $contextId = null, bool $coverage = false): string + public function runTests(array $filters, array $suites = [], array $groups = [], array $options = [], bool $isRerun = false, ?string $contextId = null, bool $coverage = false): void { - $runId = Uuid::uuid4()->toString(); + if ($this->runningProcess instanceof Process) { + $this->output->writeln('A test run is already in progress.'); + return; + } - $this->runContexts[$runId] = [ + $this->runContext = [ 'filters' => $filters, 'suites' => $suites, 'groups' => $groups, @@ -212,26 +238,26 @@ public function runTests(array $filters, array $suites = [], array $groups = [], 'coverage' => $coverage, ]; - $this->output->writeln(sprintf('Starting test run #%s with filters: ', $runId) . implode(', ', $filters)); + $this->output->writeln('Starting test run with filters: ' . implode(', ', $filters)); - $jsonBroadcast = json_encode(['type' => 'start', 'runId' => $runId, 'contextId' => $contextId], JSON_THROW_ON_ERROR); // Include contextId + $jsonBroadcast = json_encode(['type' => 'start', 'contextId' => $contextId], JSON_THROW_ON_ERROR); // Include contextId $this->statusHandler->broadcast($jsonBroadcast); - $process = $this->testRunner->run($this->runContexts[$runId], $runId); + $process = $this->testRunner->run($this->runContext); // Keep a reference so we can terminate later - $this->runningProcesses[$runId] = $process; + $this->runningProcess = $process; // Debug: Listen to STDOUT to see normal output - $process->stdout->on('data', function ($chunk) use ($runId) { - $this->output->writeln(sprintf('[DEBUG STDOUT] Run %s: %s', $runId, trim($chunk))); + $process->stdout->on('data', function ($chunk) { + $this->output->writeln(sprintf('[DEBUG STDOUT] %s', trim($chunk))); }); // Listen to STDERR for realtime events $buffer = ''; - $process->stderr->on('data', function ($chunk) use (&$buffer, $runId) { - $this->output->writeln(sprintf('[DEBUG] Received STDERR chunk for run %s: %s bytes', $runId, strlen($chunk))); + $process->stderr->on('data', function ($chunk) use (&$buffer) { + $this->output->writeln(sprintf('[DEBUG] Received STDERR chunk: %s bytes', strlen($chunk))); $buffer .= $chunk; $lines = explode("\n", $buffer); @@ -265,17 +291,17 @@ public function runTests(array $filters, array $suites = [], array $groups = [], // Store the summary if it's the execution.ended event if ($decodedLine['event'] === 'execution.ended') { - $this->lastRunSummaries[$runId] = $decodedLine['data']['summary']; + $this->lastRunSummary = $decodedLine['data']['summary']; } - $jsonBroadcast = json_encode(['type' => 'realtime', 'runId' => $runId, 'data' => $line], JSON_THROW_ON_ERROR); + $jsonBroadcast = json_encode(['type' => 'realtime', 'data' => $line], JSON_THROW_ON_ERROR); $this->output->writeln('[DEBUG] Broadcasting realtime event'); $this->statusHandler->broadcast($jsonBroadcast); } }); - $process->on('exit', function ($exitCode) use ($runId, $isRerun, $contextId, &$buffer) { // Pass contextId to closure - $this->output->writeln(sprintf('Test run #%s finished with code %s.', $runId, $exitCode)); + $process->on('exit', function ($exitCode) use ($isRerun, $contextId, &$buffer) { // Pass contextId to closure + $this->output->writeln(sprintf('Test run finished with code %s.', $exitCode)); // Ensure all buffered data is processed if ($buffer !== '' && $buffer !== '0') { @@ -300,16 +326,16 @@ public function runTests(array $filters, array $suites = [], array $groups = [], } if ($decodedLine['event'] === 'execution.ended') { - $this->lastRunSummaries[$runId] = $decodedLine['data']['summary']; + $this->lastRunSummary = $decodedLine['data']['summary']; } - $jsonBroadcast = json_encode(['type' => 'realtime', 'runId' => $runId, 'data' => $line], JSON_THROW_ON_ERROR); + $jsonBroadcast = json_encode(['type' => 'realtime', 'data' => $line], JSON_THROW_ON_ERROR); $this->statusHandler->broadcast($jsonBroadcast); } } // Update failedTests based on the summary - $summary = $this->lastRunSummaries[$runId] ?? null; + $summary = $this->lastRunSummary; if ($summary !== null && !$isRerun) { if (($summary['numberOfFailures'] ?? 0) > 0 || ($summary['numberOfErrors'] ?? 0) > 0) { // If there are failures/errors, we need to collect the actual failed test names @@ -323,7 +349,6 @@ public function runTests(array $filters, array $suites = [], array $groups = [], $jsonBroadcast = json_encode([ 'type' => 'exit', - 'runId' => $runId, 'exitCode' => $exitCode, 'contextId' => $contextId, // Include contextId in exit message ], JSON_THROW_ON_ERROR); @@ -331,37 +356,32 @@ public function runTests(array $filters, array $suites = [], array $groups = [], $this->statusHandler->broadcast($jsonBroadcast); if ($exitCode) { - $this->notify($exitCode, $summary, $runId); + $this->notify($exitCode, $summary); } - // Clear running process/runId state - unset($this->runningProcesses[$runId]); + // Clear running process state + $this->runningProcess = null; + $this->runContext = null; }); - - return $runId; } public function getLastFilters(): array { - // This now refers to the last global run, not a specific single test run return $this->lastFilters; } public function getLastGroups(): array { - // This now refers to the last global run, not a specific single test run return $this->lastGroups; } public function getLastOptions(): array { - // This now refers to the last global run, not a specific single test run return $this->lastOptions; } public function getLastSuites(): array { - // This now refers to the last global run, not a specific single test run return $this->lastSuites; } @@ -370,14 +390,12 @@ public function getLastSuites(): array */ private function stopAllTests(): GuzzleResponse { - if ($this->runningProcesses === []) { + if (!$this->runningProcess instanceof Process) { $json = json_encode(['error' => 'No test run in progress.'], JSON_THROW_ON_ERROR); return new GuzzleResponse(400, ['Content-Type' => 'application/json'], $json); } - foreach (array_keys($this->runningProcesses) as $runId) { - $this->terminateProcess($runId); - } + $this->terminateProcess(); $json = json_encode(['message' => 'Stop requested for all running tests.'], JSON_THROW_ON_ERROR); return new GuzzleResponse(202, ['Content-Type' => 'application/json'], $json); @@ -386,22 +404,22 @@ private function stopAllTests(): GuzzleResponse /** * Attempt to stop a specific running test process. */ - private function stopSingleTest(string $runId): GuzzleResponse + private function stopSingleTest(): GuzzleResponse { - if (!isset($this->runningProcesses[$runId])) { - $json = json_encode(['error' => sprintf('No test run found with ID %s.', $runId)], JSON_THROW_ON_ERROR); + if (!$this->runningProcess instanceof Process) { + $json = json_encode(['error' => 'No test run in progress.'], JSON_THROW_ON_ERROR); return new GuzzleResponse(404, ['Content-Type' => 'application/json'], $json); } - $this->terminateProcess($runId); + $this->terminateProcess(); - $json = json_encode(['message' => sprintf('Stop requested for test run %s.', $runId)], JSON_THROW_ON_ERROR); + $json = json_encode(['message' => 'Stop requested for test run.'], JSON_THROW_ON_ERROR); return new GuzzleResponse(202, ['Content-Type' => 'application/json'], $json); } - private function terminateProcess(string $runId): void + private function terminateProcess(): void { - $process = $this->runningProcesses[$runId] ?? null; + $process = $this->runningProcess; if (!$process instanceof Process || !$process->isRunning()) { return; } @@ -409,31 +427,31 @@ private function terminateProcess(string $runId): void try { $process->terminate(); } catch (Exception $exception) { - $this->output->writeln(sprintf('Failed to terminate process for run %s: %s', $runId, $exception->getMessage())); + $this->output->writeln(sprintf('Failed to terminate process: %s', $exception->getMessage())); return; } // Broadcast a stopped message immediately so the UI can react quickly - $jsonBroadcast = json_encode(['type' => 'stopped', 'runId' => $runId], JSON_THROW_ON_ERROR); + $jsonBroadcast = json_encode(['type' => 'stopped'], JSON_THROW_ON_ERROR); $this->statusHandler->broadcast($jsonBroadcast); // If the process doesn't exit within a short timeout, force-kill it (SIGKILL) try { $timeoutSeconds = 2.0; - Loop::get()->addTimer($timeoutSeconds, function () use ($runId, $process) { + Loop::get()->addTimer($timeoutSeconds, function () use ($process) { // force kill $sigkill = defined('SIGKILL') ? SIGKILL : 9; try { $process->terminate($sigkill); - $jsonBroadcast = json_encode(['type' => 'stopped', 'runId' => $runId, 'forced' => true], JSON_THROW_ON_ERROR); + $jsonBroadcast = json_encode(['type' => 'stopped', 'forced' => true], JSON_THROW_ON_ERROR); $this->statusHandler->broadcast($jsonBroadcast); } catch (Exception $exception) { - $this->output->writeln(sprintf('Failed to force-kill process for run %s: %s', $runId, $exception->getMessage())); + $this->output->writeln(sprintf('Failed to force-kill process: %s', $exception->getMessage())); } }); } catch (Exception $exception) { // If scheduling the timer fails for any reason, just log it and continue - $this->output->writeln(sprintf('Failed to schedule force-kill timer for run %s: %s', $runId, $exception->getMessage())); + $this->output->writeln(sprintf('Failed to schedule force-kill timer: %s', $exception->getMessage())); } } @@ -486,9 +504,8 @@ public function onError(ConnectionInterface $conn, Exception $e): void * * @param int $exitCode The exit code of the PHPUnit process. * @param array|null $summary The summary data from the 'execution.ended' event. - * @param string $runId The ID of the test run. */ - private function notify(int $exitCode, ?array $summary, string $runId): void + private function notify(int $exitCode, ?array $summary): void { $notificationTitle = 'PHPUnit Hub Test Results'; @@ -506,19 +523,19 @@ private function notify(int $exitCode, ?array $summary, string $runId): void $notificationProcess = new Process($command); $notificationProcess->start(Loop::get()); // Usa il loop di eventi predefinito - $notificationProcess->on('exit', function ($code) use ($runId, $notificationTitle, $notificationMessage, $command) { + $notificationProcess->on('exit', function ($code) use ($notificationTitle, $notificationMessage, $command) { if ($code !== 0) { - $this->output->writeln(sprintf('Failed to send notification for run #%s. Command: "%s", Exit Code: %s', $runId, $command, $code)); + $this->output->writeln(sprintf('Failed to send notification. Command: "%s", Exit Code: %s', $command, $code)); } else { - $this->output->writeln(sprintf('Notification sent for run #%s: "%s - %s"', $runId, $notificationTitle, $notificationMessage)); + $this->output->writeln(sprintf('Notification sent: "%s - %s"', $notificationTitle, $notificationMessage)); } }); } - private function getCoverage(string $runId): GuzzleResponse + private function getCoverage(): GuzzleResponse { if (!$this->coverage instanceof Coverage) { - $coveragePath = $this->projectRoot . sprintf('/clover-%s.xml', $runId); + $coveragePath = $this->projectRoot . '/clover.xml'; $this->coverage = new Coverage($this->projectRoot, $coveragePath); } @@ -527,17 +544,13 @@ private function getCoverage(string $runId): GuzzleResponse return new GuzzleResponse(200, ['Content-Type' => 'application/json'], json_encode($data, JSON_THROW_ON_ERROR)); } - private function getFileCoverage(?string $runId, ?string $filePath): GuzzleResponse + private function getFileCoverage(?string $filePath): GuzzleResponse { if ($filePath === null) { return new GuzzleResponse(400, ['Content-Type' => 'application/json'], json_encode(['error' => 'File path not provided.'], JSON_THROW_ON_ERROR)); } - if ($runId === null) { - return new GuzzleResponse(400, ['Content-Type' => 'application/json'], json_encode(['error' => 'Run ID not provided.'], JSON_THROW_ON_ERROR)); - } - - $coveragePath = $this->projectRoot . sprintf('/clover-%s.xml', $runId); + $coveragePath = $this->projectRoot . '/clover.xml'; $coverage = new Coverage($this->projectRoot, $coveragePath); diff --git a/src/Command/RouterInterface.php b/src/Command/RouterInterface.php index 9cd7cfd..50a263a 100644 --- a/src/Command/RouterInterface.php +++ b/src/Command/RouterInterface.php @@ -12,7 +12,7 @@ interface RouterInterface extends HttpServerInterface * @param string[] $groups * @param array $options */ - public function runTests(array $filters, array $suites = [], array $groups = [], array $options = [], bool $isRerun = false): string; + public function runTests(array $filters, array $suites = [], array $groups = [], array $options = [], bool $isRerun = false): void; /** * @return string[] diff --git a/src/Coverage/Coverage.php b/src/Coverage/Coverage.php index 4b18302..fe9dc26 100644 --- a/src/Coverage/Coverage.php +++ b/src/Coverage/Coverage.php @@ -38,7 +38,7 @@ public function parse(): array $files = []; $sourceDirectories = $this->getSourceDirectories(); - $fileNodes = $project->xpath('//package/file'); + $fileNodes = $project->xpath('//project/file'); if ($fileNodes) { foreach ($fileNodes as $fileNode) { @@ -102,6 +102,7 @@ public function parseFile(string $filePath): array return ['lines' => []]; } + // Changed XPath query to find all 'file' nodes regardless of parent 'package' $fileNode = $xml->xpath(sprintf("//file[@name='%s']", $fullPath))[0] ?? null; $coverageData = []; if ($fileNode) { diff --git a/src/PHPUnit/PhpUnitHubExtension.php b/src/PHPUnit/PhpUnitHubExtension.php index 5a83f2a..090adbd 100644 --- a/src/PHPUnit/PhpUnitHubExtension.php +++ b/src/PHPUnit/PhpUnitHubExtension.php @@ -70,7 +70,6 @@ public function bootstrap(Configuration $configuration, Facade $facade, Paramete return $testId; }; - // Register individual subscribers for each event type $facade->registerSubscriber(new class ($writeEvent, $formatTestId) implements PreparedSubscriber { private readonly Closure $writeEvent; diff --git a/src/TestRunner/TestRunner.php b/src/TestRunner/TestRunner.php index 70b4bf7..65d802a 100644 --- a/src/TestRunner/TestRunner.php +++ b/src/TestRunner/TestRunner.php @@ -16,7 +16,6 @@ use function implode; use function preg_quote; use function preg_replace; -use function sprintf; use function strtolower; use function trim; @@ -40,7 +39,7 @@ public function __construct( * coverage: bool * } $context */ - public function run(array $context, string $runId): Process + public function run(array $context): Process { $phpunitPath = Composer::getComposerBinDir($this->projectRoot) . DIRECTORY_SEPARATOR . 'phpunit'; @@ -97,7 +96,7 @@ public function run(array $context, string $runId): Process } if ($context['coverage']) { - $this->addCoverageOptions($command, $phpunitXmlPath, $runId); + $this->addCoverageOptions($command, $phpunitXmlPath); } $this->lastCommand = $command; @@ -113,7 +112,7 @@ public function getLastCommand(): ?string return $this->lastCommand; } - private function addCoverageOptions(string &$command, string $phpunitXmlPath, string $runId): void + private function addCoverageOptions(string &$command, string $phpunitXmlPath): void { $domDocument = new DOMDocument(); @$domDocument->load($phpunitXmlPath); @@ -121,7 +120,7 @@ private function addCoverageOptions(string &$command, string $phpunitXmlPath, st $cloverReport = $domxPath->query('//coverage/report/clover')->item(0); - $cloverFile = $this->projectRoot . sprintf('/clover-%s.xml', $runId); + $cloverFile = $this->projectRoot . '/clover.xml'; if ($cloverReport instanceof DOMElement) { $cloverFile = $cloverReport->getAttribute('outputFile'); diff --git a/tailwind.config.js b/tailwind.config.js index 0ea1f58..3b7cb09 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,24 +1,27 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: [ - "./public/**/*.html", - "./public/**/*.js", - ], - safelist: [ - { - pattern: /^status-/, + content: [ + "./public/**/*.html", + "./public/**/*.js", + ], + safelist: [ + { + pattern: /^status-/, + }, + { + pattern: /^token-/, + }, + { + pattern: /^bg-(red|green|amber|purple|yellow|gray)-(500|600|700|800|900)/, + }, + { + pattern: /^text-(red|green|amber|purple|yellow|gray)-(200|300|400)/, + }, + 'rotated', + 'rotate-90' + ], + theme: { + extend: {}, }, - { - pattern: /^bg-(red|green|amber|purple|yellow|gray)-(500|600|700|800|900)/, - }, - { - pattern: /^text-(red|green|amber|purple|yellow|gray)-(200|300|400)/, - }, - 'rotated', - 'rotate-90' - ], - theme: { - extend: {}, - }, - plugins: [], + plugins: [], } diff --git a/tests/Command/RouterTest.php b/tests/Command/RouterTest.php index 483d3b5..3cc49fb 100644 --- a/tests/Command/RouterTest.php +++ b/tests/Command/RouterTest.php @@ -135,14 +135,10 @@ public function testStopAllEndpointTerminatesAllProcesses(): void $router = $this->createRouter(); $process = $this->createMockProcess(true); - $mockProcess2 = $this->createMockProcess(true); $reflectionObject = new ReflectionObject($router); - $reflectionProperty = $reflectionObject->getProperty('runningProcesses'); - $reflectionProperty->setValue($router, [ - 'run-id-1' => $process, - 'run-id-2' => $mockProcess2, - ]); + $reflectionProperty = $reflectionObject->getProperty('runningProcess'); + $reflectionProperty->setValue($router, $process); $sent = []; $mockConnection = $this->createMockConnection($sent); @@ -159,18 +155,14 @@ public function testStopSingleEndpointTerminatesSpecificProcess(): void $router = $this->createRouter(); $process = $this->createMockProcess(true); - $mockProcessToKeep = $this->createMockProcess(false); // Should not be terminated $reflectionObject = new ReflectionObject($router); - $reflectionProperty = $reflectionObject->getProperty('runningProcesses'); - $reflectionProperty->setValue($router, [ - 'run-id-to-terminate' => $process, - 'run-id-to-keep' => $mockProcessToKeep, - ]); + $reflectionProperty = $reflectionObject->getProperty('runningProcess'); + $reflectionProperty->setValue($router, $process); $sent = []; $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/stop-single-test/run-id-to-terminate', 'POST'); + $mockRequest = $this->createMockRequest('/api/stop-single-test', 'POST'); $router->onOpen($mockConnection, $mockRequest); @@ -182,7 +174,7 @@ public function testStopEndpointReturns400IfNoProcessIsRunning(): void { $router = $this->createRouter(); - // runningProcesses is empty by default + // runningProcess is null by default $sent = []; $mockConnection = $this->createMockConnection($sent); @@ -195,26 +187,21 @@ public function testStopEndpointReturns400IfNoProcessIsRunning(): void $this->assertStringContainsString('No test run in progress.', $sent[0]); } - public function testStopSingleEndpointReturns404IfRunIdNotFound(): void + public function testStopSingleEndpointReturns404IfNoProcessIsRunning(): void { $router = $this->createRouter(); - $mockProcess = $this->createMockProcess(false); // No terminate expected - $reflectionObject = new ReflectionObject($router); - $reflectionProperty = $reflectionObject->getProperty('runningProcesses'); - $reflectionProperty->setValue($router, [ - 'some-other-run-id' => $mockProcess, - ]); + // runningProcess is null by default $sent = []; $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/stop-single-test/non-existent-run-id', 'POST'); + $mockRequest = $this->createMockRequest('/api/stop-single-test', 'POST'); $router->onOpen($mockConnection, $mockRequest); $this->assertNotEmpty($sent, 'No response sent'); $this->assertStringContainsString('HTTP/1.1 404', $sent[0]); - $this->assertStringContainsString('No test run found with ID non-existent-run-id.', $sent[0]); + $this->assertStringContainsString('No test run in progress.', $sent[0]); } public function testGetCoverageReturnsCoverageData(): void @@ -229,7 +216,7 @@ public function testGetCoverageReturnsCoverageData(): void $sent = []; $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/coverage/some-run-id', 'GET'); + $mockRequest = $this->createMockRequest('/api/coverage', 'GET'); $router->onOpen($mockConnection, $mockRequest); @@ -258,7 +245,7 @@ public function testGetFileCoverageReturnsCoverageData(): void '/api/file-coverage', 'GET', '', - 'runId=some-run-id&path=' . $filePath + 'path=' . $filePath ); $router->onOpen($mockConnection, $mockRequest); @@ -499,7 +486,6 @@ public function testServesIndexHtml(): void $this->assertStringContainsString('Content-Type: text/html', $sent[0]); $this->assertStringContainsString("window.WS_HOST = '127.0.0.1'", $sent[0]); $this->assertStringContainsString("window.WS_PORT = '8080'", $sent[0]); - $this->assertMatchesRegularExpression('/css\/styles\.css\?v=[a-f0-9]{32}/', $sent[0]); } public function testNotFoundResponse(): void @@ -535,23 +521,15 @@ public function testGetFileCoverageErrorResponses(): void // No file path $sent = []; $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/file-coverage', 'GET', '', 'runId=123'); + $mockRequest = $this->createMockRequest('/api/file-coverage', 'GET'); $router->onOpen($mockConnection, $mockRequest); $this->assertStringContainsString('HTTP/1.1 400', $sent[0]); $this->assertStringContainsString('File path not provided.', $sent[0]); - // No run ID - $sent = []; - $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/file-coverage', 'GET', '', 'path=some/file.php'); - $router->onOpen($mockConnection, $mockRequest); - $this->assertStringContainsString('HTTP/1.1 400', $sent[0]); - $this->assertStringContainsString('Run ID not provided.', $sent[0]); - // Access denied $sent = []; $mockConnection = $this->createMockConnection($sent); - $mockRequest = $this->createMockRequest('/api/file-coverage', 'GET', '', 'runId=123&path=../outside/file.php'); + $mockRequest = $this->createMockRequest('/api/file-coverage', 'GET', '', 'path=../outside/file.php'); $router->onOpen($mockConnection, $mockRequest); $this->assertStringContainsString('HTTP/1.1 403', $sent[0]); $this->assertStringContainsString('Access denied.', $sent[0]); diff --git a/tests/Coverage/CoverageTest.php b/tests/Coverage/CoverageTest.php index bff7c89..5219325 100644 --- a/tests/Coverage/CoverageTest.php +++ b/tests/Coverage/CoverageTest.php @@ -43,14 +43,12 @@ public function testParseReturnsCorrectData(): void - - XML; @@ -227,11 +225,9 @@ public function testParseWithNoStatements(): void - - XML; @@ -264,11 +260,9 @@ public function testParseWithNoPhpunitConfig(): void - - XML; diff --git a/tests/TestRunner/TestRunnerTest.php b/tests/TestRunner/TestRunnerTest.php index 9541451..bd37164 100644 --- a/tests/TestRunner/TestRunnerTest.php +++ b/tests/TestRunner/TestRunnerTest.php @@ -52,7 +52,7 @@ protected function tearDown(): void public function testRunReturnsProcessInstance(): void { $testRunner = new TestRunner($this->loop, $this->tempDir); - $process = $testRunner->run(['filters' => [], 'coverage' => false], 'test-run-id'); + $process = $testRunner->run(['filters' => [], 'coverage' => false]); $this->assertInstanceOf(Process::class, $process); } @@ -85,7 +85,7 @@ public function testRunBuildsCorrectCommandWithCoverage(): void file_put_contents($this->tempDir . '/phpunit.xml', $phpunitXmlContent); $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['filters' => [], 'coverage' => true], 'test-run-id'); + $testRunner->run(['filters' => [], 'coverage' => true]); $command = $testRunner->getLastCommand(); @@ -98,7 +98,7 @@ public function testRunBuildsCorrectCommandWithCoverage(): void public function testRunBuildsCorrectCommandWithFilters(): void { $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['filters' => ['MyTest', 'AnotherTest'], 'coverage' => false], 'test-run-id'); + $testRunner->run(['filters' => ['MyTest', 'AnotherTest'], 'coverage' => false]); $command = $testRunner->getLastCommand(); @@ -109,7 +109,7 @@ public function testRunBuildsCorrectCommandWithFilters(): void public function testRunBuildsCorrectCommandWithSuites(): void { $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['suites' => ['MySuite', 'AnotherSuite'], 'filters' => [], 'coverage' => false], 'test-run-id'); + $testRunner->run(['suites' => ['MySuite', 'AnotherSuite'], 'filters' => [], 'coverage' => false]); $command = $testRunner->getLastCommand(); @@ -121,7 +121,7 @@ public function testRunBuildsCorrectCommandWithSuites(): void public function testRunBuildsCorrectCommandWithGroups(): void { $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['groups' => ['MyGroup', 'AnotherGroup'], 'filters' => [], 'coverage' => false], 'test-run-id'); + $testRunner->run(['groups' => ['MyGroup', 'AnotherGroup'], 'filters' => [], 'coverage' => false]); $command = $testRunner->getLastCommand(); @@ -133,7 +133,7 @@ public function testRunBuildsCorrectCommandWithGroups(): void public function testRunBuildsCorrectCommandWithOptions(): void { $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['options' => ['stopOnFailure' => true], 'filters' => [], 'coverage' => false], 'test-run-id'); + $testRunner->run(['options' => ['stopOnFailure' => true], 'filters' => [], 'coverage' => false]); $command = $testRunner->getLastCommand(); @@ -163,7 +163,7 @@ public function testRunBuildsCorrectCommandWithCoverageAndNoSource(): void file_put_contents($this->tempDir . '/phpunit.xml', $phpunitXmlContent); $testRunner = new TestRunner($this->loop, $this->tempDir); - $testRunner->run(['filters' => [], 'coverage' => true], 'test-run-id'); + $testRunner->run(['filters' => [], 'coverage' => true]); $command = $testRunner->getLastCommand(); diff --git a/vite.config.mjs b/vite.config.mjs new file mode 100644 index 0000000..2291f3b --- /dev/null +++ b/vite.config.mjs @@ -0,0 +1,30 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; + +export default defineConfig({ + plugins: [vue()], + build: { + outDir: 'public/build', + manifest: true, + rollupOptions: { + input: { + main: 'assets/js/main.js', + }, + }, + }, + server: { + watch: { + usePolling: true, + }, + hmr: { + overlay: true, // Mostra errori overlay + }, + }, + test: { + globals: true, + environment: 'jsdom', // Necessario per testare componenti Vue + setupFiles: ['assets/js/tests/vitest.setup.js'], + }, + publicDir: false, // ← Disabilita publicDir o usa un'altra cartella + // Oppure se hai assets statici: publicDir: 'assets' +}); \ No newline at end of file