diff options
78 files changed, 5 insertions, 16978 deletions
@@ -39,7 +39,6 @@ install: build test: ${GO} test -cover ./... - cd frontend && ${NPM} test -- --run cd frontend-vanilla && ${NPM} test -- --run test-race: diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/frontend/.prettierrc b/frontend/.prettierrc deleted file mode 100644 index 1f4c4bb..0000000 --- a/frontend/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "semi": true, - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "es5", - "printWidth": 100 -} diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index c987b94..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## React Compiler - -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]); -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x'; -import reactDom from 'eslint-plugin-react-dom'; - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]); -``` diff --git a/frontend/coverage/base.css b/frontend/coverage/base.css deleted file mode 100644 index f418035..0000000 --- a/frontend/coverage/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/frontend/coverage/block-navigation.js b/frontend/coverage/block-navigation.js deleted file mode 100644 index 530d1ed..0000000 --- a/frontend/coverage/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selector that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/frontend/coverage/clover.xml b/frontend/coverage/clover.xml deleted file mode 100644 index 8eba461..0000000 --- a/frontend/coverage/clover.xml +++ /dev/null @@ -1,385 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<coverage generated="1771133450877" clover="3.2.0"> - <project timestamp="1771133450877" name="All files"> - <metrics statements="331" coveredstatements="286" conditionals="228" coveredconditionals="167" methods="108" coveredmethods="88" elements="667" coveredelements="541" complexity="0" loc="331" ncloc="331" packages="2" files="14" classes="14"/> - <package name="src"> - <metrics statements="45" coveredstatements="32" conditionals="35" coveredconditionals="23" methods="15" coveredmethods="9"/> - <file name="App.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/App.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="App.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx"> - <metrics statements="34" coveredstatements="22" conditionals="25" coveredconditionals="15" methods="13" coveredmethods="7"/> - <line num="9" count="2" type="stmt"/> - <line num="10" count="2" type="stmt"/> - <line num="12" count="2" type="stmt"/> - <line num="13" count="1" type="stmt"/> - <line num="15" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="16" count="1" type="stmt"/> - <line num="18" count="0" type="stmt"/> - <line num="21" count="0" type="stmt"/> - <line num="24" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="25" count="1" type="stmt"/> - <line num="28" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="29" count="0" type="stmt"/> - <line num="32" count="1" type="stmt"/> - <line num="47" count="1" type="stmt"/> - <line num="49" count="1" type="stmt"/> - <line num="50" count="1" type="stmt"/> - <line num="51" count="0" type="cond" truecount="0" falsecount="2"/> - <line num="52" count="0" type="stmt"/> - <line num="54" count="0" type="stmt"/> - <line num="57" count="1" type="stmt"/> - <line num="58" count="1" type="stmt"/> - <line num="61" count="1" type="stmt"/> - <line num="69" count="0" type="stmt"/> - <line num="78" count="0" type="stmt"/> - <line num="103" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="104" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="106" count="2" type="stmt"/> - <line num="107" count="0" type="stmt"/> - <line num="108" count="0" type="stmt"/> - <line num="111" count="2" type="stmt"/> - <line num="112" count="0" type="stmt"/> - <line num="113" count="0" type="stmt"/> - <line num="116" count="2" type="cond" truecount="1" falsecount="1"/> - <line num="118" count="2" type="stmt"/> - </file> - <file name="utils.ts" path="/Users/adam/workspace/vibecode/neko/frontend/src/utils.ts"> - <metrics statements="11" coveredstatements="10" conditionals="10" coveredconditionals="8" methods="2" coveredmethods="2"/> - <line num="2" count="14" type="stmt"/> - <line num="3" count="14" type="stmt"/> - <line num="4" count="14" type="cond" truecount="1" falsecount="1"/> - <line num="12" count="54" type="cond" truecount="2" falsecount="0"/> - <line num="13" count="54" type="stmt"/> - <line num="15" count="54" type="cond" truecount="2" falsecount="0"/> - <line num="17" count="54" type="cond" truecount="2" falsecount="0"/> - <line num="18" count="14" type="stmt"/> - <line num="19" count="14" type="cond" truecount="1" falsecount="1"/> - <line num="20" count="0" type="stmt"/> - <line num="27" count="54" type="stmt"/> - </file> - </package> - <package name="src.components"> - <metrics statements="286" coveredstatements="254" conditionals="193" coveredconditionals="144" methods="93" coveredmethods="79"/> - <file name="FeedItem.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="FeedItem.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.tsx"> - <metrics statements="31" coveredstatements="25" conditionals="23" coveredconditionals="20" methods="12" coveredmethods="10"/> - <line num="12" count="56" type="stmt"/> - <line num="13" count="56" type="stmt"/> - <line num="15" count="56" type="stmt"/> - <line num="16" count="22" type="stmt"/> - <line num="19" count="56" type="stmt"/> - <line num="20" count="1" type="stmt"/> - <line num="23" count="56" type="stmt"/> - <line num="24" count="1" type="stmt"/> - <line num="26" count="1" type="stmt"/> - <line num="27" count="1" type="stmt"/> - <line num="29" count="1" type="stmt"/> - <line num="41" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="42" count="0" type="stmt"/> - <line num="44" count="1" type="stmt"/> - <line num="49" count="1" type="stmt"/> - <line num="52" count="0" type="stmt"/> - <line num="54" count="0" type="stmt"/> - <line num="55" count="0" type="stmt"/> - <line num="59" count="56" type="stmt"/> - <line num="60" count="1" type="stmt"/> - <line num="61" count="1" type="stmt"/> - <line num="62" count="1" type="stmt"/> - <line num="64" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="65" count="1" type="stmt"/> - <line num="68" count="1" type="stmt"/> - <line num="69" count="1" type="stmt"/> - <line num="72" count="0" type="stmt"/> - <line num="73" count="0" type="stmt"/> - <line num="77" count="56" type="stmt"/> - <line num="85" count="1" type="stmt"/> - <line num="86" count="1" type="stmt"/> - </file> - <file name="FeedItems.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="FeedItems.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx"> - <metrics statements="119" coveredstatements="106" conditionals="84" coveredconditionals="64" methods="31" coveredmethods="27"/> - <line num="9" count="36" type="stmt"/> - <line num="10" count="36" type="stmt"/> - <line num="11" count="36" type="cond" truecount="2" falsecount="0"/> - <line num="13" count="36" type="stmt"/> - <line num="14" count="36" type="stmt"/> - <line num="15" count="36" type="stmt"/> - <line num="16" count="36" type="stmt"/> - <line num="17" count="36" type="stmt"/> - <line num="18" count="36" type="stmt"/> - <line num="20" count="36" type="stmt"/> - <line num="21" count="11" type="cond" truecount="2" falsecount="0"/> - <line num="22" count="3" type="stmt"/> - <line num="24" count="8" type="stmt"/> - <line num="25" count="8" type="stmt"/> - <line num="27" count="11" type="stmt"/> - <line num="29" count="11" type="stmt"/> - <line num="30" count="11" type="stmt"/> - <line num="32" count="11" type="cond" truecount="2" falsecount="0"/> - <line num="33" count="2" type="stmt"/> - <line num="34" count="9" type="cond" truecount="2" falsecount="0"/> - <line num="35" count="1" type="stmt"/> - <line num="38" count="11" type="cond" truecount="2" falsecount="0"/> - <line num="39" count="3" type="stmt"/> - <line num="43" count="11" type="stmt"/> - <line num="44" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="45" count="0" type="stmt"/> - <line num="48" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="49" count="0" type="stmt"/> - <line num="50" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="51" count="0" type="stmt"/> - <line num="52" count="0" type="stmt"/> - <line num="55" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="56" count="11" type="stmt"/> - <line num="60" count="11" type="stmt"/> - <line num="61" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="62" count="11" type="stmt"/> - <line num="65" count="11" type="stmt"/> - <line num="67" count="10" type="cond" truecount="1" falsecount="1"/> - <line num="68" count="0" type="stmt"/> - <line num="70" count="10" type="stmt"/> - <line num="73" count="9" type="cond" truecount="2" falsecount="0"/> - <line num="74" count="3" type="stmt"/> - <line num="76" count="6" type="stmt"/> - <line num="78" count="9" type="stmt"/> - <line num="79" count="9" type="stmt"/> - <line num="80" count="9" type="stmt"/> - <line num="83" count="1" type="stmt"/> - <line num="84" count="1" type="stmt"/> - <line num="85" count="1" type="stmt"/> - <line num="89" count="36" type="stmt"/> - <line num="90" count="8" type="stmt"/> - <line num="91" count="8" type="stmt"/> - <line num="96" count="36" type="stmt"/> - <line num="97" count="5" type="stmt"/> - <line num="98" count="5" type="cond" truecount="1" falsecount="1"/> - <line num="99" count="5" type="stmt"/> - <line num="103" count="36" type="stmt"/> - <line num="104" count="2" type="stmt"/> - <line num="106" count="3" type="cond" truecount="2" falsecount="0"/> - <line num="108" count="2" type="stmt"/> - <line num="112" count="0" type="stmt"/> - <line num="115" count="36" type="stmt"/> - <line num="116" count="1" type="stmt"/> - <line num="118" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="120" count="1" type="stmt"/> - <line num="124" count="0" type="stmt"/> - <line num="127" count="36" type="stmt"/> - <line num="128" count="31" type="stmt"/> - <line num="129" count="6" type="cond" truecount="1" falsecount="1"/> - <line num="131" count="6" type="cond" truecount="2" falsecount="0"/> - <line num="132" count="5" type="stmt"/> - <line num="133" count="5" type="stmt"/> - <line num="134" count="5" type="cond" truecount="1" falsecount="1"/> - <line num="135" count="5" type="stmt"/> - <line num="136" count="5" type="cond" truecount="2" falsecount="0"/> - <line num="137" count="1" type="stmt"/> - <line num="139" count="5" type="stmt"/> - <line num="144" count="5" type="cond" truecount="5" falsecount="0"/> - <line num="145" count="2" type="stmt"/> - <line num="148" count="5" type="stmt"/> - <line num="150" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="151" count="0" type="stmt"/> - <line num="152" count="0" type="stmt"/> - <line num="153" count="0" type="cond" truecount="0" falsecount="2"/> - <line num="154" count="0" type="stmt"/> - <line num="156" count="0" type="stmt"/> - <line num="158" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="159" count="1" type="stmt"/> - <line num="160" count="1" type="cond" truecount="3" falsecount="1"/> - <line num="161" count="1" type="stmt"/> - <line num="163" count="1" type="stmt"/> - <line num="168" count="31" type="stmt"/> - <line num="169" count="31" type="stmt"/> - <line num="175" count="36" type="stmt"/> - <line num="177" count="31" type="stmt"/> - <line num="179" count="1" type="stmt"/> - <line num="181" count="1" type="cond" truecount="3" falsecount="1"/> - <line num="182" count="1" type="stmt"/> - <line num="183" count="1" type="cond" truecount="4" falsecount="1"/> - <line num="184" count="1" type="stmt"/> - <line num="185" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="186" count="1" type="stmt"/> - <line num="196" count="31" type="stmt"/> - <line num="198" count="1" type="stmt"/> - <line num="199" count="1" type="cond" truecount="5" falsecount="1"/> - <line num="200" count="1" type="stmt"/> - <line num="207" count="31" type="stmt"/> - <line num="208" count="31" type="stmt"/> - <line num="209" count="31" type="cond" truecount="1" falsecount="1"/> - <line num="212" count="31" type="stmt"/> - <line num="213" count="31" type="cond" truecount="2" falsecount="0"/> - <line num="215" count="31" type="stmt"/> - <line num="216" count="31" type="stmt"/> - <line num="217" count="31" type="stmt"/> - <line num="222" count="36" type="cond" truecount="2" falsecount="0"/> - <line num="223" count="21" type="cond" truecount="2" falsecount="0"/> - <line num="225" count="20" type="stmt"/> - <line num="232" count="44" type="stmt"/> - <line num="237" count="0" type="stmt"/> - </file> - <file name="FeedList.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="FeedList.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.tsx"> - <metrics statements="50" coveredstatements="45" conditionals="50" coveredconditionals="35" methods="19" coveredmethods="15"/> - <line num="19" count="22" type="stmt"/> - <line num="20" count="22" type="stmt"/> - <line num="21" count="22" type="stmt"/> - <line num="22" count="22" type="stmt"/> - <line num="23" count="22" type="stmt"/> - <line num="24" count="22" type="stmt"/> - <line num="25" count="22" type="stmt"/> - <line num="26" count="22" type="stmt"/> - <line num="27" count="22" type="stmt"/> - <line num="28" count="22" type="stmt"/> - <line num="29" count="22" type="stmt"/> - <line num="31" count="22" type="cond" truecount="3" falsecount="0"/> - <line num="33" count="22" type="stmt"/> - <line num="34" count="11" type="stmt"/> - <line num="35" count="11" type="cond" truecount="1" falsecount="1"/> - <line num="36" count="0" type="stmt"/> - <line num="41" count="22" type="cond" truecount="2" falsecount="0"/> - <line num="44" count="22" type="stmt"/> - <line num="45" count="1" type="stmt"/> - <line num="46" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="47" count="1" type="stmt"/> - <line num="51" count="22" type="stmt"/> - <line num="52" count="2" type="stmt"/> - <line num="55" count="22" type="stmt"/> - <line num="56" count="0" type="stmt"/> - <line num="59" count="22" type="stmt"/> - <line num="60" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="61" count="1" type="stmt"/> - <line num="65" count="22" type="stmt"/> - <line num="66" count="9" type="stmt"/> - <line num="68" count="7" type="cond" truecount="1" falsecount="1"/> - <line num="69" count="7" type="stmt"/> - <line num="72" count="7" type="cond" truecount="1" falsecount="1"/> - <line num="73" count="7" type="stmt"/> - <line num="77" count="7" type="stmt"/> - <line num="78" count="7" type="stmt"/> - <line num="79" count="7" type="stmt"/> - <line num="82" count="1" type="stmt"/> - <line num="83" count="1" type="stmt"/> - <line num="87" count="22" type="cond" truecount="2" falsecount="0"/> - <line num="88" count="13" type="cond" truecount="2" falsecount="0"/> - <line num="90" count="12" type="stmt"/> - <line num="91" count="2" type="stmt"/> - <line num="94" count="12" type="stmt"/> - <line num="96" count="0" type="stmt"/> - <line num="106" count="1" type="stmt"/> - <line num="139" count="4" type="stmt"/> - <line num="163" count="2" type="stmt"/> - <line num="195" count="0" type="stmt"/> - <line num="202" count="0" type="stmt"/> - </file> - <file name="FeedListVariants.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedListVariants.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="Login.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="Login.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.tsx"> - <metrics statements="20" coveredstatements="20" conditionals="6" coveredconditionals="5" methods="4" coveredmethods="4"/> - <line num="8" count="17" type="stmt"/> - <line num="9" count="17" type="stmt"/> - <line num="10" count="17" type="stmt"/> - <line num="11" count="17" type="stmt"/> - <line num="13" count="17" type="stmt"/> - <line num="14" count="3" type="stmt"/> - <line num="15" count="3" type="stmt"/> - <line num="17" count="3" type="stmt"/> - <line num="19" count="3" type="stmt"/> - <line num="20" count="3" type="stmt"/> - <line num="21" count="3" type="stmt"/> - <line num="23" count="3" type="stmt"/> - <line num="28" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="29" count="1" type="stmt"/> - <line num="31" count="1" type="stmt"/> - <line num="32" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="35" count="1" type="stmt"/> - <line num="39" count="17" type="stmt"/> - <line num="49" count="3" type="stmt"/> - <line num="58" count="3" type="stmt"/> - </file> - <file name="Settings.css" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.css"> - <metrics statements="0" coveredstatements="0" conditionals="0" coveredconditionals="0" methods="0" coveredmethods="0"/> - </file> - <file name="Settings.tsx" path="/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.tsx"> - <metrics statements="66" coveredstatements="58" conditionals="30" coveredconditionals="20" methods="27" coveredmethods="23"/> - <line num="12" count="34" type="stmt"/> - <line num="14" count="34" type="stmt"/> - <line num="15" count="34" type="stmt"/> - <line num="16" count="34" type="stmt"/> - <line num="18" count="34" type="stmt"/> - <line num="21" count="34" type="stmt"/> - <line num="22" count="9" type="stmt"/> - <line num="23" count="9" type="stmt"/> - <line num="25" count="9" type="cond" truecount="1" falsecount="1"/> - <line num="26" count="9" type="stmt"/> - <line num="29" count="9" type="stmt"/> - <line num="30" count="9" type="stmt"/> - <line num="33" count="0" type="stmt"/> - <line num="34" count="0" type="stmt"/> - <line num="38" count="34" type="stmt"/> - <line num="40" count="7" type="stmt"/> - <line num="44" count="34" type="stmt"/> - <line num="45" count="2" type="stmt"/> - <line num="46" count="2" type="cond" truecount="1" falsecount="1"/> - <line num="48" count="2" type="stmt"/> - <line num="49" count="2" type="stmt"/> - <line num="55" count="2" type="cond" truecount="2" falsecount="0"/> - <line num="56" count="1" type="stmt"/> - <line num="59" count="1" type="stmt"/> - <line num="60" count="1" type="stmt"/> - <line num="63" count="1" type="stmt"/> - <line num="64" count="1" type="stmt"/> - <line num="68" count="34" type="stmt"/> - <line num="69" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="71" count="1" type="stmt"/> - <line num="72" count="1" type="stmt"/> - <line num="76" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="77" count="1" type="stmt"/> - <line num="78" count="1" type="stmt"/> - <line num="81" count="0" type="stmt"/> - <line num="82" count="0" type="stmt"/> - <line num="86" count="34" type="stmt"/> - <line num="87" count="1" type="stmt"/> - <line num="88" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="90" count="1" type="stmt"/> - <line num="91" count="1" type="stmt"/> - <line num="92" count="1" type="stmt"/> - <line num="93" count="1" type="stmt"/> - <line num="95" count="1" type="stmt"/> - <line num="100" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="101" count="1" type="stmt"/> - <line num="104" count="1" type="stmt"/> - <line num="105" count="1" type="stmt"/> - <line num="106" count="1" type="stmt"/> - <line num="109" count="0" type="stmt"/> - <line num="110" count="0" type="stmt"/> - <line num="114" count="34" type="stmt"/> - <line num="115" count="1" type="stmt"/> - <line num="116" count="1" type="stmt"/> - <line num="120" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="121" count="1" type="stmt"/> - <line num="124" count="1" type="stmt"/> - <line num="125" count="1" type="stmt"/> - <line num="128" count="0" type="stmt"/> - <line num="129" count="0" type="stmt"/> - <line num="133" count="34" type="stmt"/> - <line num="145" count="1" type="stmt"/> - <line num="163" count="2" type="stmt"/> - <line num="183" count="1" type="cond" truecount="1" falsecount="1"/> - <line num="217" count="6" type="stmt"/> - <line num="223" count="1" type="stmt"/> - </file> - </package> - </project> -</coverage> diff --git a/frontend/coverage/coverage-final.json b/frontend/coverage/coverage-final.json deleted file mode 100644 index b8f97aa..0000000 --- a/frontend/coverage/coverage-final.json +++ /dev/null @@ -1,15 +0,0 @@ -{"/Users/adam/workspace/vibecode/neko/frontend/src/App.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/App.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx","statementMap":{"0":{"start":{"line":9,"column":22},"end":{"line":9,"column":null}},"1":{"start":{"line":10,"column":8},"end":{"line":10,"column":null}},"2":{"start":{"line":12,"column":2},"end":{"line":22,"column":null}},"3":{"start":{"line":13,"column":4},"end":{"line":21,"column":null}},"4":{"start":{"line":15,"column":8},"end":{"line":19,"column":null}},"5":{"start":{"line":16,"column":10},"end":{"line":16,"column":null}},"6":{"start":{"line":18,"column":10},"end":{"line":18,"column":null}},"7":{"start":{"line":21,"column":19},"end":{"line":21,"column":33}},"8":{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},"9":{"start":{"line":25,"column":4},"end":{"line":25,"column":null}},"10":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"11":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"12":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"13":{"start":{"line":47,"column":42},"end":{"line":47,"column":null}},"14":{"start":{"line":49,"column":2},"end":{"line":59,"column":null}},"15":{"start":{"line":50,"column":25},"end":{"line":56,"column":null}},"16":{"start":{"line":51,"column":6},"end":{"line":55,"column":null}},"17":{"start":{"line":52,"column":8},"end":{"line":52,"column":null}},"18":{"start":{"line":54,"column":8},"end":{"line":54,"column":null}},"19":{"start":{"line":57,"column":4},"end":{"line":57,"column":null}},"20":{"start":{"line":58,"column":4},"end":{"line":58,"column":null}},"21":{"start":{"line":58,"column":17},"end":{"line":58,"column":null}},"22":{"start":{"line":61,"column":2},"end":{"line":98,"column":null}},"23":{"start":{"line":69,"column":27},"end":{"line":69,"column":null}},"24":{"start":{"line":78,"column":27},"end":{"line":78,"column":null}},"25":{"start":{"line":103,"column":24},"end":{"line":103,"column":null}},"26":{"start":{"line":104,"column":32},"end":{"line":104,"column":null}},"27":{"start":{"line":106,"column":25},"end":{"line":109,"column":null}},"28":{"start":{"line":107,"column":4},"end":{"line":107,"column":null}},"29":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"30":{"start":{"line":111,"column":29},"end":{"line":114,"column":null}},"31":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"32":{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},"33":{"start":{"line":116,"column":19},"end":{"line":116,"column":null}},"34":{"start":{"line":118,"column":2},"end":{"line":136,"column":null}}},"fnMap":{"0":{"name":"RequireAuth","decl":{"start":{"line":8,"column":9},"end":{"line":8,"column":21}},"loc":{"start":{"line":8,"column":69},"end":{"line":33,"column":null}},"line":8},"1":{"name":"(anonymous_1)","decl":{"start":{"line":12,"column":12},"end":{"line":12,"column":18}},"loc":{"start":{"line":12,"column":18},"end":{"line":22,"column":5}},"line":12},"2":{"name":"(anonymous_2)","decl":{"start":{"line":14,"column":12},"end":{"line":14,"column":13}},"loc":{"start":{"line":14,"column":21},"end":{"line":20,"column":7}},"line":14},"3":{"name":"(anonymous_3)","decl":{"start":{"line":21,"column":13},"end":{"line":21,"column":19}},"loc":{"start":{"line":21,"column":19},"end":{"line":21,"column":33}},"line":21},"4":{"name":"Dashboard","decl":{"start":{"line":46,"column":9},"end":{"line":46,"column":19}},"loc":{"start":{"line":46,"column":81},"end":{"line":100,"column":null}},"line":46},"5":{"name":"(anonymous_5)","decl":{"start":{"line":49,"column":12},"end":{"line":49,"column":18}},"loc":{"start":{"line":49,"column":18},"end":{"line":59,"column":5}},"line":49},"6":{"name":"(anonymous_6)","decl":{"start":{"line":50,"column":25},"end":{"line":50,"column":31}},"loc":{"start":{"line":50,"column":31},"end":{"line":56,"column":null}},"line":50},"7":{"name":"(anonymous_7)","decl":{"start":{"line":58,"column":11},"end":{"line":58,"column":17}},"loc":{"start":{"line":58,"column":17},"end":{"line":58,"column":null}},"line":58},"8":{"name":"(anonymous_8)","decl":{"start":{"line":69,"column":21},"end":{"line":69,"column":27}},"loc":{"start":{"line":69,"column":27},"end":{"line":69,"column":null}},"line":69},"9":{"name":"(anonymous_9)","decl":{"start":{"line":78,"column":21},"end":{"line":78,"column":27}},"loc":{"start":{"line":78,"column":27},"end":{"line":78,"column":null}},"line":78},"10":{"name":"App","decl":{"start":{"line":102,"column":9},"end":{"line":102,"column":15}},"loc":{"start":{"line":102,"column":15},"end":{"line":138,"column":null}},"line":102},"11":{"name":"(anonymous_11)","decl":{"start":{"line":106,"column":25},"end":{"line":106,"column":26}},"loc":{"start":{"line":106,"column":47},"end":{"line":109,"column":null}},"line":106},"12":{"name":"(anonymous_12)","decl":{"start":{"line":111,"column":29},"end":{"line":111,"column":30}},"loc":{"start":{"line":111,"column":55},"end":{"line":114,"column":null}},"line":111}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":8},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":8},"end":{"line":19,"column":null}},{"start":{"line":17,"column":15},"end":{"line":19,"column":null}}],"line":15},"1":{"loc":{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},{"start":{},"end":{}}],"line":24},"2":{"loc":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":28},"3":{"loc":{"start":{"line":51,"column":6},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":55,"column":null}},{"start":{"line":53,"column":13},"end":{"line":55,"column":null}}],"line":51},"4":{"loc":{"start":{"line":63,"column":30},"end":{"line":63,"column":83}},"type":"cond-expr","locations":[{"start":{"line":63,"column":47},"end":{"line":63,"column":67}},{"start":{"line":63,"column":67},"end":{"line":63,"column":83}}],"line":63},"5":{"loc":{"start":{"line":66,"column":10},"end":{"line":73,"column":null}},"type":"binary-expr","locations":[{"start":{"line":66,"column":10},"end":{"line":66,"column":29}},{"start":{"line":66,"column":29},"end":{"line":66,"column":null}},{"start":{"line":67,"column":10},"end":{"line":73,"column":null}}],"line":66},"6":{"loc":{"start":{"line":70,"column":19},"end":{"line":70,"column":null}},"type":"cond-expr","locations":[{"start":{"line":70,"column":36},"end":{"line":70,"column":53}},{"start":{"line":70,"column":53},"end":{"line":70,"column":null}}],"line":70},"7":{"loc":{"start":{"line":75,"column":9},"end":{"line":79,"column":null}},"type":"binary-expr","locations":[{"start":{"line":75,"column":9},"end":{"line":75,"column":null}},{"start":{"line":76,"column":10},"end":{"line":79,"column":null}}],"line":75},"8":{"loc":{"start":{"line":81,"column":47},"end":{"line":81,"column":77}},"type":"cond-expr","locations":[{"start":{"line":81,"column":64},"end":{"line":81,"column":69}},{"start":{"line":81,"column":69},"end":{"line":81,"column":77}}],"line":81},"9":{"loc":{"start":{"line":103,"column":37},"end":{"line":103,"column":82}},"type":"binary-expr","locations":[{"start":{"line":103,"column":37},"end":{"line":103,"column":75}},{"start":{"line":103,"column":75},"end":{"line":103,"column":82}}],"line":103},"10":{"loc":{"start":{"line":104,"column":45},"end":{"line":104,"column":97}},"type":"binary-expr","locations":[{"start":{"line":104,"column":45},"end":{"line":104,"column":88}},{"start":{"line":104,"column":88},"end":{"line":104,"column":97}}],"line":104},"11":{"loc":{"start":{"line":116,"column":19},"end":{"line":116,"column":null}},"type":"cond-expr","locations":[{"start":{"line":116,"column":64},"end":{"line":116,"column":72}},{"start":{"line":116,"column":72},"end":{"line":116,"column":null}}],"line":116}},"s":{"0":2,"1":2,"2":2,"3":1,"4":1,"5":1,"6":0,"7":0,"8":2,"9":1,"10":1,"11":0,"12":1,"13":1,"14":1,"15":1,"16":0,"17":0,"18":0,"19":1,"20":1,"21":1,"22":1,"23":0,"24":0,"25":2,"26":2,"27":2,"28":0,"29":0,"30":2,"31":0,"32":0,"33":2,"34":2},"f":{"0":2,"1":1,"2":1,"3":0,"4":1,"5":1,"6":0,"7":1,"8":0,"9":0,"10":2,"11":0,"12":0},"b":{"0":[1,0],"1":[1,1],"2":[0,1],"3":[0,0],"4":[1,0],"5":[1,1,0],"6":[0,0],"7":[1,1],"8":[1,0],"9":[2,2],"10":[2,2],"11":[2,0]},"meta":{"lastBranch":12,"lastFunction":13,"lastStatement":35,"seen":{"f:8:9:8:21":0,"s:9:22:9:Infinity":0,"s:10:8:10:Infinity":1,"s:12:2:22:Infinity":2,"f:12:12:12:18":1,"s:13:4:21:Infinity":3,"f:14:12:14:13":2,"b:15:8:19:Infinity:17:15:19:Infinity":0,"s:15:8:19:Infinity":4,"s:16:10:16:Infinity":5,"s:18:10:18:Infinity":6,"f:21:13:21:19":3,"s:21:19:21:33":7,"b:24:2:26:Infinity:undefined:undefined:undefined:undefined":1,"s:24:2:26:Infinity":8,"s:25:4:25:Infinity":9,"b:28:2:30:Infinity:undefined:undefined:undefined:undefined":2,"s:28:2:30:Infinity":10,"s:29:4:29:Infinity":11,"s:32:2:32:Infinity":12,"f:46:9:46:19":4,"s:47:42:47:Infinity":13,"s:49:2:59:Infinity":14,"f:49:12:49:18":5,"s:50:25:56:Infinity":15,"f:50:25:50:31":6,"b:51:6:55:Infinity:53:13:55:Infinity":3,"s:51:6:55:Infinity":16,"s:52:8:52:Infinity":17,"s:54:8:54:Infinity":18,"s:57:4:57:Infinity":19,"s:58:4:58:Infinity":20,"f:58:11:58:17":7,"s:58:17:58:Infinity":21,"s:61:2:98:Infinity":22,"b:63:47:63:67:63:67:63:83":4,"b:66:10:66:29:66:29:66:Infinity:67:10:73:Infinity":5,"f:69:21:69:27":8,"s:69:27:69:Infinity":23,"b:70:36:70:53:70:53:70:Infinity":6,"b:75:9:75:Infinity:76:10:79:Infinity":7,"f:78:21:78:27":9,"s:78:27:78:Infinity":24,"b:81:64:81:69:81:69:81:77":8,"f:102:9:102:15":10,"s:103:24:103:Infinity":25,"b:103:37:103:75:103:75:103:82":9,"s:104:32:104:Infinity":26,"b:104:45:104:88:104:88:104:97":10,"s:106:25:109:Infinity":27,"f:106:25:106:26":11,"s:107:4:107:Infinity":28,"s:108:4:108:Infinity":29,"s:111:29:114:Infinity":30,"f:111:29:111:30":12,"s:112:4:112:Infinity":31,"s:113:4:113:Infinity":32,"s:116:19:116:Infinity":33,"b:116:64:116:72:116:72:116:Infinity":11,"s:118:2:136:Infinity":34}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/utils.ts": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/utils.ts","statementMap":{"0":{"start":{"line":2,"column":18},"end":{"line":2,"column":null}},"1":{"start":{"line":3,"column":18},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":4},"end":{"line":4,"column":null}},"3":{"start":{"line":4,"column":28},"end":{"line":4,"column":null}},"4":{"start":{"line":12,"column":19},"end":{"line":12,"column":null}},"5":{"start":{"line":13,"column":28},"end":{"line":13,"column":null}},"6":{"start":{"line":15,"column":20},"end":{"line":15,"column":null}},"7":{"start":{"line":17,"column":4},"end":{"line":22,"column":null}},"8":{"start":{"line":18,"column":22},"end":{"line":18,"column":null}},"9":{"start":{"line":19,"column":8},"end":{"line":21,"column":null}},"10":{"start":{"line":20,"column":12},"end":{"line":20,"column":null}},"11":{"start":{"line":27,"column":4},"end":{"line":31,"column":null}}},"fnMap":{"0":{"name":"getCookie","decl":{"start":{"line":1,"column":16},"end":{"line":1,"column":26}},"loc":{"start":{"line":1,"column":60},"end":{"line":5,"column":null}},"line":1},"1":{"name":"apiFetch","decl":{"start":{"line":11,"column":22},"end":{"line":11,"column":31}},"loc":{"start":{"line":11,"column":96},"end":{"line":32,"column":null}},"line":11}},"branchMap":{"0":{"loc":{"start":{"line":4,"column":4},"end":{"line":4,"column":null}},"type":"if","locations":[{"start":{"line":4,"column":4},"end":{"line":4,"column":null}},{"start":{},"end":{}}],"line":4},"1":{"loc":{"start":{"line":12,"column":19},"end":{"line":12,"column":null}},"type":"binary-expr","locations":[{"start":{"line":12,"column":19},"end":{"line":12,"column":50}},{"start":{"line":12,"column":50},"end":{"line":12,"column":null}}],"line":12},"2":{"loc":{"start":{"line":15,"column":32},"end":{"line":15,"column":51}},"type":"binary-expr","locations":[{"start":{"line":15,"column":32},"end":{"line":15,"column":49}},{"start":{"line":15,"column":49},"end":{"line":15,"column":51}}],"line":15},"3":{"loc":{"start":{"line":17,"column":4},"end":{"line":22,"column":null}},"type":"if","locations":[{"start":{"line":17,"column":4},"end":{"line":22,"column":null}},{"start":{},"end":{}}],"line":17},"4":{"loc":{"start":{"line":19,"column":8},"end":{"line":21,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":8},"end":{"line":21,"column":null}},{"start":{},"end":{}}],"line":19}},"s":{"0":14,"1":14,"2":14,"3":0,"4":54,"5":54,"6":54,"7":54,"8":14,"9":14,"10":0,"11":54},"f":{"0":14,"1":54},"b":{"0":[0,14],"1":[54,40],"2":[54,48],"3":[14,40],"4":[0,14]},"meta":{"lastBranch":5,"lastFunction":2,"lastStatement":12,"seen":{"f:1:16:1:26":0,"s:2:18:2:Infinity":0,"s:3:18:3:Infinity":1,"b:4:4:4:Infinity:undefined:undefined:undefined:undefined":0,"s:4:4:4:Infinity":2,"s:4:28:4:Infinity":3,"f:11:22:11:31":1,"s:12:19:12:Infinity":4,"b:12:19:12:50:12:50:12:Infinity":1,"s:13:28:13:Infinity":5,"s:15:20:15:Infinity":6,"b:15:32:15:49:15:49:15:51":2,"b:17:4:22:Infinity:undefined:undefined:undefined:undefined":3,"s:17:4:22:Infinity":7,"s:18:22:18:Infinity":8,"b:19:8:21:Infinity:undefined:undefined:undefined:undefined":4,"s:19:8:21:Infinity":9,"s:20:12:20:Infinity":10,"s:27:4:31:Infinity":11}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.tsx","statementMap":{"0":{"start":{"line":12,"column":22},"end":{"line":12,"column":null}},"1":{"start":{"line":13,"column":28},"end":{"line":13,"column":null}},"2":{"start":{"line":15,"column":2},"end":{"line":17,"column":null}},"3":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"4":{"start":{"line":19,"column":21},"end":{"line":21,"column":null}},"5":{"start":{"line":20,"column":4},"end":{"line":20,"column":null}},"6":{"start":{"line":23,"column":21},"end":{"line":57,"column":null}},"7":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"8":{"start":{"line":26,"column":25},"end":{"line":26,"column":null}},"9":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"10":{"start":{"line":29,"column":4},"end":{"line":56,"column":null}},"11":{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},"12":{"start":{"line":42,"column":10},"end":{"line":42,"column":null}},"13":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"14":{"start":{"line":49,"column":8},"end":{"line":49,"column":null}},"15":{"start":{"line":52,"column":8},"end":{"line":52,"column":null}},"16":{"start":{"line":54,"column":8},"end":{"line":54,"column":null}},"17":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"18":{"start":{"line":59,"column":26},"end":{"line":75,"column":null}},"19":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"20":{"start":{"line":61,"column":4},"end":{"line":61,"column":null}},"21":{"start":{"line":62,"column":4},"end":{"line":74,"column":null}},"22":{"start":{"line":64,"column":8},"end":{"line":64,"column":null}},"23":{"start":{"line":64,"column":21},"end":{"line":64,"column":null}},"24":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"25":{"start":{"line":68,"column":8},"end":{"line":68,"column":null}},"26":{"start":{"line":69,"column":8},"end":{"line":69,"column":null}},"27":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"28":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}},"29":{"start":{"line":77,"column":2},"end":{"line":113,"column":null}},"30":{"start":{"line":85,"column":12},"end":{"line":85,"column":null}},"31":{"start":{"line":86,"column":12},"end":{"line":86,"column":null}}},"fnMap":{"0":{"name":"FeedItem","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":33}},"loc":{"start":{"line":11,"column":71},"end":{"line":115,"column":null}},"line":11},"1":{"name":"(anonymous_1)","decl":{"start":{"line":15,"column":12},"end":{"line":15,"column":18}},"loc":{"start":{"line":15,"column":18},"end":{"line":17,"column":5}},"line":15},"2":{"name":"(anonymous_2)","decl":{"start":{"line":19,"column":21},"end":{"line":19,"column":27}},"loc":{"start":{"line":19,"column":27},"end":{"line":21,"column":null}},"line":19},"3":{"name":"(anonymous_3)","decl":{"start":{"line":23,"column":21},"end":{"line":23,"column":22}},"loc":{"start":{"line":23,"column":40},"end":{"line":57,"column":null}},"line":23},"4":{"name":"(anonymous_4)","decl":{"start":{"line":40,"column":12},"end":{"line":40,"column":13}},"loc":{"start":{"line":40,"column":21},"end":{"line":45,"column":7}},"line":40},"5":{"name":"(anonymous_5)","decl":{"start":{"line":46,"column":12},"end":{"line":46,"column":18}},"loc":{"start":{"line":46,"column":18},"end":{"line":50,"column":7}},"line":46},"6":{"name":"(anonymous_6)","decl":{"start":{"line":51,"column":13},"end":{"line":51,"column":14}},"loc":{"start":{"line":51,"column":22},"end":{"line":56,"column":7}},"line":51},"7":{"name":"(anonymous_7)","decl":{"start":{"line":59,"column":26},"end":{"line":59,"column":27}},"loc":{"start":{"line":59,"column":51},"end":{"line":75,"column":null}},"line":59},"8":{"name":"(anonymous_8)","decl":{"start":{"line":63,"column":12},"end":{"line":63,"column":13}},"loc":{"start":{"line":63,"column":21},"end":{"line":66,"column":7}},"line":63},"9":{"name":"(anonymous_9)","decl":{"start":{"line":67,"column":12},"end":{"line":67,"column":13}},"loc":{"start":{"line":67,"column":22},"end":{"line":70,"column":7}},"line":67},"10":{"name":"(anonymous_10)","decl":{"start":{"line":71,"column":13},"end":{"line":71,"column":14}},"loc":{"start":{"line":71,"column":22},"end":{"line":74,"column":7}},"line":71},"11":{"name":"(anonymous_11)","decl":{"start":{"line":84,"column":19},"end":{"line":84,"column":20}},"loc":{"start":{"line":84,"column":26},"end":{"line":87,"column":null}},"line":84}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":8},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":41},"1":{"loc":{"start":{"line":64,"column":8},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":64},"2":{"loc":{"start":{"line":78,"column":32},"end":{"line":78,"column":61}},"type":"cond-expr","locations":[{"start":{"line":78,"column":44},"end":{"line":78,"column":53}},{"start":{"line":78,"column":53},"end":{"line":78,"column":61}}],"line":78},"3":{"loc":{"start":{"line":78,"column":65},"end":{"line":78,"column":89}},"type":"cond-expr","locations":[{"start":{"line":78,"column":75},"end":{"line":78,"column":87}},{"start":{"line":78,"column":87},"end":{"line":78,"column":89}}],"line":78},"4":{"loc":{"start":{"line":81,"column":11},"end":{"line":81,"column":null}},"type":"binary-expr","locations":[{"start":{"line":81,"column":11},"end":{"line":81,"column":25}},{"start":{"line":81,"column":25},"end":{"line":81,"column":null}}],"line":81},"5":{"loc":{"start":{"line":88,"column":33},"end":{"line":88,"column":77}},"type":"cond-expr","locations":[{"start":{"line":88,"column":48},"end":{"line":88,"column":63}},{"start":{"line":88,"column":63},"end":{"line":88,"column":77}}],"line":88},"6":{"loc":{"start":{"line":89,"column":17},"end":{"line":89,"column":null}},"type":"cond-expr","locations":[{"start":{"line":89,"column":32},"end":{"line":89,"column":43}},{"start":{"line":89,"column":43},"end":{"line":89,"column":null}}],"line":89},"7":{"loc":{"start":{"line":97,"column":11},"end":{"line":97,"column":null}},"type":"binary-expr","locations":[{"start":{"line":97,"column":11},"end":{"line":97,"column":30}},{"start":{"line":97,"column":30},"end":{"line":97,"column":null}}],"line":97},"8":{"loc":{"start":{"line":100,"column":11},"end":{"line":103,"column":null}},"type":"binary-expr","locations":[{"start":{"line":100,"column":11},"end":{"line":100,"column":null}},{"start":{"line":101,"column":12},"end":{"line":103,"column":null}}],"line":100},"9":{"loc":{"start":{"line":106,"column":6},"end":{"line":111,"column":null}},"type":"binary-expr","locations":[{"start":{"line":107,"column":8},"end":{"line":107,"column":29}},{"start":{"line":107,"column":29},"end":{"line":107,"column":null}},{"start":{"line":108,"column":8},"end":{"line":111,"column":null}}],"line":106},"10":{"loc":{"start":{"line":110,"column":45},"end":{"line":110,"column":83}},"type":"binary-expr","locations":[{"start":{"line":110,"column":45},"end":{"line":110,"column":66}},{"start":{"line":110,"column":66},"end":{"line":110,"column":83}}],"line":110}},"s":{"0":56,"1":56,"2":56,"3":22,"4":56,"5":1,"6":56,"7":1,"8":1,"9":1,"10":1,"11":1,"12":0,"13":1,"14":1,"15":0,"16":0,"17":0,"18":56,"19":1,"20":1,"21":1,"22":1,"23":0,"24":1,"25":1,"26":1,"27":0,"28":0,"29":56,"30":1,"31":1},"f":{"0":56,"1":22,"2":1,"3":1,"4":1,"5":1,"6":0,"7":1,"8":1,"9":1,"10":0,"11":1},"b":{"0":[0,1],"1":[0,1],"2":[38,18],"3":[4,52],"4":[56,0],"5":[5,51],"6":[5,51],"7":[56,13],"8":[56,55],"9":[56,55,12],"10":[12,11]},"meta":{"lastBranch":11,"lastFunction":12,"lastStatement":32,"seen":{"f:11:24:11:33":0,"s:12:22:12:Infinity":0,"s:13:28:13:Infinity":1,"s:15:2:17:Infinity":2,"f:15:12:15:18":1,"s:16:4:16:Infinity":3,"s:19:21:21:Infinity":4,"f:19:21:19:27":2,"s:20:4:20:Infinity":5,"s:23:21:57:Infinity":6,"f:23:21:23:22":3,"s:24:4:24:Infinity":7,"s:26:25:26:Infinity":8,"s:27:4:27:Infinity":9,"s:29:4:56:Infinity":10,"f:40:12:40:13":4,"b:41:8:43:Infinity:undefined:undefined:undefined:undefined":0,"s:41:8:43:Infinity":11,"s:42:10:42:Infinity":12,"s:44:8:44:Infinity":13,"f:46:12:46:18":5,"s:49:8:49:Infinity":14,"f:51:13:51:14":6,"s:52:8:52:Infinity":15,"s:54:8:54:Infinity":16,"s:55:8:55:Infinity":17,"s:59:26:75:Infinity":18,"f:59:26:59:27":7,"s:60:4:60:Infinity":19,"s:61:4:61:Infinity":20,"s:62:4:74:Infinity":21,"f:63:12:63:13":8,"b:64:8:64:Infinity:undefined:undefined:undefined:undefined":1,"s:64:8:64:Infinity":22,"s:64:21:64:Infinity":23,"s:65:8:65:Infinity":24,"f:67:12:67:13":9,"s:68:8:68:Infinity":25,"s:69:8:69:Infinity":26,"f:71:13:71:14":10,"s:72:8:72:Infinity":27,"s:73:8:73:Infinity":28,"s:77:2:113:Infinity":29,"b:78:44:78:53:78:53:78:61":2,"b:78:75:78:87:78:87:78:89":3,"b:81:11:81:25:81:25:81:Infinity":4,"f:84:19:84:20":11,"s:85:12:85:Infinity":30,"s:86:12:86:Infinity":31,"b:88:48:88:63:88:63:88:77":5,"b:89:32:89:43:89:43:89:Infinity":6,"b:97:11:97:30:97:30:97:Infinity":7,"b:100:11:100:Infinity:101:12:103:Infinity":8,"b:107:8:107:29:107:29:107:Infinity:108:8:111:Infinity":9,"b:110:45:110:66:110:66:110:83":10}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx","statementMap":{"0":{"start":{"line":9,"column":26},"end":{"line":9,"column":null}},"1":{"start":{"line":10,"column":21},"end":{"line":10,"column":null}},"2":{"start":{"line":11,"column":19},"end":{"line":11,"column":null}},"3":{"start":{"line":13,"column":24},"end":{"line":13,"column":null}},"4":{"start":{"line":14,"column":28},"end":{"line":14,"column":null}},"5":{"start":{"line":15,"column":36},"end":{"line":15,"column":null}},"6":{"start":{"line":16,"column":28},"end":{"line":16,"column":null}},"7":{"start":{"line":17,"column":24},"end":{"line":17,"column":null}},"8":{"start":{"line":18,"column":40},"end":{"line":18,"column":null}},"9":{"start":{"line":20,"column":21},"end":{"line":87,"column":null}},"10":{"start":{"line":21,"column":4},"end":{"line":26,"column":null}},"11":{"start":{"line":22,"column":6},"end":{"line":22,"column":null}},"12":{"start":{"line":24,"column":6},"end":{"line":24,"column":null}},"13":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"14":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"15":{"start":{"line":29,"column":14},"end":{"line":29,"column":null}},"16":{"start":{"line":30,"column":19},"end":{"line":30,"column":null}},"17":{"start":{"line":32,"column":4},"end":{"line":36,"column":null}},"18":{"start":{"line":33,"column":6},"end":{"line":33,"column":null}},"19":{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},"20":{"start":{"line":35,"column":6},"end":{"line":35,"column":null}},"21":{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},"22":{"start":{"line":39,"column":6},"end":{"line":39,"column":null}},"23":{"start":{"line":43,"column":24},"end":{"line":43,"column":null}},"24":{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},"25":{"start":{"line":45,"column":6},"end":{"line":45,"column":null}},"26":{"start":{"line":48,"column":4},"end":{"line":58,"column":null}},"27":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"28":{"start":{"line":50,"column":4},"end":{"line":58,"column":null}},"29":{"start":{"line":51,"column":6},"end":{"line":51,"column":null}},"30":{"start":{"line":52,"column":6},"end":{"line":52,"column":null}},"31":{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},"32":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"33":{"start":{"line":60,"column":24},"end":{"line":60,"column":null}},"34":{"start":{"line":61,"column":4},"end":{"line":63,"column":null}},"35":{"start":{"line":62,"column":6},"end":{"line":62,"column":null}},"36":{"start":{"line":65,"column":4},"end":{"line":86,"column":null}},"37":{"start":{"line":67,"column":8},"end":{"line":69,"column":null}},"38":{"start":{"line":68,"column":10},"end":{"line":68,"column":null}},"39":{"start":{"line":70,"column":8},"end":{"line":70,"column":null}},"40":{"start":{"line":73,"column":8},"end":{"line":77,"column":null}},"41":{"start":{"line":74,"column":10},"end":{"line":74,"column":null}},"42":{"start":{"line":74,"column":29},"end":{"line":74,"column":47}},"43":{"start":{"line":76,"column":10},"end":{"line":76,"column":null}},"44":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"45":{"start":{"line":79,"column":8},"end":{"line":79,"column":null}},"46":{"start":{"line":80,"column":8},"end":{"line":80,"column":null}},"47":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"48":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"49":{"start":{"line":85,"column":8},"end":{"line":85,"column":null}},"50":{"start":{"line":89,"column":2},"end":{"line":93,"column":null}},"51":{"start":{"line":90,"column":4},"end":{"line":90,"column":null}},"52":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"53":{"start":{"line":96,"column":23},"end":{"line":101,"column":null}},"54":{"start":{"line":97,"column":20},"end":{"line":97,"column":null}},"55":{"start":{"line":98,"column":4},"end":{"line":100,"column":null}},"56":{"start":{"line":99,"column":6},"end":{"line":99,"column":null}},"57":{"start":{"line":103,"column":21},"end":{"line":113,"column":null}},"58":{"start":{"line":104,"column":24},"end":{"line":104,"column":null}},"59":{"start":{"line":106,"column":4},"end":{"line":106,"column":null}},"60":{"start":{"line":106,"column":28},"end":{"line":106,"column":88}},"61":{"start":{"line":106,"column":50},"end":{"line":106,"column":87}},"62":{"start":{"line":108,"column":4},"end":{"line":112,"column":null}},"63":{"start":{"line":112,"column":22},"end":{"line":112,"column":63}},"64":{"start":{"line":115,"column":21},"end":{"line":125,"column":null}},"65":{"start":{"line":116,"column":24},"end":{"line":116,"column":null}},"66":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"67":{"start":{"line":118,"column":28},"end":{"line":118,"column":88}},"68":{"start":{"line":118,"column":50},"end":{"line":118,"column":87}},"69":{"start":{"line":120,"column":4},"end":{"line":124,"column":null}},"70":{"start":{"line":124,"column":22},"end":{"line":124,"column":65}},"71":{"start":{"line":127,"column":2},"end":{"line":171,"column":null}},"72":{"start":{"line":128,"column":26},"end":{"line":166,"column":null}},"73":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"74":{"start":{"line":129,"column":30},"end":{"line":129,"column":null}},"75":{"start":{"line":131,"column":6},"end":{"line":165,"column":null}},"76":{"start":{"line":132,"column":8},"end":{"line":149,"column":null}},"77":{"start":{"line":133,"column":28},"end":{"line":133,"column":null}},"78":{"start":{"line":134,"column":10},"end":{"line":140,"column":null}},"79":{"start":{"line":135,"column":25},"end":{"line":135,"column":null}},"80":{"start":{"line":136,"column":12},"end":{"line":138,"column":null}},"81":{"start":{"line":137,"column":14},"end":{"line":137,"column":null}},"82":{"start":{"line":139,"column":12},"end":{"line":139,"column":null}},"83":{"start":{"line":144,"column":10},"end":{"line":146,"column":null}},"84":{"start":{"line":145,"column":12},"end":{"line":145,"column":null}},"85":{"start":{"line":148,"column":10},"end":{"line":148,"column":null}},"86":{"start":{"line":150,"column":6},"end":{"line":165,"column":null}},"87":{"start":{"line":151,"column":8},"end":{"line":157,"column":null}},"88":{"start":{"line":152,"column":28},"end":{"line":152,"column":null}},"89":{"start":{"line":153,"column":10},"end":{"line":155,"column":null}},"90":{"start":{"line":154,"column":12},"end":{"line":154,"column":null}},"91":{"start":{"line":156,"column":10},"end":{"line":156,"column":null}},"92":{"start":{"line":158,"column":6},"end":{"line":165,"column":null}},"93":{"start":{"line":159,"column":8},"end":{"line":164,"column":null}},"94":{"start":{"line":160,"column":10},"end":{"line":162,"column":null}},"95":{"start":{"line":161,"column":12},"end":{"line":161,"column":null}},"96":{"start":{"line":163,"column":10},"end":{"line":163,"column":null}},"97":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"98":{"start":{"line":169,"column":4},"end":{"line":169,"column":null}},"99":{"start":{"line":169,"column":17},"end":{"line":169,"column":null}},"100":{"start":{"line":175,"column":2},"end":{"line":220,"column":null}},"101":{"start":{"line":177,"column":25},"end":{"line":193,"column":null}},"102":{"start":{"line":179,"column":8},"end":{"line":190,"column":null}},"103":{"start":{"line":181,"column":10},"end":{"line":189,"column":null}},"104":{"start":{"line":182,"column":26},"end":{"line":182,"column":null}},"105":{"start":{"line":183,"column":12},"end":{"line":188,"column":null}},"106":{"start":{"line":184,"column":27},"end":{"line":184,"column":null}},"107":{"start":{"line":185,"column":14},"end":{"line":187,"column":null}},"108":{"start":{"line":186,"column":16},"end":{"line":186,"column":null}},"109":{"start":{"line":196,"column":29},"end":{"line":205,"column":null}},"110":{"start":{"line":198,"column":8},"end":{"line":202,"column":null}},"111":{"start":{"line":199,"column":10},"end":{"line":201,"column":null}},"112":{"start":{"line":200,"column":12},"end":{"line":200,"column":null}},"113":{"start":{"line":207,"column":4},"end":{"line":210,"column":null}},"114":{"start":{"line":208,"column":17},"end":{"line":208,"column":null}},"115":{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},"116":{"start":{"line":209,"column":14},"end":{"line":209,"column":null}},"117":{"start":{"line":212,"column":21},"end":{"line":212,"column":null}},"118":{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},"119":{"start":{"line":213,"column":18},"end":{"line":213,"column":null}},"120":{"start":{"line":215,"column":4},"end":{"line":218,"column":null}},"121":{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},"122":{"start":{"line":217,"column":6},"end":{"line":217,"column":null}},"123":{"start":{"line":222,"column":2},"end":{"line":222,"column":null}},"124":{"start":{"line":222,"column":15},"end":{"line":222,"column":null}},"125":{"start":{"line":223,"column":2},"end":{"line":223,"column":null}},"126":{"start":{"line":223,"column":13},"end":{"line":223,"column":null}},"127":{"start":{"line":225,"column":2},"end":{"line":249,"column":null}},"128":{"start":{"line":232,"column":12},"end":{"line":240,"column":null}},"129":{"start":{"line":237,"column":29},"end":{"line":237,"column":null}}},"fnMap":{"0":{"name":"FeedItems","decl":{"start":{"line":8,"column":24},"end":{"line":8,"column":36}},"loc":{"start":{"line":8,"column":36},"end":{"line":251,"column":null}},"line":8},"1":{"name":"(anonymous_1)","decl":{"start":{"line":20,"column":21},"end":{"line":20,"column":22}},"loc":{"start":{"line":20,"column":41},"end":{"line":87,"column":null}},"line":20},"2":{"name":"(anonymous_2)","decl":{"start":{"line":66,"column":12},"end":{"line":66,"column":13}},"loc":{"start":{"line":66,"column":21},"end":{"line":71,"column":7}},"line":66},"3":{"name":"(anonymous_3)","decl":{"start":{"line":72,"column":12},"end":{"line":72,"column":13}},"loc":{"start":{"line":72,"column":22},"end":{"line":81,"column":7}},"line":72},"4":{"name":"(anonymous_4)","decl":{"start":{"line":74,"column":19},"end":{"line":74,"column":20}},"loc":{"start":{"line":74,"column":29},"end":{"line":74,"column":47}},"line":74},"5":{"name":"(anonymous_5)","decl":{"start":{"line":82,"column":13},"end":{"line":82,"column":14}},"loc":{"start":{"line":82,"column":22},"end":{"line":86,"column":7}},"line":82},"6":{"name":"(anonymous_6)","decl":{"start":{"line":89,"column":12},"end":{"line":89,"column":18}},"loc":{"start":{"line":89,"column":18},"end":{"line":93,"column":5}},"line":89},"7":{"name":"(anonymous_7)","decl":{"start":{"line":96,"column":23},"end":{"line":96,"column":24}},"loc":{"start":{"line":96,"column":42},"end":{"line":101,"column":null}},"line":96},"8":{"name":"(anonymous_8)","decl":{"start":{"line":103,"column":21},"end":{"line":103,"column":22}},"loc":{"start":{"line":103,"column":37},"end":{"line":113,"column":null}},"line":103},"9":{"name":"(anonymous_9)","decl":{"start":{"line":106,"column":13},"end":{"line":106,"column":14}},"loc":{"start":{"line":106,"column":28},"end":{"line":106,"column":88}},"line":106},"10":{"name":"(anonymous_10)","decl":{"start":{"line":106,"column":42},"end":{"line":106,"column":43}},"loc":{"start":{"line":106,"column":50},"end":{"line":106,"column":87}},"line":106},"11":{"name":"(anonymous_11)","decl":{"start":{"line":112,"column":13},"end":{"line":112,"column":14}},"loc":{"start":{"line":112,"column":22},"end":{"line":112,"column":63}},"line":112},"12":{"name":"(anonymous_12)","decl":{"start":{"line":115,"column":21},"end":{"line":115,"column":22}},"loc":{"start":{"line":115,"column":37},"end":{"line":125,"column":null}},"line":115},"13":{"name":"(anonymous_13)","decl":{"start":{"line":118,"column":13},"end":{"line":118,"column":14}},"loc":{"start":{"line":118,"column":28},"end":{"line":118,"column":88}},"line":118},"14":{"name":"(anonymous_14)","decl":{"start":{"line":118,"column":42},"end":{"line":118,"column":43}},"loc":{"start":{"line":118,"column":50},"end":{"line":118,"column":87}},"line":118},"15":{"name":"(anonymous_15)","decl":{"start":{"line":124,"column":13},"end":{"line":124,"column":14}},"loc":{"start":{"line":124,"column":22},"end":{"line":124,"column":65}},"line":124},"16":{"name":"(anonymous_16)","decl":{"start":{"line":127,"column":12},"end":{"line":127,"column":18}},"loc":{"start":{"line":127,"column":18},"end":{"line":171,"column":5}},"line":127},"17":{"name":"(anonymous_17)","decl":{"start":{"line":128,"column":26},"end":{"line":128,"column":27}},"loc":{"start":{"line":128,"column":48},"end":{"line":166,"column":null}},"line":128},"18":{"name":"(anonymous_18)","decl":{"start":{"line":132,"column":25},"end":{"line":132,"column":26}},"loc":{"start":{"line":132,"column":35},"end":{"line":149,"column":9}},"line":132},"19":{"name":"(anonymous_19)","decl":{"start":{"line":151,"column":25},"end":{"line":151,"column":26}},"loc":{"start":{"line":151,"column":35},"end":{"line":157,"column":9}},"line":151},"20":{"name":"(anonymous_20)","decl":{"start":{"line":159,"column":25},"end":{"line":159,"column":26}},"loc":{"start":{"line":159,"column":43},"end":{"line":164,"column":9}},"line":159},"21":{"name":"(anonymous_21)","decl":{"start":{"line":169,"column":11},"end":{"line":169,"column":17}},"loc":{"start":{"line":169,"column":17},"end":{"line":169,"column":null}},"line":169},"22":{"name":"(anonymous_22)","decl":{"start":{"line":175,"column":12},"end":{"line":175,"column":18}},"loc":{"start":{"line":175,"column":18},"end":{"line":220,"column":5}},"line":175},"23":{"name":"(anonymous_23)","decl":{"start":{"line":178,"column":6},"end":{"line":178,"column":7}},"loc":{"start":{"line":178,"column":19},"end":{"line":191,"column":null}},"line":178},"24":{"name":"(anonymous_24)","decl":{"start":{"line":179,"column":24},"end":{"line":179,"column":25}},"loc":{"start":{"line":179,"column":35},"end":{"line":190,"column":9}},"line":179},"25":{"name":"(anonymous_25)","decl":{"start":{"line":197,"column":6},"end":{"line":197,"column":7}},"loc":{"start":{"line":197,"column":19},"end":{"line":203,"column":null}},"line":197},"26":{"name":"(anonymous_26)","decl":{"start":{"line":198,"column":24},"end":{"line":198,"column":25}},"loc":{"start":{"line":198,"column":35},"end":{"line":202,"column":9}},"line":198},"27":{"name":"(anonymous_27)","decl":{"start":{"line":207,"column":18},"end":{"line":207,"column":19}},"loc":{"start":{"line":207,"column":32},"end":{"line":210,"column":5}},"line":207},"28":{"name":"(anonymous_28)","decl":{"start":{"line":215,"column":11},"end":{"line":215,"column":17}},"loc":{"start":{"line":215,"column":17},"end":{"line":218,"column":null}},"line":215},"29":{"name":"(anonymous_29)","decl":{"start":{"line":231,"column":21},"end":{"line":231,"column":22}},"loc":{"start":{"line":232,"column":12},"end":{"line":240,"column":null}},"line":232},"30":{"name":"(anonymous_30)","decl":{"start":{"line":237,"column":23},"end":{"line":237,"column":29}},"loc":{"start":{"line":237,"column":29},"end":{"line":237,"column":null}},"line":237}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":19},"end":{"line":11,"column":null}},"type":"binary-expr","locations":[{"start":{"line":11,"column":19},"end":{"line":11,"column":49}},{"start":{"line":11,"column":49},"end":{"line":11,"column":null}}],"line":11},"1":{"loc":{"start":{"line":21,"column":4},"end":{"line":26,"column":null}},"type":"if","locations":[{"start":{"line":21,"column":4},"end":{"line":26,"column":null}},{"start":{"line":23,"column":11},"end":{"line":26,"column":null}}],"line":21},"2":{"loc":{"start":{"line":32,"column":4},"end":{"line":36,"column":null}},"type":"if","locations":[{"start":{"line":32,"column":4},"end":{"line":36,"column":null}},{"start":{"line":34,"column":4},"end":{"line":36,"column":null}}],"line":32},"3":{"loc":{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},{"start":{},"end":{}}],"line":34},"4":{"loc":{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},{"start":{},"end":{}}],"line":38},"5":{"loc":{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":4},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":44},"6":{"loc":{"start":{"line":48,"column":4},"end":{"line":58,"column":null}},"type":"if","locations":[{"start":{"line":48,"column":4},"end":{"line":58,"column":null}},{"start":{"line":50,"column":4},"end":{"line":58,"column":null}}],"line":48},"7":{"loc":{"start":{"line":50,"column":4},"end":{"line":58,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":4},"end":{"line":58,"column":null}},{"start":{"line":53,"column":11},"end":{"line":58,"column":null}}],"line":50},"8":{"loc":{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},{"start":{},"end":{}}],"line":55},"9":{"loc":{"start":{"line":61,"column":4},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":61,"column":4},"end":{"line":63,"column":null}},{"start":{},"end":{}}],"line":61},"10":{"loc":{"start":{"line":67,"column":8},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":8},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":67},"11":{"loc":{"start":{"line":73,"column":8},"end":{"line":77,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":8},"end":{"line":77,"column":null}},{"start":{"line":75,"column":15},"end":{"line":77,"column":null}}],"line":73},"12":{"loc":{"start":{"line":98,"column":4},"end":{"line":100,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":4},"end":{"line":100,"column":null}},{"start":{},"end":{}}],"line":98},"13":{"loc":{"start":{"line":106,"column":50},"end":{"line":106,"column":87}},"type":"cond-expr","locations":[{"start":{"line":106,"column":71},"end":{"line":106,"column":85}},{"start":{"line":106,"column":85},"end":{"line":106,"column":87}}],"line":106},"14":{"loc":{"start":{"line":118,"column":50},"end":{"line":118,"column":87}},"type":"cond-expr","locations":[{"start":{"line":118,"column":71},"end":{"line":118,"column":85}},{"start":{"line":118,"column":85},"end":{"line":118,"column":87}}],"line":118},"15":{"loc":{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},"type":"if","locations":[{"start":{"line":129,"column":6},"end":{"line":129,"column":null}},{"start":{},"end":{}}],"line":129},"16":{"loc":{"start":{"line":131,"column":6},"end":{"line":165,"column":null}},"type":"if","locations":[{"start":{"line":131,"column":6},"end":{"line":165,"column":null}},{"start":{"line":150,"column":6},"end":{"line":165,"column":null}}],"line":131},"17":{"loc":{"start":{"line":134,"column":10},"end":{"line":140,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":10},"end":{"line":140,"column":null}},{"start":{},"end":{}}],"line":134},"18":{"loc":{"start":{"line":136,"column":12},"end":{"line":138,"column":null}},"type":"if","locations":[{"start":{"line":136,"column":12},"end":{"line":138,"column":null}},{"start":{},"end":{}}],"line":136},"19":{"loc":{"start":{"line":144,"column":10},"end":{"line":146,"column":null}},"type":"if","locations":[{"start":{"line":144,"column":10},"end":{"line":146,"column":null}},{"start":{},"end":{}}],"line":144},"20":{"loc":{"start":{"line":144,"column":14},"end":{"line":144,"column":73}},"type":"binary-expr","locations":[{"start":{"line":144,"column":14},"end":{"line":144,"column":48}},{"start":{"line":144,"column":48},"end":{"line":144,"column":59}},{"start":{"line":144,"column":59},"end":{"line":144,"column":73}}],"line":144},"21":{"loc":{"start":{"line":150,"column":6},"end":{"line":165,"column":null}},"type":"if","locations":[{"start":{"line":150,"column":6},"end":{"line":165,"column":null}},{"start":{"line":158,"column":6},"end":{"line":165,"column":null}}],"line":150},"22":{"loc":{"start":{"line":153,"column":10},"end":{"line":155,"column":null}},"type":"if","locations":[{"start":{"line":153,"column":10},"end":{"line":155,"column":null}},{"start":{},"end":{}}],"line":153},"23":{"loc":{"start":{"line":158,"column":6},"end":{"line":165,"column":null}},"type":"if","locations":[{"start":{"line":158,"column":6},"end":{"line":165,"column":null}},{"start":{},"end":{}}],"line":158},"24":{"loc":{"start":{"line":160,"column":10},"end":{"line":162,"column":null}},"type":"if","locations":[{"start":{"line":160,"column":10},"end":{"line":162,"column":null}},{"start":{},"end":{}}],"line":160},"25":{"loc":{"start":{"line":160,"column":14},"end":{"line":160,"column":64}},"type":"binary-expr","locations":[{"start":{"line":160,"column":14},"end":{"line":160,"column":35}},{"start":{"line":160,"column":35},"end":{"line":160,"column":64}}],"line":160},"26":{"loc":{"start":{"line":181,"column":10},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":10},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":181},"27":{"loc":{"start":{"line":181,"column":14},"end":{"line":181,"column":73}},"type":"binary-expr","locations":[{"start":{"line":181,"column":14},"end":{"line":181,"column":39}},{"start":{"line":181,"column":39},"end":{"line":181,"column":73}}],"line":181},"28":{"loc":{"start":{"line":183,"column":12},"end":{"line":188,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":12},"end":{"line":188,"column":null}},{"start":{},"end":{}}],"line":183},"29":{"loc":{"start":{"line":183,"column":16},"end":{"line":183,"column":69}},"type":"binary-expr","locations":[{"start":{"line":183,"column":16},"end":{"line":183,"column":33}},{"start":{"line":183,"column":33},"end":{"line":183,"column":47}},{"start":{"line":183,"column":47},"end":{"line":183,"column":69}}],"line":183},"30":{"loc":{"start":{"line":185,"column":14},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":14},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":185},"31":{"loc":{"start":{"line":199,"column":10},"end":{"line":201,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":10},"end":{"line":201,"column":null}},{"start":{},"end":{}}],"line":199},"32":{"loc":{"start":{"line":199,"column":14},"end":{"line":199,"column":83}},"type":"binary-expr","locations":[{"start":{"line":199,"column":14},"end":{"line":199,"column":38}},{"start":{"line":199,"column":38},"end":{"line":199,"column":54}},{"start":{"line":199,"column":54},"end":{"line":199,"column":65}},{"start":{"line":199,"column":65},"end":{"line":199,"column":83}}],"line":199},"33":{"loc":{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":6},"end":{"line":209,"column":null}},{"start":{},"end":{}}],"line":209},"34":{"loc":{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},"type":"if","locations":[{"start":{"line":213,"column":4},"end":{"line":213,"column":null}},{"start":{},"end":{}}],"line":213},"35":{"loc":{"start":{"line":222,"column":2},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":2},"end":{"line":222,"column":null}},{"start":{},"end":{}}],"line":222},"36":{"loc":{"start":{"line":223,"column":2},"end":{"line":223,"column":null}},"type":"if","locations":[{"start":{"line":223,"column":2},"end":{"line":223,"column":null}},{"start":{},"end":{}}],"line":223},"37":{"loc":{"start":{"line":227,"column":7},"end":{"line":247,"column":null}},"type":"cond-expr","locations":[{"start":{"line":228,"column":8},"end":{"line":228,"column":null}},{"start":{"line":230,"column":8},"end":{"line":247,"column":null}}],"line":227},"38":{"loc":{"start":{"line":242,"column":11},"end":{"line":245,"column":null}},"type":"binary-expr","locations":[{"start":{"line":242,"column":11},"end":{"line":242,"column":null}},{"start":{"line":243,"column":12},"end":{"line":245,"column":null}}],"line":242},"39":{"loc":{"start":{"line":244,"column":15},"end":{"line":244,"column":null}},"type":"cond-expr","locations":[{"start":{"line":244,"column":29},"end":{"line":244,"column":49}},{"start":{"line":244,"column":49},"end":{"line":244,"column":null}}],"line":244}},"s":{"0":36,"1":36,"2":36,"3":36,"4":36,"5":36,"6":36,"7":36,"8":36,"9":36,"10":11,"11":3,"12":8,"13":8,"14":11,"15":11,"16":11,"17":11,"18":2,"19":9,"20":1,"21":11,"22":3,"23":11,"24":11,"25":0,"26":11,"27":0,"28":11,"29":0,"30":0,"31":11,"32":11,"33":11,"34":11,"35":11,"36":11,"37":10,"38":0,"39":10,"40":9,"41":3,"42":3,"43":6,"44":9,"45":9,"46":9,"47":1,"48":1,"49":1,"50":36,"51":8,"52":8,"53":36,"54":5,"55":5,"56":5,"57":36,"58":2,"59":2,"60":2,"61":3,"62":2,"63":0,"64":36,"65":1,"66":1,"67":1,"68":2,"69":1,"70":0,"71":36,"72":31,"73":6,"74":0,"75":6,"76":5,"77":5,"78":5,"79":5,"80":5,"81":1,"82":5,"83":5,"84":2,"85":5,"86":1,"87":0,"88":0,"89":0,"90":0,"91":0,"92":1,"93":1,"94":1,"95":1,"96":1,"97":31,"98":31,"99":31,"100":36,"101":31,"102":1,"103":1,"104":1,"105":1,"106":1,"107":1,"108":1,"109":31,"110":1,"111":1,"112":1,"113":31,"114":31,"115":31,"116":31,"117":31,"118":31,"119":15,"120":31,"121":31,"122":31,"123":36,"124":15,"125":21,"126":21,"127":20,"128":44,"129":0},"f":{"0":36,"1":11,"2":10,"3":9,"4":3,"5":1,"6":8,"7":5,"8":2,"9":2,"10":3,"11":0,"12":1,"13":1,"14":2,"15":0,"16":31,"17":6,"18":5,"19":0,"20":1,"21":31,"22":31,"23":1,"24":1,"25":1,"26":1,"27":31,"28":31,"29":44,"30":0},"b":{"0":[36,36],"1":[3,8],"2":[2,9],"3":[1,8],"4":[3,8],"5":[0,11],"6":[0,11],"7":[0,11],"8":[11,0],"9":[11,0],"10":[0,10],"11":[3,6],"12":[5,0],"13":[2,1],"14":[1,1],"15":[0,6],"16":[5,1],"17":[5,0],"18":[1,4],"19":[2,3],"20":[5,2,2],"21":[0,1],"22":[0,0],"23":[1,0],"24":[1,0],"25":[1,1],"26":[1,0],"27":[1,1],"28":[1,0],"29":[1,1,1],"30":[1,0],"31":[1,0],"32":[1,1,1,1],"33":[31,0],"34":[15,16],"35":[15,21],"36":[1,20],"37":[0,20],"38":[20,20],"39":[5,15]},"meta":{"lastBranch":40,"lastFunction":31,"lastStatement":130,"seen":{"f:8:24:8:36":0,"s:9:26:9:Infinity":0,"s:10:21:10:Infinity":1,"s:11:19:11:Infinity":2,"b:11:19:11:49:11:49:11:Infinity":0,"s:13:24:13:Infinity":3,"s:14:28:14:Infinity":4,"s:15:36:15:Infinity":5,"s:16:28:16:Infinity":6,"s:17:24:17:Infinity":7,"s:18:40:18:Infinity":8,"s:20:21:87:Infinity":9,"f:20:21:20:22":1,"b:21:4:26:Infinity:23:11:26:Infinity":1,"s:21:4:26:Infinity":10,"s:22:6:22:Infinity":11,"s:24:6:24:Infinity":12,"s:25:6:25:Infinity":13,"s:27:4:27:Infinity":14,"s:29:14:29:Infinity":15,"s:30:19:30:Infinity":16,"b:32:4:36:Infinity:34:4:36:Infinity":2,"s:32:4:36:Infinity":17,"s:33:6:33:Infinity":18,"b:34:4:36:Infinity:undefined:undefined:undefined:undefined":3,"s:34:4:36:Infinity":19,"s:35:6:35:Infinity":20,"b:38:4:40:Infinity:undefined:undefined:undefined:undefined":4,"s:38:4:40:Infinity":21,"s:39:6:39:Infinity":22,"s:43:24:43:Infinity":23,"b:44:4:46:Infinity:undefined:undefined:undefined:undefined":5,"s:44:4:46:Infinity":24,"s:45:6:45:Infinity":25,"b:48:4:58:Infinity:50:4:58:Infinity":6,"s:48:4:58:Infinity":26,"s:49:6:49:Infinity":27,"b:50:4:58:Infinity:53:11:58:Infinity":7,"s:50:4:58:Infinity":28,"s:51:6:51:Infinity":29,"s:52:6:52:Infinity":30,"b:55:6:57:Infinity:undefined:undefined:undefined:undefined":8,"s:55:6:57:Infinity":31,"s:56:8:56:Infinity":32,"s:60:24:60:Infinity":33,"b:61:4:63:Infinity:undefined:undefined:undefined:undefined":9,"s:61:4:63:Infinity":34,"s:62:6:62:Infinity":35,"s:65:4:86:Infinity":36,"f:66:12:66:13":2,"b:67:8:69:Infinity:undefined:undefined:undefined:undefined":10,"s:67:8:69:Infinity":37,"s:68:10:68:Infinity":38,"s:70:8:70:Infinity":39,"f:72:12:72:13":3,"b:73:8:77:Infinity:75:15:77:Infinity":11,"s:73:8:77:Infinity":40,"s:74:10:74:Infinity":41,"f:74:19:74:20":4,"s:74:29:74:47":42,"s:76:10:76:Infinity":43,"s:78:8:78:Infinity":44,"s:79:8:79:Infinity":45,"s:80:8:80:Infinity":46,"f:82:13:82:14":5,"s:83:8:83:Infinity":47,"s:84:8:84:Infinity":48,"s:85:8:85:Infinity":49,"s:89:2:93:Infinity":50,"f:89:12:89:18":6,"s:90:4:90:Infinity":51,"s:91:4:91:Infinity":52,"s:96:23:101:Infinity":53,"f:96:23:96:24":7,"s:97:20:97:Infinity":54,"b:98:4:100:Infinity:undefined:undefined:undefined:undefined":12,"s:98:4:100:Infinity":55,"s:99:6:99:Infinity":56,"s:103:21:113:Infinity":57,"f:103:21:103:22":8,"s:104:24:104:Infinity":58,"s:106:4:106:Infinity":59,"f:106:13:106:14":9,"s:106:28:106:88":60,"f:106:42:106:43":10,"s:106:50:106:87":61,"b:106:71:106:85:106:85:106:87":13,"s:108:4:112:Infinity":62,"f:112:13:112:14":11,"s:112:22:112:63":63,"s:115:21:125:Infinity":64,"f:115:21:115:22":12,"s:116:24:116:Infinity":65,"s:118:4:118:Infinity":66,"f:118:13:118:14":13,"s:118:28:118:88":67,"f:118:42:118:43":14,"s:118:50:118:87":68,"b:118:71:118:85:118:85:118:87":14,"s:120:4:124:Infinity":69,"f:124:13:124:14":15,"s:124:22:124:65":70,"s:127:2:171:Infinity":71,"f:127:12:127:18":16,"s:128:26:166:Infinity":72,"f:128:26:128:27":17,"b:129:6:129:Infinity:undefined:undefined:undefined:undefined":15,"s:129:6:129:Infinity":73,"s:129:30:129:Infinity":74,"b:131:6:165:Infinity:150:6:165:Infinity":16,"s:131:6:165:Infinity":75,"s:132:8:149:Infinity":76,"f:132:25:132:26":18,"s:133:28:133:Infinity":77,"b:134:10:140:Infinity:undefined:undefined:undefined:undefined":17,"s:134:10:140:Infinity":78,"s:135:25:135:Infinity":79,"b:136:12:138:Infinity:undefined:undefined:undefined:undefined":18,"s:136:12:138:Infinity":80,"s:137:14:137:Infinity":81,"s:139:12:139:Infinity":82,"b:144:10:146:Infinity:undefined:undefined:undefined:undefined":19,"s:144:10:146:Infinity":83,"b:144:14:144:48:144:48:144:59:144:59:144:73":20,"s:145:12:145:Infinity":84,"s:148:10:148:Infinity":85,"b:150:6:165:Infinity:158:6:165:Infinity":21,"s:150:6:165:Infinity":86,"s:151:8:157:Infinity":87,"f:151:25:151:26":19,"s:152:28:152:Infinity":88,"b:153:10:155:Infinity:undefined:undefined:undefined:undefined":22,"s:153:10:155:Infinity":89,"s:154:12:154:Infinity":90,"s:156:10:156:Infinity":91,"b:158:6:165:Infinity:undefined:undefined:undefined:undefined":23,"s:158:6:165:Infinity":92,"s:159:8:164:Infinity":93,"f:159:25:159:26":20,"b:160:10:162:Infinity:undefined:undefined:undefined:undefined":24,"s:160:10:162:Infinity":94,"b:160:14:160:35:160:35:160:64":25,"s:161:12:161:Infinity":95,"s:163:10:163:Infinity":96,"s:168:4:168:Infinity":97,"s:169:4:169:Infinity":98,"f:169:11:169:17":21,"s:169:17:169:Infinity":99,"s:175:2:220:Infinity":100,"f:175:12:175:18":22,"s:177:25:193:Infinity":101,"f:178:6:178:7":23,"s:179:8:190:Infinity":102,"f:179:24:179:25":24,"b:181:10:189:Infinity:undefined:undefined:undefined:undefined":26,"s:181:10:189:Infinity":103,"b:181:14:181:39:181:39:181:73":27,"s:182:26:182:Infinity":104,"b:183:12:188:Infinity:undefined:undefined:undefined:undefined":28,"s:183:12:188:Infinity":105,"b:183:16:183:33:183:33:183:47:183:47:183:69":29,"s:184:27:184:Infinity":106,"b:185:14:187:Infinity:undefined:undefined:undefined:undefined":30,"s:185:14:187:Infinity":107,"s:186:16:186:Infinity":108,"s:196:29:205:Infinity":109,"f:197:6:197:7":25,"s:198:8:202:Infinity":110,"f:198:24:198:25":26,"b:199:10:201:Infinity:undefined:undefined:undefined:undefined":31,"s:199:10:201:Infinity":111,"b:199:14:199:38:199:38:199:54:199:54:199:65:199:65:199:83":32,"s:200:12:200:Infinity":112,"s:207:4:210:Infinity":113,"f:207:18:207:19":27,"s:208:17:208:Infinity":114,"b:209:6:209:Infinity:undefined:undefined:undefined:undefined":33,"s:209:6:209:Infinity":115,"s:209:14:209:Infinity":116,"s:212:21:212:Infinity":117,"b:213:4:213:Infinity:undefined:undefined:undefined:undefined":34,"s:213:4:213:Infinity":118,"s:213:18:213:Infinity":119,"s:215:4:218:Infinity":120,"f:215:11:215:17":28,"s:216:6:216:Infinity":121,"s:217:6:217:Infinity":122,"b:222:2:222:Infinity:undefined:undefined:undefined:undefined":35,"s:222:2:222:Infinity":123,"s:222:15:222:Infinity":124,"b:223:2:223:Infinity:undefined:undefined:undefined:undefined":36,"s:223:2:223:Infinity":125,"s:223:13:223:Infinity":126,"s:225:2:249:Infinity":127,"b:228:8:228:Infinity:230:8:247:Infinity":37,"f:231:21:231:22":29,"s:232:12:240:Infinity":128,"f:237:23:237:29":30,"s:237:29:237:Infinity":129,"b:242:11:242:Infinity:243:12:245:Infinity":38,"b:244:29:244:49:244:49:244:Infinity":39}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.tsx","statementMap":{"0":{"start":{"line":19,"column":24},"end":{"line":19,"column":null}},"1":{"start":{"line":20,"column":22},"end":{"line":20,"column":null}},"2":{"start":{"line":21,"column":28},"end":{"line":21,"column":null}},"3":{"start":{"line":22,"column":24},"end":{"line":22,"column":null}},"4":{"start":{"line":23,"column":40},"end":{"line":23,"column":null}},"5":{"start":{"line":24,"column":38},"end":{"line":24,"column":null}},"6":{"start":{"line":25,"column":36},"end":{"line":25,"column":null}},"7":{"start":{"line":26,"column":8},"end":{"line":26,"column":null}},"8":{"start":{"line":27,"column":21},"end":{"line":27,"column":null}},"9":{"start":{"line":28,"column":8},"end":{"line":28,"column":null}},"10":{"start":{"line":29,"column":26},"end":{"line":29,"column":null}},"11":{"start":{"line":31,"column":25},"end":{"line":31,"column":null}},"12":{"start":{"line":33,"column":2},"end":{"line":38,"column":null}},"13":{"start":{"line":34,"column":20},"end":{"line":34,"column":null}},"14":{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},"15":{"start":{"line":36,"column":6},"end":{"line":36,"column":null}},"16":{"start":{"line":41,"column":4},"end":{"line":42,"column":null}},"17":{"start":{"line":44,"column":23},"end":{"line":49,"column":null}},"18":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"19":{"start":{"line":46,"column":4},"end":{"line":48,"column":null}},"20":{"start":{"line":47,"column":6},"end":{"line":47,"column":null}},"21":{"start":{"line":51,"column":22},"end":{"line":53,"column":null}},"22":{"start":{"line":52,"column":4},"end":{"line":52,"column":null}},"23":{"start":{"line":55,"column":21},"end":{"line":57,"column":null}},"24":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"25":{"start":{"line":59,"column":26},"end":{"line":63,"column":null}},"26":{"start":{"line":60,"column":4},"end":{"line":62,"column":null}},"27":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"28":{"start":{"line":65,"column":2},"end":{"line":85,"column":null}},"29":{"start":{"line":66,"column":4},"end":{"line":84,"column":null}},"30":{"start":{"line":68,"column":8},"end":{"line":68,"column":null}},"31":{"start":{"line":68,"column":21},"end":{"line":68,"column":null}},"32":{"start":{"line":69,"column":8},"end":{"line":69,"column":null}},"33":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"34":{"start":{"line":72,"column":21},"end":{"line":72,"column":null}},"35":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}},"36":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"37":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"38":{"start":{"line":79,"column":8},"end":{"line":79,"column":null}},"39":{"start":{"line":82,"column":8},"end":{"line":82,"column":null}},"40":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"41":{"start":{"line":87,"column":2},"end":{"line":87,"column":null}},"42":{"start":{"line":87,"column":15},"end":{"line":87,"column":null}},"43":{"start":{"line":88,"column":2},"end":{"line":88,"column":null}},"44":{"start":{"line":88,"column":13},"end":{"line":88,"column":null}},"45":{"start":{"line":90,"column":23},"end":{"line":92,"column":null}},"46":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"47":{"start":{"line":91,"column":60},"end":{"line":91,"column":95}},"48":{"start":{"line":94,"column":2},"end":{"line":210,"column":null}},"49":{"start":{"line":96,"column":42},"end":{"line":96,"column":68}},"50":{"start":{"line":106,"column":29},"end":{"line":106,"column":null}},"51":{"start":{"line":139,"column":14},"end":{"line":147,"column":null}},"52":{"start":{"line":163,"column":16},"end":{"line":171,"column":null}},"53":{"start":{"line":195,"column":27},"end":{"line":195,"column":null}},"54":{"start":{"line":202,"column":27},"end":{"line":202,"column":null}}},"fnMap":{"0":{"name":"FeedList","decl":{"start":{"line":8,"column":24},"end":{"line":8,"column":33}},"loc":{"start":{"line":18,"column":3},"end":{"line":212,"column":null}},"line":18},"1":{"name":"(anonymous_1)","decl":{"start":{"line":33,"column":12},"end":{"line":33,"column":18}},"loc":{"start":{"line":33,"column":18},"end":{"line":38,"column":5}},"line":33},"2":{"name":"(anonymous_2)","decl":{"start":{"line":44,"column":23},"end":{"line":44,"column":24}},"loc":{"start":{"line":44,"column":47},"end":{"line":49,"column":null}},"line":44},"3":{"name":"(anonymous_3)","decl":{"start":{"line":51,"column":22},"end":{"line":51,"column":28}},"loc":{"start":{"line":51,"column":28},"end":{"line":53,"column":null}},"line":51},"4":{"name":"(anonymous_4)","decl":{"start":{"line":55,"column":21},"end":{"line":55,"column":27}},"loc":{"start":{"line":55,"column":27},"end":{"line":57,"column":null}},"line":55},"5":{"name":"(anonymous_5)","decl":{"start":{"line":59,"column":26},"end":{"line":59,"column":32}},"loc":{"start":{"line":59,"column":32},"end":{"line":63,"column":null}},"line":59},"6":{"name":"(anonymous_6)","decl":{"start":{"line":65,"column":12},"end":{"line":65,"column":18}},"loc":{"start":{"line":65,"column":18},"end":{"line":85,"column":5}},"line":65},"7":{"name":"(anonymous_7)","decl":{"start":{"line":67,"column":34},"end":{"line":67,"column":35}},"loc":{"start":{"line":67,"column":43},"end":{"line":70,"column":7}},"line":67},"8":{"name":"(anonymous_8)","decl":{"start":{"line":71,"column":32},"end":{"line":71,"column":33}},"loc":{"start":{"line":71,"column":41},"end":{"line":74,"column":7}},"line":71},"9":{"name":"(anonymous_9)","decl":{"start":{"line":76,"column":12},"end":{"line":76,"column":13}},"loc":{"start":{"line":76,"column":39},"end":{"line":80,"column":7}},"line":76},"10":{"name":"(anonymous_10)","decl":{"start":{"line":81,"column":13},"end":{"line":81,"column":14}},"loc":{"start":{"line":81,"column":22},"end":{"line":84,"column":7}},"line":81},"11":{"name":"(anonymous_11)","decl":{"start":{"line":90,"column":23},"end":{"line":90,"column":29}},"loc":{"start":{"line":90,"column":29},"end":{"line":92,"column":null}},"line":90},"12":{"name":"(anonymous_12)","decl":{"start":{"line":91,"column":53},"end":{"line":91,"column":60}},"loc":{"start":{"line":91,"column":60},"end":{"line":91,"column":95}},"line":91},"13":{"name":"(anonymous_13)","decl":{"start":{"line":96,"column":36},"end":{"line":96,"column":42}},"loc":{"start":{"line":96,"column":42},"end":{"line":96,"column":68}},"line":96},"14":{"name":"(anonymous_14)","decl":{"start":{"line":106,"column":22},"end":{"line":106,"column":23}},"loc":{"start":{"line":106,"column":29},"end":{"line":106,"column":null}},"line":106},"15":{"name":"(anonymous_15)","decl":{"start":{"line":138,"column":22},"end":{"line":138,"column":23}},"loc":{"start":{"line":139,"column":14},"end":{"line":147,"column":null}},"line":139},"16":{"name":"(anonymous_16)","decl":{"start":{"line":162,"column":25},"end":{"line":162,"column":26}},"loc":{"start":{"line":163,"column":16},"end":{"line":171,"column":null}},"line":163},"17":{"name":"(anonymous_17)","decl":{"start":{"line":195,"column":21},"end":{"line":195,"column":27}},"loc":{"start":{"line":195,"column":27},"end":{"line":195,"column":null}},"line":195},"18":{"name":"(anonymous_18)","decl":{"start":{"line":202,"column":21},"end":{"line":202,"column":27}},"loc":{"start":{"line":202,"column":27},"end":{"line":202,"column":null}},"line":202}},"branchMap":{"0":{"loc":{"start":{"line":31,"column":25},"end":{"line":31,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":25},"end":{"line":31,"column":56}},{"start":{"line":31,"column":56},"end":{"line":31,"column":104}},{"start":{"line":31,"column":104},"end":{"line":31,"column":null}}],"line":31},"1":{"loc":{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":35,"column":4},"end":{"line":37,"column":null}},{"start":{},"end":{}}],"line":35},"2":{"loc":{"start":{"line":41,"column":4},"end":{"line":42,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},{"start":{"line":42,"column":5},"end":{"line":42,"column":null}}],"line":41},"3":{"loc":{"start":{"line":42,"column":5},"end":{"line":42,"column":null}},"type":"cond-expr","locations":[{"start":{"line":42,"column":56},"end":{"line":42,"column":67}},{"start":{"line":42,"column":67},"end":{"line":42,"column":null}}],"line":42},"4":{"loc":{"start":{"line":42,"column":5},"end":{"line":42,"column":56}},"type":"binary-expr","locations":[{"start":{"line":42,"column":5},"end":{"line":42,"column":34}},{"start":{"line":42,"column":34},"end":{"line":42,"column":45}},{"start":{"line":42,"column":45},"end":{"line":42,"column":56}}],"line":42},"5":{"loc":{"start":{"line":46,"column":4},"end":{"line":48,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":4},"end":{"line":48,"column":null}},{"start":{},"end":{}}],"line":46},"6":{"loc":{"start":{"line":60,"column":4},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":4},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":60},"7":{"loc":{"start":{"line":68,"column":8},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":8},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":68},"8":{"loc":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":72},"9":{"loc":{"start":{"line":87,"column":2},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":2},"end":{"line":87,"column":null}},{"start":{},"end":{}}],"line":87},"10":{"loc":{"start":{"line":88,"column":2},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":2},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":88},"11":{"loc":{"start":{"line":115,"column":50},"end":{"line":115,"column":94}},"type":"cond-expr","locations":[{"start":{"line":115,"column":79},"end":{"line":115,"column":90}},{"start":{"line":115,"column":90},"end":{"line":115,"column":94}}],"line":115},"12":{"loc":{"start":{"line":120,"column":47},"end":{"line":120,"column":88}},"type":"cond-expr","locations":[{"start":{"line":120,"column":73},"end":{"line":120,"column":84}},{"start":{"line":120,"column":84},"end":{"line":120,"column":88}}],"line":120},"13":{"loc":{"start":{"line":125,"column":51},"end":{"line":125,"column":96}},"type":"cond-expr","locations":[{"start":{"line":125,"column":81},"end":{"line":125,"column":92}},{"start":{"line":125,"column":92},"end":{"line":125,"column":96}}],"line":125},"14":{"loc":{"start":{"line":134,"column":36},"end":{"line":134,"column":66}},"type":"cond-expr","locations":[{"start":{"line":134,"column":51},"end":{"line":134,"column":64}},{"start":{"line":134,"column":64},"end":{"line":134,"column":66}}],"line":134},"15":{"loc":{"start":{"line":136,"column":9},"end":{"line":149,"column":null}},"type":"binary-expr","locations":[{"start":{"line":136,"column":9},"end":{"line":136,"column":null}},{"start":{"line":137,"column":10},"end":{"line":149,"column":null}}],"line":136},"16":{"loc":{"start":{"line":142,"column":41},"end":{"line":142,"column":78}},"type":"cond-expr","locations":[{"start":{"line":142,"column":65},"end":{"line":142,"column":76}},{"start":{"line":142,"column":76},"end":{"line":142,"column":78}}],"line":142},"17":{"loc":{"start":{"line":155,"column":36},"end":{"line":155,"column":67}},"type":"cond-expr","locations":[{"start":{"line":155,"column":52},"end":{"line":155,"column":65}},{"start":{"line":155,"column":65},"end":{"line":155,"column":67}}],"line":155},"18":{"loc":{"start":{"line":157,"column":9},"end":{"line":173,"column":null}},"type":"binary-expr","locations":[{"start":{"line":157,"column":9},"end":{"line":157,"column":null}},{"start":{"line":158,"column":11},"end":{"line":173,"column":null}}],"line":157},"19":{"loc":{"start":{"line":158,"column":11},"end":{"line":173,"column":null}},"type":"cond-expr","locations":[{"start":{"line":159,"column":12},"end":{"line":159,"column":null}},{"start":{"line":161,"column":12},"end":{"line":173,"column":null}}],"line":158},"20":{"loc":{"start":{"line":166,"column":45},"end":{"line":166,"column":88}},"type":"cond-expr","locations":[{"start":{"line":166,"column":75},"end":{"line":166,"column":86}},{"start":{"line":166,"column":86},"end":{"line":166,"column":88}}],"line":166},"21":{"loc":{"start":{"line":169,"column":21},"end":{"line":169,"column":null}},"type":"binary-expr","locations":[{"start":{"line":169,"column":21},"end":{"line":169,"column":35}},{"start":{"line":169,"column":35},"end":{"line":169,"column":null}}],"line":169},"22":{"loc":{"start":{"line":196,"column":23},"end":{"line":196,"column":null}},"type":"cond-expr","locations":[{"start":{"line":196,"column":43},"end":{"line":196,"column":54}},{"start":{"line":196,"column":54},"end":{"line":196,"column":null}}],"line":196},"23":{"loc":{"start":{"line":203,"column":23},"end":{"line":203,"column":null}},"type":"cond-expr","locations":[{"start":{"line":203,"column":42},"end":{"line":203,"column":53}},{"start":{"line":203,"column":53},"end":{"line":203,"column":null}}],"line":203}},"s":{"0":22,"1":22,"2":22,"3":22,"4":22,"5":22,"6":22,"7":22,"8":22,"9":22,"10":22,"11":22,"12":22,"13":11,"14":11,"15":0,"16":22,"17":22,"18":1,"19":1,"20":1,"21":22,"22":2,"23":22,"24":0,"25":22,"26":1,"27":1,"28":22,"29":9,"30":7,"31":0,"32":7,"33":7,"34":0,"35":7,"36":7,"37":7,"38":7,"39":1,"40":1,"41":22,"42":9,"43":13,"44":13,"45":12,"46":2,"47":2,"48":12,"49":0,"50":1,"51":4,"52":2,"53":0,"54":0},"f":{"0":22,"1":11,"2":1,"3":2,"4":0,"5":1,"6":9,"7":7,"8":7,"9":7,"10":1,"11":2,"12":2,"13":0,"14":1,"15":4,"16":2,"17":0,"18":0},"b":{"0":[22,22,22],"1":[0,11],"2":[22,21],"3":[21,0],"4":[21,21,21],"5":[1,0],"6":[1,0],"7":[0,7],"8":[0,7],"9":[9,13],"10":[1,12],"11":[12,0],"12":[0,12],"13":[0,12],"14":[12,0],"15":[22,12],"16":[0,4],"17":[2,10],"18":[22,2],"19":[1,1],"20":[0,2],"21":[2,0],"22":[12,0],"23":[0,12]},"meta":{"lastBranch":24,"lastFunction":19,"lastStatement":55,"seen":{"f:8:24:8:33":0,"s:19:24:19:Infinity":0,"s:20:22:20:Infinity":1,"s:21:28:21:Infinity":2,"s:22:24:22:Infinity":3,"s:23:40:23:Infinity":4,"s:24:38:24:Infinity":5,"s:25:36:25:Infinity":6,"s:26:8:26:Infinity":7,"s:27:21:27:Infinity":8,"s:28:8:28:Infinity":9,"s:29:26:29:Infinity":10,"s:31:25:31:Infinity":11,"b:31:25:31:56:31:56:31:104:31:104:31:Infinity":0,"s:33:2:38:Infinity":12,"f:33:12:33:18":1,"s:34:20:34:Infinity":13,"b:35:4:37:Infinity:undefined:undefined:undefined:undefined":1,"s:35:4:37:Infinity":14,"s:36:6:36:Infinity":15,"s:41:4:42:Infinity":16,"b:41:4:41:Infinity:42:5:42:Infinity":2,"b:42:56:42:67:42:67:42:Infinity":3,"b:42:5:42:34:42:34:42:45:42:45:42:56":4,"s:44:23:49:Infinity":17,"f:44:23:44:24":2,"s:45:4:45:Infinity":18,"b:46:4:48:Infinity:undefined:undefined:undefined:undefined":5,"s:46:4:48:Infinity":19,"s:47:6:47:Infinity":20,"s:51:22:53:Infinity":21,"f:51:22:51:28":3,"s:52:4:52:Infinity":22,"s:55:21:57:Infinity":23,"f:55:21:55:27":4,"s:56:4:56:Infinity":24,"s:59:26:63:Infinity":25,"f:59:26:59:32":5,"b:60:4:62:Infinity:undefined:undefined:undefined:undefined":6,"s:60:4:62:Infinity":26,"s:61:6:61:Infinity":27,"s:65:2:85:Infinity":28,"f:65:12:65:18":6,"s:66:4:84:Infinity":29,"f:67:34:67:35":7,"b:68:8:68:Infinity:undefined:undefined:undefined:undefined":7,"s:68:8:68:Infinity":30,"s:68:21:68:Infinity":31,"s:69:8:69:Infinity":32,"f:71:32:71:33":8,"b:72:8:72:Infinity:undefined:undefined:undefined:undefined":8,"s:72:8:72:Infinity":33,"s:72:21:72:Infinity":34,"s:73:8:73:Infinity":35,"f:76:12:76:13":9,"s:77:8:77:Infinity":36,"s:78:8:78:Infinity":37,"s:79:8:79:Infinity":38,"f:81:13:81:14":10,"s:82:8:82:Infinity":39,"s:83:8:83:Infinity":40,"b:87:2:87:Infinity:undefined:undefined:undefined:undefined":9,"s:87:2:87:Infinity":41,"s:87:15:87:Infinity":42,"b:88:2:88:Infinity:undefined:undefined:undefined:undefined":10,"s:88:2:88:Infinity":43,"s:88:13:88:Infinity":44,"s:90:23:92:Infinity":45,"f:90:23:90:29":11,"s:91:4:91:Infinity":46,"f:91:53:91:60":12,"s:91:60:91:95":47,"s:94:2:210:Infinity":48,"f:96:36:96:42":13,"s:96:42:96:68":49,"f:106:22:106:23":14,"s:106:29:106:Infinity":50,"b:115:79:115:90:115:90:115:94":11,"b:120:73:120:84:120:84:120:88":12,"b:125:81:125:92:125:92:125:96":13,"b:134:51:134:64:134:64:134:66":14,"b:136:9:136:Infinity:137:10:149:Infinity":15,"f:138:22:138:23":15,"s:139:14:147:Infinity":51,"b:142:65:142:76:142:76:142:78":16,"b:155:52:155:65:155:65:155:67":17,"b:157:9:157:Infinity:158:11:173:Infinity":18,"b:159:12:159:Infinity:161:12:173:Infinity":19,"f:162:25:162:26":16,"s:163:16:171:Infinity":52,"b:166:75:166:86:166:86:166:88":20,"b:169:21:169:35:169:35:169:Infinity":21,"f:195:21:195:27":17,"s:195:27:195:Infinity":53,"b:196:43:196:54:196:54:196:Infinity":22,"f:202:21:202:27":18,"s:202:27:202:Infinity":54,"b:203:42:203:53:203:53:203:Infinity":23}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedListVariants.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedListVariants.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.tsx","statementMap":{"0":{"start":{"line":8,"column":30},"end":{"line":8,"column":null}},"1":{"start":{"line":9,"column":30},"end":{"line":9,"column":null}},"2":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"3":{"start":{"line":11,"column":8},"end":{"line":11,"column":null}},"4":{"start":{"line":13,"column":23},"end":{"line":37,"column":null}},"5":{"start":{"line":14,"column":4},"end":{"line":14,"column":null}},"6":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"7":{"start":{"line":17,"column":4},"end":{"line":36,"column":null}},"8":{"start":{"line":19,"column":21},"end":{"line":19,"column":null}},"9":{"start":{"line":20,"column":6},"end":{"line":20,"column":null}},"10":{"start":{"line":21,"column":6},"end":{"line":21,"column":null}},"11":{"start":{"line":23,"column":18},"end":{"line":26,"column":null}},"12":{"start":{"line":28,"column":6},"end":{"line":33,"column":null}},"13":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"14":{"start":{"line":31,"column":21},"end":{"line":31,"column":null}},"15":{"start":{"line":32,"column":8},"end":{"line":32,"column":null}},"16":{"start":{"line":35,"column":6},"end":{"line":35,"column":null}},"17":{"start":{"line":39,"column":2},"end":{"line":65,"column":null}},"18":{"start":{"line":49,"column":29},"end":{"line":49,"column":null}},"19":{"start":{"line":58,"column":29},"end":{"line":58,"column":null}}},"fnMap":{"0":{"name":"Login","decl":{"start":{"line":7,"column":24},"end":{"line":7,"column":32}},"loc":{"start":{"line":7,"column":32},"end":{"line":67,"column":null}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":23},"end":{"line":13,"column":30}},"loc":{"start":{"line":13,"column":47},"end":{"line":37,"column":null}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":49,"column":22},"end":{"line":49,"column":23}},"loc":{"start":{"line":49,"column":29},"end":{"line":49,"column":null}},"line":49},"3":{"name":"(anonymous_3)","decl":{"start":{"line":58,"column":22},"end":{"line":58,"column":23}},"loc":{"start":{"line":58,"column":29},"end":{"line":58,"column":null}},"line":58}},"branchMap":{"0":{"loc":{"start":{"line":28,"column":6},"end":{"line":33,"column":null}},"type":"if","locations":[{"start":{"line":28,"column":6},"end":{"line":33,"column":null}},{"start":{"line":30,"column":13},"end":{"line":33,"column":null}}],"line":28},"1":{"loc":{"start":{"line":32,"column":17},"end":{"line":32,"column":47}},"type":"binary-expr","locations":[{"start":{"line":32,"column":17},"end":{"line":32,"column":33}},{"start":{"line":32,"column":33},"end":{"line":32,"column":47}}],"line":32},"2":{"loc":{"start":{"line":62,"column":9},"end":{"line":62,"column":null}},"type":"binary-expr","locations":[{"start":{"line":62,"column":9},"end":{"line":62,"column":18}},{"start":{"line":62,"column":18},"end":{"line":62,"column":null}}],"line":62}},"s":{"0":17,"1":17,"2":17,"3":17,"4":17,"5":3,"6":3,"7":3,"8":3,"9":3,"10":3,"11":3,"12":2,"13":1,"14":1,"15":1,"16":1,"17":17,"18":3,"19":3},"f":{"0":17,"1":3,"2":3,"3":3},"b":{"0":[1,1],"1":[1,0],"2":[17,2]},"meta":{"lastBranch":3,"lastFunction":4,"lastStatement":20,"seen":{"f:7:24:7:32":0,"s:8:30:8:Infinity":0,"s:9:30:9:Infinity":1,"s:10:24:10:Infinity":2,"s:11:8:11:Infinity":3,"s:13:23:37:Infinity":4,"f:13:23:13:30":1,"s:14:4:14:Infinity":5,"s:15:4:15:Infinity":6,"s:17:4:36:Infinity":7,"s:19:21:19:Infinity":8,"s:20:6:20:Infinity":9,"s:21:6:21:Infinity":10,"s:23:18:26:Infinity":11,"b:28:6:33:Infinity:30:13:33:Infinity":0,"s:28:6:33:Infinity":12,"s:29:8:29:Infinity":13,"s:31:21:31:Infinity":14,"s:32:8:32:Infinity":15,"b:32:17:32:33:32:33:32:47":1,"s:35:6:35:Infinity":16,"s:39:2:65:Infinity":17,"f:49:22:49:23":2,"s:49:29:49:Infinity":18,"f:58:22:58:23":3,"s:58:29:58:Infinity":19,"b:62:9:62:18:62:18:62:Infinity":2}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.tsx","statementMap":{"0":{"start":{"line":12,"column":24},"end":{"line":12,"column":null}},"1":{"start":{"line":14,"column":34},"end":{"line":14,"column":null}},"2":{"start":{"line":15,"column":28},"end":{"line":15,"column":null}},"3":{"start":{"line":16,"column":24},"end":{"line":16,"column":null}},"4":{"start":{"line":18,"column":34},"end":{"line":18,"column":null}},"5":{"start":{"line":21,"column":21},"end":{"line":36,"column":null}},"6":{"start":{"line":22,"column":4},"end":{"line":22,"column":null}},"7":{"start":{"line":23,"column":4},"end":{"line":35,"column":null}},"8":{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},"9":{"start":{"line":25,"column":21},"end":{"line":25,"column":null}},"10":{"start":{"line":26,"column":8},"end":{"line":26,"column":null}},"11":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"12":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"13":{"start":{"line":33,"column":8},"end":{"line":33,"column":null}},"14":{"start":{"line":34,"column":8},"end":{"line":34,"column":null}},"15":{"start":{"line":38,"column":2},"end":{"line":41,"column":null}},"16":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"17":{"start":{"line":44,"column":24},"end":{"line":66,"column":null}},"18":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"19":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"20":{"start":{"line":46,"column":21},"end":{"line":46,"column":null}},"21":{"start":{"line":48,"column":4},"end":{"line":48,"column":null}},"22":{"start":{"line":49,"column":4},"end":{"line":65,"column":null}},"23":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"24":{"start":{"line":55,"column":21},"end":{"line":55,"column":null}},"25":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"26":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"27":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"28":{"start":{"line":63,"column":8},"end":{"line":63,"column":null}},"29":{"start":{"line":64,"column":8},"end":{"line":64,"column":null}},"30":{"start":{"line":68,"column":27},"end":{"line":84,"column":null}},"31":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"32":{"start":{"line":69,"column":75},"end":{"line":69,"column":null}},"33":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"34":{"start":{"line":72,"column":4},"end":{"line":83,"column":null}},"35":{"start":{"line":76,"column":8},"end":{"line":76,"column":null}},"36":{"start":{"line":76,"column":21},"end":{"line":76,"column":null}},"37":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"38":{"start":{"line":77,"column":37},"end":{"line":77,"column":49}},"39":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"40":{"start":{"line":81,"column":8},"end":{"line":81,"column":null}},"41":{"start":{"line":82,"column":8},"end":{"line":82,"column":null}},"42":{"start":{"line":86,"column":23},"end":{"line":112,"column":null}},"43":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"44":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"45":{"start":{"line":88,"column":21},"end":{"line":88,"column":null}},"46":{"start":{"line":90,"column":4},"end":{"line":90,"column":null}},"47":{"start":{"line":91,"column":21},"end":{"line":91,"column":null}},"48":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"49":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"50":{"start":{"line":95,"column":4},"end":{"line":111,"column":null}},"51":{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},"52":{"start":{"line":100,"column":21},"end":{"line":100,"column":null}},"53":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"54":{"start":{"line":104,"column":8},"end":{"line":104,"column":null}},"55":{"start":{"line":105,"column":8},"end":{"line":105,"column":null}},"56":{"start":{"line":106,"column":8},"end":{"line":106,"column":null}},"57":{"start":{"line":109,"column":8},"end":{"line":109,"column":null}},"58":{"start":{"line":110,"column":8},"end":{"line":110,"column":null}},"59":{"start":{"line":114,"column":22},"end":{"line":131,"column":null}},"60":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"61":{"start":{"line":116,"column":4},"end":{"line":130,"column":null}},"62":{"start":{"line":120,"column":8},"end":{"line":120,"column":null}},"63":{"start":{"line":120,"column":21},"end":{"line":120,"column":null}},"64":{"start":{"line":121,"column":8},"end":{"line":121,"column":null}},"65":{"start":{"line":124,"column":8},"end":{"line":124,"column":null}},"66":{"start":{"line":125,"column":8},"end":{"line":125,"column":null}},"67":{"start":{"line":128,"column":8},"end":{"line":128,"column":null}},"68":{"start":{"line":129,"column":8},"end":{"line":129,"column":null}},"69":{"start":{"line":133,"column":2},"end":{"line":234,"column":null}},"70":{"start":{"line":145,"column":31},"end":{"line":145,"column":null}},"71":{"start":{"line":163,"column":29},"end":{"line":163,"column":null}},"72":{"start":{"line":183,"column":31},"end":{"line":183,"column":null}},"73":{"start":{"line":217,"column":12},"end":{"line":230,"column":null}},"74":{"start":{"line":223,"column":31},"end":{"line":223,"column":null}}},"fnMap":{"0":{"name":"Settings","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":33}},"loc":{"start":{"line":11,"column":77},"end":{"line":236,"column":null}},"line":11},"1":{"name":"(anonymous_1)","decl":{"start":{"line":21,"column":39},"end":{"line":21,"column":45}},"loc":{"start":{"line":21,"column":45},"end":{"line":36,"column":5}},"line":21},"2":{"name":"(anonymous_2)","decl":{"start":{"line":24,"column":12},"end":{"line":24,"column":13}},"loc":{"start":{"line":24,"column":21},"end":{"line":27,"column":7}},"line":24},"3":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":12},"end":{"line":28,"column":13}},"loc":{"start":{"line":28,"column":22},"end":{"line":31,"column":7}},"line":28},"4":{"name":"(anonymous_4)","decl":{"start":{"line":32,"column":13},"end":{"line":32,"column":14}},"loc":{"start":{"line":32,"column":22},"end":{"line":35,"column":7}},"line":32},"5":{"name":"(anonymous_5)","decl":{"start":{"line":38,"column":12},"end":{"line":38,"column":18}},"loc":{"start":{"line":38,"column":18},"end":{"line":41,"column":5}},"line":38},"6":{"name":"(anonymous_6)","decl":{"start":{"line":44,"column":24},"end":{"line":44,"column":25}},"loc":{"start":{"line":44,"column":48},"end":{"line":66,"column":null}},"line":44},"7":{"name":"(anonymous_7)","decl":{"start":{"line":54,"column":12},"end":{"line":54,"column":13}},"loc":{"start":{"line":54,"column":21},"end":{"line":57,"column":7}},"line":54},"8":{"name":"(anonymous_8)","decl":{"start":{"line":58,"column":12},"end":{"line":58,"column":18}},"loc":{"start":{"line":58,"column":18},"end":{"line":61,"column":7}},"line":58},"9":{"name":"(anonymous_9)","decl":{"start":{"line":62,"column":13},"end":{"line":62,"column":14}},"loc":{"start":{"line":62,"column":22},"end":{"line":65,"column":7}},"line":62},"10":{"name":"(anonymous_10)","decl":{"start":{"line":68,"column":27},"end":{"line":68,"column":28}},"loc":{"start":{"line":68,"column":43},"end":{"line":84,"column":null}},"line":68},"11":{"name":"(anonymous_11)","decl":{"start":{"line":75,"column":12},"end":{"line":75,"column":13}},"loc":{"start":{"line":75,"column":21},"end":{"line":79,"column":7}},"line":75},"12":{"name":"(anonymous_12)","decl":{"start":{"line":77,"column":30},"end":{"line":77,"column":31}},"loc":{"start":{"line":77,"column":37},"end":{"line":77,"column":49}},"line":77},"13":{"name":"(anonymous_13)","decl":{"start":{"line":80,"column":13},"end":{"line":80,"column":14}},"loc":{"start":{"line":80,"column":22},"end":{"line":83,"column":7}},"line":80},"14":{"name":"(anonymous_14)","decl":{"start":{"line":86,"column":23},"end":{"line":86,"column":24}},"loc":{"start":{"line":86,"column":47},"end":{"line":112,"column":null}},"line":86},"15":{"name":"(anonymous_15)","decl":{"start":{"line":99,"column":12},"end":{"line":99,"column":13}},"loc":{"start":{"line":99,"column":21},"end":{"line":102,"column":7}},"line":99},"16":{"name":"(anonymous_16)","decl":{"start":{"line":103,"column":12},"end":{"line":103,"column":18}},"loc":{"start":{"line":103,"column":18},"end":{"line":107,"column":7}},"line":103},"17":{"name":"(anonymous_17)","decl":{"start":{"line":108,"column":13},"end":{"line":108,"column":14}},"loc":{"start":{"line":108,"column":22},"end":{"line":111,"column":7}},"line":108},"18":{"name":"(anonymous_18)","decl":{"start":{"line":114,"column":22},"end":{"line":114,"column":28}},"loc":{"start":{"line":114,"column":28},"end":{"line":131,"column":null}},"line":114},"19":{"name":"(anonymous_19)","decl":{"start":{"line":119,"column":12},"end":{"line":119,"column":13}},"loc":{"start":{"line":119,"column":21},"end":{"line":122,"column":7}},"line":119},"20":{"name":"(anonymous_20)","decl":{"start":{"line":123,"column":12},"end":{"line":123,"column":18}},"loc":{"start":{"line":123,"column":18},"end":{"line":126,"column":7}},"line":123},"21":{"name":"(anonymous_21)","decl":{"start":{"line":127,"column":13},"end":{"line":127,"column":14}},"loc":{"start":{"line":127,"column":22},"end":{"line":130,"column":7}},"line":127},"22":{"name":"(anonymous_22)","decl":{"start":{"line":145,"column":24},"end":{"line":145,"column":25}},"loc":{"start":{"line":145,"column":31},"end":{"line":145,"column":null}},"line":145},"23":{"name":"(anonymous_23)","decl":{"start":{"line":163,"column":22},"end":{"line":163,"column":23}},"loc":{"start":{"line":163,"column":29},"end":{"line":163,"column":null}},"line":163},"24":{"name":"(anonymous_24)","decl":{"start":{"line":183,"column":24},"end":{"line":183,"column":25}},"loc":{"start":{"line":183,"column":31},"end":{"line":183,"column":null}},"line":183},"25":{"name":"(anonymous_25)","decl":{"start":{"line":216,"column":21},"end":{"line":216,"column":22}},"loc":{"start":{"line":217,"column":12},"end":{"line":230,"column":null}},"line":217},"26":{"name":"(anonymous_26)","decl":{"start":{"line":223,"column":25},"end":{"line":223,"column":31}},"loc":{"start":{"line":223,"column":31},"end":{"line":223,"column":null}},"line":223}},"branchMap":{"0":{"loc":{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},"type":"if","locations":[{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},{"start":{},"end":{}}],"line":25},"1":{"loc":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":46},"2":{"loc":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":55},"3":{"loc":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":69},"4":{"loc":{"start":{"line":76,"column":8},"end":{"line":76,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":8},"end":{"line":76,"column":null}},{"start":{},"end":{}}],"line":76},"5":{"loc":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"type":"if","locations":[{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},{"start":{},"end":{}}],"line":88},"6":{"loc":{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},"type":"if","locations":[{"start":{"line":100,"column":8},"end":{"line":100,"column":null}},{"start":{},"end":{}}],"line":100},"7":{"loc":{"start":{"line":120,"column":8},"end":{"line":120,"column":null}},"type":"if","locations":[{"start":{"line":120,"column":8},"end":{"line":120,"column":null}},{"start":{},"end":{}}],"line":120},"8":{"loc":{"start":{"line":137,"column":7},"end":{"line":154,"column":null}},"type":"binary-expr","locations":[{"start":{"line":137,"column":7},"end":{"line":137,"column":null}},{"start":{"line":138,"column":8},"end":{"line":154,"column":null}}],"line":137},"9":{"loc":{"start":{"line":144,"column":21},"end":{"line":144,"column":null}},"type":"binary-expr","locations":[{"start":{"line":144,"column":21},"end":{"line":144,"column":34}},{"start":{"line":144,"column":34},"end":{"line":144,"column":null}}],"line":144},"10":{"loc":{"start":{"line":183,"column":45},"end":{"line":183,"column":72}},"type":"binary-expr","locations":[{"start":{"line":183,"column":45},"end":{"line":183,"column":68}},{"start":{"line":183,"column":68},"end":{"line":183,"column":72}}],"line":183},"11":{"loc":{"start":{"line":187,"column":44},"end":{"line":187,"column":68}},"type":"binary-expr","locations":[{"start":{"line":187,"column":44},"end":{"line":187,"column":59}},{"start":{"line":187,"column":59},"end":{"line":187,"column":68}}],"line":187},"12":{"loc":{"start":{"line":210,"column":7},"end":{"line":210,"column":null}},"type":"binary-expr","locations":[{"start":{"line":210,"column":7},"end":{"line":210,"column":16}},{"start":{"line":210,"column":16},"end":{"line":210,"column":null}}],"line":210},"13":{"loc":{"start":{"line":214,"column":9},"end":{"line":214,"column":null}},"type":"binary-expr","locations":[{"start":{"line":214,"column":9},"end":{"line":214,"column":20}},{"start":{"line":214,"column":20},"end":{"line":214,"column":null}}],"line":214},"14":{"loc":{"start":{"line":219,"column":46},"end":{"line":219,"column":73}},"type":"binary-expr","locations":[{"start":{"line":219,"column":46},"end":{"line":219,"column":60}},{"start":{"line":219,"column":60},"end":{"line":219,"column":73}}],"line":219}},"s":{"0":34,"1":34,"2":34,"3":34,"4":34,"5":34,"6":9,"7":9,"8":9,"9":0,"10":9,"11":9,"12":9,"13":0,"14":0,"15":34,"16":7,"17":34,"18":2,"19":2,"20":0,"21":2,"22":2,"23":2,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":34,"31":1,"32":0,"33":1,"34":1,"35":1,"36":0,"37":1,"38":1,"39":1,"40":0,"41":0,"42":34,"43":1,"44":1,"45":0,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":0,"53":1,"54":1,"55":1,"56":1,"57":0,"58":0,"59":34,"60":1,"61":1,"62":1,"63":0,"64":1,"65":1,"66":1,"67":0,"68":0,"69":34,"70":1,"71":2,"72":1,"73":6,"74":1},"f":{"0":34,"1":9,"2":9,"3":9,"4":0,"5":7,"6":2,"7":2,"8":1,"9":1,"10":1,"11":1,"12":1,"13":0,"14":1,"15":1,"16":1,"17":0,"18":1,"19":1,"20":1,"21":0,"22":1,"23":2,"24":1,"25":6,"26":1},"b":{"0":[0,9],"1":[0,2],"2":[1,1],"3":[0,1],"4":[0,1],"5":[0,1],"6":[0,1],"7":[0,1],"8":[34,3],"9":[3,0],"10":[1,0],"11":[34,3],"12":[34,1],"13":[34,13],"14":[6,0]},"meta":{"lastBranch":15,"lastFunction":27,"lastStatement":75,"seen":{"f:11:24:11:33":0,"s:12:24:12:Infinity":0,"s:14:34:14:Infinity":1,"s:15:28:15:Infinity":2,"s:16:24:16:Infinity":3,"s:18:34:18:Infinity":4,"s:21:21:36:Infinity":5,"f:21:39:21:45":1,"s:22:4:22:Infinity":6,"s:23:4:35:Infinity":7,"f:24:12:24:13":2,"b:25:8:25:Infinity:undefined:undefined:undefined:undefined":0,"s:25:8:25:Infinity":8,"s:25:21:25:Infinity":9,"s:26:8:26:Infinity":10,"f:28:12:28:13":3,"s:29:8:29:Infinity":11,"s:30:8:30:Infinity":12,"f:32:13:32:14":4,"s:33:8:33:Infinity":13,"s:34:8:34:Infinity":14,"s:38:2:41:Infinity":15,"f:38:12:38:18":5,"s:40:4:40:Infinity":16,"s:44:24:66:Infinity":17,"f:44:24:44:25":6,"s:45:4:45:Infinity":18,"b:46:4:46:Infinity:undefined:undefined:undefined:undefined":1,"s:46:4:46:Infinity":19,"s:46:21:46:Infinity":20,"s:48:4:48:Infinity":21,"s:49:4:65:Infinity":22,"f:54:12:54:13":7,"b:55:8:55:Infinity:undefined:undefined:undefined:undefined":2,"s:55:8:55:Infinity":23,"s:55:21:55:Infinity":24,"s:56:8:56:Infinity":25,"f:58:12:58:18":8,"s:59:8:59:Infinity":26,"s:60:8:60:Infinity":27,"f:62:13:62:14":9,"s:63:8:63:Infinity":28,"s:64:8:64:Infinity":29,"s:68:27:84:Infinity":30,"f:68:27:68:28":10,"b:69:4:69:Infinity:undefined:undefined:undefined:undefined":3,"s:69:4:69:Infinity":31,"s:69:75:69:Infinity":32,"s:71:4:71:Infinity":33,"s:72:4:83:Infinity":34,"f:75:12:75:13":11,"b:76:8:76:Infinity:undefined:undefined:undefined:undefined":4,"s:76:8:76:Infinity":35,"s:76:21:76:Infinity":36,"s:77:8:77:Infinity":37,"f:77:30:77:31":12,"s:77:37:77:49":38,"s:78:8:78:Infinity":39,"f:80:13:80:14":13,"s:81:8:81:Infinity":40,"s:82:8:82:Infinity":41,"s:86:23:112:Infinity":42,"f:86:23:86:24":14,"s:87:4:87:Infinity":43,"b:88:4:88:Infinity:undefined:undefined:undefined:undefined":5,"s:88:4:88:Infinity":44,"s:88:21:88:Infinity":45,"s:90:4:90:Infinity":46,"s:91:21:91:Infinity":47,"s:92:4:92:Infinity":48,"s:93:4:93:Infinity":49,"s:95:4:111:Infinity":50,"f:99:12:99:13":15,"b:100:8:100:Infinity:undefined:undefined:undefined:undefined":6,"s:100:8:100:Infinity":51,"s:100:21:100:Infinity":52,"s:101:8:101:Infinity":53,"f:103:12:103:18":16,"s:104:8:104:Infinity":54,"s:105:8:105:Infinity":55,"s:106:8:106:Infinity":56,"f:108:13:108:14":17,"s:109:8:109:Infinity":57,"s:110:8:110:Infinity":58,"s:114:22:131:Infinity":59,"f:114:22:114:28":18,"s:115:4:115:Infinity":60,"s:116:4:130:Infinity":61,"f:119:12:119:13":19,"b:120:8:120:Infinity:undefined:undefined:undefined:undefined":7,"s:120:8:120:Infinity":62,"s:120:21:120:Infinity":63,"s:121:8:121:Infinity":64,"f:123:12:123:18":20,"s:124:8:124:Infinity":65,"s:125:8:125:Infinity":66,"f:127:13:127:14":21,"s:128:8:128:Infinity":67,"s:129:8:129:Infinity":68,"s:133:2:234:Infinity":69,"b:137:7:137:Infinity:138:8:154:Infinity":8,"b:144:21:144:34:144:34:144:Infinity":9,"f:145:24:145:25":22,"s:145:31:145:Infinity":70,"f:163:22:163:23":23,"s:163:29:163:Infinity":71,"f:183:24:183:25":24,"s:183:31:183:Infinity":72,"b:183:45:183:68:183:68:183:72":10,"b:187:44:187:59:187:59:187:68":11,"b:210:7:210:16:210:16:210:Infinity":12,"b:214:9:214:20:214:20:214:Infinity":13,"f:216:21:216:22":25,"s:217:12:230:Infinity":73,"b:219:46:219:60:219:60:219:73":14,"f:223:25:223:31":26,"s:223:31:223:Infinity":74}}} -} diff --git a/frontend/coverage/favicon.png b/frontend/coverage/favicon.png Binary files differdeleted file mode 100644 index c1525b8..0000000 --- a/frontend/coverage/favicon.png +++ /dev/null diff --git a/frontend/coverage/index.html b/frontend/coverage/index.html deleted file mode 100644 index 3c8ce1b..0000000 --- a/frontend/coverage/index.html +++ /dev/null @@ -1,131 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for All files</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="prettify.css" /> - <link rel="stylesheet" href="base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1>All files</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">84.12% </span> - <span class="quiet">Statements</span> - <span class='fraction'>302/359</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">73.24% </span> - <span class="quiet">Branches</span> - <span class='fraction'>167/228</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">81.48% </span> - <span class="quiet">Functions</span> - <span class='fraction'>88/108</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">86.4% </span> - <span class="quiet">Lines</span> - <span class='fraction'>286/331</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <div class="pad1"> -<table class="coverage-summary"> -<thead> -<tr> - <th data-col="file" data-fmt="html" data-html="true" class="file">File</th> - <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th> - <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th> - <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th> - <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th> - <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th> - <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th> -</tr> -</thead> -<tbody><tr> - <td class="file medium" data-value="src"><a href="src/index.html">src</a></td> - <td data-value="70.21" class="pic medium"> - <div class="chart"><div class="cover-fill" style="width: 70%"></div><div class="cover-empty" style="width: 30%"></div></div> - </td> - <td data-value="70.21" class="pct medium">70.21%</td> - <td data-value="47" class="abs medium">33/47</td> - <td data-value="65.71" class="pct medium">65.71%</td> - <td data-value="35" class="abs medium">23/35</td> - <td data-value="60" class="pct medium">60%</td> - <td data-value="15" class="abs medium">9/15</td> - <td data-value="71.11" class="pct medium">71.11%</td> - <td data-value="45" class="abs medium">32/45</td> - </tr> - -<tr> - <td class="file high" data-value="src/components"><a href="src/components/index.html">src/components</a></td> - <td data-value="86.21" class="pic high"> - <div class="chart"><div class="cover-fill" style="width: 86%"></div><div class="cover-empty" style="width: 14%"></div></div> - </td> - <td data-value="86.21" class="pct high">86.21%</td> - <td data-value="312" class="abs high">269/312</td> - <td data-value="74.61" class="pct medium">74.61%</td> - <td data-value="193" class="abs medium">144/193</td> - <td data-value="84.94" class="pct high">84.94%</td> - <td data-value="93" class="abs high">79/93</td> - <td data-value="88.81" class="pct high">88.81%</td> - <td data-value="286" class="abs high">254/286</td> - </tr> - -</tbody> -</table> -</div> - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="sorter.js"></script> - <script src="block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/prettify.css b/frontend/coverage/prettify.css deleted file mode 100644 index b317a7c..0000000 --- a/frontend/coverage/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/frontend/coverage/prettify.js b/frontend/coverage/prettify.js deleted file mode 100644 index b322523..0000000 --- a/frontend/coverage/prettify.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.ignoreCase){ac=true}else{if(/[a-z]/i.test(ae.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){S=true;ac=false;break}}}var Y={b:8,t:9,n:10,v:11,f:12,r:13};function ab(ah){var ag=ah.charCodeAt(0);if(ag!==92){return ag}var af=ah.charAt(1);ag=Y[af];if(ag){return ag}else{if("0"<=af&&af<="7"){return parseInt(ah.substring(1),8)}else{if(af==="u"||af==="x"){return parseInt(ah.substring(2),16)}else{return ah.charCodeAt(1)}}}}function T(af){if(af<32){return(af<16?"\\x0":"\\x")+af.toString(16)}var ag=String.fromCharCode(af);if(ag==="\\"||ag==="-"||ag==="["||ag==="]"){ag="\\"+ag}return ag}function X(am){var aq=am.substring(1,am.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ak=[];var af=[];var ao=aq[0]==="^";for(var ar=ao?1:0,aj=aq.length;ar<aj;++ar){var ah=aq[ar];if(/\\[bdsw]/i.test(ah)){ak.push(ah)}else{var ag=ab(ah);var al;if(ar+2<aj&&"-"===aq[ar+1]){al=ab(aq[ar+2]);ar+=2}else{al=ag}af.push([ag,al]);if(!(al<65||ag>122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;ar<af.length;++ar){var at=af[ar];if(at[0]<=ap[1]+1){ap[1]=Math.max(ap[1],at[1])}else{ai.push(ap=at)}}var an=["["];if(ao){an.push("^")}an.push.apply(an,ak);for(var ar=0;ar<ai.length;++ar){var at=ai[ar];an.push(T(at[0]));if(at[1]>at[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){an[af]=-1}}}}for(var ak=1;ak<an.length;++ak){if(-1===an[ak]){an[ak]=++ad}}for(var ak=0,am=0;ak<ah;++ak){var ag=aj[ak];if(ag==="("){++am;if(an[am]===undefined){aj[ak]="(?:"}}else{if("\\"===ag.charAt(0)){var af=+ag.substring(1);if(af&&af<=am){aj[ak]="\\"+an[am]}}}}for(var ak=0,am=0;ak<ah;++ak){if("^"===aj[ak]&&"^"!==aj[ak+1]){aj[ak]=""}}if(al.ignoreCase&&S){for(var ak=0;ak<ah;++ak){var ag=aj[ak];var ai=ag.charAt(0);if(ag.length>=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V<U;++V){var ae=Z[V];if(ae.global||ae.multiline){throw new Error(""+ae)}aa.push("(?:"+W(ae)+")")}return new RegExp(aa.join("|"),ac?"gi":"g")}function a(V){var U=/(?:^|\s)nocode(?:\s|$)/;var X=[];var T=0;var Z=[];var W=0;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=document.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Y=S&&"pre"===S.substring(0,3);function aa(ab){switch(ab.nodeType){case 1:if(U.test(ab.className)){return}for(var ae=ab.firstChild;ae;ae=ae.nextSibling){aa(ae)}var ad=ab.nodeName;if("BR"===ad||"LI"===ad){X[W]="\n";Z[W<<1]=T++;Z[(W++<<1)|1]=ab}break;case 3:case 4:var ac=ab.nodeValue;if(ac.length){if(!Y){ac=ac.replace(/[ \t\r\n]+/g," ")}else{ac=ac.replace(/\r\n?/g,"\n")}X[W]=ac;Z[W<<1]=T;T+=ac.length;Z[(W++<<1)|1]=ab}break}}aa(V);return{sourceCode:X.join("").replace(/\n$/,""),spans:Z}}function B(S,U,W,T){if(!U){return}var V={sourceCode:U,basePos:S};W(V);T.push.apply(T,V.decorations)}var v=/\S/;function o(S){var V=undefined;for(var U=S.firstChild;U;U=U.nextSibling){var T=U.nodeType;V=(T===1)?(V?S:U):(T===3)?(v.test(U.nodeValue)?S:V):V}return V===S?undefined:V}function g(U,T){var S={};var V;(function(){var ad=U.concat(T);var ah=[];var ag={};for(var ab=0,Z=ad.length;ab<Z;++ab){var Y=ad[ab];var ac=Y[3];if(ac){for(var ae=ac.length;--ae>=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae<aq;++ae){var ag=an[ae];var ap=aj[ag];var ai=void 0;var am;if(typeof ap==="string"){am=false}else{var aa=S[ag.charAt(0)];if(aa){ai=ag.match(aa[1]);ap=aa[0]}else{for(var ao=0;ao<X;++ao){aa=T[ao];ai=ag.match(aa[1]);if(ai){ap=aa[0];break}}if(!ai){ap=F}}am=ap.length>=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y<W.length;++Y){ae(W[Y])}if(ag===(ag|0)){W[0].setAttribute("value",ag)}var aa=ac.createElement("OL");aa.className="linenums";var X=Math.max(0,((ag-1))|0)||0;for(var Y=0,T=W.length;Y<T;++Y){af=W[Y];af.className="L"+((Y+X)%10);if(!af.firstChild){af.appendChild(ac.createTextNode("\xA0"))}aa.appendChild(af)}V.appendChild(aa)}function D(ac){var aj=/\bMSIE\b/.test(navigator.userAgent);var am=/\n/g;var al=ac.sourceCode;var an=al.length;var V=0;var aa=ac.spans;var T=aa.length;var ah=0;var X=ac.decorations;var Y=X.length;var Z=0;X[Y]=an;var ar,aq;for(aq=ar=0;aq<Y;){if(X[aq]!==X[aq+2]){X[ar++]=X[aq++];X[ar++]=X[aq++]}else{aq+=2}}Y=ar;for(aq=ar=0;aq<Y;){var at=X[aq];var ab=X[aq+1];var W=aq+2;while(W+2<=Y&&X[W+1]===ab){W+=2}X[ar++]=at;X[ar++]=ab;aq=W}Y=X.length=ar;var ae=null;while(ah<T){var af=aa[ah];var S=aa[ah+2]||an;var ag=X[Z];var ap=X[Z+2]||an;var W=Math.min(S,ap);var ak=aa[ah+1];var U;if(ak.nodeType!==1&&(U=al.substring(V,W))){if(aj){U=U.replace(am,"\r")}ak.nodeValue=U;var ai=ak.ownerDocument;var ao=ai.createElement("SPAN");ao.className=X[Z+1];var ad=ak.parentNode;ad.replaceChild(ao,ak);ao.appendChild(ak);if(V<S){aa[ah+1]=ak=ai.createTextNode(al.substring(W,S));ad.insertBefore(ak,ao.nextSibling)}}V=W;if(V>=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*</.test(S)?"default-markup":"default-code"}return t[T]}c(K,["default-code"]);c(g([],[[F,/^[^<?]+/],[E,/^<!\w[^>]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa<ac.length;++aa){for(var Z=0,V=ac[aa].length;Z<V;++Z){T.push(ac[aa][Z])}}ac=null;var W=Date;if(!W.now){W={now:function(){return +(new Date)}}}var X=0;var S;var ab=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ae=/\bprettyprint\b/;function U(){var ag=(window.PR_SHOULD_USE_CONTINUATION?W.now()+250:Infinity);for(;X<T.length&&W.now()<ag;X++){var aj=T[X];var ai=aj.className;if(ai.indexOf("prettyprint")>=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X<T.length){setTimeout(U,250)}else{if(ad){ad()}}}U()}window.prettyPrintOne=y;window.prettyPrint=b;window.PR={createSimpleLexer:g,registerLangHandler:c,sourceDecorator:i,PR_ATTRIB_NAME:P,PR_ATTRIB_VALUE:n,PR_COMMENT:j,PR_DECLARATION:E,PR_KEYWORD:z,PR_LITERAL:G,PR_NOCODE:N,PR_PLAIN:F,PR_PUNCTUATION:L,PR_SOURCE:J,PR_STRING:C,PR_TAG:m,PR_TYPE:O}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/frontend/coverage/sort-arrow-sprite.png b/frontend/coverage/sort-arrow-sprite.png Binary files differdeleted file mode 100644 index 6ed6831..0000000 --- a/frontend/coverage/sort-arrow-sprite.png +++ /dev/null diff --git a/frontend/coverage/sorter.js b/frontend/coverage/sorter.js deleted file mode 100644 index 4ed70ae..0000000 --- a/frontend/coverage/sorter.js +++ /dev/null @@ -1,210 +0,0 @@ -/* eslint-disable */ -var addSorting = (function() { - 'use strict'; - var cols, - currentSort = { - index: 0, - desc: false - }; - - // returns the summary table element - function getTable() { - return document.querySelector('.coverage-summary'); - } - // returns the thead element of the summary table - function getTableHeader() { - return getTable().querySelector('thead tr'); - } - // returns the tbody element of the summary table - function getTableBody() { - return getTable().querySelector('tbody'); - } - // returns the th element for nth column - function getNthColumn(n) { - return getTableHeader().querySelectorAll('th')[n]; - } - - function onFilterInput() { - const searchValue = document.getElementById('fileSearch').value; - const rows = document.getElementsByTagName('tbody')[0].children; - - // Try to create a RegExp from the searchValue. If it fails (invalid regex), - // it will be treated as a plain text search - let searchRegex; - try { - searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive - } catch (error) { - searchRegex = null; - } - - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - let isMatch = false; - - if (searchRegex) { - // If a valid regex was created, use it for matching - isMatch = searchRegex.test(row.textContent); - } else { - // Otherwise, fall back to the original plain text search - isMatch = row.textContent - .toLowerCase() - .includes(searchValue.toLowerCase()); - } - - row.style.display = isMatch ? '' : 'none'; - } - } - - // loads the search box - function addSearchBox() { - var template = document.getElementById('filterTemplate'); - var templateClone = template.content.cloneNode(true); - templateClone.getElementById('fileSearch').oninput = onFilterInput; - template.parentElement.appendChild(templateClone); - } - - // loads all columns - function loadColumns() { - var colNodes = getTableHeader().querySelectorAll('th'), - colNode, - cols = [], - col, - i; - - for (i = 0; i < colNodes.length; i += 1) { - colNode = colNodes[i]; - col = { - key: colNode.getAttribute('data-col'), - sortable: !colNode.getAttribute('data-nosort'), - type: colNode.getAttribute('data-type') || 'string' - }; - cols.push(col); - if (col.sortable) { - col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + '<span class="sorter"></span>'; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function(a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function(a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc - ? ' sorted-desc' - : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function() { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i = 0; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function() { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(); - addSearchBox(); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/frontend/coverage/src/App.css.html b/frontend/coverage/src/App.css.html deleted file mode 100644 index d23e87b..0000000 --- a/frontend/coverage/src/App.css.html +++ /dev/null @@ -1,478 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/App.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../prettify.css" /> - <link rel="stylesheet" href="../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> App.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/* Resets and Base Styles */ -* { - box-sizing: border-box; -} - -body { - margin: 0; -} - -/* Dashboard Layout */ -.dashboard { - display: flex; - flex-direction: column; - height: 100vh; - overflow: hidden; - /* Prevent body scroll */ -} - -/* Header styles removed as we moved to sidebar navigation */ - -.dashboard-content { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -.dashboard-sidebar { - width: 11rem; - background: transparent; - border-right: 1px solid var(--border-color); - display: flex; - flex-direction: column; - overflow-y: auto; - transition: margin-left 0.4s ease; - /* No padding here, handled in FeedList */ -} - -.dashboard-sidebar.hidden { - margin-left: -11rem; -} - -.dashboard-main { - flex: 1; - padding: 2rem; - overflow-y: auto; - background: var(--bg-color); - margin-left: 0; -} - -.dashboard-main>* { - max-width: 35em; - margin: 0 auto; -} - -.fixed-toggle { - position: absolute; - top: 1rem; - left: 1rem; - z-index: 1000; - background: var(--bg-color); - /* Added bg to be visible over content if needed */ - border: none; - font-size: 2rem; - line-height: 1; - cursor: pointer; - padding: 0.2rem; - color: var(--text-color); - border-radius: 50%; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); - display: flex; - align-items: center; - justify-content: center; -} - -.fixed-toggle:hover { - transform: scale(1.1); -} - -/* Mobile Responsiveness */ -@media (max-width: 768px) { - .dashboard-sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 1100; - box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2); - width: 14rem; - /* Slightly wider on mobile for better target area */ - } - - .dashboard-sidebar.hidden { - margin-left: -14rem; - } - - .dashboard-main { - padding: 1rem; - padding-top: 4rem; - /* Space for the toggle button */ - } - - .dashboard-main>* { - max-width: 100%; - } - - /* When sidebar is visible on mobile, we show a backdrop */ - .sidebar-backdrop { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.4); - z-index: 1050; - animation: fadeIn 0.3s ease; - } - - .dashboard.sidebar-visible::after { - display: none; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } -}</pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../sorter.js"></script> - <script src="../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/App.tsx.html b/frontend/coverage/src/App.tsx.html deleted file mode 100644 index 6ec66af..0000000 --- a/frontend/coverage/src/App.tsx.html +++ /dev/null @@ -1,505 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/App.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../prettify.css" /> - <link rel="stylesheet" href="../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> App.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">65.71% </span> - <span class="quiet">Statements</span> - <span class='fraction'>23/35</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">60% </span> - <span class="quiet">Branches</span> - <span class='fraction'>15/25</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">53.84% </span> - <span class="quiet">Functions</span> - <span class='fraction'>7/13</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">64.7% </span> - <span class="quiet">Lines</span> - <span class='fraction'>22/34</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line medium'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import React, { useEffect, useState } from 'react'; -import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom'; -import Login from './components/Login'; -import './App.css'; -import { apiFetch } from './utils'; - -// Protected Route wrapper -function RequireAuth({ children }: { children: React.ReactElement }) { - const [auth, setAuth] = useState<boolean | null>(null); - const location = useLocation(); - - useEffect(() => { - apiFetch('/api/auth') - .then((res) => { - if (res.ok) { - setAuth(true); - } else <span class="missing-if-branch" title="else path not taken" >E</span>{ -<span class="cstat-no" title="statement not covered" > setAuth(false);</span> - } - }) - .catch(<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etAuth(false))</span>; - }, []); - - if (auth === null) { - return <div>Loading...</div>; - } - - <span class="missing-if-branch" title="if path not taken" >I</span>if (!auth) { -<span class="cstat-no" title="statement not covered" > return <Navigate to="/login" state={{ from: location }} replace />;</span> - } - - return children; -} - -import FeedList from './components/FeedList'; -import FeedItems from './components/FeedItems'; -import Settings from './components/Settings'; - -interface DashboardProps { - theme: string; - setTheme: (t: string) => void; - fontTheme: string; - setFontTheme: (t: string) => void; -} - -function Dashboard({ theme, setTheme, fontTheme, setFontTheme }: DashboardProps) { - const [sidebarVisible, setSidebarVisible] = useState(window.innerWidth > 768); - - useEffect(() => { - const handleResize = <span class="fstat-no" title="function not covered" >() => {</span> -<span class="cstat-no" title="statement not covered" > if (window.innerWidth > 768) {</span> -<span class="cstat-no" title="statement not covered" > setSidebarVisible(true);</span> - } else { -<span class="cstat-no" title="statement not covered" > setSidebarVisible(false);</span> - } - }; - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); - - return ( - <div - className={`dashboard ${sidebarVisible ? 'sidebar-visible' : <span class="branch-1 cbranch-no" title="branch not covered" >'sidebar-hidden'}</span> theme-${theme} font-${fontTheme}`} - > - <div className="dashboard-content"> - {(!sidebarVisible || window.innerWidth <= 768) && ( -<span class="branch-2 cbranch-no" title="branch not covered" > <button</span> - className="sidebar-toggle fixed-toggle" - onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(!sidebarVisible)}</span> - title={sidebarVisible ? "Hide Sidebar" : "Show Sidebar"} - > - 🐱 - </button> - )} - {sidebarVisible && ( - <div - className="sidebar-backdrop" - onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(false)}</span> - /> - )} - <aside className={`dashboard-sidebar ${sidebarVisible ? '' : <span class="branch-1 cbranch-no" title="branch not covered" >'hidden'}</span>`}> - <FeedList - theme={theme} - setTheme={setTheme} - setSidebarVisible={setSidebarVisible} - isMobile={window.innerWidth <= 768} - /> - </aside> - <main className="dashboard-main"> - <Routes> - <Route path="/feed/:feedId" element={<FeedItems />} /> - <Route path="/tag/:tagName" element={<FeedItems />} /> - <Route path="/settings" element={<Settings fontTheme={fontTheme} setFontTheme={setFontTheme} />} /> - <Route path="/" element={<FeedItems />} /> - </Routes> - </main> - </div> - </div> - ); -} - -function App() { - const [theme, setTheme] = useState(localStorage.getItem('neko-theme') || 'light'); - const [fontTheme, setFontTheme] = useState(localStorage.getItem('neko-font-theme') || 'default'); - - const handleSetTheme = <span class="fstat-no" title="function not covered" >(n</span>ewTheme: string) => { -<span class="cstat-no" title="statement not covered" > setTheme(newTheme);</span> -<span class="cstat-no" title="statement not covered" > localStorage.setItem('neko-theme', newTheme);</span> - }; - - const handleSetFontTheme = <span class="fstat-no" title="function not covered" >(n</span>ewFontTheme: string) => { -<span class="cstat-no" title="statement not covered" > setFontTheme(newFontTheme);</span> -<span class="cstat-no" title="statement not covered" > localStorage.setItem('neko-font-theme', newFontTheme);</span> - }; - - const basename = window.location.pathname.startsWith('/v2') ? '/v2' : <span class="branch-1 cbranch-no" title="branch not covered" >'/';</span> - - return ( - <BrowserRouter basename={basename}> - <Routes> - <Route path="/login" element={<Login />} /> - <Route - path="/*" - element={ - <RequireAuth> - <Dashboard - theme={theme} - setTheme={handleSetTheme} - fontTheme={fontTheme} - setFontTheme={handleSetFontTheme} - /> - </RequireAuth> - } - /> - </Routes> - </BrowserRouter> - ); -} - -export default App; - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../sorter.js"></script> - <script src="../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItem.css.html b/frontend/coverage/src/components/FeedItem.css.html deleted file mode 100644 index 192959f..0000000 --- a/frontend/coverage/src/components/FeedItem.css.html +++ /dev/null @@ -1,526 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedItem.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItem.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">.feed-item { - padding: 1rem; - margin-top: 5rem; - list-style: none; - border-bottom: none; -} - -/* removed read/unread specific font-weight to keep it always bold as requested */ - -.item-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - margin-bottom: 0.5rem; -} - -.item-title { - font-family: var(--font-heading); - font-size: 1.8rem; - font-weight: bold; - text-decoration: none; - color: var(--link-color); - display: block; - flex: 1; -} - -.item-title:hover { - text-decoration: none; - color: var(--link-color); -} - -.item-actions { - display: flex; - gap: 0.5rem; - margin-left: 1rem; -} - -/* Legacy controls were simple text/links, but buttons are fine if minimal */ -.star-btn { - background: none; - border: none; - cursor: pointer; - font-size: 1.25rem; - padding: 0 0 0 0.5rem; - vertical-align: middle; - transition: color 0.2s; - line-height: 1; -} - -.star-btn.is-starred { - color: blue; -} - -.star-btn.is-unstarred { - color: var(--text-color); - opacity: 0.3; -} - -.star-btn:hover { - color: blue; -} - -.action-btn { - background: var(--sidebar-bg); - border: 1px solid var(--border-color, #ccc); - cursor: pointer; - padding: 2px 6px; - font-size: 1rem; - color: blue; - font-weight: bold; -} - -.action-btn:hover { - background-color: #eee; -} - -.dateline { - margin-top: 0; - font-weight: normal; - font-size: 0.75em; - color: #ccc; - margin-bottom: 1rem; -} - -.dateline a { - color: #ccc; - text-decoration: none; -} - -.item-description { - color: var(--text-color); - line-height: 1.5; - font-size: 1rem; - margin-top: 1rem; -} - -.item-description img { - max-width: 100%; - height: auto; - display: block; - margin: 1rem 0; -} - -.item-description blockquote { - padding: 1rem 1rem 0 1rem; - border-left: 4px solid var(--sidebar-bg); - color: var(--text-color); - opacity: 0.8; - margin-left: 0; -} - -.scrape-btn { - background: var(--bg-color); - border: 1px solid var(--border-color, #ccc); - color: blue; - cursor: pointer; - font-family: var(--font-heading); - font-weight: bold; - font-size: 0.8rem; - padding: 2px 6px; - margin-left: 0.5rem; -} - -.scrape-btn:hover { - background: var(--sidebar-bg); -} - -@media (max-width: 768px) { - .feed-item { - margin-top: 2rem; - padding: 0.5rem; - } - - .item-title { - font-size: 1.4rem; - word-break: break-word; - } - - .item-header { - flex-direction: column; - gap: 0.5rem; - } - - .item-actions { - margin-left: 0; - margin-bottom: 0.5rem; - } -}</pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItem.tsx.html b/frontend/coverage/src/components/FeedItem.tsx.html deleted file mode 100644 index 6df1fec..0000000 --- a/frontend/coverage/src/components/FeedItem.tsx.html +++ /dev/null @@ -1,430 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedItem.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItem.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">78.12% </span> - <span class="quiet">Statements</span> - <span class='fraction'>25/32</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">86.95% </span> - <span class="quiet">Branches</span> - <span class='fraction'>20/23</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">83.33% </span> - <span class="quiet">Functions</span> - <span class='fraction'>10/12</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">80.64% </span> - <span class="quiet">Lines</span> - <span class='fraction'>25/31</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line medium'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">56x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useEffect } from 'react'; -import type { Item } from '../types'; -import './FeedItem.css'; - -import { apiFetch } from '../utils'; - -interface FeedItemProps { - item: Item; -} - -export default function FeedItem({ item: initialItem }: FeedItemProps) { - const [item, setItem] = useState(initialItem); - const [loading, setLoading] = useState(false); - - useEffect(() => { - setItem(initialItem); - }, [initialItem]); - - const toggleStar = () => { - updateItem({ ...item, starred: !item.starred }); - }; - - const updateItem = (newItem: Item) => { - setLoading(true); - // Optimistic update - const previousItem = item; - setItem(newItem); - - apiFetch(`/api/item/${newItem._id}`, { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - _id: newItem._id, - read: newItem.read, - starred: newItem.starred, - }), - }) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) { -<span class="cstat-no" title="statement not covered" > throw new Error('Failed to update item');</span> - } - return res.json(); - }) - .then(() => { - // Confirm with server response if needed, but for now we trust the optimistic update - // or we could setItem(updated) if the server returns the full object - setLoading(false); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > console.error('Error updating item:', err);</span> - // Revert on error -<span class="cstat-no" title="statement not covered" > setItem(previousItem);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }; - - const loadFullContent = (e: React.MouseEvent) => { - e.stopPropagation(); - setLoading(true); - apiFetch(`/api/item/${item._id}`) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to fetch full content');</span> - return res.json(); - }) - .then((data) => { - setItem({ ...item, ...data }); - setLoading(false); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > console.error('Error fetching full content:', err);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }; - - return ( - <li className={`feed-item ${item.read ? 'read' : 'unread'} ${loading ? 'loading' : ''}`}> - <div className="item-header"> - <a href={item.url} target="_blank" rel="noopener noreferrer" className="item-title"> - {item.title || <span class="branch-1 cbranch-no" title="branch not covered" >'(No Title)'}</span> - </a> - <button - onClick={(e) => { - e.stopPropagation(); - toggleStar(); - }} - className={`star-btn ${item.starred ? 'is-starred' : 'is-unstarred'}`} - title={item.starred ? 'Unstar' : 'Star'} - > - ★ - </button> - </div> - <div className="dateline"> - <a href={item.url} target="_blank" rel="noopener noreferrer"> - {new Date(item.publish_date).toLocaleDateString()} - {item.feed_title && ` - ${item.feed_title}`} - </a> - <div className="item-actions" style={{ display: 'inline-block', float: 'right' }}> - {!item.full_content && ( - <button onClick={loadFullContent} className="scrape-btn" title="Load Full Content"> - text - </button> - )} - </div> - </div> - {(item.full_content || item.description) && ( - <div - className="item-description" - dangerouslySetInnerHTML={{ __html: item.full_content || item.description }} - /> - )} - </li> - ); -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItems.css.html b/frontend/coverage/src/components/FeedItems.css.html deleted file mode 100644 index 66a3307..0000000 --- a/frontend/coverage/src/components/FeedItems.css.html +++ /dev/null @@ -1,151 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedItems.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItems.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">.feed-items { - padding: 1rem 0; - /* Removing horizontal padding to avoid double-padding with FeedItem */ -} - -.feed-items h2 { - margin-top: 0; - border-bottom: 2px solid var(--border-color); - padding-bottom: 0.5rem; -} - -.item-list { - list-style: none; - padding: 0; -} - -.loading-more { - padding: 2rem; - text-align: center; - color: #888; - font-size: 0.9rem; - min-height: 50px; -}</pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItems.tsx.html b/frontend/coverage/src/components/FeedItems.tsx.html deleted file mode 100644 index 9811743..0000000 --- a/frontend/coverage/src/components/FeedItems.tsx.html +++ /dev/null @@ -1,838 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedItems.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItems.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">89.23% </span> - <span class="quiet">Statements</span> - <span class='fraction'>116/130</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">76.19% </span> - <span class="quiet">Branches</span> - <span class='fraction'>64/84</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">87.09% </span> - <span class="quiet">Functions</span> - <span class='fraction'>27/31</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">89.07% </span> - <span class="quiet">Lines</span> - <span class='fraction'>106/119</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a> -<a name='L149'></a><a href='#L149'>149</a> -<a name='L150'></a><a href='#L150'>150</a> -<a name='L151'></a><a href='#L151'>151</a> -<a name='L152'></a><a href='#L152'>152</a> -<a name='L153'></a><a href='#L153'>153</a> -<a name='L154'></a><a href='#L154'>154</a> -<a name='L155'></a><a href='#L155'>155</a> -<a name='L156'></a><a href='#L156'>156</a> -<a name='L157'></a><a href='#L157'>157</a> -<a name='L158'></a><a href='#L158'>158</a> -<a name='L159'></a><a href='#L159'>159</a> -<a name='L160'></a><a href='#L160'>160</a> -<a name='L161'></a><a href='#L161'>161</a> -<a name='L162'></a><a href='#L162'>162</a> -<a name='L163'></a><a href='#L163'>163</a> -<a name='L164'></a><a href='#L164'>164</a> -<a name='L165'></a><a href='#L165'>165</a> -<a name='L166'></a><a href='#L166'>166</a> -<a name='L167'></a><a href='#L167'>167</a> -<a name='L168'></a><a href='#L168'>168</a> -<a name='L169'></a><a href='#L169'>169</a> -<a name='L170'></a><a href='#L170'>170</a> -<a name='L171'></a><a href='#L171'>171</a> -<a name='L172'></a><a href='#L172'>172</a> -<a name='L173'></a><a href='#L173'>173</a> -<a name='L174'></a><a href='#L174'>174</a> -<a name='L175'></a><a href='#L175'>175</a> -<a name='L176'></a><a href='#L176'>176</a> -<a name='L177'></a><a href='#L177'>177</a> -<a name='L178'></a><a href='#L178'>178</a> -<a name='L179'></a><a href='#L179'>179</a> -<a name='L180'></a><a href='#L180'>180</a> -<a name='L181'></a><a href='#L181'>181</a> -<a name='L182'></a><a href='#L182'>182</a> -<a name='L183'></a><a href='#L183'>183</a> -<a name='L184'></a><a href='#L184'>184</a> -<a name='L185'></a><a href='#L185'>185</a> -<a name='L186'></a><a href='#L186'>186</a> -<a name='L187'></a><a href='#L187'>187</a> -<a name='L188'></a><a href='#L188'>188</a> -<a name='L189'></a><a href='#L189'>189</a> -<a name='L190'></a><a href='#L190'>190</a> -<a name='L191'></a><a href='#L191'>191</a> -<a name='L192'></a><a href='#L192'>192</a> -<a name='L193'></a><a href='#L193'>193</a> -<a name='L194'></a><a href='#L194'>194</a> -<a name='L195'></a><a href='#L195'>195</a> -<a name='L196'></a><a href='#L196'>196</a> -<a name='L197'></a><a href='#L197'>197</a> -<a name='L198'></a><a href='#L198'>198</a> -<a name='L199'></a><a href='#L199'>199</a> -<a name='L200'></a><a href='#L200'>200</a> -<a name='L201'></a><a href='#L201'>201</a> -<a name='L202'></a><a href='#L202'>202</a> -<a name='L203'></a><a href='#L203'>203</a> -<a name='L204'></a><a href='#L204'>204</a> -<a name='L205'></a><a href='#L205'>205</a> -<a name='L206'></a><a href='#L206'>206</a> -<a name='L207'></a><a href='#L207'>207</a> -<a name='L208'></a><a href='#L208'>208</a> -<a name='L209'></a><a href='#L209'>209</a> -<a name='L210'></a><a href='#L210'>210</a> -<a name='L211'></a><a href='#L211'>211</a> -<a name='L212'></a><a href='#L212'>212</a> -<a name='L213'></a><a href='#L213'>213</a> -<a name='L214'></a><a href='#L214'>214</a> -<a name='L215'></a><a href='#L215'>215</a> -<a name='L216'></a><a href='#L216'>216</a> -<a name='L217'></a><a href='#L217'>217</a> -<a name='L218'></a><a href='#L218'>218</a> -<a name='L219'></a><a href='#L219'>219</a> -<a name='L220'></a><a href='#L220'>220</a> -<a name='L221'></a><a href='#L221'>221</a> -<a name='L222'></a><a href='#L222'>222</a> -<a name='L223'></a><a href='#L223'>223</a> -<a name='L224'></a><a href='#L224'>224</a> -<a name='L225'></a><a href='#L225'>225</a> -<a name='L226'></a><a href='#L226'>226</a> -<a name='L227'></a><a href='#L227'>227</a> -<a name='L228'></a><a href='#L228'>228</a> -<a name='L229'></a><a href='#L229'>229</a> -<a name='L230'></a><a href='#L230'>230</a> -<a name='L231'></a><a href='#L231'>231</a> -<a name='L232'></a><a href='#L232'>232</a> -<a name='L233'></a><a href='#L233'>233</a> -<a name='L234'></a><a href='#L234'>234</a> -<a name='L235'></a><a href='#L235'>235</a> -<a name='L236'></a><a href='#L236'>236</a> -<a name='L237'></a><a href='#L237'>237</a> -<a name='L238'></a><a href='#L238'>238</a> -<a name='L239'></a><a href='#L239'>239</a> -<a name='L240'></a><a href='#L240'>240</a> -<a name='L241'></a><a href='#L241'>241</a> -<a name='L242'></a><a href='#L242'>242</a> -<a name='L243'></a><a href='#L243'>243</a> -<a name='L244'></a><a href='#L244'>244</a> -<a name='L245'></a><a href='#L245'>245</a> -<a name='L246'></a><a href='#L246'>246</a> -<a name='L247'></a><a href='#L247'>247</a> -<a name='L248'></a><a href='#L248'>248</a> -<a name='L249'></a><a href='#L249'>249</a> -<a name='L250'></a><a href='#L250'>250</a> -<a name='L251'></a><a href='#L251'>251</a> -<a name='L252'></a><a href='#L252'>252</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">8x</span> -<span class="cline-any cline-yes">8x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">10x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">10x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">6x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">8x</span> -<span class="cline-any cline-yes">8x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">6x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">6x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">5x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-yes">31x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">36x</span> -<span class="cline-any cline-yes">21x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">20x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">44x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useEffect, useState } from 'react'; -import { useParams, useSearchParams } from 'react-router-dom'; -import type { Item } from '../types'; -import FeedItem from './FeedItem'; -import './FeedItems.css'; -import { apiFetch } from '../utils'; - -export default function FeedItems() { - const { feedId, tagName } = useParams<{ feedId: string; tagName: string }>(); - const [searchParams] = useSearchParams(); - const filterFn = searchParams.get('filter') || 'unread'; - - const [items, setItems] = useState<Item[]>([]); - const [loading, setLoading] = useState(true); - const [loadingMore, setLoadingMore] = useState(false); - const [hasMore, setHasMore] = useState(true); - const [error, setError] = useState(''); - const [selectedIndex, setSelectedIndex] = useState(-1); - - const fetchItems = (maxId?: string) => { - if (maxId) { - setLoadingMore(true); - } else { - setLoading(true); - setItems([]); - } - setError(''); - - let url = '/api/stream'; - const params = new URLSearchParams(); - - if (feedId) { - params.append('feed_id', feedId); - } else if (tagName) { - params.append('tag', tagName); - } - - if (maxId) { - params.append('max_id', maxId); - } - - // Apply filters - const searchQuery = searchParams.get('q'); - <span class="missing-if-branch" title="if path not taken" >I</span>if (searchQuery) { -<span class="cstat-no" title="statement not covered" > params.append('q', searchQuery);</span> - } - - <span class="missing-if-branch" title="if path not taken" >I</span>if (filterFn === 'all') { -<span class="cstat-no" title="statement not covered" > params.append('read_filter', 'all');</span> - <span class="missing-if-branch" title="if path not taken" >I</span>} else if (filterFn === 'starred') { -<span class="cstat-no" title="statement not covered" > params.append('starred', 'true');</span> -<span class="cstat-no" title="statement not covered" > params.append('read_filter', 'all');</span> - } else { - // default to unread - <span class="missing-if-branch" title="else path not taken" >E</span>if (!searchQuery) { - params.append('read_filter', 'unread'); - } - } - - const queryString = params.toString(); - <span class="missing-if-branch" title="else path not taken" >E</span>if (queryString) { - url += `?${queryString}`; - } - - apiFetch(url) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) { -<span class="cstat-no" title="statement not covered" > throw new Error('Failed to fetch items');</span> - } - return res.json(); - }) - .then((data) => { - if (maxId) { - setItems((prev) => [...prev, ...data]); - } else { - setItems(data); - } - setHasMore(data.length > 0); - setLoading(false); - setLoadingMore(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - setLoadingMore(false); - }); - }; - - useEffect(() => { - fetchItems(); - setSelectedIndex(-1); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [feedId, tagName, filterFn, searchParams]); - - - const scrollToItem = (index: number) => { - const element = document.getElementById(`item-${index}`); - <span class="missing-if-branch" title="else path not taken" >E</span>if (element) { - element.scrollIntoView({ behavior: 'auto', block: 'start' }); - } - }; - - const markAsRead = (item: Item) => { - const updatedItem = { ...item, read: true }; - // Optimistic update - setItems((prevItems) => prevItems.map((i) => (i._id === item._id ? updatedItem : i))); - - apiFetch(`/api/item/${item._id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ read: true, starred: item.starred }), - }).catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => <span class="cstat-no" title="statement not covered" >console.error('Failed to mark read', err))</span>; - }; - - const toggleStar = (item: Item) => { - const updatedItem = { ...item, starred: !item.starred }; - // Optimistic update - setItems((prevItems) => prevItems.map((i) => (i._id === item._id ? updatedItem : i))); - - apiFetch(`/api/item/${item._id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ read: item.read, starred: !item.starred }), - }).catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => <span class="cstat-no" title="statement not covered" >console.error('Failed to toggle star', err))</span>; - }; - - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (items.length === 0) <span class="cstat-no" title="statement not covered" >return;</span> - - if (e.key === 'j') { - setSelectedIndex((prev) => { - const nextIndex = Math.min(prev + 1, items.length - 1); - <span class="missing-if-branch" title="else path not taken" >E</span>if (nextIndex !== prev) { - const item = items[nextIndex]; - if (!item.read) { - markAsRead(item); - } - scrollToItem(nextIndex); - } - - // If we're now on the last item and there are more items to load, - // trigger loading them so the next 'j' press will work - if (nextIndex === items.length - 1 && hasMore && !loadingMore) { - fetchItems(String(items[items.length - 1]._id)); - } - - return nextIndex; - }); - <span class="missing-if-branch" title="if path not taken" >I</span>} else if (e.key === 'k') { -<span class="cstat-no" title="statement not covered" > setSelectedIndex(<span class="fstat-no" title="function not covered" >(p</span>rev) => {</span> - const nextIndex = <span class="cstat-no" title="statement not covered" >Math.max(prev - 1, 0);</span> -<span class="cstat-no" title="statement not covered" > if (nextIndex !== prev) {</span> -<span class="cstat-no" title="statement not covered" > scrollToItem(nextIndex);</span> - } -<span class="cstat-no" title="statement not covered" > return nextIndex;</span> - }); - <span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 's') { - setSelectedIndex((currentIndex) => { - <span class="missing-if-branch" title="else path not taken" >E</span>if (currentIndex >= 0 && currentIndex < items.length) { - toggleStar(items[currentIndex]); - } - return currentIndex; - }); - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [items, hasMore, loadingMore]); - - - - useEffect(() => { - // Observer for marking items as read - const itemObserver = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - // If item is not intersecting and is above the viewport, it's been scrolled past - <span class="missing-if-branch" title="else path not taken" >E</span>if (!entry.isIntersecting && entry.boundingClientRect.top < 0) { - const index = Number(entry.target.getAttribute('data-index')); - <span class="missing-if-branch" title="else path not taken" >E</span>if (!isNaN(index) && index >= 0 && index < items.length) { - const item = items[index]; - <span class="missing-if-branch" title="else path not taken" >E</span>if (!item.read) { - markAsRead(item); - } - } - } - }); - }, - { root: null, threshold: 0 } - ); - - // Observer for infinite scroll (less aggressive, must be fully visible) - const sentinelObserver = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - <span class="missing-if-branch" title="else path not taken" >E</span>if (entry.isIntersecting && !loadingMore && hasMore && items.length > 0) { - fetchItems(String(items[items.length - 1]._id)); - } - }); - }, - { root: null, threshold: 1.0 } - ); - - items.forEach((_, index) => { - const el = document.getElementById(`item-${index}`); - <span class="missing-if-branch" title="else path not taken" >E</span>if (el) itemObserver.observe(el); - }); - - const sentinel = document.getElementById('load-more-sentinel'); - if (sentinel) sentinelObserver.observe(sentinel); - - return () => { - itemObserver.disconnect(); - sentinelObserver.disconnect(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [items, loadingMore, hasMore]); - - if (loading) return <div className="feed-items-loading">Loading items...</div>; - if (error) return <div className="feed-items-error">Error: {error}</div>; - - return ( - <div className="feed-items"> - {items.length === 0 ? ( -<span class="branch-0 cbranch-no" title="branch not covered" > <p>No items found.</p></span> - ) : ( - <ul className="item-list"> - {items.map((item, index) => ( - <div - id={`item-${index}`} - key={item._id} - data-index={index} - data-selected={index === selectedIndex} - onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSelectedIndex(index)}</span> - > - <FeedItem item={item} /> - </div> - ))} - {hasMore && ( - <div id="load-more-sentinel" className="loading-more"> - {loadingMore ? 'Loading more...' : ''} - </div> - )} - </ul> - )} - </div> - ); -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedList.css.html b/frontend/coverage/src/components/FeedList.css.html deleted file mode 100644 index d892e77..0000000 --- a/frontend/coverage/src/components/FeedList.css.html +++ /dev/null @@ -1,724 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedList.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedList.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a> -<a name='L149'></a><a href='#L149'>149</a> -<a name='L150'></a><a href='#L150'>150</a> -<a name='L151'></a><a href='#L151'>151</a> -<a name='L152'></a><a href='#L152'>152</a> -<a name='L153'></a><a href='#L153'>153</a> -<a name='L154'></a><a href='#L154'>154</a> -<a name='L155'></a><a href='#L155'>155</a> -<a name='L156'></a><a href='#L156'>156</a> -<a name='L157'></a><a href='#L157'>157</a> -<a name='L158'></a><a href='#L158'>158</a> -<a name='L159'></a><a href='#L159'>159</a> -<a name='L160'></a><a href='#L160'>160</a> -<a name='L161'></a><a href='#L161'>161</a> -<a name='L162'></a><a href='#L162'>162</a> -<a name='L163'></a><a href='#L163'>163</a> -<a name='L164'></a><a href='#L164'>164</a> -<a name='L165'></a><a href='#L165'>165</a> -<a name='L166'></a><a href='#L166'>166</a> -<a name='L167'></a><a href='#L167'>167</a> -<a name='L168'></a><a href='#L168'>168</a> -<a name='L169'></a><a href='#L169'>169</a> -<a name='L170'></a><a href='#L170'>170</a> -<a name='L171'></a><a href='#L171'>171</a> -<a name='L172'></a><a href='#L172'>172</a> -<a name='L173'></a><a href='#L173'>173</a> -<a name='L174'></a><a href='#L174'>174</a> -<a name='L175'></a><a href='#L175'>175</a> -<a name='L176'></a><a href='#L176'>176</a> -<a name='L177'></a><a href='#L177'>177</a> -<a name='L178'></a><a href='#L178'>178</a> -<a name='L179'></a><a href='#L179'>179</a> -<a name='L180'></a><a href='#L180'>180</a> -<a name='L181'></a><a href='#L181'>181</a> -<a name='L182'></a><a href='#L182'>182</a> -<a name='L183'></a><a href='#L183'>183</a> -<a name='L184'></a><a href='#L184'>184</a> -<a name='L185'></a><a href='#L185'>185</a> -<a name='L186'></a><a href='#L186'>186</a> -<a name='L187'></a><a href='#L187'>187</a> -<a name='L188'></a><a href='#L188'>188</a> -<a name='L189'></a><a href='#L189'>189</a> -<a name='L190'></a><a href='#L190'>190</a> -<a name='L191'></a><a href='#L191'>191</a> -<a name='L192'></a><a href='#L192'>192</a> -<a name='L193'></a><a href='#L193'>193</a> -<a name='L194'></a><a href='#L194'>194</a> -<a name='L195'></a><a href='#L195'>195</a> -<a name='L196'></a><a href='#L196'>196</a> -<a name='L197'></a><a href='#L197'>197</a> -<a name='L198'></a><a href='#L198'>198</a> -<a name='L199'></a><a href='#L199'>199</a> -<a name='L200'></a><a href='#L200'>200</a> -<a name='L201'></a><a href='#L201'>201</a> -<a name='L202'></a><a href='#L202'>202</a> -<a name='L203'></a><a href='#L203'>203</a> -<a name='L204'></a><a href='#L204'>204</a> -<a name='L205'></a><a href='#L205'>205</a> -<a name='L206'></a><a href='#L206'>206</a> -<a name='L207'></a><a href='#L207'>207</a> -<a name='L208'></a><a href='#L208'>208</a> -<a name='L209'></a><a href='#L209'>209</a> -<a name='L210'></a><a href='#L210'>210</a> -<a name='L211'></a><a href='#L211'>211</a> -<a name='L212'></a><a href='#L212'>212</a> -<a name='L213'></a><a href='#L213'>213</a> -<a name='L214'></a><a href='#L214'>214</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">.feed-list { - padding: 1rem; - font-family: var(--font-heading); - color: #777; - /* specific v1 color */ - font-size: 0.8rem; - background: var(--sidebar-bg); - min-height: 100%; - flex: 1; -} - -.feed-list h1.logo { - font-size: 2rem; - /* match v1 */ - margin: 0 0 1rem 0; - line-height: 1; - cursor: pointer; - position: sticky; - top: 0; - background: var(--sidebar-bg); - z-index: 10; - padding-bottom: 0.5rem; - color: var(--text-color); -} - -/* Override logo color if necessary for themes */ -.theme-light .feed-list h1.logo { - color: #333; -} - -.theme-dark .feed-list h1.logo { - color: #eee; -} - -.search-section { - margin-bottom: 1rem; -} - -.search-input { - width: 100%; - padding: 0.25rem; - border: 1px solid var(--border-color, #999); - background: var(--bg-color); - color: var(--text-color); - font-size: 0.8rem; - font-family: inherit; - border-radius: 0; - /* v1 didn't have rounded inputs usually */ -} - -.section-header { - font-size: 1rem; - /* v1 h4 size? */ - font-weight: bold; - margin: 1rem 0 0.25rem 0; - cursor: pointer; - user-select: none; - font-family: var(--font-heading); - color: #333; - /* Darker than list items */ - text-transform: lowercase; - font-variant: small-caps; - display: flex; - align-items: center; - gap: 0.5rem; -} - -.caret { - display: inline-block; - font-size: 0.6rem; - transition: transform 0.2s ease; - color: #777; -} - -.caret.expanded { - transform: rotate(90deg); -} - -.filter-list, -.tag-list-items, -.feed-list-items, -.nav-list { - list-style: none; - padding: 0; - margin: 0; -} - -.filter-list li, -.nav-list li { - margin-bottom: 0.1rem; -} - -.filter-list a, -.nav-list a, -.tag-link, -.feed-title, -.logout-link { - text-decoration: none; - color: var(--link-color, blue); - font-size: 0.8rem; - /* Matches v1 .75em approx */ - display: block; - cursor: pointer; - background: none; - border: none; - padding: 0; - font-family: inherit; - font-variant: small-caps; - text-transform: lowercase; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.filter-list a:hover, -.nav-list a:hover, -.tag-link:hover, -.feed-title:hover, -.logout-link:hover { - text-decoration: underline; - color: var(--link-color, blue); -} - -.filter-list a.active, -.tag-link.active, -.feed-title.active { - font-weight: bold; - color: #000; - /* Active state black */ -} - -.tag-item, -.sidebar-feed-item { - margin-bottom: 0; -} - -.feed-category { - display: none; -} - -.nav-section { - margin-top: 2rem; - border-top: 1px solid var(--border-color, #eee); - padding-top: 1rem; -} - -.logout-link { - text-align: left; - width: 100%; - color: #777; - display: block; -} - -.nav-link, -.logout-link { - padding: 0.25rem 0; -} - -.logout-link:hover { - color: var(--link-color, blue); - text-decoration: underline; -} - -.theme-section { - margin-top: 1rem; -} - -.theme-selector { - display: flex; - gap: 0.5rem; - margin-top: 0.5rem; -} - -.theme-selector button { - background: rgba(0, 0, 0, 0.05); - border: none; - cursor: pointer; - padding: 0.4rem; - font-size: 1rem; - border-radius: 8px; - line-height: 1; - transition: all 0.2s ease; - display: flex; - align-items: center; - justify-content: center; -} - -.theme-selector button:hover { - background: rgba(0, 0, 0, 0.1); - transform: translateY(-2px); -} - -.theme-selector button.active { - background: var(--border-color, #999); - color: white; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); -} - -.theme-dark .theme-selector button { - background: rgba(255, 255, 255, 0.1); -} - -.theme-dark .theme-selector button:hover { - background: rgba(255, 255, 255, 0.2); -} - -/* Scrollbar styling for webkit */ -.dashboard-sidebar::-webkit-scrollbar { - width: 4px; -} - -.dashboard-sidebar::-webkit-scrollbar-thumb { - background-color: var(--border-color, #999); -}</pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/FeedList.tsx.html b/frontend/coverage/src/components/FeedList.tsx.html deleted file mode 100644 index 4061422..0000000 --- a/frontend/coverage/src/components/FeedList.tsx.html +++ /dev/null @@ -1,721 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/FeedList.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedList.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">87.27% </span> - <span class="quiet">Statements</span> - <span class='fraction'>48/55</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">70% </span> - <span class="quiet">Branches</span> - <span class='fraction'>35/50</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">78.94% </span> - <span class="quiet">Functions</span> - <span class='fraction'>15/19</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">90% </span> - <span class="quiet">Lines</span> - <span class='fraction'>45/50</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a> -<a name='L149'></a><a href='#L149'>149</a> -<a name='L150'></a><a href='#L150'>150</a> -<a name='L151'></a><a href='#L151'>151</a> -<a name='L152'></a><a href='#L152'>152</a> -<a name='L153'></a><a href='#L153'>153</a> -<a name='L154'></a><a href='#L154'>154</a> -<a name='L155'></a><a href='#L155'>155</a> -<a name='L156'></a><a href='#L156'>156</a> -<a name='L157'></a><a href='#L157'>157</a> -<a name='L158'></a><a href='#L158'>158</a> -<a name='L159'></a><a href='#L159'>159</a> -<a name='L160'></a><a href='#L160'>160</a> -<a name='L161'></a><a href='#L161'>161</a> -<a name='L162'></a><a href='#L162'>162</a> -<a name='L163'></a><a href='#L163'>163</a> -<a name='L164'></a><a href='#L164'>164</a> -<a name='L165'></a><a href='#L165'>165</a> -<a name='L166'></a><a href='#L166'>166</a> -<a name='L167'></a><a href='#L167'>167</a> -<a name='L168'></a><a href='#L168'>168</a> -<a name='L169'></a><a href='#L169'>169</a> -<a name='L170'></a><a href='#L170'>170</a> -<a name='L171'></a><a href='#L171'>171</a> -<a name='L172'></a><a href='#L172'>172</a> -<a name='L173'></a><a href='#L173'>173</a> -<a name='L174'></a><a href='#L174'>174</a> -<a name='L175'></a><a href='#L175'>175</a> -<a name='L176'></a><a href='#L176'>176</a> -<a name='L177'></a><a href='#L177'>177</a> -<a name='L178'></a><a href='#L178'>178</a> -<a name='L179'></a><a href='#L179'>179</a> -<a name='L180'></a><a href='#L180'>180</a> -<a name='L181'></a><a href='#L181'>181</a> -<a name='L182'></a><a href='#L182'>182</a> -<a name='L183'></a><a href='#L183'>183</a> -<a name='L184'></a><a href='#L184'>184</a> -<a name='L185'></a><a href='#L185'>185</a> -<a name='L186'></a><a href='#L186'>186</a> -<a name='L187'></a><a href='#L187'>187</a> -<a name='L188'></a><a href='#L188'>188</a> -<a name='L189'></a><a href='#L189'>189</a> -<a name='L190'></a><a href='#L190'>190</a> -<a name='L191'></a><a href='#L191'>191</a> -<a name='L192'></a><a href='#L192'>192</a> -<a name='L193'></a><a href='#L193'>193</a> -<a name='L194'></a><a href='#L194'>194</a> -<a name='L195'></a><a href='#L195'>195</a> -<a name='L196'></a><a href='#L196'>196</a> -<a name='L197'></a><a href='#L197'>197</a> -<a name='L198'></a><a href='#L198'>198</a> -<a name='L199'></a><a href='#L199'>199</a> -<a name='L200'></a><a href='#L200'>200</a> -<a name='L201'></a><a href='#L201'>201</a> -<a name='L202'></a><a href='#L202'>202</a> -<a name='L203'></a><a href='#L203'>203</a> -<a name='L204'></a><a href='#L204'>204</a> -<a name='L205'></a><a href='#L205'>205</a> -<a name='L206'></a><a href='#L206'>206</a> -<a name='L207'></a><a href='#L207'>207</a> -<a name='L208'></a><a href='#L208'>208</a> -<a name='L209'></a><a href='#L209'>209</a> -<a name='L210'></a><a href='#L210'>210</a> -<a name='L211'></a><a href='#L211'>211</a> -<a name='L212'></a><a href='#L212'>212</a> -<a name='L213'></a><a href='#L213'>213</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-yes">11x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">22x</span> -<span class="cline-any cline-yes">13x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">12x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">12x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">4x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useEffect, useState } from 'react'; -import { Link, useNavigate, useSearchParams, useLocation, useParams } from 'react-router-dom'; -import type { Feed, Category } from '../types'; -import './FeedList.css'; -import './FeedListVariants.css'; -import { apiFetch } from '../utils'; - -export default function FeedList({ - theme, - setTheme, - setSidebarVisible, - isMobile, -}: { - theme: string; - setTheme: (t: string) => void; - setSidebarVisible: (visible: boolean) => void; - isMobile: boolean; -}) { - const [feeds, setFeeds] = useState<Feed[]>([]); - const [tags, setTags] = useState<Category[]>([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); - const [feedsExpanded, setFeedsExpanded] = useState(false); - const [tagsExpanded, setTagsExpanded] = useState(true); - const [searchQuery, setSearchQuery] = useState(''); - const navigate = useNavigate(); - const [searchParams] = useSearchParams(); - const location = useLocation(); - const { feedId, tagName } = useParams(); - - const sidebarVariant = searchParams.get('sidebar') || localStorage.getItem('neko-sidebar-variant') || 'glass'; - - useEffect(() => { - const variant = searchParams.get('sidebar'); - <span class="missing-if-branch" title="if path not taken" >I</span>if (variant) { -<span class="cstat-no" title="statement not covered" > localStorage.setItem('neko-sidebar-variant', variant);</span> - } - }, [searchParams]); - - const currentFilter = - searchParams.get('filter') || - (location.pathname === '/' && !feedId && !tagName ? 'unread' : <span class="branch-1 cbranch-no" title="branch not covered" >'');</span> - - const handleSearch = (e: React.FormEvent) => { - e.preventDefault(); - <span class="missing-if-branch" title="else path not taken" >E</span>if (searchQuery.trim()) { - navigate(`/?q=${encodeURIComponent(searchQuery.trim())}`); - } - }; - - const toggleFeeds = () => { - setFeedsExpanded(!feedsExpanded); - }; - - const toggleTags = <span class="fstat-no" title="function not covered" >() => {</span> -<span class="cstat-no" title="statement not covered" > setTagsExpanded(!tagsExpanded);</span> - }; - - const handleLinkClick = () => { - <span class="missing-if-branch" title="else path not taken" >E</span>if (isMobile) { - setSidebarVisible(false); - } - }; - - useEffect(() => { - Promise.all([ - apiFetch('/api/feed/').then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to fetch feeds');</span> - return res.json() as Promise<Feed[]>; - }), - apiFetch('/api/tag').then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to fetch tags');</span> - return res.json() as Promise<Category[]>; - }), - ]) - .then(([feedsData, tagsData]) => { - setFeeds(feedsData); - setTags(tagsData); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }, []); - - if (loading) return <div className="feed-list-loading">Loading feeds...</div>; - if (error) return <div className="feed-list-error">Error: {error}</div>; - - const handleLogout = () => { - apiFetch('/api/logout', { method: 'POST' }).then(() => (window.location.href = '/v2/login')); - }; - - return ( - <div className={`feed-list variant-${sidebarVariant}`}> - <h1 className="logo" onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(false)}></span> - 🐱 - </h1> - - <div className="search-section"> - <form onSubmit={handleSearch} className="search-form"> - <input - type="search" - placeholder="search..." - value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - className="search-input" - /> - </form> - </div> - - <div className="filter-section"> - <ul className="filter-list"> - <li className="unread_filter"> - <Link to="/?filter=unread" className={currentFilter === 'unread' ? 'active' : <span class="branch-1 cbranch-no" title="branch not covered" >''} o</span>nClick={handleLinkClick}> - unread - </Link> - </li> - <li className="all_filter"> - <Link to="/?filter=all" className={currentFilter === 'all' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'} onClick={handleLinkClick}> - all - </Link> - </li> - <li className="starred_filter"> - <Link to="/?filter=starred" className={currentFilter === 'starred' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'} onClick={handleLinkClick}> - starred - </Link> - </li> - </ul> - </div> - - <div className="tag-section"> - <h4 onClick={toggleTags} className="section-header"> - <span className={`caret ${tagsExpanded ? 'expanded' : <span class="branch-1 cbranch-no" title="branch not covered" >''}</span>`}>▶</span> Tags - </h4> - {tagsExpanded && ( - <ul className="tag-list-items"> - {tags.map((tag) => ( - <li key={tag.title} className="tag-item"> - <Link - to={`/tag/${encodeURIComponent(tag.title)}`} - className={`tag-link ${tagName === tag.title ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}`} - onClick={handleLinkClick} - > - {tag.title} - </Link> - </li> - ))} - </ul> - )} - </div> - - <div className="feed-section"> - <h4 onClick={toggleFeeds} className="section-header"> - <span className={`caret ${feedsExpanded ? 'expanded' : ''}`}>▶</span> Feeds - </h4> - {feedsExpanded && - (feeds.length === 0 ? ( - <p>No feeds found.</p> - ) : ( - <ul className="feed-list-items"> - {feeds.map((feed) => ( - <li key={feed._id} className="sidebar-feed-item"> - <Link - to={`/feed/${feed._id}`} - className={`feed-title ${feedId === String(feed._id) ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}`} - onClick={handleLinkClick} - > - {feed.title || <span class="branch-1 cbranch-no" title="branch not covered" >feed.url}</span> - </Link> - </li> - ))} - </ul> - ))} - </div> - - <div className="nav-section"> - <ul className="nav-list"> - <li> - <Link to="/settings" className="nav-link" onClick={handleLinkClick}> - settings - </Link> - </li> - <li> - <button onClick={handleLogout} className="logout-link"> - logout - </button> - </li> - </ul> - </div> - - <div className="theme-section"> - <div className="theme-selector"> - <button - onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etTheme('light')}</span> - className={theme === 'light' ? 'active' : <span class="branch-1 cbranch-no" title="branch not covered" >''}</span> - title="Light Theme" - > - ☀️ - </button> - <button - onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etTheme('dark')}</span> - className={theme === 'dark' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'} - title="Dark Theme" - > - 🌙 - </button> - </div> - </div> - </div> - ); -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/Login.css.html b/frontend/coverage/src/components/Login.css.html deleted file mode 100644 index 140a86b..0000000 --- a/frontend/coverage/src/components/Login.css.html +++ /dev/null @@ -1,274 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/Login.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Login.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">.login-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - background-color: #f5f5f5; -} - -.login-form { - background: white; - padding: 2rem; - border-radius: 8px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - width: 100%; - max-width: 400px; -} - -.login-form h1 { - margin-bottom: 2rem; - text-align: center; - color: #333; -} - -.form-group { - margin-bottom: 1.5rem; -} - -.form-group label { - display: block; - margin-bottom: 0.5rem; - font-weight: bold; - color: #555; -} - -.form-group input { - width: 100%; - padding: 0.75rem; - border: 1px solid #ddd; - border-radius: 4px; - font-size: 1rem; -} - -.error-message { - color: #dc3545; - margin-bottom: 1rem; - text-align: center; -} - -button[type='submit'] { - width: 100%; - padding: 0.75rem; - background-color: #007bff; - color: white; - border: none; - border-radius: 4px; - font-size: 1rem; - cursor: pointer; - transition: background-color 0.2s; -} - -button[type='submit']:hover { - background-color: #0056b3; -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/Login.tsx.html b/frontend/coverage/src/components/Login.tsx.html deleted file mode 100644 index 111dcba..0000000 --- a/frontend/coverage/src/components/Login.tsx.html +++ /dev/null @@ -1,286 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/Login.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Login.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">100% </span> - <span class="quiet">Statements</span> - <span class='fraction'>20/20</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">83.33% </span> - <span class="quiet">Branches</span> - <span class='fraction'>5/6</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">100% </span> - <span class="quiet">Functions</span> - <span class='fraction'>4/4</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">100% </span> - <span class="quiet">Lines</span> - <span class='fraction'>20/20</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">17x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">3x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, type FormEvent } from 'react'; -import { useNavigate } from 'react-router-dom'; -import './Login.css'; - -import { apiFetch } from '../utils'; - -export default function Login() { - const [username, setUsername] = useState('neko'); - const [password, setPassword] = useState(''); - const [error, setError] = useState(''); - const navigate = useNavigate(); - - const handleSubmit = async (e: FormEvent) => { - e.preventDefault(); - setError(''); - - try { - // Use URLSearchParams to send as form-urlencoded, matching backend expectation - const params = new URLSearchParams(); - params.append('username', username); - params.append('password', password); - - const res = await apiFetch('/api/login', { - method: 'POST', - body: params, - }); - - if (res.ok) { - navigate('/'); - } else { - const data = await res.json(); - setError(data.message || <span class="branch-1 cbranch-no" title="branch not covered" >'Login failed')</span>; - } - } catch (_err) { - setError('Network error'); - } - }; - - return ( - <div className="login-container"> - <form onSubmit={handleSubmit} className="login-form"> - <h1>neko rss mode</h1> - <div className="form-group"> - <label htmlFor="username">username</label> - <input - id="username" - type="text" - value={username} - onChange={(e) => setUsername(e.target.value)} - /> - </div> - <div className="form-group"> - <label htmlFor="password">password</label> - <input - id="password" - type="password" - value={password} - onChange={(e) => setPassword(e.target.value)} - autoFocus - /> - </div> - {error && <div className="error-message">{error}</div>} - <button type="submit">login</button> - </form> - </div> - ); -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/Settings.css.html b/frontend/coverage/src/components/Settings.css.html deleted file mode 100644 index 4109bba..0000000 --- a/frontend/coverage/src/components/Settings.css.html +++ /dev/null @@ -1,802 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/Settings.css</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Settings.css</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Statements</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Branches</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Functions</span> - <span class='fraction'>0/0</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">0% </span> - <span class="quiet">Lines</span> - <span class='fraction'>0/0</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line low'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a> -<a name='L149'></a><a href='#L149'>149</a> -<a name='L150'></a><a href='#L150'>150</a> -<a name='L151'></a><a href='#L151'>151</a> -<a name='L152'></a><a href='#L152'>152</a> -<a name='L153'></a><a href='#L153'>153</a> -<a name='L154'></a><a href='#L154'>154</a> -<a name='L155'></a><a href='#L155'>155</a> -<a name='L156'></a><a href='#L156'>156</a> -<a name='L157'></a><a href='#L157'>157</a> -<a name='L158'></a><a href='#L158'>158</a> -<a name='L159'></a><a href='#L159'>159</a> -<a name='L160'></a><a href='#L160'>160</a> -<a name='L161'></a><a href='#L161'>161</a> -<a name='L162'></a><a href='#L162'>162</a> -<a name='L163'></a><a href='#L163'>163</a> -<a name='L164'></a><a href='#L164'>164</a> -<a name='L165'></a><a href='#L165'>165</a> -<a name='L166'></a><a href='#L166'>166</a> -<a name='L167'></a><a href='#L167'>167</a> -<a name='L168'></a><a href='#L168'>168</a> -<a name='L169'></a><a href='#L169'>169</a> -<a name='L170'></a><a href='#L170'>170</a> -<a name='L171'></a><a href='#L171'>171</a> -<a name='L172'></a><a href='#L172'>172</a> -<a name='L173'></a><a href='#L173'>173</a> -<a name='L174'></a><a href='#L174'>174</a> -<a name='L175'></a><a href='#L175'>175</a> -<a name='L176'></a><a href='#L176'>176</a> -<a name='L177'></a><a href='#L177'>177</a> -<a name='L178'></a><a href='#L178'>178</a> -<a name='L179'></a><a href='#L179'>179</a> -<a name='L180'></a><a href='#L180'>180</a> -<a name='L181'></a><a href='#L181'>181</a> -<a name='L182'></a><a href='#L182'>182</a> -<a name='L183'></a><a href='#L183'>183</a> -<a name='L184'></a><a href='#L184'>184</a> -<a name='L185'></a><a href='#L185'>185</a> -<a name='L186'></a><a href='#L186'>186</a> -<a name='L187'></a><a href='#L187'>187</a> -<a name='L188'></a><a href='#L188'>188</a> -<a name='L189'></a><a href='#L189'>189</a> -<a name='L190'></a><a href='#L190'>190</a> -<a name='L191'></a><a href='#L191'>191</a> -<a name='L192'></a><a href='#L192'>192</a> -<a name='L193'></a><a href='#L193'>193</a> -<a name='L194'></a><a href='#L194'>194</a> -<a name='L195'></a><a href='#L195'>195</a> -<a name='L196'></a><a href='#L196'>196</a> -<a name='L197'></a><a href='#L197'>197</a> -<a name='L198'></a><a href='#L198'>198</a> -<a name='L199'></a><a href='#L199'>199</a> -<a name='L200'></a><a href='#L200'>200</a> -<a name='L201'></a><a href='#L201'>201</a> -<a name='L202'></a><a href='#L202'>202</a> -<a name='L203'></a><a href='#L203'>203</a> -<a name='L204'></a><a href='#L204'>204</a> -<a name='L205'></a><a href='#L205'>205</a> -<a name='L206'></a><a href='#L206'>206</a> -<a name='L207'></a><a href='#L207'>207</a> -<a name='L208'></a><a href='#L208'>208</a> -<a name='L209'></a><a href='#L209'>209</a> -<a name='L210'></a><a href='#L210'>210</a> -<a name='L211'></a><a href='#L211'>211</a> -<a name='L212'></a><a href='#L212'>212</a> -<a name='L213'></a><a href='#L213'>213</a> -<a name='L214'></a><a href='#L214'>214</a> -<a name='L215'></a><a href='#L215'>215</a> -<a name='L216'></a><a href='#L216'>216</a> -<a name='L217'></a><a href='#L217'>217</a> -<a name='L218'></a><a href='#L218'>218</a> -<a name='L219'></a><a href='#L219'>219</a> -<a name='L220'></a><a href='#L220'>220</a> -<a name='L221'></a><a href='#L221'>221</a> -<a name='L222'></a><a href='#L222'>222</a> -<a name='L223'></a><a href='#L223'>223</a> -<a name='L224'></a><a href='#L224'>224</a> -<a name='L225'></a><a href='#L225'>225</a> -<a name='L226'></a><a href='#L226'>226</a> -<a name='L227'></a><a href='#L227'>227</a> -<a name='L228'></a><a href='#L228'>228</a> -<a name='L229'></a><a href='#L229'>229</a> -<a name='L230'></a><a href='#L230'>230</a> -<a name='L231'></a><a href='#L231'>231</a> -<a name='L232'></a><a href='#L232'>232</a> -<a name='L233'></a><a href='#L233'>233</a> -<a name='L234'></a><a href='#L234'>234</a> -<a name='L235'></a><a href='#L235'>235</a> -<a name='L236'></a><a href='#L236'>236</a> -<a name='L237'></a><a href='#L237'>237</a> -<a name='L238'></a><a href='#L238'>238</a> -<a name='L239'></a><a href='#L239'>239</a> -<a name='L240'></a><a href='#L240'>240</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">.settings-page.variant-glass { - padding: 2.5rem; - max-width: 800px; - margin: 0 auto; - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-radius: 24px; - border: 1px solid rgba(255, 255, 255, 0.1); - font-family: system-ui, -apple-system, sans-serif; - color: var(--text-color); - margin-top: 2rem; - margin-bottom: 2rem; -} - -.settings-page.variant-glass h2, -.settings-page.variant-glass h3 { - font-weight: 700; - letter-spacing: -0.02em; - color: var(--text-color); - opacity: 0.9; -} - -.add-feed-section, -.appearance-section, -.import-section, -.export-section, -.feed-list-section { - background: rgba(255, 255, 255, 0.03); - padding: 1.5rem; - border-radius: 16px; - margin-bottom: 2rem; - border: 1px solid rgba(255, 255, 255, 0.05); - transition: all 0.3s ease; -} - -.add-feed-section:hover, -.appearance-section:hover, -.import-section:hover, -.export-section:hover, -.feed-list-section:hover { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 255, 255, 0.1); -} - -.font-selector { - display: flex; - align-items: center; - gap: 1rem; -} - -.font-select { - padding: 0.6rem 1rem; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(0, 0, 0, 0.1); - color: var(--text-color); - border-radius: 20px; - font-size: 1rem; - min-width: 200px; - cursor: pointer; - outline: none; - transition: border-color 0.2s; -} - -.font-select:focus { - border-color: rgba(255, 255, 255, 0.3); -} - -.add-feed-form { - display: flex; - gap: 1rem; -} - -.feed-input { - flex: 1; - padding: 0.6rem 1.2rem; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(0, 0, 0, 0.1); - color: var(--text-color); - border-radius: 20px; - font-size: 1rem; - outline: none; - transition: border-color 0.2s; -} - -.feed-input:focus { - border-color: rgba(255, 255, 255, 0.3); -} - -.error-message { - color: #ff5252; - margin-top: 1rem; - font-weight: 600; -} - -.settings-feed-list { - list-style: none; - padding: 0; - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: 12px; - overflow: hidden; -} - -.settings-feed-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1.2rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); - transition: background 0.2s; -} - -.settings-feed-item:hover { - background: rgba(255, 255, 255, 0.02); -} - -.settings-feed-item:last-child { - border-bottom: none; -} - -.feed-info { - display: flex; - flex-direction: column; - gap: 0.2rem; -} - -.feed-title { - font-weight: 600; - font-size: 1.05rem; - opacity: 0.9; -} - -.feed-url { - color: var(--text-color); - opacity: 0.5; - font-size: 0.85rem; -} - -.delete-btn { - background: rgba(255, 82, 82, 0.15); - color: #ff8a80; - border: 1px solid rgba(255, 82, 82, 0.2); - padding: 0.5rem 1rem; - border-radius: 12px; - cursor: pointer; - font-weight: 600; - transition: all 0.2s; -} - -.delete-btn:hover:not(:disabled) { - background: rgba(255, 82, 82, 0.3); - color: #fff; - border-color: rgba(255, 82, 82, 0.4); - transform: scale(1.05); -} - -.import-export-section { - display: flex; - gap: 2rem; -} - -@media (max-width: 600px) { - .settings-page.variant-glass { - padding: 1.5rem; - margin-top: 1rem; - } - - .add-feed-form { - flex-direction: column; - } - - .import-export-section { - flex-direction: column; - gap: 1rem; - } - - .settings-feed-item { - flex-direction: column; - align-items: flex-start; - gap: 1rem; - } -} - -.import-form { - display: flex; - flex-direction: column; - gap: 1.2rem; -} - -.file-input { - font-size: 0.9rem; - max-width: 100%; - color: var(--text-color); - opacity: 0.8; -} - -.export-buttons { - display: flex; - gap: 0.8rem; - flex-wrap: wrap; -} - -.export-btn { - display: inline-block; - padding: 0.6rem 1.2rem; - background: rgba(255, 255, 255, 0.05); - color: var(--text-color); - text-decoration: none; - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 12px; - font-weight: 600; - transition: all 0.2s; -} - -.export-btn:hover { - background: rgba(255, 255, 255, 0.1); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); -} - -button:not(.delete-btn) { - cursor: pointer; - padding: 0.6rem 1.2rem; - border-radius: 12px; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(255, 255, 255, 0.1); - color: var(--text-color); - font-weight: 600; - transition: all 0.2s; -} - -button:not(.delete-btn):hover:not(:disabled) { - background: rgba(255, 255, 255, 0.2); - transform: scale(1.02); -} - -button:disabled { - opacity: 0.4; - cursor: not-allowed; -}</pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/Settings.tsx.html b/frontend/coverage/src/components/Settings.tsx.html deleted file mode 100644 index 892218e..0000000 --- a/frontend/coverage/src/components/Settings.tsx.html +++ /dev/null @@ -1,793 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components/Settings.tsx</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Settings.tsx</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">80% </span> - <span class="quiet">Statements</span> - <span class='fraction'>60/75</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">66.66% </span> - <span class="quiet">Branches</span> - <span class='fraction'>20/30</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">85.18% </span> - <span class="quiet">Functions</span> - <span class='fraction'>23/27</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">87.87% </span> - <span class="quiet">Lines</span> - <span class='fraction'>58/66</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <pre><table class="coverage"> -<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a> -<a name='L2'></a><a href='#L2'>2</a> -<a name='L3'></a><a href='#L3'>3</a> -<a name='L4'></a><a href='#L4'>4</a> -<a name='L5'></a><a href='#L5'>5</a> -<a name='L6'></a><a href='#L6'>6</a> -<a name='L7'></a><a href='#L7'>7</a> -<a name='L8'></a><a href='#L8'>8</a> -<a name='L9'></a><a href='#L9'>9</a> -<a name='L10'></a><a href='#L10'>10</a> -<a name='L11'></a><a href='#L11'>11</a> -<a name='L12'></a><a href='#L12'>12</a> -<a name='L13'></a><a href='#L13'>13</a> -<a name='L14'></a><a href='#L14'>14</a> -<a name='L15'></a><a href='#L15'>15</a> -<a name='L16'></a><a href='#L16'>16</a> -<a name='L17'></a><a href='#L17'>17</a> -<a name='L18'></a><a href='#L18'>18</a> -<a name='L19'></a><a href='#L19'>19</a> -<a name='L20'></a><a href='#L20'>20</a> -<a name='L21'></a><a href='#L21'>21</a> -<a name='L22'></a><a href='#L22'>22</a> -<a name='L23'></a><a href='#L23'>23</a> -<a name='L24'></a><a href='#L24'>24</a> -<a name='L25'></a><a href='#L25'>25</a> -<a name='L26'></a><a href='#L26'>26</a> -<a name='L27'></a><a href='#L27'>27</a> -<a name='L28'></a><a href='#L28'>28</a> -<a name='L29'></a><a href='#L29'>29</a> -<a name='L30'></a><a href='#L30'>30</a> -<a name='L31'></a><a href='#L31'>31</a> -<a name='L32'></a><a href='#L32'>32</a> -<a name='L33'></a><a href='#L33'>33</a> -<a name='L34'></a><a href='#L34'>34</a> -<a name='L35'></a><a href='#L35'>35</a> -<a name='L36'></a><a href='#L36'>36</a> -<a name='L37'></a><a href='#L37'>37</a> -<a name='L38'></a><a href='#L38'>38</a> -<a name='L39'></a><a href='#L39'>39</a> -<a name='L40'></a><a href='#L40'>40</a> -<a name='L41'></a><a href='#L41'>41</a> -<a name='L42'></a><a href='#L42'>42</a> -<a name='L43'></a><a href='#L43'>43</a> -<a name='L44'></a><a href='#L44'>44</a> -<a name='L45'></a><a href='#L45'>45</a> -<a name='L46'></a><a href='#L46'>46</a> -<a name='L47'></a><a href='#L47'>47</a> -<a name='L48'></a><a href='#L48'>48</a> -<a name='L49'></a><a href='#L49'>49</a> -<a name='L50'></a><a href='#L50'>50</a> -<a name='L51'></a><a href='#L51'>51</a> -<a name='L52'></a><a href='#L52'>52</a> -<a name='L53'></a><a href='#L53'>53</a> -<a name='L54'></a><a href='#L54'>54</a> -<a name='L55'></a><a href='#L55'>55</a> -<a name='L56'></a><a href='#L56'>56</a> -<a name='L57'></a><a href='#L57'>57</a> -<a name='L58'></a><a href='#L58'>58</a> -<a name='L59'></a><a href='#L59'>59</a> -<a name='L60'></a><a href='#L60'>60</a> -<a name='L61'></a><a href='#L61'>61</a> -<a name='L62'></a><a href='#L62'>62</a> -<a name='L63'></a><a href='#L63'>63</a> -<a name='L64'></a><a href='#L64'>64</a> -<a name='L65'></a><a href='#L65'>65</a> -<a name='L66'></a><a href='#L66'>66</a> -<a name='L67'></a><a href='#L67'>67</a> -<a name='L68'></a><a href='#L68'>68</a> -<a name='L69'></a><a href='#L69'>69</a> -<a name='L70'></a><a href='#L70'>70</a> -<a name='L71'></a><a href='#L71'>71</a> -<a name='L72'></a><a href='#L72'>72</a> -<a name='L73'></a><a href='#L73'>73</a> -<a name='L74'></a><a href='#L74'>74</a> -<a name='L75'></a><a href='#L75'>75</a> -<a name='L76'></a><a href='#L76'>76</a> -<a name='L77'></a><a href='#L77'>77</a> -<a name='L78'></a><a href='#L78'>78</a> -<a name='L79'></a><a href='#L79'>79</a> -<a name='L80'></a><a href='#L80'>80</a> -<a name='L81'></a><a href='#L81'>81</a> -<a name='L82'></a><a href='#L82'>82</a> -<a name='L83'></a><a href='#L83'>83</a> -<a name='L84'></a><a href='#L84'>84</a> -<a name='L85'></a><a href='#L85'>85</a> -<a name='L86'></a><a href='#L86'>86</a> -<a name='L87'></a><a href='#L87'>87</a> -<a name='L88'></a><a href='#L88'>88</a> -<a name='L89'></a><a href='#L89'>89</a> -<a name='L90'></a><a href='#L90'>90</a> -<a name='L91'></a><a href='#L91'>91</a> -<a name='L92'></a><a href='#L92'>92</a> -<a name='L93'></a><a href='#L93'>93</a> -<a name='L94'></a><a href='#L94'>94</a> -<a name='L95'></a><a href='#L95'>95</a> -<a name='L96'></a><a href='#L96'>96</a> -<a name='L97'></a><a href='#L97'>97</a> -<a name='L98'></a><a href='#L98'>98</a> -<a name='L99'></a><a href='#L99'>99</a> -<a name='L100'></a><a href='#L100'>100</a> -<a name='L101'></a><a href='#L101'>101</a> -<a name='L102'></a><a href='#L102'>102</a> -<a name='L103'></a><a href='#L103'>103</a> -<a name='L104'></a><a href='#L104'>104</a> -<a name='L105'></a><a href='#L105'>105</a> -<a name='L106'></a><a href='#L106'>106</a> -<a name='L107'></a><a href='#L107'>107</a> -<a name='L108'></a><a href='#L108'>108</a> -<a name='L109'></a><a href='#L109'>109</a> -<a name='L110'></a><a href='#L110'>110</a> -<a name='L111'></a><a href='#L111'>111</a> -<a name='L112'></a><a href='#L112'>112</a> -<a name='L113'></a><a href='#L113'>113</a> -<a name='L114'></a><a href='#L114'>114</a> -<a name='L115'></a><a href='#L115'>115</a> -<a name='L116'></a><a href='#L116'>116</a> -<a name='L117'></a><a href='#L117'>117</a> -<a name='L118'></a><a href='#L118'>118</a> -<a name='L119'></a><a href='#L119'>119</a> -<a name='L120'></a><a href='#L120'>120</a> -<a name='L121'></a><a href='#L121'>121</a> -<a name='L122'></a><a href='#L122'>122</a> -<a name='L123'></a><a href='#L123'>123</a> -<a name='L124'></a><a href='#L124'>124</a> -<a name='L125'></a><a href='#L125'>125</a> -<a name='L126'></a><a href='#L126'>126</a> -<a name='L127'></a><a href='#L127'>127</a> -<a name='L128'></a><a href='#L128'>128</a> -<a name='L129'></a><a href='#L129'>129</a> -<a name='L130'></a><a href='#L130'>130</a> -<a name='L131'></a><a href='#L131'>131</a> -<a name='L132'></a><a href='#L132'>132</a> -<a name='L133'></a><a href='#L133'>133</a> -<a name='L134'></a><a href='#L134'>134</a> -<a name='L135'></a><a href='#L135'>135</a> -<a name='L136'></a><a href='#L136'>136</a> -<a name='L137'></a><a href='#L137'>137</a> -<a name='L138'></a><a href='#L138'>138</a> -<a name='L139'></a><a href='#L139'>139</a> -<a name='L140'></a><a href='#L140'>140</a> -<a name='L141'></a><a href='#L141'>141</a> -<a name='L142'></a><a href='#L142'>142</a> -<a name='L143'></a><a href='#L143'>143</a> -<a name='L144'></a><a href='#L144'>144</a> -<a name='L145'></a><a href='#L145'>145</a> -<a name='L146'></a><a href='#L146'>146</a> -<a name='L147'></a><a href='#L147'>147</a> -<a name='L148'></a><a href='#L148'>148</a> -<a name='L149'></a><a href='#L149'>149</a> -<a name='L150'></a><a href='#L150'>150</a> -<a name='L151'></a><a href='#L151'>151</a> -<a name='L152'></a><a href='#L152'>152</a> -<a name='L153'></a><a href='#L153'>153</a> -<a name='L154'></a><a href='#L154'>154</a> -<a name='L155'></a><a href='#L155'>155</a> -<a name='L156'></a><a href='#L156'>156</a> -<a name='L157'></a><a href='#L157'>157</a> -<a name='L158'></a><a href='#L158'>158</a> -<a name='L159'></a><a href='#L159'>159</a> -<a name='L160'></a><a href='#L160'>160</a> -<a name='L161'></a><a href='#L161'>161</a> -<a name='L162'></a><a href='#L162'>162</a> -<a name='L163'></a><a href='#L163'>163</a> -<a name='L164'></a><a href='#L164'>164</a> -<a name='L165'></a><a href='#L165'>165</a> -<a name='L166'></a><a href='#L166'>166</a> -<a name='L167'></a><a href='#L167'>167</a> -<a name='L168'></a><a href='#L168'>168</a> -<a name='L169'></a><a href='#L169'>169</a> -<a name='L170'></a><a href='#L170'>170</a> -<a name='L171'></a><a href='#L171'>171</a> -<a name='L172'></a><a href='#L172'>172</a> -<a name='L173'></a><a href='#L173'>173</a> -<a name='L174'></a><a href='#L174'>174</a> -<a name='L175'></a><a href='#L175'>175</a> -<a name='L176'></a><a href='#L176'>176</a> -<a name='L177'></a><a href='#L177'>177</a> -<a name='L178'></a><a href='#L178'>178</a> -<a name='L179'></a><a href='#L179'>179</a> -<a name='L180'></a><a href='#L180'>180</a> -<a name='L181'></a><a href='#L181'>181</a> -<a name='L182'></a><a href='#L182'>182</a> -<a name='L183'></a><a href='#L183'>183</a> -<a name='L184'></a><a href='#L184'>184</a> -<a name='L185'></a><a href='#L185'>185</a> -<a name='L186'></a><a href='#L186'>186</a> -<a name='L187'></a><a href='#L187'>187</a> -<a name='L188'></a><a href='#L188'>188</a> -<a name='L189'></a><a href='#L189'>189</a> -<a name='L190'></a><a href='#L190'>190</a> -<a name='L191'></a><a href='#L191'>191</a> -<a name='L192'></a><a href='#L192'>192</a> -<a name='L193'></a><a href='#L193'>193</a> -<a name='L194'></a><a href='#L194'>194</a> -<a name='L195'></a><a href='#L195'>195</a> -<a name='L196'></a><a href='#L196'>196</a> -<a name='L197'></a><a href='#L197'>197</a> -<a name='L198'></a><a href='#L198'>198</a> -<a name='L199'></a><a href='#L199'>199</a> -<a name='L200'></a><a href='#L200'>200</a> -<a name='L201'></a><a href='#L201'>201</a> -<a name='L202'></a><a href='#L202'>202</a> -<a name='L203'></a><a href='#L203'>203</a> -<a name='L204'></a><a href='#L204'>204</a> -<a name='L205'></a><a href='#L205'>205</a> -<a name='L206'></a><a href='#L206'>206</a> -<a name='L207'></a><a href='#L207'>207</a> -<a name='L208'></a><a href='#L208'>208</a> -<a name='L209'></a><a href='#L209'>209</a> -<a name='L210'></a><a href='#L210'>210</a> -<a name='L211'></a><a href='#L211'>211</a> -<a name='L212'></a><a href='#L212'>212</a> -<a name='L213'></a><a href='#L213'>213</a> -<a name='L214'></a><a href='#L214'>214</a> -<a name='L215'></a><a href='#L215'>215</a> -<a name='L216'></a><a href='#L216'>216</a> -<a name='L217'></a><a href='#L217'>217</a> -<a name='L218'></a><a href='#L218'>218</a> -<a name='L219'></a><a href='#L219'>219</a> -<a name='L220'></a><a href='#L220'>220</a> -<a name='L221'></a><a href='#L221'>221</a> -<a name='L222'></a><a href='#L222'>222</a> -<a name='L223'></a><a href='#L223'>223</a> -<a name='L224'></a><a href='#L224'>224</a> -<a name='L225'></a><a href='#L225'>225</a> -<a name='L226'></a><a href='#L226'>226</a> -<a name='L227'></a><a href='#L227'>227</a> -<a name='L228'></a><a href='#L228'>228</a> -<a name='L229'></a><a href='#L229'>229</a> -<a name='L230'></a><a href='#L230'>230</a> -<a name='L231'></a><a href='#L231'>231</a> -<a name='L232'></a><a href='#L232'>232</a> -<a name='L233'></a><a href='#L233'>233</a> -<a name='L234'></a><a href='#L234'>234</a> -<a name='L235'></a><a href='#L235'>235</a> -<a name='L236'></a><a href='#L236'>236</a> -<a name='L237'></a><a href='#L237'>237</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-yes">9x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">7x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-no"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">34x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">2x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">6x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-yes">1x</span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span> -<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import React, { useEffect, useState } from 'react'; -import type { Feed } from '../types'; -import './Settings.css'; -import { apiFetch } from '../utils'; - -interface SettingsProps { - fontTheme?: string; - setFontTheme?: (t: string) => void; -} - -export default function Settings({ fontTheme, setFontTheme }: SettingsProps) { - const [feeds, setFeeds] = useState<Feed[]>([]); - /* ... existing state ... */ - const [newFeedUrl, setNewFeedUrl] = useState(''); - const [loading, setLoading] = useState(false); - const [error, setError] = useState<string | null>(null); - - const [importFile, setImportFile] = useState<File | null>(null); - - /* ... existing fetchFeeds ... */ - const fetchFeeds = React.useCallback(() => { - setLoading(true); - apiFetch('/api/feed/') - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to fetch feeds');</span> - return res.json(); - }) - .then((data) => { - setFeeds(data); - setLoading(false); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > setError(err.message);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }, []); - - useEffect(() => { - // eslint-disable-next-line - fetchFeeds(); - }, [fetchFeeds]); - - /* ... existing handlers ... */ - const handleAddFeed = (e: React.FormEvent) => { - e.preventDefault(); - <span class="missing-if-branch" title="if path not taken" >I</span>if (!newFeedUrl) <span class="cstat-no" title="statement not covered" >return;</span> - - setLoading(true); - apiFetch('/api/feed/', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url: newFeedUrl }), - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to add feed'); - return res.json(); - }) - .then(() => { - setNewFeedUrl(''); - fetchFeeds(); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - - const handleDeleteFeed = (id: number) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!globalThis.confirm('Are you sure you want to delete this feed?')) <span class="cstat-no" title="statement not covered" >return;</span> - - setLoading(true); - apiFetch(`/api/feed/${id}`, { - method: 'DELETE', - }) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to delete feed');</span> - setFeeds(feeds.filter((f) => f._id !== id)); - setLoading(false); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > setError(err.message);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }; - - const handleImport = (e: React.FormEvent) => { - e.preventDefault(); - <span class="missing-if-branch" title="if path not taken" >I</span>if (!importFile) <span class="cstat-no" title="statement not covered" >return;</span> - - setLoading(true); - const formData = new FormData(); - formData.append('file', importFile); - formData.append('format', 'opml'); - - apiFetch('/api/import', { - method: 'POST', - body: formData, - }) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to import feeds');</span> - return res.json(); - }) - .then(() => { - setImportFile(null); - fetchFeeds(); - alert('Import successful!'); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > setError(err.message);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }; - - const handleCrawl = () => { - setLoading(true); - apiFetch('/api/crawl', { - method: 'POST', - }) - .then((res) => { - <span class="missing-if-branch" title="if path not taken" >I</span>if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to start crawl');</span> - return res.json(); - }) - .then(() => { - setLoading(false); - alert('Crawl started!'); - }) - .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => { -<span class="cstat-no" title="statement not covered" > setError(err.message);</span> -<span class="cstat-no" title="statement not covered" > setLoading(false);</span> - }); - }; - - return ( - <div className="settings-page variant-glass"> - <h2>Settings</h2> - - {setFontTheme && ( - <div className="appearance-section"> - <h3>Appearance</h3> - <div className="font-selector"> - <label htmlFor="font-theme-select">Font Theme:</label> - <select - id="font-theme-select" - value={fontTheme || <span class="branch-1 cbranch-no" title="branch not covered" >'default'}</span> - onChange={(e) => setFontTheme(e.target.value)} - className="font-select" - > - <option value="default">Default</option> - <option value="serif">Serif</option> - <option value="sans">Sans-Serif</option> - <option value="mono">Monospace</option> - </select> - </div> - </div> - )} - - <div className="add-feed-section"> - <h3>Add New Feed</h3> - <form onSubmit={handleAddFeed} className="add-feed-form"> - <input - type="url" - value={newFeedUrl} - onChange={(e) => setNewFeedUrl(e.target.value)} - placeholder="https://example.com/feed.xml" - required - className="feed-input" - disabled={loading} - /> - <button type="submit" disabled={loading}> - Add Feed - </button> - </form> - </div> - - <div className="import-export-section"> - <div className="import-section"> - <h3>Import Feeds (OPML)</h3> - <form onSubmit={handleImport} className="import-form"> - <input - type="file" - accept=".opml,.xml,.txt" - aria-label="Import Feeds" - onChange={(e) => setImportFile(e.target.files?.[0] || <span class="branch-1 cbranch-no" title="branch not covered" >null)</span>} - className="file-input" - disabled={loading} - /> - <button type="submit" disabled={!importFile || loading}> - Import - </button> - </form> - </div> - - <div className="export-section"> - <h3>Export Feeds</h3> - <div className="export-buttons"> - <a href="/api/export/opml" className="export-btn">OPML</a> - <a href="/api/export/text" className="export-btn">Text</a> - <a href="/api/export/json" className="export-btn">JSON</a> - </div> - </div> - - <div className="crawl-section"> - <h3>Actions</h3> - <button onClick={handleCrawl} disabled={loading} className="crawl-btn"> - Crawl All Feeds Now - </button> - </div> - </div> - - {error && <p className="error-message">{error}</p>} - - <div className="feed-list-section"> - <h3>Manage Feeds</h3> - {loading && <p>Loading...</p>} - <ul className="settings-feed-list"> - {feeds.map((feed) => ( - <li key={feed._id} className="settings-feed-item"> - <div className="feed-info"> - <span className="feed-title">{feed.title || <span class="branch-1 cbranch-no" title="branch not covered" >'(No Title)'}<</span>/span> - <span className="feed-url">{feed.url}</span> - </div> - <button - onClick={() => handleDeleteFeed(feed._id)} - className="delete-btn" - disabled={loading} - title="Delete Feed" - > - Delete - </button> - </li> - ))} - </ul> - </div> - </div> - ); -} - </pre></td></tr></table></pre> - - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/components/index.html b/frontend/coverage/src/components/index.html deleted file mode 100644 index fc333bb..0000000 --- a/frontend/coverage/src/components/index.html +++ /dev/null @@ -1,266 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src/components</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../../prettify.css" /> - <link rel="stylesheet" href="../../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../../index.html">All files</a> src/components</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">86.21% </span> - <span class="quiet">Statements</span> - <span class='fraction'>269/312</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">74.61% </span> - <span class="quiet">Branches</span> - <span class='fraction'>144/193</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">84.94% </span> - <span class="quiet">Functions</span> - <span class='fraction'>79/93</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">88.81% </span> - <span class="quiet">Lines</span> - <span class='fraction'>254/286</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line high'></div> - <div class="pad1"> -<table class="coverage-summary"> -<thead> -<tr> - <th data-col="file" data-fmt="html" data-html="true" class="file">File</th> - <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th> - <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th> - <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th> - <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th> - <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th> - <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th> -</tr> -</thead> -<tbody><tr> - <td class="file empty" data-value="FeedItem.css"><a href="FeedItem.css.html">FeedItem.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file medium" data-value="FeedItem.tsx"><a href="FeedItem.tsx.html">FeedItem.tsx</a></td> - <td data-value="78.12" class="pic medium"> - <div class="chart"><div class="cover-fill" style="width: 78%"></div><div class="cover-empty" style="width: 22%"></div></div> - </td> - <td data-value="78.12" class="pct medium">78.12%</td> - <td data-value="32" class="abs medium">25/32</td> - <td data-value="86.95" class="pct high">86.95%</td> - <td data-value="23" class="abs high">20/23</td> - <td data-value="83.33" class="pct high">83.33%</td> - <td data-value="12" class="abs high">10/12</td> - <td data-value="80.64" class="pct high">80.64%</td> - <td data-value="31" class="abs high">25/31</td> - </tr> - -<tr> - <td class="file empty" data-value="FeedItems.css"><a href="FeedItems.css.html">FeedItems.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file high" data-value="FeedItems.tsx"><a href="FeedItems.tsx.html">FeedItems.tsx</a></td> - <td data-value="89.23" class="pic high"> - <div class="chart"><div class="cover-fill" style="width: 89%"></div><div class="cover-empty" style="width: 11%"></div></div> - </td> - <td data-value="89.23" class="pct high">89.23%</td> - <td data-value="130" class="abs high">116/130</td> - <td data-value="76.19" class="pct medium">76.19%</td> - <td data-value="84" class="abs medium">64/84</td> - <td data-value="87.09" class="pct high">87.09%</td> - <td data-value="31" class="abs high">27/31</td> - <td data-value="89.07" class="pct high">89.07%</td> - <td data-value="119" class="abs high">106/119</td> - </tr> - -<tr> - <td class="file empty" data-value="FeedList.css"><a href="FeedList.css.html">FeedList.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file high" data-value="FeedList.tsx"><a href="FeedList.tsx.html">FeedList.tsx</a></td> - <td data-value="87.27" class="pic high"> - <div class="chart"><div class="cover-fill" style="width: 87%"></div><div class="cover-empty" style="width: 13%"></div></div> - </td> - <td data-value="87.27" class="pct high">87.27%</td> - <td data-value="55" class="abs high">48/55</td> - <td data-value="70" class="pct medium">70%</td> - <td data-value="50" class="abs medium">35/50</td> - <td data-value="78.94" class="pct medium">78.94%</td> - <td data-value="19" class="abs medium">15/19</td> - <td data-value="90" class="pct high">90%</td> - <td data-value="50" class="abs high">45/50</td> - </tr> - -<tr> - <td class="file empty" data-value="FeedListVariants.css"><a href="FeedListVariants.css.html">FeedListVariants.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file empty" data-value="Login.css"><a href="Login.css.html">Login.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file high" data-value="Login.tsx"><a href="Login.tsx.html">Login.tsx</a></td> - <td data-value="100" class="pic high"> - <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div> - </td> - <td data-value="100" class="pct high">100%</td> - <td data-value="20" class="abs high">20/20</td> - <td data-value="83.33" class="pct high">83.33%</td> - <td data-value="6" class="abs high">5/6</td> - <td data-value="100" class="pct high">100%</td> - <td data-value="4" class="abs high">4/4</td> - <td data-value="100" class="pct high">100%</td> - <td data-value="20" class="abs high">20/20</td> - </tr> - -<tr> - <td class="file empty" data-value="Settings.css"><a href="Settings.css.html">Settings.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file high" data-value="Settings.tsx"><a href="Settings.tsx.html">Settings.tsx</a></td> - <td data-value="80" class="pic high"> - <div class="chart"><div class="cover-fill" style="width: 80%"></div><div class="cover-empty" style="width: 20%"></div></div> - </td> - <td data-value="80" class="pct high">80%</td> - <td data-value="75" class="abs high">60/75</td> - <td data-value="66.66" class="pct medium">66.66%</td> - <td data-value="30" class="abs medium">20/30</td> - <td data-value="85.18" class="pct high">85.18%</td> - <td data-value="27" class="abs high">23/27</td> - <td data-value="87.87" class="pct high">87.87%</td> - <td data-value="66" class="abs high">58/66</td> - </tr> - -</tbody> -</table> -</div> - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../../sorter.js"></script> - <script src="../../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/coverage/src/index.html b/frontend/coverage/src/index.html deleted file mode 100644 index 091ffa0..0000000 --- a/frontend/coverage/src/index.html +++ /dev/null @@ -1,146 +0,0 @@ - -<!doctype html> -<html lang="en"> - -<head> - <title>Code coverage report for src</title> - <meta charset="utf-8" /> - <link rel="stylesheet" href="../prettify.css" /> - <link rel="stylesheet" href="../base.css" /> - <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> - <style type='text/css'> - .coverage-summary .sorter { - background-image: url(../sort-arrow-sprite.png); - } - </style> -</head> - -<body> -<div class='wrapper'> - <div class='pad1'> - <h1><a href="../index.html">All files</a> src</h1> - <div class='clearfix'> - - <div class='fl pad1y space-right2'> - <span class="strong">70.21% </span> - <span class="quiet">Statements</span> - <span class='fraction'>33/47</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">65.71% </span> - <span class="quiet">Branches</span> - <span class='fraction'>23/35</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">60% </span> - <span class="quiet">Functions</span> - <span class='fraction'>9/15</span> - </div> - - - <div class='fl pad1y space-right2'> - <span class="strong">71.11% </span> - <span class="quiet">Lines</span> - <span class='fraction'>32/45</span> - </div> - - - </div> - <p class="quiet"> - Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block. - </p> - <template id="filterTemplate"> - <div class="quiet"> - Filter: - <input type="search" id="fileSearch"> - </div> - </template> - </div> - <div class='status-line medium'></div> - <div class="pad1"> -<table class="coverage-summary"> -<thead> -<tr> - <th data-col="file" data-fmt="html" data-html="true" class="file">File</th> - <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th> - <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th> - <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th> - <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th> - <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th> - <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th> - <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th> -</tr> -</thead> -<tbody><tr> - <td class="file empty" data-value="App.css"><a href="App.css.html">App.css</a></td> - <td data-value="0" class="pic empty"> - <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div> - </td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - <td data-value="0" class="pct empty">0%</td> - <td data-value="0" class="abs empty">0/0</td> - </tr> - -<tr> - <td class="file medium" data-value="App.tsx"><a href="App.tsx.html">App.tsx</a></td> - <td data-value="65.71" class="pic medium"> - <div class="chart"><div class="cover-fill" style="width: 65%"></div><div class="cover-empty" style="width: 35%"></div></div> - </td> - <td data-value="65.71" class="pct medium">65.71%</td> - <td data-value="35" class="abs medium">23/35</td> - <td data-value="60" class="pct medium">60%</td> - <td data-value="25" class="abs medium">15/25</td> - <td data-value="53.84" class="pct medium">53.84%</td> - <td data-value="13" class="abs medium">7/13</td> - <td data-value="64.7" class="pct medium">64.7%</td> - <td data-value="34" class="abs medium">22/34</td> - </tr> - -<tr> - <td class="file high" data-value="utils.ts"><a href="utils.ts.html">utils.ts</a></td> - <td data-value="83.33" class="pic high"> - <div class="chart"><div class="cover-fill" style="width: 83%"></div><div class="cover-empty" style="width: 17%"></div></div> - </td> - <td data-value="83.33" class="pct high">83.33%</td> - <td data-value="12" class="abs high">10/12</td> - <td data-value="80" class="pct high">80%</td> - <td data-value="10" class="abs high">8/10</td> - <td data-value="100" class="pct high">100%</td> - <td data-value="2" class="abs high">2/2</td> - <td data-value="90.9" class="pct high">90.9%</td> - <td data-value="11" class="abs high">10/11</td> - </tr> - -</tbody> -</table> -</div> - <div class='push'></div><!-- for sticky footer --> - </div><!-- /wrapper --> - <div class='footer quiet pad2 space-top1 center small'> - Code coverage generated by - <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> - at 2026-02-15T05:30:50.842Z - </div> - <script src="../prettify.js"></script> - <script> - window.onload = function () { - prettyPrint(); - }; - </script> - <script src="../sorter.js"></script> - <script src="../block-navigation.js"></script> - </body> -</html> -
\ No newline at end of file diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js deleted file mode 100644 index d2de7f8..0000000 --- a/frontend/eslint.config.js +++ /dev/null @@ -1,32 +0,0 @@ -import js from '@eslint/js'; -import globals from 'globals'; -import reactHooks from 'eslint-plugin-react-hooks'; -import reactRefresh from 'eslint-plugin-react-refresh'; -import tseslint from 'typescript-eslint'; -import eslintConfigPrettier from 'eslint-config-prettier'; - -export default tseslint.config( - { ignores: ['dist', 'coverage', 'playwright-report'] }, - { - extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ['**/*.{ts,tsx}'], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], - '@typescript-eslint/no-unused-vars': ['warn', { - argsIgnorePattern: '^_', - caughtErrorsIgnorePattern: '^_' - }], - '@typescript-eslint/no-explicit-any': 'warn', - }, - }, - eslintConfigPrettier -); diff --git a/frontend/index.html b/frontend/index.html deleted file mode 100644 index a1475a5..0000000 --- a/frontend/index.html +++ /dev/null @@ -1,13 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, viewport-fit=cover" /> - <title>Neko Reader</title> - </head> - <body> - <div id="root"></div> - <script type="module" src="/src/main.tsx"></script> - </body> -</html> diff --git a/frontend/package-lock.json b/frontend/package-lock.json deleted file mode 100644 index fda0116..0000000 --- a/frontend/package-lock.json +++ /dev/null @@ -1,4469 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "react": "^19.2.0", - "react-dom": "^19.2.0", - "react-router-dom": "^7.13.0" - }, - "devDependencies": { - "@eslint/js": "^9.39.1", - "@playwright/test": "^1.58.2", - "@testing-library/jest-dom": "^6.9.1", - "@testing-library/react": "^16.3.2", - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "@vitest/coverage-v8": "^4.0.18", - "eslint": "^9.39.1", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-prettier": "^5.5.5", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "jsdom": "^28.0.0", - "prettier": "^3.8.1", - "typescript": "~5.9.3", - "typescript-eslint": "^8.48.0", - "vite": "^7.3.1", - "vitest": "^4.0.18" - } - }, - "node_modules/@acemir/cssom": { - "version": "0.9.31", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", - "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", - "dev": true - }, - "node_modules/@adobe/css-tools": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", - "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", - "dev": true - }, - "node_modules/@asamuzakjp/css-color": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", - "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", - "dev": true, - "dependencies": { - "@csstools/css-calc": "^3.0.0", - "@csstools/css-color-parser": "^4.0.1", - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0", - "lru-cache": "^11.2.5" - } - }, - "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@asamuzakjp/dom-selector": { - "version": "6.7.8", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.8.tgz", - "integrity": "sha512-stisC1nULNc9oH5lakAj8MH88ZxeGxzyWNDfbdCxvJSJIvDsHNZqYvscGTgy/ysgXWLJPt6K/4t0/GjvtKcFJQ==", - "dev": true, - "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.5" - } - }, - "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "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 - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/color-helpers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.1.tgz", - "integrity": "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/@csstools/css-calc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.0.tgz", - "integrity": "sha512-JWouqB5za07FUA2iXZWq4gPXNGWXjRwlfwEXNr7cSsGr7OKgzhDVwkJjlsrbqSyFmDGSi1Rt7zs8ln87jX9yRg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.1.tgz", - "integrity": "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "dependencies": { - "@csstools/color-helpers": "^6.0.1", - "@csstools/css-calc": "^3.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", - "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.27.tgz", - "integrity": "sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ] - }, - "node_modules/@csstools/css-tokenizer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", - "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "dev": true, - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@exodus/bytes": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", - "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", - "dev": true, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@noble/hashes": "^1.8.0 || ^2.0.0" - }, - "peerDependenciesMeta": { - "@noble/hashes": { - "optional": true - } - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, - "node_modules/@playwright/test": { - "version": "1.58.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", - "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", - "dev": true, - "dependencies": { - "playwright": "1.58.2" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", - "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true - }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", - "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "picocolors": "^1.1.1", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "dev": true - }, - "node_modules/@testing-library/react": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", - "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "peer": true - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "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, - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "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 - }, - "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 - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "24.10.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", - "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", - "dev": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.55.0.tgz", - "integrity": "sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.55.0", - "@typescript-eslint/type-utils": "8.55.0", - "@typescript-eslint/utils": "8.55.0", - "@typescript-eslint/visitor-keys": "8.55.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.55.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.55.0.tgz", - "integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "8.55.0", - "@typescript-eslint/types": "8.55.0", - "@typescript-eslint/typescript-estree": "8.55.0", - "@typescript-eslint/visitor-keys": "8.55.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.55.0.tgz", - "integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.55.0", - "@typescript-eslint/types": "^8.55.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.55.0.tgz", - "integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.55.0", - "@typescript-eslint/visitor-keys": "8.55.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.55.0.tgz", - "integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.55.0.tgz", - "integrity": "sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.55.0", - "@typescript-eslint/typescript-estree": "8.55.0", - "@typescript-eslint/utils": "8.55.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", - "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.55.0.tgz", - "integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==", - "dev": true, - "dependencies": { - "@typescript-eslint/project-service": "8.55.0", - "@typescript-eslint/tsconfig-utils": "8.55.0", - "@typescript-eslint/types": "8.55.0", - "@typescript-eslint/visitor-keys": "8.55.0", - "debug": "^4.4.3", - "minimatch": "^9.0.5", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.55.0.tgz", - "integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.55.0", - "@typescript-eslint/types": "8.55.0", - "@typescript-eslint/typescript-estree": "8.55.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.55.0.tgz", - "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.55.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", - "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-rc.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", - "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", - "obug": "^2.1.1", - "std-env": "^3.10.0", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } - } - }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", - "dev": true, - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", - "dev": true, - "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "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/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", - "dev": true, - "dependencies": { - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", - "dev": true, - "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", - "dev": true, - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", - "dev": true, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", - "dev": true, - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/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, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "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, - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-v8-to-istanbul": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.11.tgz", - "integrity": "sha512-Qya9fkoofMjCBNVdWINMjB5KZvkYfaO9/anwkWnjxibpWUxo5iHl2sOdP7/uAqaRuUYuoo8rDwnbaaKVFxoUvw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "estree-walker": "^3.0.3", - "js-tokens": "^10.0.0" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", - "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "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, - "dependencies": { - "require-from-string": "^2.0.2" - } - }, - "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==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001769", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", - "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "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, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "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, - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", - "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", - "dev": true, - "dependencies": { - "@asamuzakjp/css-color": "^4.1.1", - "@csstools/css-syntax-patches-for-csstree": "^1.0.21", - "css-tree": "^3.1.0", - "lru-cache": "^11.2.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cssstyle/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, - "engines": { - "node": "20 || >=22" - } - }, - "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 - }, - "node_modules/data-urls": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", - "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", - "dev": true, - "dependencies": { - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "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 - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true, - "peer": true - }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "dev": true - }, - "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, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "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 - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "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, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "10.1.8", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", - "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.5.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", - "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.1", - "synckit": "^0.11.12" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", - "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.26", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", - "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", - "dev": true, - "peerDependencies": { - "eslint": ">=8.40" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", - "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", - "dev": true, - "dependencies": { - "@exodus/bytes": "^1.6.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/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, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.0.0.tgz", - "integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==", - "dev": true, - "dependencies": { - "@acemir/cssom": "^0.9.31", - "@asamuzakjp/dom-selector": "^6.7.6", - "@exodus/bytes": "^1.11.0", - "cssstyle": "^5.3.7", - "data-urls": "^7.0.0", - "decimal.js": "^10.6.0", - "html-encoding-sniffer": "^6.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", - "undici": "^7.20.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^8.0.1", - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "peer": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "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, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/magicast": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", - "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "source-map-js": "^1.2.1" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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 - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "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" - } - ], - "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 - }, - "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 - }, - "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" - ] - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", - "dev": true, - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/playwright": { - "version": "1.58.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", - "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", - "dev": true, - "dependencies": { - "playwright-core": "1.58.2" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.58.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", - "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", - "dev": true, - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", - "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/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, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "peer": true - }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz", - "integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz", - "integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==", - "dependencies": { - "react-router": "7.13.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", - "dev": true, - "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.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/synckit": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", - "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.2.9" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, - "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 - }, - "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, - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "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, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tldts": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", - "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", - "dev": true, - "dependencies": { - "tldts-core": "^7.0.23" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", - "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", - "dev": true - }, - "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", - "dev": true, - "dependencies": { - "tldts": "^7.0.5" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", - "dev": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", - "dev": true, - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.55.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.55.0.tgz", - "integrity": "sha512-HE4wj+r5lmDVS9gdaN0/+iqNvPZwGfnJ5lZuz7s5vLlg9ODw0bIiiETaios9LvFI1U94/VBXGm3CB2Y5cNFMpw==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.55.0", - "@typescript-eslint/parser": "8.55.0", - "@typescript-eslint/typescript-estree": "8.55.0", - "@typescript-eslint/utils": "8.55.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/undici": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.21.0.tgz", - "integrity": "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==", - "dev": true, - "engines": { - "node": ">=20.18.1" - } - }, - "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 - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "dev": true, - "dependencies": { - "esbuild": "^0.27.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/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", - "dev": true, - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "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.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "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/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/webidl-conversions": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", - "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", - "dev": true, - "engines": { - "node": ">=20" - } - }, - "node_modules/whatwg-mimetype": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", - "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", - "dev": true, - "engines": { - "node": ">=20" - } - }, - "node_modules/whatwg-url": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.0.tgz", - "integrity": "sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ==", - "dev": true, - "dependencies": { - "@exodus/bytes": "^1.11.0", - "tr46": "^6.0.0", - "webidl-conversions": "^8.0.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/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, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } - } - } -} diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index 4bed8f9..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint . --max-warnings 0", - "format": "prettier --write .", - "preview": "vite preview", - "test": "vitest", - "test:e2e": "playwright test", - "test:mocked": "playwright test tests/mocked-api.spec.ts", - "coverage": "vitest run --coverage" - }, - "dependencies": { - "react": "^19.2.0", - "react-dom": "^19.2.0", - "react-router-dom": "^7.13.0" - }, - "devDependencies": { - "@eslint/js": "^9.39.1", - "@playwright/test": "^1.58.2", - "@testing-library/jest-dom": "^6.9.1", - "@testing-library/react": "^16.3.2", - "@types/node": "^24.10.1", - "@types/react": "^19.2.7", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "@vitest/coverage-v8": "^4.0.18", - "eslint": "^9.39.1", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-prettier": "^5.5.5", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "jsdom": "^28.0.0", - "prettier": "^3.8.1", - "typescript": "~5.9.3", - "typescript-eslint": "^8.48.0", - "vite": "^7.3.1", - "vitest": "^4.0.18" - } -}
\ No newline at end of file diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts deleted file mode 100644 index 26e0b59..0000000 --- a/frontend/playwright.config.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { defineConfig, devices } from '@playwright/test'; - -export default defineConfig({ - testDir: './tests', - fullyParallel: true, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - workers: 1, // Avoid VM crash - reporter: 'html', - use: { - baseURL: 'http://localhost:5173', // Vite dev server - trace: 'on-first-retry', - }, - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - ], - webServer: { - command: 'npm run dev', - url: 'http://localhost:5173', - reuseExistingServer: !process.env.CI, - }, -}); diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
\ No newline at end of file diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index 0723023..0000000 --- a/frontend/src/App.css +++ /dev/null @@ -1,136 +0,0 @@ -/* Resets and Base Styles */ -* { - box-sizing: border-box; -} - -body { - margin: 0; -} - -/* Dashboard Layout */ -.dashboard { - display: flex; - flex-direction: column; - height: 100vh; - height: 100dvh; - width: 100%; - overflow: hidden; - /* Prevent body scroll */ -} - -/* Header styles removed as we moved to sidebar navigation */ - -.dashboard-content { - display: flex; - flex: 1; - overflow: hidden; - position: relative; - width: 100%; -} - -.dashboard-sidebar { - width: 11rem; - background: transparent; - border-right: 1px solid var(--border-color); - display: flex; - flex-direction: column; - overflow-y: auto; - transition: margin-left 0.4s ease; - /* No padding here, handled in FeedList */ -} - -.dashboard-sidebar.hidden { - margin-left: -11rem; -} - -.dashboard-main { - flex: 1; - min-width: 0; - padding: 2rem; - overflow-y: auto; - overflow-x: hidden; - background: var(--bg-color); - margin-left: 0; -} - -.dashboard-main>* { - max-width: 35em; - margin: 0 auto; -} - -.fixed-toggle { - position: absolute; - top: 1rem; - left: 1rem; - z-index: 1000; - background: var(--bg-color); - /* Added bg to be visible over content if needed */ - background: none; - border: none; - font-size: 2rem; - line-height: 1; - cursor: pointer; - padding: 0.2rem; - color: var(--text-color); - display: flex; - align-items: center; - justify-content: center; -} - -.fixed-toggle:hover { - transform: scale(1.1); -} - -/* Mobile Responsiveness */ -@media (max-width: 768px) { - .dashboard-sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 1100; - box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2); - width: 14rem; - /* Slightly wider on mobile for better target area */ - } - - .dashboard-sidebar.hidden { - margin-left: -14rem; - } - - .dashboard-main { - padding: 1rem; - padding-top: 4rem; - /* Space for the toggle button */ - } - - .dashboard-main>* { - max-width: 100%; - } - - /* When sidebar is visible on mobile, we show a backdrop */ - .sidebar-backdrop { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: rgba(0, 0, 0, 0.4); - z-index: 1050; - animation: fadeIn 0.3s ease; - } - - .dashboard.sidebar-visible::after { - display: none; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } -}
\ No newline at end of file diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx deleted file mode 100644 index 27b9da2..0000000 --- a/frontend/src/App.test.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, waitFor, fireEvent } from '@testing-library/react'; -import App from './App'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; - -describe('App', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - }); - - it('renders login on initial load (unauthenticated)', async () => { - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: false, - } as Response); - window.history.pushState({}, 'Test page', '/v2/login'); - render(<App />); - expect(await screen.findByRole('button', { name: /login/i })).toBeInTheDocument(); - }); - - it('renders dashboard when authenticated', async () => { - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/auth')) return Promise.resolve({ ok: true } as Response); - if (urlStr.includes('/api/feed/')) return Promise.resolve({ ok: true, json: async () => [] } as Response); - if (urlStr.includes('/api/tag')) return Promise.resolve({ ok: true, json: async () => [] } as Response); - return Promise.resolve({ ok: true } as Response); // Fallback - }); - - window.history.pushState({}, 'Test page', '/v2/'); - render(<App />); - - await waitFor(() => { - expect(screen.getByText('🐱')).toBeInTheDocument(); - }); - - // Test Logout - const logoutBtn = screen.getByText(/logout/i); - expect(logoutBtn).toBeInTheDocument(); - - // Mock window.location - Object.defineProperty(window, 'location', { - configurable: true, - value: { href: '' }, - }); - - vi.mocked(global.fetch).mockResolvedValueOnce({ ok: true } as Response); - - fireEvent.click(logoutBtn); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/logout', - expect.objectContaining({ method: 'POST' }) - ); - expect(window.location.href).toBe('/v2/#/login'); - }); - }); -}); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx deleted file mode 100644 index cc45949..0000000 --- a/frontend/src/App.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { HashRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom'; -import Login from './components/Login'; -import './App.css'; -import { apiFetch } from './utils'; - -// Protected Route wrapper -function RequireAuth({ children }: { children: React.ReactElement }) { - const [auth, setAuth] = useState<boolean | null>(null); - const location = useLocation(); - - useEffect(() => { - apiFetch('/api/auth') - .then((res) => { - if (res.ok) { - setAuth(true); - } else { - setAuth(false); - } - }) - .catch(() => setAuth(false)); - }, []); - - if (auth === null) { - return <div>Loading...</div>; - } - - if (!auth) { - return <Navigate to="/login" state={{ from: location }} replace />; - } - - return children; -} - -import FeedList from './components/FeedList'; -import FeedItems from './components/FeedItems'; -import Settings from './components/Settings'; - -interface DashboardProps { - theme: string; - setTheme: (t: string) => void; - fontTheme: string; - setFontTheme: (t: string) => void; -} - -function Dashboard({ theme, setTheme, fontTheme, setFontTheme }: DashboardProps) { - const [sidebarVisible, setSidebarVisible] = useState(window.innerWidth > 768); - - useEffect(() => { - const handleResize = () => { - if (window.innerWidth > 768) { - setSidebarVisible(true); - } else { - setSidebarVisible(false); - } - }; - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); - - return ( - <div - className={`dashboard ${sidebarVisible ? 'sidebar-visible' : 'sidebar-hidden'} theme-${theme} font-${fontTheme}`} - > - <div className="dashboard-content"> - {(!sidebarVisible || window.innerWidth <= 768) && ( - <button - className="sidebar-toggle fixed-toggle" - onClick={() => setSidebarVisible(!sidebarVisible)} - title={sidebarVisible ? "Hide Sidebar" : "Show Sidebar"} - > - 🐱 - </button> - )} - {sidebarVisible && ( - <div - className="sidebar-backdrop" - onClick={() => setSidebarVisible(false)} - /> - )} - <aside className={`dashboard-sidebar ${sidebarVisible ? '' : 'hidden'}`}> - <FeedList - theme={theme} - setTheme={setTheme} - setSidebarVisible={setSidebarVisible} - isMobile={window.innerWidth <= 768} - /> - </aside> - <main className="dashboard-main"> - <Routes> - <Route path="/feed/:feedId" element={<FeedItems />} /> - <Route path="/tag/:tagName" element={<FeedItems />} /> - <Route path="/settings" element={<Settings fontTheme={fontTheme} setFontTheme={setFontTheme} />} /> - <Route path="/" element={<FeedItems />} /> - </Routes> - </main> - </div> - </div> - ); -} - -function App() { - const [theme, setTheme] = useState(localStorage.getItem('neko-theme') || 'light'); - const [fontTheme, setFontTheme] = useState(localStorage.getItem('neko-font-theme') || 'default'); - - const handleSetTheme = (newTheme: string) => { - setTheme(newTheme); - localStorage.setItem('neko-theme', newTheme); - }; - - const handleSetFontTheme = (newFontTheme: string) => { - setFontTheme(newFontTheme); - localStorage.setItem('neko-font-theme', newFontTheme); - }; - - - - return ( - <HashRouter> - <Routes> - <Route path="/login" element={<Login />} /> - <Route - path="/*" - element={ - <RequireAuth> - <Dashboard - theme={theme} - setTheme={handleSetTheme} - fontTheme={fontTheme} - setFontTheme={handleSetFontTheme} - /> - </RequireAuth> - } - /> - </Routes> - </HashRouter> - ); -} - -export default App; diff --git a/frontend/src/Navigation.test.tsx b/frontend/src/Navigation.test.tsx deleted file mode 100644 index b0bae86..0000000 --- a/frontend/src/Navigation.test.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import React from 'react'; -import App from './App'; -import '@testing-library/jest-dom'; - -describe('Navigation and Filtering', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - // Default mock response for auth - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/auth')) return Promise.resolve({ ok: true, json: async () => ({ status: 'ok' }) } as Response); - if (urlStr.includes('/api/feed/')) return Promise.resolve({ - ok: true, - json: async () => [ - { _id: 1, title: 'Feed 1', url: 'http://f1.com' }, - { _id: 2, title: 'Feed 2', url: 'http://f2.com' } - ] - } as Response); - if (urlStr.includes('/api/tag')) return Promise.resolve({ ok: true, json: async () => [] } as Response); - if (urlStr.includes('/api/stream')) return Promise.resolve({ ok: true, json: async () => [] } as Response); - return Promise.resolve({ ok: true, json: async () => ({}) } as Response); - }); - }); - - it('preserves "all" filter when clicking a feed', async () => { - Object.defineProperty(window, 'innerWidth', { writable: true, configurable: true, value: 1024 }); - window.history.pushState({}, '', '/#/'); - render(<App />); - - // Wait for sidebar to load and feeds section to be visible - await waitFor(() => { - expect(screen.queryByText(/Loading feeds/i)).not.toBeInTheDocument(); - }); - - // Expand feeds if not expanded - const feedsHeader = await screen.findByRole('heading', { name: /Feeds/i, level: 4 }); - fireEvent.click(feedsHeader); - - await waitFor(() => { - expect(screen.getByText('Feed 1')).toBeInTheDocument(); - }); - // Click 'all' filter - const allFilter = screen.getByText('all'); - fireEvent.click(allFilter); - - // Verify URL has filter=all - await waitFor(() => { - expect(window.location.hash).toContain('filter=all'); - }); - - // Click Feed 1 - const feed1Link = screen.getByText('Feed 1'); - fireEvent.click(feed1Link); - - // Verify URL is /feed/1?filter=all (or similar) - await waitFor(() => { - expect(window.location.hash).toContain('/feed/1'); - expect(window.location.hash).toContain('filter=all'); - }); - - // Click Feed 2 - const feed2Link = screen.getByText('Feed 2'); - fireEvent.click(feed2Link); - - // Verify URL is /feed/2?filter=all - await waitFor(() => { - expect(window.location.hash).toContain('/feed/2'); - expect(window.location.hash).toContain('filter=all'); - }); - }); - - it('highlights the correct filter link', async () => { - window.history.pushState({}, '', '/#/'); - render(<App />); - - await waitFor(() => { - const unreadLink = screen.getByText('unread'); - expect(unreadLink.className).toContain('active'); - }); - - fireEvent.click(screen.getByText('all')); - await waitFor(() => { - const allLink = screen.getByText('all'); - const unreadLink = screen.getByText('unread'); - expect(allLink.className).toContain('active'); - expect(unreadLink.className).not.toContain('active'); - }); - }); - - it('highlights "unread" as active even when on a feed page without filter param', async () => { - window.history.pushState({}, '', '/#/feed/1'); - render(<App />); - - await waitFor(() => { - const unreadLink = screen.getByText('unread'); - expect(unreadLink.className).toContain('active'); - }); - }); - - it('preserves search query when clicking a feed', async () => { - window.history.pushState({}, '', '/#/?q=linux'); - render(<App />); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText(/Loading feeds/i)).not.toBeInTheDocument(); - }); - - const feedsHeader = await screen.findByRole('heading', { name: /Feeds/i, level: 4 }); - fireEvent.click(feedsHeader); - - await screen.findByText('Feed 1'); - fireEvent.click(screen.getByText('Feed 1')); - - await waitFor(() => { - expect(window.location.hash).toContain('/feed/1'); - expect(window.location.hash).toContain('q=linux'); - }); - }); -}); diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
\ No newline at end of file diff --git a/frontend/src/components/FeedItem.css b/frontend/src/components/FeedItem.css deleted file mode 100644 index 876fc66..0000000 --- a/frontend/src/components/FeedItem.css +++ /dev/null @@ -1,158 +0,0 @@ -.feed-item { - padding: 1rem; - margin-top: 5rem; - list-style: none; - border-bottom: none; -} - -/* removed read/unread specific font-weight to keep it always bold as requested */ - -.item-header { - display: flex; - justify-content: space-between; - align-items: flex-start; - margin-bottom: 0.5rem; -} - -.item-title { - font-family: var(--font-heading); - font-size: 1.8rem; - font-weight: bold; - text-decoration: none; - color: var(--link-color); - display: block; - flex: 1; -} - -.item-title:hover { - text-decoration: none; - color: var(--link-color); -} - -.item-actions { - display: flex; - gap: 0.5rem; - margin-left: 1rem; -} - -/* Legacy controls were simple text/links, but buttons are fine if minimal */ -.star-btn { - background: none; - border: none; - cursor: pointer; - font-size: 1.25rem; - padding: 0 0 0 0.5rem; - vertical-align: middle; - transition: color 0.2s; - line-height: 1; -} - -.star-btn.is-starred { - color: blue; -} - -.star-btn.is-unstarred { - color: var(--text-color); - opacity: 0.3; -} - -.star-btn:hover { - color: blue; -} - -.action-btn { - background: var(--sidebar-bg); - border: 1px solid var(--border-color, #ccc); - cursor: pointer; - padding: 2px 6px; - font-size: 1rem; - color: blue; - font-weight: bold; -} - -.action-btn:hover { - background-color: #eee; -} - -.dateline { - margin-top: 0; - font-weight: normal; - font-size: 0.75em; - color: #ccc; - margin-bottom: 1rem; -} - -.dateline a { - color: #ccc; - text-decoration: none; -} - -.item-description { - color: var(--text-color); - line-height: 1.5; - font-size: 1rem; - margin-top: 1rem; - overflow-wrap: break-word; - word-break: break-word; -} - -.item-description table, -.item-description pre, -.item-description code { - max-width: 100%; - overflow-x: auto; - display: block; -} - -.item-description img { - max-width: 100%; - height: auto; - display: block; - margin: 1rem 0; -} - -.item-description blockquote { - padding: 1rem 1rem 0 1rem; - border-left: 4px solid var(--sidebar-bg); - color: var(--text-color); - opacity: 0.8; - margin-left: 0; -} - -.scrape-btn { - background: var(--bg-color); - border: 1px solid var(--border-color, #ccc); - color: blue; - cursor: pointer; - font-family: var(--font-heading); - font-weight: bold; - font-size: 0.8rem; - padding: 2px 6px; - margin-left: 0.5rem; -} - -.scrape-btn:hover { - background: var(--sidebar-bg); -} - -@media (max-width: 768px) { - .feed-item { - margin-top: 2rem; - padding: 0.5rem; - } - - .item-title { - font-size: 1.4rem; - word-break: break-word; - } - - .item-header { - flex-direction: column; - gap: 0.5rem; - } - - .item-actions { - margin-left: 0; - margin-bottom: 0.5rem; - } -}
\ No newline at end of file diff --git a/frontend/src/components/FeedItem.test.tsx b/frontend/src/components/FeedItem.test.tsx deleted file mode 100644 index ab2ca45..0000000 --- a/frontend/src/components/FeedItem.test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import FeedItem from './FeedItem'; -import type { Item } from '../types'; - -const mockItem: Item = { - _id: 1, - feed_id: 101, - title: 'Test Item', - url: 'http://example.com/item', - description: '<p>Description</p>', - publish_date: '2023-01-01', - read: false, - starred: false, - feed_title: 'Test Feed', -}; - -describe('FeedItem Component', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - }); - - it('renders item details', () => { - render(<FeedItem item={mockItem} />); - expect(screen.getByText('Test Item')).toBeInTheDocument(); - expect(screen.getByText(/Test Feed/)).toBeInTheDocument(); - }); - - it('calls onToggleStar when star clicked', () => { - const onToggleStar = vi.fn(); - render(<FeedItem item={mockItem} onToggleStar={onToggleStar} />); - - const starBtn = screen.getByTitle('Star'); - fireEvent.click(starBtn); - - expect(onToggleStar).toHaveBeenCalledWith(mockItem); - }); - - it('updates styling when read state changes', () => { - const { rerender } = render(<FeedItem item={{ ...mockItem, read: false }} />); - const link = screen.getByText('Test Item'); - const listItem = link.closest('li'); - expect(listItem).toHaveClass('unread'); - expect(listItem).not.toHaveClass('read'); - - rerender(<FeedItem item={{ ...mockItem, read: true }} />); - expect(listItem).toHaveClass('read'); - expect(listItem).not.toHaveClass('unread'); - }); - - it('loads full content and calls onUpdate', async () => { - const onUpdate = vi.fn(); - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: true, - json: async () => ({ full_content: '<p>Full Content Loaded</p>' }), - } as Response); - - const { rerender } = render(<FeedItem item={mockItem} onUpdate={onUpdate} />); - - const scrapeBtn = screen.getByTitle('Load Full Content'); - fireEvent.click(scrapeBtn); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith('/api/item/1', expect.anything()); - }); - - await waitFor(() => { - expect(onUpdate).toHaveBeenCalledWith(expect.objectContaining({ - full_content: '<p>Full Content Loaded</p>' - })); - }); - - // Simulate parent updating prop - rerender(<FeedItem item={{ ...mockItem, full_content: '<p>Full Content Loaded</p>' }} onUpdate={onUpdate} />); - expect(screen.getByText('Full Content Loaded')).toBeInTheDocument(); - }); -}); diff --git a/frontend/src/components/FeedItem.tsx b/frontend/src/components/FeedItem.tsx deleted file mode 100644 index 865c080..0000000 --- a/frontend/src/components/FeedItem.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { useState, memo } from 'react'; -import type { Item } from '../types'; -import './FeedItem.css'; - -import { apiFetch } from '../utils'; - -interface FeedItemProps { - item: Item; - onToggleStar?: (item: Item) => void; - onUpdate?: (item: Item) => void; -} - -const FeedItem = memo(function FeedItem({ item, onToggleStar, onUpdate }: FeedItemProps) { - const [loading, setLoading] = useState(false); - - // We rely on props.item for data. - // If we fetch full content, we notify the parent via onUpdate. - - const handleToggleStar = (e: React.MouseEvent) => { - e.stopPropagation(); - if (onToggleStar) { - onToggleStar(item); - } else { - // Fallback if no handler passed (backward compat or isolated usage) - // But really we should rely on parent. - // For now, let's keep the optimistic local update logic if we were standalone, - // but since we are optimizing, we assume parent handles it. - } - }; - - const loadFullContent = (e: React.MouseEvent) => { - e.stopPropagation(); - setLoading(true); - apiFetch(`/api/item/${item._id}`) - .then((res) => { - if (!res.ok) throw new Error('Failed to fetch full content'); - return res.json(); - }) - .then((data) => { - // Merge the new data (full_content) into the item and notify parent - const newItem = { ...item, ...data }; - if (onUpdate) { - onUpdate(newItem); - } - setLoading(false); - }) - .catch((err) => { - console.error('Error fetching full content:', err); - setLoading(false); - }); - }; - - return ( - <li className={`feed-item ${item.read ? 'read' : 'unread'} ${loading ? 'loading' : ''}`}> - <div className="item-header"> - <a href={item.url} target="_blank" rel="noopener noreferrer" className="item-title"> - {item.title || '(No Title)'} - </a> - <button - onClick={handleToggleStar} - className={`star-btn ${item.starred ? 'is-starred' : 'is-unstarred'}`} - title={item.starred ? 'Unstar' : 'Star'} - > - ★ - </button> - </div> - <div className="dateline"> - <a href={item.url} target="_blank" rel="noopener noreferrer"> - {new Date(item.publish_date).toLocaleDateString()} - {item.feed_title && ` - ${item.feed_title}`} - </a> - <div className="item-actions" style={{ display: 'inline-block', float: 'right' }}> - {!item.full_content && ( - <button onClick={loadFullContent} className="scrape-btn" title="Load Full Content"> - text - </button> - )} - </div> - </div> - {(item.full_content || item.description) && ( - <div - className="item-description" - dangerouslySetInnerHTML={{ __html: item.full_content || item.description }} - /> - )} - </li> - ); -}); - -export default FeedItem; diff --git a/frontend/src/components/FeedItems.css b/frontend/src/components/FeedItems.css deleted file mode 100644 index 7154ac2..0000000 --- a/frontend/src/components/FeedItems.css +++ /dev/null @@ -1,23 +0,0 @@ -.feed-items { - padding: 1rem 0; - /* Removing horizontal padding to avoid double-padding with FeedItem */ -} - -.feed-items h2 { - margin-top: 0; - border-bottom: 2px solid var(--border-color); - padding-bottom: 0.5rem; -} - -.item-list { - list-style: none; - padding: 0; -} - -.loading-more { - padding: 2rem; - text-align: center; - color: #888; - font-size: 0.9rem; - min-height: 50px; -}
\ No newline at end of file diff --git a/frontend/src/components/FeedItems.test.tsx b/frontend/src/components/FeedItems.test.tsx deleted file mode 100644 index 1a002d8..0000000 --- a/frontend/src/components/FeedItems.test.tsx +++ /dev/null @@ -1,250 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, waitFor, fireEvent, act } from '@testing-library/react'; -import { MemoryRouter, Route, Routes } from 'react-router-dom'; -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import FeedItems from './FeedItems'; - -describe('FeedItems Component', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - window.HTMLElement.prototype.scrollIntoView = vi.fn(); - - // Mock IntersectionObserver - class MockIntersectionObserver { - observe = vi.fn(); - unobserve = vi.fn(); - disconnect = vi.fn(); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.IntersectionObserver = MockIntersectionObserver as any; - }); - - it('renders loading state', () => { - vi.mocked(global.fetch).mockImplementation(() => new Promise(() => { })); - render( - <MemoryRouter initialEntries={['/feed/1']}> - <Routes> - <Route path="/feed/:feedId" element={<FeedItems />} /> - </Routes> - </MemoryRouter> - ); - expect(screen.getByText(/loading items/i)).toBeInTheDocument(); - }); - - it('renders items for a feed', async () => { - const mockItems = [ - { - _id: 101, - title: 'Item One', - url: 'http://example.com/1', - publish_date: '2023-01-01', - read: false, - }, - { - _id: 102, - title: 'Item Two', - url: 'http://example.com/2', - publish_date: '2023-01-02', - read: true, - }, - ]; - - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: true, - json: async () => mockItems, - } as Response); - - render( - <MemoryRouter initialEntries={['/feed/1']}> - <Routes> - <Route path="/feed/:feedId" element={<FeedItems />} /> - </Routes> - </MemoryRouter> - ); - - await waitFor(() => { - expect(screen.getByText('Item One')).toBeInTheDocument(); - }); - - const params = new URLSearchParams(); - params.append('feed_id', '1'); - params.append('read_filter', 'unread'); - expect(global.fetch).toHaveBeenCalledWith(`/api/stream?${params.toString()}`, expect.anything()); - }); - - - - afterEach(() => { - vi.useRealTimers(); - vi.restoreAllMocks(); - }); - - it('marks items as read when scrolled past', async () => { - const mockItems = [{ _id: 101, title: 'Item 1', url: 'u1', read: false, starred: false }]; - vi.mocked(global.fetch).mockResolvedValue({ - ok: true, - json: async () => mockItems, - } as Response); - - // Mock getBoundingClientRect - const getBoundingClientRectMock = vi.spyOn(Element.prototype, 'getBoundingClientRect'); - getBoundingClientRectMock.mockImplementation(function (this: Element) { - if (this.classList && this.classList.contains('dashboard-main')) { - return { - top: 0, bottom: 500, height: 500, left: 0, right: 1000, width: 1000, x: 0, y: 0, - toJSON: () => { } - } as DOMRect; - } - if (this.id && this.id.startsWith('item-')) { - // Item top is -50 (above container top 0) - return { - top: -150, bottom: -50, height: 100, left: 0, right: 1000, width: 1000, x: 0, y: 0, - toJSON: () => { } - } as DOMRect; - } - return { - top: 0, bottom: 0, height: 0, left: 0, right: 0, width: 0, x: 0, y: 0, - toJSON: () => { } - } as DOMRect; - }); - - render( - <MemoryRouter> - <div className="dashboard-main"> - <FeedItems /> - </div> - </MemoryRouter> - ); - - // Initial load fetch - await waitFor(() => { - expect(screen.getByText('Item 1')).toBeVisible(); - }); - - // Trigger scroll - const container = document.querySelector('.dashboard-main'); - expect(container).not.toBeNull(); - - act(() => { - // Dispatch scroll event - fireEvent.scroll(container!); - }); - - // Wait for throttle (500ms) + buffer - await new Promise(r => setTimeout(r, 600)); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/item/101', - expect.objectContaining({ - method: 'PUT', - body: JSON.stringify({ read: true, starred: false }), - }) - ); - }); - }); - - it('loads more items when sentinel becomes visible', async () => { - const initialItems = [{ _id: 101, title: 'Item 1', url: 'u1', read: true, starred: false }]; - const moreItems = [{ _id: 100, title: 'Item 0', url: 'u0', read: true, starred: false }]; - - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => initialItems } as Response) - .mockResolvedValueOnce({ ok: true, json: async () => moreItems } as Response); - - const observerCallbacks: IntersectionObserverCallback[] = []; - class MockIntersectionObserver { - constructor(callback: IntersectionObserverCallback) { - observerCallbacks.push(callback); - } - observe = vi.fn(); - unobserve = vi.fn(); - disconnect = vi.fn(); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.IntersectionObserver = MockIntersectionObserver as any; - - render( - <MemoryRouter> - <FeedItems /> - </MemoryRouter> - ); - - await waitFor(() => { - expect(screen.getByText('Item 1')).toBeInTheDocument(); - }); - - const entry = { - isIntersecting: true, - target: { id: 'load-more-sentinel' } as unknown as Element, - boundingClientRect: {} as DOMRectReadOnly, - intersectionRatio: 1, - time: 0, - rootBounds: null, - intersectionRect: {} as DOMRectReadOnly, - } as IntersectionObserverEntry; - - act(() => { - // Trigger all observers - observerCallbacks.forEach(cb => cb([entry], {} as IntersectionObserver)); - }); - - await waitFor(() => { - expect(screen.getByText('Item 0')).toBeInTheDocument(); - const params = new URLSearchParams(); - params.append('max_id', '101'); - params.append('read_filter', 'unread'); - // Verify the second fetch call content - expect(global.fetch).toHaveBeenCalledWith( - expect.stringContaining('max_id=101'), - expect.anything() - ); - }); - }); - - it('loads more items when pressing j on last item', async () => { - const initialItems = [ - { _id: 103, title: 'Item 3', url: 'u3', read: true, starred: false }, - { _id: 102, title: 'Item 2', url: 'u2', read: true, starred: false }, - { _id: 101, title: 'Item 1', url: 'u1', read: true, starred: false }, - ]; - const moreItems = [ - { _id: 100, title: 'Item 0', url: 'u0', read: true, starred: false }, - ]; - - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => initialItems } as Response) - .mockResolvedValueOnce({ ok: true, json: async () => moreItems } as Response); - - render( - <MemoryRouter> - <FeedItems /> - </MemoryRouter> - ); - - await waitFor(() => { - expect(screen.getByText('Item 1')).toBeInTheDocument(); - }); - - fireEvent.keyDown(window, { key: 'j' }); // index 0 - await waitFor(() => expect(document.getElementById('item-0')).toHaveAttribute('data-selected', 'true')); - - fireEvent.keyDown(window, { key: 'j' }); // index 1 - await waitFor(() => expect(document.getElementById('item-1')).toHaveAttribute('data-selected', 'true')); - - fireEvent.keyDown(window, { key: 'j' }); // index 2 (last item) - await waitFor(() => expect(document.getElementById('item-2')).toHaveAttribute('data-selected', 'true')); - - await waitFor(() => { - expect(screen.getByText('Item 0')).toBeInTheDocument(); - }); - - // Check fetch call - expect(global.fetch).toHaveBeenCalledWith( - expect.stringContaining('max_id=101'), - expect.anything() - ); - }); -}); diff --git a/frontend/src/components/FeedItems.tsx b/frontend/src/components/FeedItems.tsx deleted file mode 100644 index e38850a..0000000 --- a/frontend/src/components/FeedItems.tsx +++ /dev/null @@ -1,313 +0,0 @@ -import { useCallback, useEffect, useRef, useState } from 'react'; -import { useParams, useSearchParams } from 'react-router-dom'; -import type { Item } from '../types'; -import FeedItem from './FeedItem'; -import './FeedItems.css'; -import { apiFetch } from '../utils'; - -export default function FeedItems() { - const { feedId, tagName } = useParams<{ feedId: string; tagName: string }>(); - const [searchParams] = useSearchParams(); - const filterFn = searchParams.get('filter') || 'unread'; - - const [items, setItems] = useState<Item[]>([]); - const itemsRef = useRef<Item[]>([]); - const [loading, setLoading] = useState(true); - const [loadingMore, setLoadingMore] = useState(false); - const loadingMoreRef = useRef(loadingMore); - const [hasMore, setHasMore] = useState(true); - const hasMoreRef = useRef(hasMore); - const [error, setError] = useState(''); - const [selectedIndex, setSelectedIndex] = useState(-1); - const selectedIndexRef = useRef(selectedIndex); - - // Sync refs - useEffect(() => { - itemsRef.current = items; - }, [items]); - - useEffect(() => { - loadingMoreRef.current = loadingMore; - }, [loadingMore]); - - useEffect(() => { - hasMoreRef.current = hasMore; - }, [hasMore]); - - useEffect(() => { - selectedIndexRef.current = selectedIndex; - }, [selectedIndex]); - - const fetchItems = useCallback((maxId?: string) => { - if (maxId) { - setLoadingMore(true); - } else { - setLoading(true); - setItems([]); - } - setError(''); - - let url = '/api/stream'; - const params = new URLSearchParams(); - - if (feedId) { - if (feedId.includes(',')) { - params.append('feed_ids', feedId); - } else { - params.append('feed_id', feedId); - } - } else if (tagName) { - params.append('tag', tagName); - } - - if (maxId) { - params.append('max_id', maxId); - } - - // Apply filters - const searchQuery = searchParams.get('q'); - if (searchQuery) { - params.append('q', searchQuery); - } - - if (filterFn === 'all') { - params.append('read_filter', 'all'); - } else if (filterFn === 'starred') { - params.append('starred', 'true'); - params.append('read_filter', 'all'); - } else { - // default to unread - if (!searchQuery) { - params.append('read_filter', 'unread'); - } - } - - const queryString = params.toString(); - if (queryString) { - url += `?${queryString}`; - } - - apiFetch(url) - .then((res) => { - if (!res.ok) { - throw new Error('Failed to fetch items'); - } - return res.json(); - }) - .then((data: Item[]) => { - if (maxId) { - setItems((prev) => { - const existingIds = new Set(prev.map(i => i._id)); - const newItems = data.filter(i => !existingIds.has(i._id)); - return [...prev, ...newItems]; - }); - } else { - setItems(data); - } - setHasMore(data.length > 0); - setLoading(false); - setLoadingMore(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - setLoadingMore(false); - }); - }, [feedId, tagName, filterFn, searchParams]); - - useEffect(() => { - fetchItems(); - setSelectedIndex(-1); - }, [fetchItems]); - - - const scrollToItem = useCallback((index: number) => { - const element = document.getElementById(`item-${index}`); - if (element) { - element.scrollIntoView({ behavior: 'auto', block: 'start' }); - } - }, []); - - const markAsRead = useCallback((item: Item) => { - const updatedItem = { ...item, read: true }; - setItems((prevItems) => prevItems.map((i) => (i._id === item._id ? updatedItem : i))); - - apiFetch(`/api/item/${item._id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ read: true, starred: item.starred }), - }).catch((err) => console.error('Failed to mark read', err)); - }, []); - - const toggleStar = useCallback((item: Item) => { - const updatedItem = { ...item, starred: !item.starred }; - setItems((prevItems) => prevItems.map((i) => (i._id === item._id ? updatedItem : i))); - - apiFetch(`/api/item/${item._id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ read: item.read, starred: !item.starred }), - }).catch((err) => console.error('Failed to toggle star', err)); - }, []); - - const handleUpdateItem = useCallback((updatedItem: Item) => { - setItems((prevItems) => prevItems.map((i) => (i._id === updatedItem._id ? updatedItem : i))); - }, []); - - - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - const currentItems = itemsRef.current; - if (currentItems.length === 0) return; - - if (e.key === 'j') { - const nextIndex = Math.min(selectedIndexRef.current + 1, currentItems.length - 1); - if (nextIndex !== selectedIndexRef.current) { - selectedIndexRef.current = nextIndex; - setSelectedIndex(nextIndex); - const item = currentItems[nextIndex]; - if (!item.read) { - markAsRead(item); - } - scrollToItem(nextIndex); - - // Trigger load more if needed - if (nextIndex === currentItems.length - 1 && hasMoreRef.current && !loadingMoreRef.current) { - fetchItems(String(currentItems[currentItems.length - 1]._id)); - } - } else if (hasMoreRef.current && !loadingMoreRef.current) { - // Already at last item, but more can be loaded - fetchItems(String(currentItems[currentItems.length - 1]._id)); - } - } else if (e.key === 'k') { - const nextIndex = Math.max(selectedIndexRef.current - 1, 0); - if (nextIndex !== selectedIndexRef.current) { - selectedIndexRef.current = nextIndex; - setSelectedIndex(nextIndex); - scrollToItem(nextIndex); - } - } else if (e.key === 's') { - if (selectedIndexRef.current >= 0 && selectedIndexRef.current < currentItems.length) { - toggleStar(currentItems[selectedIndexRef.current]); - } - } - }; - - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, [markAsRead, scrollToItem, toggleStar, fetchItems]); - - - // Scroll listener to mark items as read - const sentinelObserverRef = useRef<IntersectionObserver | null>(null); - - const checkReadStatus = useCallback(() => { - const container = document.querySelector('.dashboard-main'); - if (!container) return; - - const containerRect = container.getBoundingClientRect(); - const currentItems = itemsRef.current; - - currentItems.forEach((item, index) => { - if (item.read) return; - - const el = document.getElementById(`item-${index}`); - if (!el) return; - - const rect = el.getBoundingClientRect(); - - // Mark as read if the bottom of the item is above the top of the container - if (rect.bottom < containerRect.top) { - markAsRead(item); - } - }); - }, [markAsRead]); - - // Setup scroll listener - useEffect(() => { - const container = document.querySelector('.dashboard-main'); - if (!container) return; - - let timeoutId: number | null = null; - const onScroll = () => { - if (timeoutId === null) { - timeoutId = window.setTimeout(() => { - checkReadStatus(); - timeoutId = null; - }, 250); - } - }; - - container.addEventListener('scroll', onScroll); - - // Initial check - checkReadStatus(); - - return () => { - if (timeoutId) clearTimeout(timeoutId); - container.removeEventListener('scroll', onScroll); - }; - }, [checkReadStatus]); - - // Re-check when items change (e.g. initial load or load more) - useEffect(() => { - checkReadStatus(); - }, [items, checkReadStatus]); - - - - useEffect(() => { - if (sentinelObserverRef.current) sentinelObserverRef.current.disconnect(); - - sentinelObserverRef.current = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting && !loadingMoreRef.current && hasMoreRef.current && itemsRef.current.length > 0) { - fetchItems(String(itemsRef.current[itemsRef.current.length - 1]._id)); - } - }); - }, - { root: null, threshold: 0, rootMargin: '100px' } - ); - - const sentinel = document.getElementById('load-more-sentinel'); - if (sentinel) sentinelObserverRef.current.observe(sentinel); - - return () => sentinelObserverRef.current?.disconnect(); - }, [hasMore, fetchItems]); // removed loadingMore from deps, using ref inside. hasMore is needed for DOM presence. - - - if (loading) return <div className="feed-items-loading">Loading items...</div>; - if (error) return <div className="feed-items-error">Error: {error}</div>; - - return ( - <div className="feed-items"> - {items.length === 0 ? ( - <p>No items found.</p> - ) : ( - <ul className="item-list"> - {items.map((item, index) => ( - <div - id={`item-${index}`} - key={item._id} - data-index={index} - data-selected={index === selectedIndex} - onClick={() => setSelectedIndex(index)} - > - <FeedItem - item={item} - onToggleStar={() => toggleStar(item)} - onUpdate={handleUpdateItem} - /> - </div> - ))} - {hasMore && ( - <li id="load-more-sentinel" className="loading-more"> - {loadingMore ? 'Loading more...' : ''} - </li> - )} - </ul> - )} - </div> - ); -} diff --git a/frontend/src/components/FeedList.css b/frontend/src/components/FeedList.css deleted file mode 100644 index 38a324b..0000000 --- a/frontend/src/components/FeedList.css +++ /dev/null @@ -1,225 +0,0 @@ -.feed-list { - padding: 1rem; - font-family: var(--font-heading); - color: #777; - /* specific v1 color */ - font-size: 0.8rem; - background: var(--sidebar-bg); - min-height: 100%; - flex: 1; -} - -.feed-list h1.logo { - font-size: 2rem; - /* match v1 */ - margin: 0 0 1rem 0; - line-height: 1; - cursor: pointer; - position: sticky; - top: 0; - background: var(--sidebar-bg); - z-index: 10; - padding-bottom: 0.5rem; - color: var(--text-color); -} - -/* Override logo color if necessary for themes */ -.theme-light .feed-list h1.logo { - color: #333; -} - -.theme-dark .feed-list h1.logo { - color: #eee; -} - -.search-section { - margin-bottom: 1rem; -} - -.search-input { - width: 100%; - padding: 0.25rem; - border: 1px solid var(--border-color, #999); - background: var(--bg-color); - color: var(--text-color); - font-size: 0.8rem; - font-family: inherit; - border-radius: 0; - /* v1 didn't have rounded inputs usually */ -} - -.section-header { - font-size: 1rem; - /* v1 h4 size? */ - font-weight: bold; - margin: 1rem 0 0.25rem 0; - cursor: pointer; - user-select: none; - font-family: var(--font-heading); - color: #333; - /* Darker than list items */ - text-transform: lowercase; - font-variant: small-caps; - display: flex; - align-items: center; - gap: 0.5rem; -} - -.caret { - display: inline-block; - font-size: 0.6rem; - transition: transform 0.2s ease; - color: #777; -} - -.caret.expanded { - transform: rotate(90deg); -} - -.filter-list, -.tag-list-items, -.feed-list-items, -.nav-list { - list-style: none; - padding: 0; - margin: 0; -} - -.filter-list li, -.nav-list li { - margin-bottom: 0.1rem; -} - -.filter-list a, -.nav-list a, -.tag-link, -.feed-title, -.logout-link { - text-decoration: none; - color: var(--link-color, blue); - font-size: 0.8rem; - /* Matches v1 .75em approx */ - display: block; - cursor: pointer; - background: none; - border: none; - padding: 0; - font-family: inherit; - font-variant: small-caps; - text-transform: lowercase; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.filter-list a:hover, -.nav-list a:hover, -.tag-link:hover, -.feed-title:hover, -.logout-link:hover { - text-decoration: underline; - color: var(--link-color, blue); -} - -.filter-list a.active, -.tag-link.active, -.feed-title.active { - font-weight: bold; - color: #000; - /* Active state black */ -} - -.tag-item, -.sidebar-feed-item { - margin-bottom: 0; -} - -.feed-item-row { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.feed-checkbox { - cursor: pointer; - margin: 0; -} - -.feed-category { - display: none; -} - -.nav-section { - margin-top: 2rem; - border-top: 1px solid var(--border-color, #eee); - padding-top: 1rem; -} - -.logout-link { - text-align: left; - width: 100%; - color: #777; - display: block; -} - -.nav-link, -.logout-link { - padding: 0.25rem 0; -} - -.logout-link:hover { - color: var(--link-color, blue); - text-decoration: underline; -} - -.theme-section { - margin-top: 1rem; -} - -.theme-selector { - display: flex; - gap: 0.5rem; - margin-top: 0.5rem; -} - -.theme-selector button { - background: rgba(0, 0, 0, 0.05); - border: none; - cursor: pointer; - padding: 0.4rem; - font-size: 1rem; - border-radius: 8px; - line-height: 1; - transition: all 0.2s ease; - display: flex; - align-items: center; - justify-content: center; -} - -.theme-selector button:hover { - background: rgba(0, 0, 0, 0.1); - transform: translateY(-2px); -} - -.theme-selector button.active { - background: var(--border-color, #999); - color: white; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); -} - -.theme-dark .theme-selector button { - background: rgba(255, 255, 255, 0.1); -} - -.theme-dark .theme-selector button:hover { - background: rgba(255, 255, 255, 0.2); -} - -/* Scrollbar styling for webkit */ -.dashboard-sidebar::-webkit-scrollbar { - width: 4px; -} - -.dashboard-sidebar::-webkit-scrollbar-thumb { - background-color: var(--border-color, #999); -}
\ No newline at end of file diff --git a/frontend/src/components/FeedList.test.tsx b/frontend/src/components/FeedList.test.tsx deleted file mode 100644 index d4e72cc..0000000 --- a/frontend/src/components/FeedList.test.tsx +++ /dev/null @@ -1,230 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, waitFor, fireEvent } from '@testing-library/react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import FeedList from './FeedList'; - -import { BrowserRouter } from 'react-router-dom'; - -describe('FeedList Component', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - }); - - it('renders loading state initially', () => { - vi.mocked(global.fetch).mockImplementation(() => new Promise(() => { })); - render( - <BrowserRouter> - <FeedList - theme="light" - setTheme={() => { }} - setSidebarVisible={() => { }} - isMobile={false} - /> - </BrowserRouter> - ); - expect(screen.getByText(/loading feeds/i)).toBeInTheDocument(); - }); - - it('renders list of feeds', async () => { - const mockFeeds = [ - { - _id: 1, - title: 'Feed One', - url: 'http://example.com/rss', - web_url: 'http://example.com', - category: 'Tech', - }, - { - _id: 2, - title: 'Feed Two', - url: 'http://test.com/rss', - web_url: 'http://test.com', - category: 'News', - }, - ]; - - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/feed/')) { - return Promise.resolve({ - ok: true, - json: async () => mockFeeds, - } as Response); - } - if (urlStr.includes('/api/tag')) { - return Promise.resolve({ - ok: true, - json: async () => [{ title: 'Tech' }], - } as Response); - } - return Promise.reject(new Error(`Unknown URL: ${url}`)); - }); - - render( - <BrowserRouter> - <FeedList - theme="light" - setTheme={() => { }} - setSidebarVisible={() => { }} - isMobile={false} - /> - </BrowserRouter> - ); - - await waitFor(() => { - expect(screen.queryByText(/loading feeds/i)).not.toBeInTheDocument(); - }); - - // Expand feeds - fireEvent.click(screen.getByText(/feeds/i, { selector: 'h4' })); - - await waitFor(() => { - expect(screen.getByText('Feed One')).toBeInTheDocument(); - expect(screen.getByText('Feed Two')).toBeInTheDocument(); - const techElements = screen.getAllByText('Tech'); - expect(techElements.length).toBeGreaterThan(0); - }); - }); - - it('handles fetch error', async () => { - vi.mocked(global.fetch).mockImplementation(() => Promise.reject(new Error('API Error'))); - - render( - <BrowserRouter> - <FeedList - theme="light" - setTheme={() => { }} - setSidebarVisible={() => { }} - isMobile={false} - /> - </BrowserRouter> - ); - - await waitFor(() => { - expect(screen.getByText(/error: api error/i)).toBeInTheDocument(); - }); - }); - - it('handles empty feed list', async () => { - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/feed/')) { - return Promise.resolve({ - ok: true, - json: async () => [], - } as Response); - } - if (urlStr.includes('/api/tag')) { - return Promise.resolve({ - ok: true, - json: async () => [], - } as Response); - } - return Promise.reject(new Error(`Unknown URL: ${url}`)); - }); - - render( - <BrowserRouter> - <FeedList - theme="light" - setTheme={() => { }} - setSidebarVisible={() => { }} - isMobile={false} - /> - </BrowserRouter> - ); - - await waitFor(() => { - expect(screen.queryByText(/loading feeds/i)).not.toBeInTheDocument(); - }); - - // Expand feeds - fireEvent.click(screen.getByText(/feeds/i, { selector: 'h4' })); - - await waitFor(() => { - expect(screen.getByText(/no feeds found/i)).toBeInTheDocument(); - }); - }); - - it('handles search submission', async () => { - vi.mocked(global.fetch).mockResolvedValue({ ok: true, json: async () => [] } as Response); - render( - <BrowserRouter> - <FeedList theme="light" setTheme={() => { }} setSidebarVisible={() => { }} isMobile={false} /> - </BrowserRouter> - ); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText(/loading feeds/i)).not.toBeInTheDocument(); - }); - - const searchInput = screen.getByPlaceholderText(/search\.\.\./i); - fireEvent.change(searchInput, { target: { value: 'test search' } }); - fireEvent.submit(searchInput.closest('form')!); - - // Should navigate to include search query - // Since we're using BrowserRouter in test, we can only check if it doesn't crash - // but we can't easily check 'navigate' unless we mock it. - }); - - it('handles logout', async () => { - vi.mocked(global.fetch).mockResolvedValue({ ok: true, json: async () => [] } as Response); - - // Mock window.location - const originalLocation = window.location; - const locationMock = new URL('http://localhost/v2/'); - - delete (window as { location?: Location }).location; - (window as { location?: unknown }).location = { - ...originalLocation, - assign: vi.fn(), - replace: vi.fn(), - get href() { return locationMock.href; }, - set href(val: string) { locationMock.href = new URL(val, locationMock.origin).href; } - }; - - render( - <BrowserRouter> - <FeedList theme="light" setTheme={() => { }} setSidebarVisible={() => { }} isMobile={false} /> - </BrowserRouter> - ); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText(/loading feeds/i)).not.toBeInTheDocument(); - }); - - const logoutBtn = screen.getByText(/logout/i); - fireEvent.click(logoutBtn); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith('/api/logout', expect.any(Object)); - expect(window.location.href).toContain('/v2/#/login'); - }); - // @ts-expect-error - restoring window.location - window.location = originalLocation; - }); - - it('closes sidebar on mobile link click', async () => { - vi.mocked(global.fetch).mockResolvedValue({ ok: true, json: async () => [] } as Response); - const setSidebarVisible = vi.fn(); - render( - <BrowserRouter> - <FeedList theme="light" setTheme={() => { }} setSidebarVisible={setSidebarVisible} isMobile={true} /> - </BrowserRouter> - ); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText(/loading feeds/i)).not.toBeInTheDocument(); - }); - - const unreadLink = screen.getByText(/unread/i); - fireEvent.click(unreadLink); - - expect(setSidebarVisible).toHaveBeenCalledWith(false); - }); -}); diff --git a/frontend/src/components/FeedList.tsx b/frontend/src/components/FeedList.tsx deleted file mode 100644 index ce83333..0000000 --- a/frontend/src/components/FeedList.tsx +++ /dev/null @@ -1,279 +0,0 @@ -import { useEffect, useState } from 'react'; -import { Link, useNavigate, useSearchParams, useLocation, useMatch } from 'react-router-dom'; -import type { Feed, Category } from '../types'; -import './FeedList.css'; -import './FeedListVariants.css'; -import { apiFetch } from '../utils'; - -export default function FeedList({ - theme, - setTheme, - setSidebarVisible, - isMobile, -}: { - theme: string; - setTheme: (t: string) => void; - setSidebarVisible: (visible: boolean) => void; - isMobile: boolean; -}) { - const [feeds, setFeeds] = useState<Feed[]>([]); - const [tags, setTags] = useState<Category[]>([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); - const [feedsExpanded, setFeedsExpanded] = useState(false); - const [tagsExpanded, setTagsExpanded] = useState(true); - const [searchQuery, setSearchQuery] = useState(''); - const navigate = useNavigate(); - const [searchParams] = useSearchParams(); - const location = useLocation(); - const feedMatch = useMatch('/feed/:feedId'); - const tagMatch = useMatch('/tag/:tagName'); - const isRoot = useMatch('/'); - const isStreamPage = !!(isRoot || feedMatch || tagMatch); - - const feedId = feedMatch?.params.feedId; - const tagName = tagMatch?.params.tagName; - - const sidebarVariant = searchParams.get('sidebar') || localStorage.getItem('neko-sidebar-variant') || 'glass'; - - useEffect(() => { - const variant = searchParams.get('sidebar'); - if (variant) { - localStorage.setItem('neko-sidebar-variant', variant); - } - }, [searchParams]); - - const currentFilter = searchParams.get('filter') || (isStreamPage ? 'unread' : ''); - - const getFilterLink = (filter: string) => { - const baseStreamPath = isStreamPage ? location.pathname : '/'; - const params = new URLSearchParams(searchParams); - params.set('filter', filter); - return `${baseStreamPath}?${params.toString()}`; - }; - - const getNavPath = (path: string) => { - const params = new URLSearchParams(searchParams); - if (!params.has('filter') && currentFilter) { - params.set('filter', currentFilter); - } - const qs = params.toString(); - return `${path}${qs ? '?' + qs : ''}`; - }; - - const handleSearch = (e: React.FormEvent) => { - e.preventDefault(); - if (searchQuery.trim()) { - const params = new URLSearchParams(searchParams); - params.set('q', searchQuery.trim()); - if (currentFilter) params.set('filter', currentFilter); - navigate(`/?${params.toString()}`); - } - }; - - const toggleFeeds = () => { - setFeedsExpanded(!feedsExpanded); - }; - - const toggleTags = () => { - setTagsExpanded(!tagsExpanded); - }; - - const handleLinkClick = () => { - if (isMobile) { - setSidebarVisible(false); - } - }; - - useEffect(() => { - Promise.all([ - apiFetch('/api/feed/').then((res) => { - if (!res.ok) throw new Error('Failed to fetch feeds'); - return res.json() as Promise<Feed[]>; - }), - apiFetch('/api/tag').then((res) => { - if (!res.ok) throw new Error('Failed to fetch tags'); - return res.json() as Promise<Category[]>; - }), - ]) - .then(([feedsData, tagsData]) => { - setFeeds(feedsData); - setTags(tagsData); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }, []); - - if (loading) return <div className="feed-list-loading">Loading feeds...</div>; - if (error) return <div className="feed-list-error">Error: {error}</div>; - - const handleLogout = () => { - apiFetch('/api/logout', { method: 'POST' }).then(() => (window.location.href = '/v2/#/login')); - }; - - return ( - <div className={`feed-list variant-${sidebarVariant}`}> - <h1 className="logo" onClick={() => setSidebarVisible(false)}> - 🐱 - </h1> - - <div className="search-section"> - <form onSubmit={handleSearch} className="search-form"> - <input - type="search" - placeholder="search..." - value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - className="search-input" - /> - </form> - </div> - - <div className="filter-section"> - <ul className="filter-list"> - <li className="unread_filter"> - <Link - to={getFilterLink('unread')} - className={currentFilter === 'unread' ? 'active' : ''} - onClick={handleLinkClick} - > - unread - </Link> - </li> - <li className="all_filter"> - <Link - to={getFilterLink('all')} - className={currentFilter === 'all' ? 'active' : ''} - onClick={handleLinkClick} - > - all - </Link> - </li> - <li className="starred_filter"> - <Link - to={getFilterLink('starred')} - className={currentFilter === 'starred' ? 'active' : ''} - onClick={handleLinkClick} - > - starred - </Link> - </li> - </ul> - </div> - - <div className="tag-section"> - <h4 onClick={toggleTags} className="section-header"> - <span className={`caret ${tagsExpanded ? 'expanded' : ''}`}>▶</span> Tags - </h4> - {tagsExpanded && ( - <ul className="tag-list-items"> - {tags.map((tag) => ( - <li key={tag.title} className="tag-item"> - <Link - to={getNavPath(`/tag/${encodeURIComponent(tag.title)}`)} - className={`tag-link ${tagName === tag.title ? 'active' : ''}`} - onClick={handleLinkClick} - > - {tag.title} - </Link> - </li> - ))} - </ul> - )} - </div> - - <div className="feed-section"> - <h4 onClick={toggleFeeds} className="section-header"> - <span className={`caret ${feedsExpanded ? 'expanded' : ''}`}>▶</span> Feeds - </h4> - {feedsExpanded && - (feeds.length === 0 ? ( - <p>No feeds found.</p> - ) : ( - <ul className="feed-list-items"> - {feeds.map((feed) => { - const isSelected = feedId?.split(',').includes(String(feed._id)); - - const toggleFeed = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - - const selectedIds = feedId ? feedId.split(',') : []; - let newIds; - if (isSelected) { - newIds = selectedIds.filter(id => id !== String(feed._id)); - } else { - newIds = [...selectedIds, String(feed._id)]; - } - - if (newIds.length === 0) { - navigate(getNavPath('/')); - } else { - navigate(getNavPath(`/feed/${newIds.join(',')}`)); - } - }; - - return ( - <li key={feed._id} className="sidebar-feed-item"> - <div className="feed-item-row"> - <input - type="checkbox" - checked={!!isSelected} - onChange={() => { }} // Controlled by div click for better hit area - onClick={toggleFeed} - className="feed-checkbox" - /> - <Link - to={getNavPath(`/feed/${feed._id}`)} - className={`feed-title ${isSelected ? 'active' : ''}`} - onClick={handleLinkClick} - > - {feed.title || feed.url} - </Link> - </div> - </li> - ); - })} - </ul> - ))} - </div> - - <div className="nav-section"> - <ul className="nav-list"> - <li> - <Link to="/settings" className="nav-link" onClick={handleLinkClick}> - settings - </Link> - </li> - <li> - <button onClick={handleLogout} className="logout-link"> - logout - </button> - </li> - </ul> - </div> - - <div className="theme-section"> - <div className="theme-selector"> - <button - onClick={() => setTheme('light')} - className={theme === 'light' ? 'active' : ''} - title="Light Theme" - > - ☀️ - </button> - <button - onClick={() => setTheme('dark')} - className={theme === 'dark' ? 'active' : ''} - title="Dark Theme" - > - 🌙 - </button> - </div> - </div> - </div> - ); -} diff --git a/frontend/src/components/FeedListVariants.css b/frontend/src/components/FeedListVariants.css deleted file mode 100644 index e97ea95..0000000 --- a/frontend/src/components/FeedListVariants.css +++ /dev/null @@ -1,342 +0,0 @@ -/* Glass Variant */ -.feed-list.variant-glass { - background: rgba(255, 255, 255, 0.05); - /* Very subtle tint */ - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-right: 1px solid rgba(255, 255, 255, 0.1); - padding: 1.5rem; - font-family: system-ui, -apple-system, sans-serif; - /* Modern sans */ - color: var(--text-color); -} - -.feed-list.variant-glass .logo { - font-size: 1.5rem; - background: transparent !important; - /* Override sticky bg */ - margin-bottom: 2rem; - opacity: 0.8; -} - -.feed-list.variant-glass .section-header { - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 0.1em; - color: var(--text-color); - opacity: 0.5; - margin-top: 2rem; - font-weight: 600; -} - -.feed-list.variant-glass a, -.feed-list.variant-glass .feed-title, -.feed-list.variant-glass .tag-link { - padding: 0.4rem 0.8rem; - margin: 0.2rem 0; - border-radius: 8px; - transition: all 0.2s ease; - font-weight: 500; - text-decoration: none !important; - /* No underlines in glass */ - color: var(--text-color); - opacity: 0.8; - border: none; - /* No default borders */ -} - -.feed-list.variant-glass a:hover, -.feed-list.variant-glass .feed-title:hover, -.feed-list.variant-glass .tag-link:hover { - background: rgba(255, 255, 255, 0.1); - opacity: 1; - transform: translateX(4px); - color: var(--text-color); -} - -.feed-list.variant-glass a.active, -.feed-list.variant-glass .feed-title.active, -.feed-list.variant-glass .tag-link.active { - background: rgba(255, 255, 255, 0.25); - color: var(--text-color); - font-weight: 700; - opacity: 1; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - border: 1px solid rgba(255, 255, 255, 0.2); -} - -.feed-list.variant-glass .search-input { - border-radius: 20px; - background: rgba(0, 0, 0, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - color: var(--text-color); - padding: 0.5rem 1rem; -} - -.feed-list.variant-glass .nav-section { - border-top: 1px solid rgba(255, 255, 255, 0.1); - margin-top: 2rem; - padding-top: 1.5rem; -} - -.feed-list.variant-glass .nav-link, -.feed-list.variant-glass .logout-link { - opacity: 0.6; - padding: 0.5rem 0.8rem; - border-radius: 8px; -} - -.feed-list.variant-glass .nav-link:hover, -.feed-list.variant-glass .logout-link:hover { - background: rgba(255, 255, 255, 0.05); - opacity: 1; - text-decoration: none; -} - -.feed-list.variant-glass .theme-selector button { - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 12px; -} - -.feed-list.variant-glass .theme-selector button.active { - background: rgba(255, 255, 255, 0.2); - border-color: rgba(255, 255, 255, 0.3); -} - - -/* Nano Banana Variant (Playful/Pop) */ -.feed-list.variant-banana { - background: #fdfdfd; - padding: 1rem; - font-family: 'Poppins', 'Verdana', sans-serif; - border-right: none; - box-shadow: 4px 0 24px rgba(0, 0, 0, 0.04); -} - -.theme-dark .feed-list.variant-banana { - background: #111; -} - -.feed-list.variant-banana .logo { - font-size: 2.5rem; - text-shadow: 2px 2px 0px #FFD700; - /* Banana yellow shadow */ - background: transparent; - transform: rotate(-3deg); - display: inline-block; - margin-bottom: 2rem; -} - -.feed-list.variant-banana .section-header { - background: #FFD700; - color: #000; - display: inline-block; - padding: 0.2rem 0.5rem; - transform: skew(-10deg); - font-size: 0.8rem; - font-weight: 800; - margin-bottom: 1rem; - border-radius: 4px; -} - -.feed-list.variant-banana .search-input { - border: 2px solid #000; - border-radius: 8px; - box-shadow: 2px 2px 0px #000; - transition: all 0.2s; -} - -.feed-list.variant-banana .search-input:focus { - transform: translate(1px, 1px); - box-shadow: 1px 1px 0px #000; - outline: none; -} - -.theme-dark .feed-list.variant-banana .search-input { - border-color: #fff; - box-shadow: 2px 2px 0px #fff; - background: #222; - color: #fff; -} - -.feed-list.variant-banana a, -.feed-list.variant-banana .feed-title, -.feed-list.variant-banana .tag-link { - border: 1px solid transparent; - padding: 0.5rem; - border-radius: 8px; - transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); - font-weight: 600; - text-decoration: none !important; - color: var(--text-color); -} - -.feed-list.variant-banana a:hover, -.feed-list.variant-banana .feed-title:hover, -.feed-list.variant-banana .tag-link:hover { - transform: scale(1.05) rotate(1deg); - background: #fff9c4; - /* Light yellow */ - color: #000; - box-shadow: 0 4px 12px rgba(255, 215, 0, 0.3); -} - -.theme-dark .feed-list.variant-banana a:hover, -.theme-dark .feed-list.variant-banana .feed-title:hover, -.theme-dark .feed-list.variant-banana .tag-link:hover { - background: #333; - color: #FFD700; -} - - -.feed-list.variant-banana a.active, -.feed-list.variant-banana .feed-title.active, -.feed-list.variant-banana .tag-link.active { - background: #FFD700; - color: #000 !important; - transform: scale(1.02); - box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.1); - border: 2px solid #000; -} - -.feed-list.variant-banana .nav-section { - border-top: 2px dashed #FFD700; - margin-top: 2rem; - padding-top: 1rem; -} - -.feed-list.variant-banana .theme-selector button { - border: 2px solid #000; - box-shadow: 2px 2px 0px #000; - border-radius: 4px; -} - -.feed-list.variant-banana .theme-selector button.active { - background: #FFD700; - transform: translate(1px, 1px); - box-shadow: 1px 1px 0px #000; -} - - -/* Type Variant (Swiss/Bold) */ -.feed-list.variant-type { - background: var(--bg-color); - padding: 2rem 1rem; - font-family: 'Helvetica Neue', 'Arial', sans-serif; - border-right: 4px solid var(--text-color); -} - -.feed-list.variant-type .logo { - font-size: 3rem; - letter-spacing: -2px; - font-weight: 900; - background: transparent; - line-height: 0.8; - margin-bottom: 3rem; - color: var(--text-color); -} - -.feed-list.variant-type .section-header { - font-size: 1.2rem; - font-weight: 900; - border-bottom: 2px solid var(--text-color); - padding-bottom: 0.5rem; - margin-top: 3rem; - margin-bottom: 1rem; - letter-spacing: -0.5px; - color: var(--text-color); -} - -.feed-list.variant-type a, -.feed-list.variant-type .feed-title, -.feed-list.variant-type .tag-link { - font-size: 1rem; - font-weight: 700; - text-decoration: none !important; - border-left: 0px solid var(--text-color); - padding-left: 0; - transition: padding-left 0.2s, border-left-width 0.2s; - opacity: 0.6; - color: var(--text-color); - padding: 0.5rem 0; - display: block; -} - -.feed-list.variant-type a:hover, -.feed-list.variant-type .feed-title:hover, -.feed-list.variant-type .tag-link:hover { - padding-left: 1rem; - border-left: 4px solid var(--text-color); - opacity: 1; - color: var(--text-color); -} - -.feed-list.variant-type a.active, -.feed-list.variant-type .feed-title.active, -.feed-list.variant-type .tag-link.active { - padding-left: 1rem; - border-left: 8px solid var(--text-color); - opacity: 1; - color: var(--text-color); -} - -.feed-list.variant-type .search-input { - border: none; - border-bottom: 2px solid var(--text-color); - background: transparent; - border-radius: 0; - padding: 1rem 0; - font-weight: bold; - font-size: 1.2rem; -} - -.feed-list.variant-type .search-input:focus { - outline: none; - border-bottom-width: 4px; -} -.feed-list.variant-type .nav-section { - border-top: 4px solid var(--text-color); - margin-top: 4rem; - padding-top: 1rem; -} - -.feed-list.variant-type .nav-link, -.feed-list.variant-type .logout-link { - font-size: 1.2rem; - font-weight: 900; -} - -.feed-list.variant-type .theme-selector button { - border-radius: 0; - border: 2px solid var(--text-color); - background: transparent; -} - -.feed-list.variant-type .theme-selector button.active { - background: var(--text-color); - color: var(--bg-color); -} - -.feed-list.variant-type .nav-section { - border-top: 4px solid var(--text-color); - margin-top: 4rem; - padding-top: 1rem; -} - -.feed-list.variant-type .nav-link, -.feed-list.variant-type .logout-link { - font-size: 1.2rem; - font-weight: 900; -} - -.feed-list.variant-type .theme-selector button { - border-radius: 0; - border: 2px solid var(--text-color); - background: transparent; -} - -.feed-list.variant-type .theme-selector button.active { - background: var(--text-color); - color: var(--bg-color); -} diff --git a/frontend/src/components/Login.css b/frontend/src/components/Login.css deleted file mode 100644 index 6f40731..0000000 --- a/frontend/src/components/Login.css +++ /dev/null @@ -1,63 +0,0 @@ -.login-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - background-color: #f5f5f5; -} - -.login-form { - background: white; - padding: 2rem; - border-radius: 8px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - width: 100%; - max-width: 400px; -} - -.login-form h1 { - margin-bottom: 2rem; - text-align: center; - color: #333; -} - -.form-group { - margin-bottom: 1.5rem; -} - -.form-group label { - display: block; - margin-bottom: 0.5rem; - font-weight: bold; - color: #555; -} - -.form-group input { - width: 100%; - padding: 0.75rem; - border: 1px solid #ddd; - border-radius: 4px; - font-size: 1rem; -} - -.error-message { - color: #dc3545; - margin-bottom: 1rem; - text-align: center; -} - -button[type='submit'] { - width: 100%; - padding: 0.75rem; - background-color: #007bff; - color: white; - border: none; - border-radius: 4px; - font-size: 1rem; - cursor: pointer; - transition: background-color 0.2s; -} - -button[type='submit']:hover { - background-color: #0056b3; -} diff --git a/frontend/src/components/Login.test.tsx b/frontend/src/components/Login.test.tsx deleted file mode 100644 index 47f37e3..0000000 --- a/frontend/src/components/Login.test.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { BrowserRouter } from 'react-router-dom'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import Login from './Login'; - -// Mock fetch -global.fetch = vi.fn(); - -const renderLogin = () => { - render( - <BrowserRouter> - <Login /> - </BrowserRouter> - ); -}; - -describe('Login Component', () => { - beforeEach(() => { - vi.resetAllMocks(); - }); - - it('renders login form', () => { - renderLogin(); - expect(screen.getByLabelText(/username/i)).toBeInTheDocument(); - expect(screen.getByLabelText(/password/i)).toBeInTheDocument(); - expect(screen.getByRole('button', { name: /login/i })).toBeInTheDocument(); - }); - - it('handles successful login', async () => { - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: true, - } as Response); - - renderLogin(); - - fireEvent.change(screen.getByLabelText(/username/i), { target: { value: 'testuser' } }); - fireEvent.change(screen.getByLabelText(/password/i), { target: { value: 'secret' } }); - fireEvent.click(screen.getByRole('button', { name: /login/i })); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/login', - expect.objectContaining({ - method: 'POST', - body: expect.any(URLSearchParams), - }) - ); - }); - - // Check if params contained username and password - const callArgs = vi.mocked(global.fetch).mock.calls[0][1]; - const body = callArgs?.body as URLSearchParams; - expect(body.get('username')).toBe('testuser'); - expect(body.get('password')).toBe('secret'); - - // Navigation assertion is tricky without mocking useNavigate, - // but if no error is shown, we assume success path was taken - expect(screen.queryByText(/login failed/i)).not.toBeInTheDocument(); - }); - - it('handles failed login', async () => { - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: false, - json: async () => ({ message: 'Bad credentials' }), - } as Response); - - renderLogin(); - - fireEvent.change(screen.getByLabelText(/username/i), { target: { value: 'testuser' } }); - fireEvent.change(screen.getByLabelText(/password/i), { target: { value: 'wrong' } }); - fireEvent.click(screen.getByRole('button', { name: /login/i })); - - await waitFor(() => { - expect(screen.getByText(/bad credentials/i)).toBeInTheDocument(); - }); - }); - - it('handles network error', async () => { - vi.mocked(global.fetch).mockRejectedValueOnce(new Error('Network error')); - - renderLogin(); - - fireEvent.change(screen.getByLabelText(/username/i), { target: { value: 'testuser' } }); - fireEvent.change(screen.getByLabelText(/password/i), { target: { value: 'secret' } }); - fireEvent.click(screen.getByRole('button', { name: /login/i })); - - await waitFor(() => { - expect(screen.getByText(/network error/i)).toBeInTheDocument(); - }); - }); -}); diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx deleted file mode 100644 index 87694cb..0000000 --- a/frontend/src/components/Login.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useState, type FormEvent } from 'react'; -import { useNavigate } from 'react-router-dom'; -import './Login.css'; - -import { apiFetch } from '../utils'; - -export default function Login() { - const [username, setUsername] = useState('neko'); - const [password, setPassword] = useState(''); - const [error, setError] = useState(''); - const navigate = useNavigate(); - - const handleSubmit = async (e: FormEvent) => { - e.preventDefault(); - setError(''); - - try { - // Use URLSearchParams to send as form-urlencoded, matching backend expectation - const params = new URLSearchParams(); - params.append('username', username); - params.append('password', password); - - const res = await apiFetch('/api/login', { - method: 'POST', - body: params, - }); - - if (res.ok) { - navigate('/'); - } else { - const data = await res.json(); - setError(data.message || 'Login failed'); - } - } catch (_err) { - setError('Network error'); - } - }; - - return ( - <div className="login-container"> - <form onSubmit={handleSubmit} className="login-form"> - <h1>neko rss mode</h1> - <div className="form-group"> - <label htmlFor="username">username</label> - <input - id="username" - type="text" - value={username} - onChange={(e) => setUsername(e.target.value)} - /> - </div> - <div className="form-group"> - <label htmlFor="password">password</label> - <input - id="password" - type="password" - value={password} - onChange={(e) => setPassword(e.target.value)} - autoFocus - /> - </div> - {error && <div className="error-message">{error}</div>} - <button type="submit">login</button> - </form> - </div> - ); -} diff --git a/frontend/src/components/Settings.css b/frontend/src/components/Settings.css deleted file mode 100644 index ae43be4..0000000 --- a/frontend/src/components/Settings.css +++ /dev/null @@ -1,240 +0,0 @@ -.settings-page.variant-glass { - padding: 2.5rem; - max-width: 800px; - margin: 0 auto; - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-radius: 24px; - border: 1px solid rgba(255, 255, 255, 0.1); - font-family: system-ui, -apple-system, sans-serif; - color: var(--text-color); - margin-top: 2rem; - margin-bottom: 2rem; -} - -.settings-page.variant-glass h2, -.settings-page.variant-glass h3 { - font-weight: 700; - letter-spacing: -0.02em; - color: var(--text-color); - opacity: 0.9; -} - -.add-feed-section, -.appearance-section, -.import-section, -.export-section, -.feed-list-section { - background: rgba(255, 255, 255, 0.03); - padding: 1.5rem; - border-radius: 16px; - margin-bottom: 2rem; - border: 1px solid rgba(255, 255, 255, 0.05); - transition: all 0.3s ease; -} - -.add-feed-section:hover, -.appearance-section:hover, -.import-section:hover, -.export-section:hover, -.feed-list-section:hover { - background: rgba(255, 255, 255, 0.06); - border-color: rgba(255, 255, 255, 0.1); -} - -.font-selector { - display: flex; - align-items: center; - gap: 1rem; -} - -.font-select { - padding: 0.6rem 1rem; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(0, 0, 0, 0.1); - color: var(--text-color); - border-radius: 20px; - font-size: 1rem; - min-width: 200px; - cursor: pointer; - outline: none; - transition: border-color 0.2s; -} - -.font-select:focus { - border-color: rgba(255, 255, 255, 0.3); -} - -.add-feed-form { - display: flex; - gap: 1rem; -} - -.feed-input { - flex: 1; - padding: 0.6rem 1.2rem; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(0, 0, 0, 0.1); - color: var(--text-color); - border-radius: 20px; - font-size: 1rem; - outline: none; - transition: border-color 0.2s; -} - -.feed-input:focus { - border-color: rgba(255, 255, 255, 0.3); -} - -.error-message { - color: #ff5252; - margin-top: 1rem; - font-weight: 600; -} - -.settings-feed-list { - list-style: none; - padding: 0; - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: 12px; - overflow: hidden; -} - -.settings-feed-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1.2rem; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); - transition: background 0.2s; -} - -.settings-feed-item:hover { - background: rgba(255, 255, 255, 0.02); -} - -.settings-feed-item:last-child { - border-bottom: none; -} - -.feed-info { - display: flex; - flex-direction: column; - gap: 0.2rem; -} - -.feed-title { - font-weight: 600; - font-size: 1.05rem; - opacity: 0.9; -} - -.feed-url { - color: var(--text-color); - opacity: 0.5; - font-size: 0.85rem; -} - -.delete-btn { - background: rgba(255, 82, 82, 0.15); - color: #ff8a80; - border: 1px solid rgba(255, 82, 82, 0.2); - padding: 0.5rem 1rem; - border-radius: 12px; - cursor: pointer; - font-weight: 600; - transition: all 0.2s; -} - -.delete-btn:hover:not(:disabled) { - background: rgba(255, 82, 82, 0.3); - color: #fff; - border-color: rgba(255, 82, 82, 0.4); - transform: scale(1.05); -} - -.import-export-section { - display: flex; - gap: 2rem; -} - -@media (max-width: 768px) { - .settings-page.variant-glass { - padding: 1.5rem; - margin-top: 1rem; - } - - .add-feed-form { - flex-direction: column; - } - - .import-export-section { - flex-direction: column; - gap: 1rem; - } - - .settings-feed-item { - flex-direction: column; - align-items: flex-start; - gap: 1rem; - } -} - -.import-form { - display: flex; - flex-direction: column; - gap: 1.2rem; -} - -.file-input { - font-size: 0.9rem; - max-width: 100%; - color: var(--text-color); - opacity: 0.8; -} - -.export-buttons { - display: flex; - gap: 0.8rem; - flex-wrap: wrap; -} - -.export-btn { - display: inline-block; - padding: 0.6rem 1.2rem; - background: rgba(255, 255, 255, 0.05); - color: var(--text-color); - text-decoration: none; - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 12px; - font-weight: 600; - transition: all 0.2s; -} - -.export-btn:hover { - background: rgba(255, 255, 255, 0.1); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); -} - -button:not(.delete-btn) { - cursor: pointer; - padding: 0.6rem 1.2rem; - border-radius: 12px; - border: 1px solid rgba(255, 255, 255, 0.1); - background: rgba(255, 255, 255, 0.1); - color: var(--text-color); - font-weight: 600; - transition: all 0.2s; -} - -button:not(.delete-btn):hover:not(:disabled) { - background: rgba(255, 255, 255, 0.2); - transform: scale(1.02); -} - -button:disabled { - opacity: 0.4; - cursor: not-allowed; -}
\ No newline at end of file diff --git a/frontend/src/components/Settings.test.tsx b/frontend/src/components/Settings.test.tsx deleted file mode 100644 index 5b0518c..0000000 --- a/frontend/src/components/Settings.test.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import React from 'react'; -import '@testing-library/jest-dom'; -import { render, screen, waitFor, fireEvent } from '@testing-library/react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import Settings from './Settings'; - -describe('Settings Component', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - // Mock confirm - global.confirm = vi.fn(() => true); - }); - - it('renders feed list', async () => { - const mockFeeds = [ - { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' }, - { _id: 2, title: 'Gaming', url: 'http://gaming.com/rss', category: 'gaming' }, - ]; - - vi.mocked(global.fetch).mockResolvedValueOnce({ - ok: true, - json: async () => mockFeeds, - } as Response); - - render(<Settings />); - - await waitFor(() => { - expect(screen.getByText('Tech News')).toBeInTheDocument(); - expect(screen.getByText('http://tech.com/rss')).toBeInTheDocument(); - expect(screen.getByText('Gaming')).toBeInTheDocument(); - }); - }); - - it('adds a new feed', async () => { - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load - .mockResolvedValueOnce({ ok: true, json: async () => ({}) } as Response) // Add feed - .mockResolvedValueOnce({ - ok: true, - json: async () => [{ _id: 3, title: 'New Feed', url: 'http://new.com/rss' }], - } as Response); // Refresh load - - render(<Settings />); - - // Wait for initial load to finish - await waitFor(() => { - expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); - }); - - const input = screen.getByPlaceholderText('https://example.com/feed.xml'); - const button = screen.getByText('Add Feed'); - - fireEvent.change(input, { target: { value: 'http://new.com/rss' } }); - fireEvent.click(button); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/feed/', - expect.objectContaining({ - method: 'POST', - body: JSON.stringify({ url: 'http://new.com/rss' }), - }) - ); - }); - - // Wait for refresh - await waitFor(() => { - expect(screen.getByText('New Feed')).toBeInTheDocument(); - }); - }); - - it('deletes a feed', async () => { - const mockFeeds = [ - { _id: 1, title: 'Tech News', url: 'http://tech.com/rss', category: 'tech' }, - ]; - - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => mockFeeds } as Response) // Initial load - .mockResolvedValueOnce({ ok: true } as Response); // Delete - - render(<Settings />); - - await waitFor(() => { - expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); - expect(screen.getByText('Tech News')).toBeInTheDocument(); - }); - - const deleteBtn = screen.getByTitle('Delete Feed'); - fireEvent.click(deleteBtn); - - await waitFor(() => { - expect(global.confirm).toHaveBeenCalled(); - expect(global.fetch).toHaveBeenCalledWith( - '/api/feed/1', - expect.objectContaining({ method: 'DELETE' }) - ); - expect(screen.queryByText('Tech News')).not.toBeInTheDocument(); - }); - }); - - it('imports an OPML file', async () => { - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load - .mockResolvedValueOnce({ ok: true, json: async () => ({ status: 'ok' }) } as Response) // Import - .mockResolvedValueOnce({ - ok: true, - json: async () => [{ _id: 1, title: 'Imported Feed', url: 'http://imported.com/rss' }], - } as Response); // Refresh load - - render(<Settings />); - - const file = new File(['<opml>...</opml>'], 'feeds.opml', { type: 'text/xml' }); - const fileInput = screen.getByLabelText(/import feeds/i, { selector: 'input[type="file"]' }); - const importButton = screen.getByText('Import'); - - fireEvent.change(fileInput, { target: { files: [file] } }); - await waitFor(() => { - expect(importButton).not.toBeDisabled(); - }); - - fireEvent.click(importButton); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/import', - expect.objectContaining({ - method: 'POST', - body: expect.any(FormData), - }) - ); - }); - - // Check if refresh happens - await waitFor(() => { - expect(screen.getByText('Imported Feed')).toBeInTheDocument(); - }); - }); - - it('triggers a crawl', async () => { - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load - .mockResolvedValueOnce({ ok: true, json: async () => ({ message: 'crawl started' }) } as Response); // Crawl - - // Mock alert - const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => { }); - - render(<Settings />); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); - }); - - const crawlBtn = screen.getByText(/crawl all feeds now/i); - fireEvent.click(crawlBtn); - - await waitFor(() => { - expect(global.fetch).toHaveBeenCalledWith( - '/api/crawl', - expect.objectContaining({ method: 'POST' }) - ); - expect(alertMock).toHaveBeenCalledWith('Crawl started!'); - }); - alertMock.mockRestore(); - }); - - it('handles API errors', async () => { - vi.mocked(global.fetch) - .mockResolvedValueOnce({ ok: true, json: async () => [] } as Response) // Initial load load - .mockResolvedValueOnce({ ok: false, json: async () => ({}) } as Response); // Add feed error - - render(<Settings />); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); - }); - - const input = screen.getByPlaceholderText('https://example.com/feed.xml'); - const button = screen.getByText('Add Feed'); - - fireEvent.change(input, { target: { value: 'http://fail.com/rss' } }); - fireEvent.click(button); - - await waitFor(() => { - expect(screen.getByText(/failed to add feed/i)).toBeInTheDocument(); - }); - }); - - it('handles font theme change', async () => { - const setFontTheme = vi.fn(); - vi.mocked(global.fetch).mockResolvedValueOnce({ ok: true, json: async () => [] } as Response); - - render(<Settings fontTheme="default" setFontTheme={setFontTheme} />); - - // Wait for load - await waitFor(() => { - expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); - }); - - const select = screen.getByLabelText(/font theme/i); - fireEvent.change(select, { target: { value: 'serif' } }); - - expect(setFontTheme).toHaveBeenCalledWith('serif'); - }); -}); diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx deleted file mode 100644 index 3dab77f..0000000 --- a/frontend/src/components/Settings.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import type { Feed } from '../types'; -import './Settings.css'; -import { apiFetch } from '../utils'; - -interface SettingsProps { - fontTheme?: string; - setFontTheme?: (t: string) => void; -} - -export default function Settings({ fontTheme, setFontTheme }: SettingsProps) { - const [feeds, setFeeds] = useState<Feed[]>([]); - /* ... existing state ... */ - const [newFeedUrl, setNewFeedUrl] = useState(''); - const [loading, setLoading] = useState(false); - const [error, setError] = useState<string | null>(null); - - const [importFile, setImportFile] = useState<File | null>(null); - - /* ... existing fetchFeeds ... */ - const fetchFeeds = React.useCallback(() => { - setLoading(true); - apiFetch('/api/feed/') - .then((res) => { - if (!res.ok) throw new Error('Failed to fetch feeds'); - return res.json(); - }) - .then((data) => { - setFeeds(data); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }, []); - - useEffect(() => { - // eslint-disable-next-line - fetchFeeds(); - }, [fetchFeeds]); - - /* ... existing handlers ... */ - const handleAddFeed = (e: React.FormEvent) => { - e.preventDefault(); - if (!newFeedUrl) return; - - setLoading(true); - apiFetch('/api/feed/', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url: newFeedUrl }), - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to add feed'); - return res.json(); - }) - .then(() => { - setNewFeedUrl(''); - fetchFeeds(); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - - const handleDeleteFeed = (id: number) => { - if (!globalThis.confirm('Are you sure you want to delete this feed?')) return; - - setLoading(true); - apiFetch(`/api/feed/${id}`, { - method: 'DELETE', - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to delete feed'); - setFeeds(feeds.filter((f) => f._id !== id)); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - - const handleImport = (e: React.FormEvent) => { - e.preventDefault(); - if (!importFile) return; - - setLoading(true); - const formData = new FormData(); - formData.append('file', importFile); - formData.append('format', 'opml'); - - apiFetch('/api/import', { - method: 'POST', - body: formData, - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to import feeds'); - return res.json(); - }) - .then(() => { - setImportFile(null); - fetchFeeds(); - alert('Import successful!'); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - - const handleCrawl = () => { - setLoading(true); - apiFetch('/api/crawl', { - method: 'POST', - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to start crawl'); - return res.json(); - }) - .then(() => { - setLoading(false); - alert('Crawl started!'); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - - return ( - <div className="settings-page variant-glass"> - <h2>Settings</h2> - - {setFontTheme && ( - <div className="appearance-section"> - <h3>Appearance</h3> - <div className="font-selector"> - <label htmlFor="font-theme-select">Font Theme:</label> - <select - id="font-theme-select" - value={fontTheme || 'default'} - onChange={(e) => setFontTheme(e.target.value)} - className="font-select" - > - <option value="default">Default</option> - <option value="serif">Serif</option> - <option value="sans">Sans-Serif</option> - <option value="mono">Monospace</option> - </select> - </div> - </div> - )} - - <div className="add-feed-section"> - <h3>Add New Feed</h3> - <form onSubmit={handleAddFeed} className="add-feed-form"> - <input - type="url" - value={newFeedUrl} - onChange={(e) => setNewFeedUrl(e.target.value)} - placeholder="https://example.com/feed.xml" - required - className="feed-input" - disabled={loading} - /> - <button type="submit" disabled={loading}> - Add Feed - </button> - </form> - </div> - - <div className="import-export-section"> - <div className="import-section"> - <h3>Import Feeds (OPML)</h3> - <form onSubmit={handleImport} className="import-form"> - <input - type="file" - accept=".opml,.xml,.txt" - aria-label="Import Feeds" - onChange={(e) => setImportFile(e.target.files?.[0] || null)} - className="file-input" - disabled={loading} - /> - <button type="submit" disabled={!importFile || loading}> - Import - </button> - </form> - </div> - - <div className="export-section"> - <h3>Export Feeds</h3> - <div className="export-buttons"> - <a href="/api/export/opml" className="export-btn">OPML</a> - <a href="/api/export/text" className="export-btn">Text</a> - <a href="/api/export/json" className="export-btn">JSON</a> - </div> - </div> - - <div className="crawl-section"> - <h3>Actions</h3> - <button onClick={handleCrawl} disabled={loading} className="crawl-btn"> - Crawl All Feeds Now - </button> - </div> - </div> - - {error && <p className="error-message">{error}</p>} - - <div className="feed-list-section"> - <h3>Manage Feeds</h3> - {loading && <p>Loading...</p>} - <ul className="settings-feed-list"> - {feeds.map((feed) => ( - <li key={feed._id} className="settings-feed-item"> - <div className="feed-info"> - <span className="feed-title">{feed.title || '(No Title)'}</span> - <span className="feed-url">{feed.url}</span> - </div> - <button - onClick={() => handleDeleteFeed(feed._id)} - className="delete-btn" - disabled={loading} - title="Delete Feed" - > - Delete - </button> - </li> - ))} - </ul> - </div> - </div> - ); -} diff --git a/frontend/src/components/TagView.test.tsx b/frontend/src/components/TagView.test.tsx deleted file mode 100644 index de0a318..0000000 --- a/frontend/src/components/TagView.test.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React from 'react'; -import { render, screen, waitFor } from '@testing-library/react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { MemoryRouter, Route, Routes } from 'react-router-dom'; -import FeedList from './FeedList'; -import FeedItems from './FeedItems'; - -describe('Tag View Integration', () => { - beforeEach(() => { - vi.resetAllMocks(); - global.fetch = vi.fn(); - }); - - it('renders tags in FeedList and navigates to tag view', async () => { - const mockFeeds = [ - { _id: 1, title: 'Feed 1', url: 'http://example.com/rss', category: 'Tech' }, - ]; - const mockTags = [{ title: 'Tech' }, { title: 'News' }]; - - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/feed/')) { - return Promise.resolve({ - ok: true, - json: async () => mockFeeds, - } as Response); - } - if (urlStr.includes('/api/tag')) { - return Promise.resolve({ - ok: true, - json: async () => mockTags, - } as Response); - } - return Promise.reject(new Error(`Unknown URL: ${url}`)); - }); - - render( - <MemoryRouter> - <FeedList - theme="light" - setTheme={() => { }} - setSidebarVisible={() => { }} - isMobile={false} - /> - </MemoryRouter> - ); - - await waitFor(() => { - const techTags = screen.getAllByText('Tech'); - expect(techTags.length).toBeGreaterThan(0); - expect(screen.getByText('News')).toBeInTheDocument(); - }); - - // Verify structure - const techTag = screen.getByText('News').closest('a'); - expect(techTag).toHaveAttribute('href', '/tag/News?filter=unread'); - }); - - it('fetches items by tag in FeedItems', async () => { - const mockItems = [ - { _id: 101, title: 'Tag Item 1', url: 'http://example.com/1', feed_title: 'Feed 1' }, - ]; - - vi.mocked(global.fetch).mockImplementation((url) => { - const urlStr = url.toString(); - if (urlStr.includes('/api/stream')) { - return Promise.resolve({ - ok: true, - json: async () => mockItems, - } as Response); - } - return Promise.reject(new Error(`Unknown URL: ${url}`)); - }); - - render( - <MemoryRouter initialEntries={['/tag/Tech']}> - <Routes> - <Route path="/tag/:tagName" element={<FeedItems />} /> - </Routes> - </MemoryRouter> - ); - - await waitFor(() => { - // expect(screen.getByText('Tag: Tech')).toBeInTheDocument(); - expect(screen.getByText('Tag Item 1')).toBeInTheDocument(); - }); - - const params = new URLSearchParams(); - params.append('tag', 'Tech'); - params.append('read_filter', 'unread'); - expect(global.fetch).toHaveBeenCalledWith(`/api/stream?${params.toString()}`, expect.anything()); - }); -}); diff --git a/frontend/src/index.css b/frontend/src/index.css deleted file mode 100644 index 22fc7d0..0000000 --- a/frontend/src/index.css +++ /dev/null @@ -1,158 +0,0 @@ -:root { - /* Font Variables */ - --font-body: Palatino, 'Palatino Linotype', 'Palatino LT STD', 'Book Antiqua', Georgia, serif; - --font-heading: 'Helvetica Neue', Helvetica, Arial, sans-serif; - - line-height: 1.5; - font-size: 18px; - - /* Light Mode Defaults */ - --bg-color: #ffffff; - --text-color: rgba(0, 0, 0, 0.87); - --sidebar-bg: #ccc; - --link-color: #0000ee; - /* Standard blue link */ - - color-scheme: light dark; - color: var(--text-color); - background-color: var(--bg-color); -} - -html, -body, -#root { - width: 100%; - height: 100%; - margin: 0; - padding: 0; - overflow: hidden; -} - -body { - font-family: var(--font-body); -} - -h1, -h2, -h3, -h4, -h5, -.logo, -.nav-link, -.logout-btn { - font-family: var(--font-heading); - font-weight: bold; -} - -/* Font Themes */ -.font-default { - /* Uses :root defaults */ - font-family: var(--font-body); -} - -.font-serif { - --font-body: Georgia, 'Times New Roman', Times, serif; - --font-heading: Georgia, 'Times New Roman', Times, serif; - font-family: var(--font-body); -} - -.font-sans { - --font-body: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - --font-heading: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - font-family: var(--font-body); -} - -.font-mono { - --font-body: Menlo, Monaco, Consolas, 'Courier New', monospace; - --font-heading: Menlo, Monaco, Consolas, 'Courier New', monospace; - font-family: var(--font-body); -} - - -.theme-light { - --bg-color: #ffffff; - --text-color: rgba(0, 0, 0, 0.87); - --sidebar-bg: #ccc; - --link-color: #0000ee; - --border-color: #999; - background-color: var(--bg-color); - color: var(--text-color); -} - -@media (prefers-color-scheme: dark) { - :root { - --bg-color: #24292e; - /* Legacy Dark */ - --text-color: #ffffff; - --sidebar-bg: #1b1f23; - /* Darker sidebar */ - --link-color: rgb(90, 200, 250); - /* Legacy dark link */ - } -} - -.theme-dark { - --bg-color: #000000; - --text-color: #ffffff; - --sidebar-bg: #111111; - --link-color: rgb(90, 200, 250); - --border-color: #333; - background-color: var(--bg-color); - color: var(--text-color); -} - -.theme-dark button { - background-color: #333; - color: #fff; -} - -body { - min-width: 320px; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: bold; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} - -button:hover { - border-color: #646cff; -} - -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -a { - color: var(--link-color); - text-decoration: none; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: blue; - text-decoration: underline; - } - - button { - background-color: #f9f9f9; - } -}
\ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx deleted file mode 100644 index df655ea..0000000 --- a/frontend/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import './index.css'; -import App from './App.tsx'; - -createRoot(document.getElementById('root')!).render( - <StrictMode> - <App /> - </StrictMode> -); diff --git a/frontend/src/setupTests.ts b/frontend/src/setupTests.ts deleted file mode 100644 index 5781184..0000000 --- a/frontend/src/setupTests.ts +++ /dev/null @@ -1,40 +0,0 @@ -import '@testing-library/jest-dom'; - -// Mock IntersectionObserver -class IntersectionObserver { - readonly root: Element | null = null; - readonly rootMargin: string = ''; - readonly thresholds: ReadonlyArray<number> = []; - - constructor(_callback: IntersectionObserverCallback, _options?: IntersectionObserverInit) { - // nothing - } - - observe(_target: Element): void { - // nothing - } - - unobserve(_target: Element): void { - // nothing - } - - disconnect(): void { - // nothing - } - - takeRecords(): IntersectionObserverEntry[] { - return []; - } -} - -Object.defineProperty(window, 'IntersectionObserver', { - writable: true, - configurable: true, - value: IntersectionObserver, -}); - -Object.defineProperty(globalThis, 'IntersectionObserver', { - writable: true, - configurable: true, - value: IntersectionObserver, -}); diff --git a/frontend/src/types.ts b/frontend/src/types.ts deleted file mode 100644 index 1feea1f..0000000 --- a/frontend/src/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -export interface Feed { - _id: number; - url: string; - web_url: string; - title: string; - category: string; -} - -export interface Item { - _id: number; - feed_id: number; - title: string; - url: string; - description: string; - publish_date: string; - read: boolean; - starred: boolean; - full_content?: string; - header_image?: string; - feed_title?: string; -} -export interface Category { - title: string; -} diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts deleted file mode 100644 index ebfb692..0000000 --- a/frontend/src/utils.ts +++ /dev/null @@ -1,32 +0,0 @@ -export function getCookie(name: string): string | undefined { - const value = `; ${document.cookie}`; - const parts = value.split(`; ${name}=`); - if (parts.length === 2) return parts.pop()?.split(';').shift(); -} - -/** - * A wrapper around fetch that automatically includes the CSRF token - * for state-changing requests (POST, PUT, DELETE). - */ -export async function apiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> { - const method = init?.method?.toUpperCase() || 'GET'; - const isStateChanging = ['POST', 'PUT', 'DELETE'].includes(method); - - const headers = new Headers(init?.headers || {}); - - if (isStateChanging) { - const token = getCookie('csrf_token'); - if (token) { - headers.set('X-CSRF-Token', token); - } - } - - // Ensure requests are treated as coming from our own origin if needed, - // but for a same-origin API, standard fetch defaults are usually fine. - - return fetch(input, { - ...init, - headers, - credentials: 'include', // Ensure cookies are sent - }); -} diff --git a/frontend/tests/auth.spec.ts b/frontend/tests/auth.spec.ts deleted file mode 100644 index 33ada85..0000000 --- a/frontend/tests/auth.spec.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { test, expect } from '@playwright/test'; - -/** - * E2E tests for authentication flows. - * - * These tests verify login behavior both with and without a password configured. - * The current setup assumes no password (default for dev), so the password-required - * tests are marked as skip. To run those, start the backend with --password=testpass. - */ - -test.describe('Authentication - No Password Required', () => { - test('should allow direct access to dashboard without login', async ({ page }) => { - // When no password is configured, users should be able to access - // the dashboard directly without seeing the login page - await page.goto('/v2/'); - - // Should not redirect to login - await expect(page).toHaveURL(/.*\/v2\/?$/); - - // Should see the dashboard elements - await expect(page.locator('h1.logo')).toContainText('🐱'); - await expect(page.getByText('Logout')).toBeVisible(); - }); - - test('should allow login with empty password', async ({ page }) => { - // Visit login page - await page.goto('/v2/login'); - - // Fill username and submit with empty password - await page.fill('input[id="username"]', 'neko'); - await page.click('button[type="submit"]'); - - // Should redirect to dashboard - await expect(page).toHaveURL(/.*\/v2\/?$/, { timeout: 5000 }); - await expect(page.locator('h1.logo')).toContainText('🐱'); - }); - - test('should report authenticated status via API when no password', async ({ request }) => { - // Check auth status - const response = await request.get('/api/auth'); - expect(response.ok()).toBeTruthy(); - - const data = await response.json(); - expect(data.authenticated).toBe(true); - }); -}); - -test.describe('Authentication - Password Required', () => { - // These tests require the backend to be started with a password - // Example: neko --password=testpass - // Skip by default since dev environment has no password - - test.skip('should redirect to login when accessing protected routes', async ({ page, context }) => { - // Clear any existing cookies - await context.clearCookies(); - - // Try to access dashboard - await page.goto('/v2/'); - - // Should redirect to login - await expect(page).toHaveURL(/.*\/login/, { timeout: 5000 }); - }); - - test.skip('should reject incorrect password', async ({ page }) => { - await page.goto('/v2/login'); - - // Enter wrong password - await page.fill('input[id="username"]', 'neko'); - await page.fill('input[type="password"]', 'wrongpassword'); - await page.click('button[type="submit"]'); - - // Should show error message - await expect(page.getByText(/bad credentials|login failed/i)).toBeVisible({ timeout: 3000 }); - - // Should still be on login page - await expect(page).toHaveURL(/.*\/login/); - }); - - test.skip('should accept correct password and redirect to dashboard', async ({ page }) => { - await page.goto('/v2/login'); - - // Enter correct password (must match what the server was started with) - await page.fill('input[id="username"]', 'neko'); - await page.fill('input[type="password"]', 'testpass'); - await page.click('button[type="submit"]'); - - // Should redirect to dashboard - await expect(page).toHaveURL(/.*\/v2\/?$/, { timeout: 5000 }); - await expect(page.locator('h1.logo')).toContainText('🐱'); - await expect(page.getByText('Logout')).toBeVisible(); - }); - - test.skip('should persist authentication across page reloads', async ({ page }) => { - // Login first - await page.goto('/v2/login'); - await page.fill('input[id="username"]', 'neko'); - await page.fill('input[type="password"]', 'testpass'); - await page.click('button[type="submit"]'); - await expect(page).toHaveURL(/.*\/v2\/?$/); - - // Reload the page - await page.reload(); - - // Should still be authenticated (not redirected to login) - await expect(page).toHaveURL(/.*\/v2\/?$/); - await expect(page.locator('h1.logo')).toContainText('🐱'); - }); - - test.skip('should logout and redirect to login page', async ({ page }) => { - // Login first - await page.goto('/v2/login'); - await page.fill('input[id="username"]', 'neko'); - await page.fill('input[type="password"]', 'testpass'); - await page.click('button[type="submit"]'); - await expect(page).toHaveURL(/.*\/v2\/?$/); - - // Click logout - await page.click('text=Logout'); - - // Should redirect to login - await expect(page).toHaveURL(/.*\/login/); - - // Try to access dashboard again - should redirect to login - await page.goto('/v2/'); - await expect(page).toHaveURL(/.*\/login/); - }); - - test.skip('should report unauthenticated status via API', async ({ request, context }) => { - // Clear cookies - await context.clearCookies(); - - // Check auth status - const response = await request.get('/api/auth'); - expect(response.ok()).toBeTruthy(); - - const data = await response.json(); - expect(data.authenticated).toBe(false); - }); -}); - -test.describe('Authentication - Complete Flow', () => { - test('should handle complete user flow without password', async ({ page }) => { - // 1. Access dashboard directly - await page.goto('/v2/'); - await expect(page.locator('h1.logo')).toContainText('🐱'); - - // 2. Navigate to settings - await page.click('text=Settings'); - await expect(page).toHaveURL(/.*\/settings/); - - // 3. Add a feed (this tests that API calls work when no password) - const feedUrl = 'http://example.com/rss.xml'; - await page.fill('input[type="url"]', feedUrl); - await page.click('text=Add Feed'); - - // Wait for success (feed should appear) - await expect(page.getByText(feedUrl)).toBeVisible({ timeout: 3000 }); - - // 4. Navigate back to main view - await page.goto('/v2/'); - await expect(page.locator('h1.logo')).toContainText('🐱'); - - // 5. Logout (should work even with no password) - await page.click('text=Logout'); - await expect(page).toHaveURL(/.*\/login/); - }); -}); diff --git a/frontend/tests/crawl.spec.ts b/frontend/tests/crawl.spec.ts deleted file mode 100644 index 175a764..0000000 --- a/frontend/tests/crawl.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test.describe('Crawl Integration', () => { - test('should add a feed and see items after crawl', async ({ page }) => { - const mockFeedUrl = 'http://localhost:9090/mock_feed.xml'; - - // 1. Login and go to Settings - await page.goto('/v2/settings'); - - // 2. Add the mock feed - await page.fill('input[type="url"]', mockFeedUrl); - await page.click('text=Add Feed'); - - // Wait for feed to be added - await expect(page.getByText(mockFeedUrl)).toBeVisible({ timeout: 5000 }); - - // 3. Trigger Crawl - const crawlButton = page.getByRole('button', { name: /crawl/i }); - await expect(crawlButton).toBeVisible(); - - // Handle the alert - page.on('dialog', dialog => dialog.accept()); - await crawlButton.click(); - - // 4. Go to Home and check for items - await page.goto('/v2/'); - - // The mock feed has "Mock Item 1" and "Mock Item 2" - await expect(page.getByText('Mock Item 1')).toBeVisible({ timeout: 10000 }); - await expect(page.getByText('Mock Item 2')).toBeVisible({ timeout: 10000 }); - }); -}); diff --git a/frontend/tests/e2e.spec.ts b/frontend/tests/e2e.spec.ts deleted file mode 100644 index 2bdf478..0000000 --- a/frontend/tests/e2e.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test.describe('Neko Reader E2E', () => { - test('should allow login, viewing feeds, and logout', async ({ page }) => { - // 1. Go to Login - await page.goto('/v2/login'); - await expect(page).toHaveTitle(/Neko/); - - // 2. Login - // 2. Login - // Password is empty by default in test env - await page.click('button[type="submit"]'); - - // Check for error message if login failed (optional, for debugging) - // await expect(page.locator('.error-message')).toBeVisible({ timeout: 2000 }).catch(() => {}); - - // 3. Verify Dashboard - // Keep checking for /v2/ or /v2 - await expect(page).toHaveURL(/.*\/v2\/?$/); - await expect(page.locator('h1.logo')).toContainText('🐱'); - await expect(page.getByText('Logout')).toBeVisible(); - - // 4. Verify Feed List - await page.click('text=Settings'); - await expect(page).toHaveURL(/.*\/v2\/settings/); - - // Add a feed - const feedUrl = 'http://localhost:9090/mock_feed.xml'; - await page.fill('input[type="url"]', feedUrl); - await page.click('text=Add Feed'); - - // Wait for it to appear - await expect(page.getByText(feedUrl)).toBeVisible(); - - const waitForLoader = async () => { - await page.waitForFunction(() => { - const loading = document.querySelector('.feed-items-loading') || - document.body.innerText.includes('Loading...'); - return !loading; - }, { timeout: 15000 }); - }; - - // 5. Navigate to Feed - console.log('Step 5: Navigate to Home'); - await page.goto('/v2/'); - await expect(page).toHaveURL(/.*\/v2\/?$/); - // Default view is now the stream. - // It should NOT show "Select a feed" anymore. - // Wait for items or "No items found" or loading state - await waitForLoader(); - await expect( - page - .locator('.feed-items') - .or(page.getByText('No items found')) - .or(page.locator('.feed-items-error')) - ).toBeVisible({ timeout: 10000 }); - - // 6. Verify Tag View - // 6. Logout - console.log('Step 6: Logout'); - await page.click('text=Logout'); - await expect(page).toHaveURL(/.*\/v2\/login/); - }); -}); diff --git a/frontend/tests/font.spec.ts b/frontend/tests/font.spec.ts deleted file mode 100644 index 0723f38..0000000 --- a/frontend/tests/font.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test.describe('Font Theme Settings', () => { - test('should change font family when theme starts', async ({ page }) => { - // 1. Login - await page.goto('/v2/login'); - await page.click('button[type="submit"]'); - await expect(page).toHaveURL(/.*\/v2\/?$/); - - // 2. Go to Settings - await page.click('text=Settings'); - await expect(page).toHaveURL(/.*\/v2\/settings/); - - // 3. Verify Default Font (Palatino) - // We check the computed style of the dashboard container or a body element - const dashboard = page.locator('.dashboard'); - await expect(dashboard).toHaveCSS('font-family', /Palatino/); - - // 4. Change to Sans-Serif - await page.selectOption('select.font-select', 'sans'); - - // 5. Verify Sans Font (Inter) - await expect(dashboard).toHaveCSS('font-family', /Inter/); - - // 6. Change to Monospace - await page.selectOption('select.font-select', 'mono'); - - // 7. Verify Mono Font (Menlo or Monaco or Courier) - await expect(dashboard).toHaveCSS('font-family', /Menlo|Monaco|Courier/); - }); -}); diff --git a/frontend/tests/mocked-api.spec.ts b/frontend/tests/mocked-api.spec.ts deleted file mode 100644 index 06f6c17..0000000 --- a/frontend/tests/mocked-api.spec.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test.describe('Mocked API UI Tests', () => { - test.beforeEach(async ({ page }) => { - // Log browser console for debugging - page.on('console', msg => { - if (msg.type() === 'error') console.log(`BROWSER ERROR: ${msg.text()} `); - }); - - // 1. Mock Auth - simulate logged in session - await page.route('**/api/auth', async (route) => { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify({ status: 'ok', authenticated: true }), - }); - }); - - // 2. Mock Feeds - await page.route('**/api/feed/', async (route) => { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify([ - { _id: 1, title: 'Mock Feed 1', url: 'http://mock1.com', category: 'News' }, - { _id: 2, title: 'Mock Feed 2', url: 'http://mock2.com', category: 'Tech' }, - ]), - }); - }); - - // 3. Mock Tags - await page.route('**/api/tag', async (route) => { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify([ - { title: 'News' }, - { title: 'Tech' }, - ]), - }); - }); - - // 4. Mock Stream/Items - await page.route('**/api/stream*', async (route) => { - const url = new URL(route.request().url()); - const maxId = url.searchParams.get('max_id'); - - if (maxId) { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify([]), - }); - return; - } - - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify([ - { - _id: 101, - feed_id: 1, - title: 'Mock Item Unread', - url: 'http://mock1.com/1', - description: 'This is an unread item', - publish_date: new Date().toISOString(), - read: false, - starred: false, - feed_title: 'Mock Feed 1' - }, - { - _id: 102, - feed_id: 2, - title: 'Mock Item Starred', - url: 'http://mock2.com/1', - description: 'This is a starred and read item', - publish_date: new Date().toISOString(), - read: true, - starred: true, - feed_title: 'Mock Feed 2' - } - ]), - }); - }); - - // 5. Mock Item Update (for marking read/starred) - await page.route('**/api/item/**', async (route) => { - if (route.request().method() === 'PUT') { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify({ status: 'ok' }), - }); - } else { - await route.continue(); - } - }); - - // 6. Mock Logout - await page.route('**/api/logout', async (route) => { - await route.fulfill({ - status: 200, - contentType: 'application/json', - body: JSON.stringify({ status: 'ok' }), - }); - }); - }); - - test('should load dashboard with mocked feeds and items', async ({ page }) => { - await page.goto('/v2/'); - - // Wait for the logo to appear (means we are on the dashboard) - await expect(page.locator('h1.logo')).toBeVisible({ timeout: 15000 }); - - // Verify items in main view (ensure they load first) - await expect(page.getByText('Mock Item Unread')).toBeVisible({ timeout: 10000 }); - await expect(page.getByText('Mock Item Starred')).toBeVisible(); - - // Verify feeds in sidebar - // Click on the Feeds header to expand - await page.getByText(/Feeds/i).click(); - - // Wait for mocked feeds to appear in sidebar - // We use a more specific selector to avoid matching the feed_title in the item list - await expect(page.locator('.feed-list-items').getByText('Mock Feed 1')).toBeVisible({ timeout: 10000 }); - await expect(page.locator('.feed-list-items').getByText('Mock Feed 2')).toBeVisible(); - - // Verify "unread" filter is active by default - const unreadFilterLink = page.locator('.unread_filter a'); - await expect(unreadFilterLink).toHaveClass(/active/); - }); - - test('should filter by mocked tag', async ({ page }) => { - await page.goto('/v2/'); - - // Click on Tech tag - await page.getByText('Tech', { exact: true }).click(); - - // URL should update - await expect(page).toHaveURL(/.*\/tag\/Tech/); - - // Verify feed items are still visible (mock stream returns both regardless of tag in this simple mock) - await expect(page.getByText('Mock Item Unread')).toBeVisible(); - }); - - test('should toggle item star status', async ({ page }) => { - await page.goto('/v2/'); - - const unreadItem = page.locator('.feed-item.unread').first(); - const starButton = unreadItem.getByTitle('Star'); - - await starButton.click(); - - // Expect star to change to "Unstar" (UI optimistic update) - await expect(starButton).toHaveAttribute('title', 'Unstar'); - }); - - test('should logout using mocked API', async ({ page }) => { - await page.goto('/v2/'); - - await page.getByText('logout').click(); - - // Should redirect to login - await expect(page).toHaveURL(/.*\/login/); - }); -}); diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json deleted file mode 100644 index 3fcc60b..0000000 --- a/frontend/tsconfig.app.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2022", - "useDefineForClassFields": true, - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "module": "ESNext", - "types": ["vite/client"], - "skipLibCheck": true, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src"], - "exclude": ["**/*.test.tsx", "**/*.test.ts"] -} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index d32ff68..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": [], - "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }] -} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json deleted file mode 100644 index 50145d1..0000000 --- a/frontend/tsconfig.node.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2023", - "lib": ["ES2023"], - "module": "ESNext", - "types": ["node", "vitest"], - "skipLibCheck": true, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts deleted file mode 100644 index 025cbb3..0000000 --- a/frontend/vite.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// <reference types="vitest" /> -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [react()], - base: '/v2/', - server: { - proxy: { - '/api': 'http://127.0.0.1:4994', - '/image': 'http://127.0.0.1:4994', - }, - }, -}); diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts deleted file mode 100644 index 9cb79ae..0000000 --- a/frontend/vitest.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// <reference types="vitest" /> -import { defineConfig } from 'vite'; - -export default defineConfig({ - test: { - globals: true, - environment: 'jsdom', - setupFiles: './src/setupTests.ts', - exclude: ['**/node_modules/**', '**/dist/**', '**/tests/**'], - }, -}); diff --git a/web/dist/v2/assets/index-BIMig4wW.css b/web/dist/v2/assets/index-BIMig4wW.css deleted file mode 100644 index 7255d3c..0000000 --- a/web/dist/v2/assets/index-BIMig4wW.css +++ /dev/null @@ -1 +0,0 @@ -:root{--font-body: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;--font-heading: "Helvetica Neue", Helvetica, Arial, sans-serif;line-height:1.5;font-size:18px;--bg-color: #ffffff;--text-color: rgba(0, 0, 0, .87);--sidebar-bg: #ccc;--link-color: #0000ee;color-scheme:light dark;color:var(--text-color);background-color:var(--bg-color)}html,body,#root{width:100%;height:100%;margin:0;padding:0;overflow:hidden}body{font-family:var(--font-body)}h1,h2,h3,h4,h5,.logo,.nav-link,.logout-btn{font-family:var(--font-heading);font-weight:700}.font-default{font-family:var(--font-body)}.font-serif{--font-body: Georgia, "Times New Roman", Times, serif;--font-heading: Georgia, "Times New Roman", Times, serif;font-family:var(--font-body)}.font-sans{--font-body: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;--font-heading: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;font-family:var(--font-body)}.font-mono{--font-body: Menlo, Monaco, Consolas, "Courier New", monospace;--font-heading: Menlo, Monaco, Consolas, "Courier New", monospace;font-family:var(--font-body)}.theme-light{--bg-color: #ffffff;--text-color: rgba(0, 0, 0, .87);--sidebar-bg: #ccc;--link-color: #0000ee;--border-color: #999;background-color:var(--bg-color);color:var(--text-color)}@media(prefers-color-scheme:dark){:root{--bg-color: #24292e;--text-color: #ffffff;--sidebar-bg: #1b1f23;--link-color: rgb(90, 200, 250)}}.theme-dark{--bg-color: #000000;--text-color: #ffffff;--sidebar-bg: #111111;--link-color: rgb(90, 200, 250);--border-color: #333;background-color:var(--bg-color);color:var(--text-color)}.theme-dark button{background-color:#333;color:#fff}body{min-width:320px}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:700;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}a{color:var(--link-color);text-decoration:none}@media(prefers-color-scheme:light){:root{color:#213547;background-color:#fff}a:hover{color:#00f;text-decoration:underline}button{background-color:#f9f9f9}}.login-container{display:flex;justify-content:center;align-items:center;height:100vh;background-color:#f5f5f5}.login-form{background:#fff;padding:2rem;border-radius:8px;box-shadow:0 4px 6px #0000001a;width:100%;max-width:400px}.login-form h1{margin-bottom:2rem;text-align:center;color:#333}.form-group{margin-bottom:1.5rem}.form-group label{display:block;margin-bottom:.5rem;font-weight:700;color:#555}.form-group input{width:100%;padding:.75rem;border:1px solid #ddd;border-radius:4px;font-size:1rem}.error-message{color:#dc3545;margin-bottom:1rem;text-align:center}button[type=submit]{width:100%;padding:.75rem;background-color:#007bff;color:#fff;border:none;border-radius:4px;font-size:1rem;cursor:pointer;transition:background-color .2s}button[type=submit]:hover{background-color:#0056b3}*{box-sizing:border-box}body{margin:0}.dashboard{display:flex;flex-direction:column;height:100vh;height:100dvh;width:100%;overflow:hidden}.dashboard-content{display:flex;flex:1;overflow:hidden;position:relative;width:100%}.dashboard-sidebar{width:11rem;background:transparent;border-right:1px solid var(--border-color);display:flex;flex-direction:column;overflow-y:auto;transition:margin-left .4s ease}.dashboard-sidebar.hidden{margin-left:-11rem}.dashboard-main{flex:1;min-width:0;padding:2rem;overflow-y:auto;overflow-x:hidden;background:var(--bg-color);margin-left:0}.dashboard-main>*{max-width:35em;margin:0 auto}.fixed-toggle{position:absolute;top:1rem;left:1rem;z-index:1000;background:var(--bg-color);background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;padding:.2rem;color:var(--text-color);display:flex;align-items:center;justify-content:center}.fixed-toggle:hover{transform:scale(1.1)}@media(max-width:768px){.dashboard-sidebar{position:fixed;top:0;left:0;bottom:0;z-index:1100;box-shadow:2px 0 10px #0003;width:14rem}.dashboard-sidebar.hidden{margin-left:-14rem}.dashboard-main{padding:4rem 1rem 1rem}.dashboard-main>*{max-width:100%}.sidebar-backdrop{position:fixed;inset:0;background:#0006;z-index:1050;animation:fadeIn .3s ease}.dashboard.sidebar-visible:after{display:none}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.feed-list{padding:1rem;font-family:var(--font-heading);color:#777;font-size:.8rem;background:var(--sidebar-bg);min-height:100%;flex:1}.feed-list h1.logo{font-size:2rem;margin:0 0 1rem;line-height:1;cursor:pointer;position:sticky;top:0;background:var(--sidebar-bg);z-index:10;padding-bottom:.5rem;color:var(--text-color)}.theme-light .feed-list h1.logo{color:#333}.theme-dark .feed-list h1.logo{color:#eee}.search-section{margin-bottom:1rem}.search-input{width:100%;padding:.25rem;border:1px solid var(--border-color, #999);background:var(--bg-color);color:var(--text-color);font-size:.8rem;font-family:inherit;border-radius:0}.section-header{font-size:1rem;font-weight:700;margin:1rem 0 .25rem;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-heading);color:#333;text-transform:lowercase;font-variant:small-caps;display:flex;align-items:center;gap:.5rem}.caret{display:inline-block;font-size:.6rem;transition:transform .2s ease;color:#777}.caret.expanded{transform:rotate(90deg)}.filter-list,.tag-list-items,.feed-list-items,.nav-list{list-style:none;padding:0;margin:0}.filter-list li,.nav-list li{margin-bottom:.1rem}.filter-list a,.nav-list a,.tag-link,.feed-title,.logout-link{text-decoration:none;color:var(--link-color, blue);font-size:.8rem;display:block;cursor:pointer;background:none;border:none;padding:0;font-family:inherit;font-variant:small-caps;text-transform:lowercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.filter-list a:hover,.nav-list a:hover,.tag-link:hover,.feed-title:hover,.logout-link:hover{text-decoration:underline;color:var(--link-color, blue)}.filter-list a.active,.tag-link.active,.feed-title.active{font-weight:700;color:#000}.tag-item,.sidebar-feed-item{margin-bottom:0}.feed-item-row{display:flex;align-items:center;gap:.5rem}.feed-checkbox{cursor:pointer;margin:0}.feed-category{display:none}.nav-section{margin-top:2rem;border-top:1px solid var(--border-color, #eee);padding-top:1rem}.logout-link{text-align:left;width:100%;color:#777;display:block}.nav-link,.logout-link{padding:.25rem 0}.logout-link:hover{color:var(--link-color, blue);text-decoration:underline}.theme-section{margin-top:1rem}.theme-selector{display:flex;gap:.5rem;margin-top:.5rem}.theme-selector button{background:#0000000d;border:none;cursor:pointer;padding:.4rem;font-size:1rem;border-radius:8px;line-height:1;transition:all .2s ease;display:flex;align-items:center;justify-content:center}.theme-selector button:hover{background:#0000001a;transform:translateY(-2px)}.theme-selector button.active{background:var(--border-color, #999);color:#fff;box-shadow:0 4px 8px #0000001a}.theme-dark .theme-selector button{background:#ffffff1a}.theme-dark .theme-selector button:hover{background:#fff3}.dashboard-sidebar::-webkit-scrollbar{width:4px}.dashboard-sidebar::-webkit-scrollbar-thumb{background-color:var(--border-color, #999)}.feed-list.variant-glass{background:#ffffff0d;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-right:1px solid rgba(255,255,255,.1);padding:1.5rem;font-family:system-ui,-apple-system,sans-serif;color:var(--text-color)}.feed-list.variant-glass .logo{font-size:1.5rem;background:transparent!important;margin-bottom:2rem;opacity:.8}.feed-list.variant-glass .section-header{font-size:.75rem;text-transform:uppercase;letter-spacing:.1em;color:var(--text-color);opacity:.5;margin-top:2rem;font-weight:600}.feed-list.variant-glass a,.feed-list.variant-glass .feed-title,.feed-list.variant-glass .tag-link{padding:.4rem .8rem;margin:.2rem 0;border-radius:8px;transition:all .2s ease;font-weight:500;text-decoration:none!important;color:var(--text-color);opacity:.8;border:none}.feed-list.variant-glass a:hover,.feed-list.variant-glass .feed-title:hover,.feed-list.variant-glass .tag-link:hover{background:#ffffff1a;opacity:1;transform:translate(4px);color:var(--text-color)}.feed-list.variant-glass a.active,.feed-list.variant-glass .feed-title.active,.feed-list.variant-glass .tag-link.active{background:#ffffff40;color:var(--text-color);font-weight:700;opacity:1;box-shadow:0 4px 12px #0000001a;border:1px solid rgba(255,255,255,.2)}.feed-list.variant-glass .search-input{border-radius:20px;background:#0000000d;border:1px solid rgba(255,255,255,.1);color:var(--text-color);padding:.5rem 1rem}.feed-list.variant-glass .nav-section{border-top:1px solid rgba(255,255,255,.1);margin-top:2rem;padding-top:1.5rem}.feed-list.variant-glass .nav-link,.feed-list.variant-glass .logout-link{opacity:.6;padding:.5rem .8rem;border-radius:8px}.feed-list.variant-glass .nav-link:hover,.feed-list.variant-glass .logout-link:hover{background:#ffffff0d;opacity:1;text-decoration:none}.feed-list.variant-glass .theme-selector button{background:#ffffff0d;border:1px solid rgba(255,255,255,.1);border-radius:12px}.feed-list.variant-glass .theme-selector button.active{background:#fff3;border-color:#ffffff4d}.feed-list.variant-banana{background:#fdfdfd;padding:1rem;font-family:Poppins,Verdana,sans-serif;border-right:none;box-shadow:4px 0 24px #0000000a}.theme-dark .feed-list.variant-banana{background:#111}.feed-list.variant-banana .logo{font-size:2.5rem;text-shadow:2px 2px 0px #FFD700;background:transparent;transform:rotate(-3deg);display:inline-block;margin-bottom:2rem}.feed-list.variant-banana .section-header{background:gold;color:#000;display:inline-block;padding:.2rem .5rem;transform:skew(-10deg);font-size:.8rem;font-weight:800;margin-bottom:1rem;border-radius:4px}.feed-list.variant-banana .search-input{border:2px solid #000;border-radius:8px;box-shadow:2px 2px #000;transition:all .2s}.feed-list.variant-banana .search-input:focus{transform:translate(1px,1px);box-shadow:1px 1px #000;outline:none}.theme-dark .feed-list.variant-banana .search-input{border-color:#fff;box-shadow:2px 2px #fff;background:#222;color:#fff}.feed-list.variant-banana a,.feed-list.variant-banana .feed-title,.feed-list.variant-banana .tag-link{border:1px solid transparent;padding:.5rem;border-radius:8px;transition:transform .2s cubic-bezier(.34,1.56,.64,1);font-weight:600;text-decoration:none!important;color:var(--text-color)}.feed-list.variant-banana a:hover,.feed-list.variant-banana .feed-title:hover,.feed-list.variant-banana .tag-link:hover{transform:scale(1.05) rotate(1deg);background:#fff9c4;color:#000;box-shadow:0 4px 12px #ffd7004d}.theme-dark .feed-list.variant-banana a:hover,.theme-dark .feed-list.variant-banana .feed-title:hover,.theme-dark .feed-list.variant-banana .tag-link:hover{background:#333;color:gold}.feed-list.variant-banana a.active,.feed-list.variant-banana .feed-title.active,.feed-list.variant-banana .tag-link.active{background:gold;color:#000!important;transform:scale(1.02);box-shadow:3px 3px #0000001a;border:2px solid #000}.feed-list.variant-banana .nav-section{border-top:2px dashed #FFD700;margin-top:2rem;padding-top:1rem}.feed-list.variant-banana .theme-selector button{border:2px solid #000;box-shadow:2px 2px #000;border-radius:4px}.feed-list.variant-banana .theme-selector button.active{background:gold;transform:translate(1px,1px);box-shadow:1px 1px #000}.feed-list.variant-type{background:var(--bg-color);padding:2rem 1rem;font-family:Helvetica Neue,Arial,sans-serif;border-right:4px solid var(--text-color)}.feed-list.variant-type .logo{font-size:3rem;letter-spacing:-2px;font-weight:900;background:transparent;line-height:.8;margin-bottom:3rem;color:var(--text-color)}.feed-list.variant-type .section-header{font-size:1.2rem;font-weight:900;border-bottom:2px solid var(--text-color);padding-bottom:.5rem;margin-top:3rem;margin-bottom:1rem;letter-spacing:-.5px;color:var(--text-color)}.feed-list.variant-type a,.feed-list.variant-type .feed-title,.feed-list.variant-type .tag-link{font-size:1rem;font-weight:700;text-decoration:none!important;border-left:0px solid var(--text-color);padding-left:0;transition:padding-left .2s,border-left-width .2s;opacity:.6;color:var(--text-color);padding:.5rem 0;display:block}.feed-list.variant-type a:hover,.feed-list.variant-type .feed-title:hover,.feed-list.variant-type .tag-link:hover{padding-left:1rem;border-left:4px solid var(--text-color);opacity:1;color:var(--text-color)}.feed-list.variant-type a.active,.feed-list.variant-type .feed-title.active,.feed-list.variant-type .tag-link.active{padding-left:1rem;border-left:8px solid var(--text-color);opacity:1;color:var(--text-color)}.feed-list.variant-type .search-input{border:none;border-bottom:2px solid var(--text-color);background:transparent;border-radius:0;padding:1rem 0;font-weight:700;font-size:1.2rem}.feed-list.variant-type .search-input:focus{outline:none;border-bottom-width:4px}.feed-list.variant-type .nav-section{border-top:4px solid var(--text-color);margin-top:4rem;padding-top:1rem}.feed-list.variant-type .nav-link,.feed-list.variant-type .logout-link{font-size:1.2rem;font-weight:900}.feed-list.variant-type .theme-selector button{border-radius:0;border:2px solid var(--text-color);background:transparent}.feed-list.variant-type .theme-selector button.active{background:var(--text-color);color:var(--bg-color)}.feed-item{padding:1rem;margin-top:5rem;list-style:none;border-bottom:none}.item-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.5rem}.item-title{font-family:var(--font-heading);font-size:1.8rem;font-weight:700;text-decoration:none;color:var(--link-color);display:block;flex:1}.item-title:hover{text-decoration:none;color:var(--link-color)}.item-actions{display:flex;gap:.5rem;margin-left:1rem}.star-btn{background:none;border:none;cursor:pointer;font-size:1.25rem;padding:0 0 0 .5rem;vertical-align:middle;transition:color .2s;line-height:1}.star-btn.is-starred{color:#00f}.star-btn.is-unstarred{color:var(--text-color);opacity:.3}.star-btn:hover{color:#00f}.action-btn{background:var(--sidebar-bg);border:1px solid var(--border-color, #ccc);cursor:pointer;padding:2px 6px;font-size:1rem;color:#00f;font-weight:700}.action-btn:hover{background-color:#eee}.dateline{margin-top:0;font-weight:400;font-size:.75em;color:#ccc;margin-bottom:1rem}.dateline a{color:#ccc;text-decoration:none}.item-description{color:var(--text-color);line-height:1.5;font-size:1rem;margin-top:1rem;overflow-wrap:break-word;word-break:break-word}.item-description table,.item-description pre,.item-description code{max-width:100%;overflow-x:auto;display:block}.item-description img{max-width:100%;height:auto;display:block;margin:1rem 0}.item-description blockquote{padding:1rem 1rem 0;border-left:4px solid var(--sidebar-bg);color:var(--text-color);opacity:.8;margin-left:0}.scrape-btn{background:var(--bg-color);border:1px solid var(--border-color, #ccc);color:#00f;cursor:pointer;font-family:var(--font-heading);font-weight:700;font-size:.8rem;padding:2px 6px;margin-left:.5rem}.scrape-btn:hover{background:var(--sidebar-bg)}@media(max-width:768px){.feed-item{margin-top:2rem;padding:.5rem}.item-title{font-size:1.4rem;word-break:break-word}.item-header{flex-direction:column;gap:.5rem}.item-actions{margin-left:0;margin-bottom:.5rem}}.feed-items{padding:1rem 0}.feed-items h2{margin-top:0;border-bottom:2px solid var(--border-color);padding-bottom:.5rem}.item-list{list-style:none;padding:0}.loading-more{padding:2rem;text-align:center;color:#888;font-size:.9rem;min-height:50px}.settings-page.variant-glass{padding:2.5rem;max-width:800px;margin:0 auto;background:#ffffff0d;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-radius:24px;border:1px solid rgba(255,255,255,.1);font-family:system-ui,-apple-system,sans-serif;color:var(--text-color);margin-top:2rem;margin-bottom:2rem}.settings-page.variant-glass h2,.settings-page.variant-glass h3{font-weight:700;letter-spacing:-.02em;color:var(--text-color);opacity:.9}.add-feed-section,.appearance-section,.import-section,.export-section,.feed-list-section{background:#ffffff08;padding:1.5rem;border-radius:16px;margin-bottom:2rem;border:1px solid rgba(255,255,255,.05);transition:all .3s ease}.add-feed-section:hover,.appearance-section:hover,.import-section:hover,.export-section:hover,.feed-list-section:hover{background:#ffffff0f;border-color:#ffffff1a}.font-selector{display:flex;align-items:center;gap:1rem}.font-select{padding:.6rem 1rem;border:1px solid rgba(255,255,255,.1);background:#0000001a;color:var(--text-color);border-radius:20px;font-size:1rem;min-width:200px;cursor:pointer;outline:none;transition:border-color .2s}.font-select:focus{border-color:#ffffff4d}.add-feed-form{display:flex;gap:1rem}.feed-input{flex:1;padding:.6rem 1.2rem;border:1px solid rgba(255,255,255,.1);background:#0000001a;color:var(--text-color);border-radius:20px;font-size:1rem;outline:none;transition:border-color .2s}.feed-input:focus{border-color:#ffffff4d}.error-message{color:#ff5252;margin-top:1rem;font-weight:600}.settings-feed-list{list-style:none;padding:0;border:1px solid rgba(255,255,255,.05);border-radius:12px;overflow:hidden}.settings-feed-item{display:flex;justify-content:space-between;align-items:center;padding:1.2rem;border-bottom:1px solid rgba(255,255,255,.05);transition:background .2s}.settings-feed-item:hover{background:#ffffff05}.settings-feed-item:last-child{border-bottom:none}.feed-info{display:flex;flex-direction:column;gap:.2rem}.feed-title{font-weight:600;font-size:1.05rem;opacity:.9}.feed-url{color:var(--text-color);opacity:.5;font-size:.85rem}.delete-btn{background:#ff525226;color:#ff8a80;border:1px solid rgba(255,82,82,.2);padding:.5rem 1rem;border-radius:12px;cursor:pointer;font-weight:600;transition:all .2s}.delete-btn:hover:not(:disabled){background:#ff52524d;color:#fff;border-color:#ff525266;transform:scale(1.05)}.import-export-section{display:flex;gap:2rem}@media(max-width:768px){.settings-page.variant-glass{padding:1.5rem;margin-top:1rem}.add-feed-form{flex-direction:column}.import-export-section{flex-direction:column;gap:1rem}.settings-feed-item{flex-direction:column;align-items:flex-start;gap:1rem}}.import-form{display:flex;flex-direction:column;gap:1.2rem}.file-input{font-size:.9rem;max-width:100%;color:var(--text-color);opacity:.8}.export-buttons{display:flex;gap:.8rem;flex-wrap:wrap}.export-btn{display:inline-block;padding:.6rem 1.2rem;background:#ffffff0d;color:var(--text-color);text-decoration:none;border:1px solid rgba(255,255,255,.1);border-radius:12px;font-weight:600;transition:all .2s}.export-btn:hover{background:#ffffff1a;transform:translateY(-2px);box-shadow:0 4px 12px #0000001a}button:not(.delete-btn){cursor:pointer;padding:.6rem 1.2rem;border-radius:12px;border:1px solid rgba(255,255,255,.1);background:#ffffff1a;color:var(--text-color);font-weight:600;transition:all .2s}button:not(.delete-btn):hover:not(:disabled){background:#fff3;transform:scale(1.02)}button:disabled{opacity:.4;cursor:not-allowed} diff --git a/web/dist/v2/assets/index-Dh9FpypQ.js b/web/dist/v2/assets/index-Dh9FpypQ.js deleted file mode 100644 index bbb2b24..0000000 --- a/web/dist/v2/assets/index-Dh9FpypQ.js +++ /dev/null @@ -1,11 +0,0 @@ -(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))f(d);new MutationObserver(d=>{for(const h of d)if(h.type==="childList")for(const p of h.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&f(p)}).observe(document,{childList:!0,subtree:!0});function o(d){const h={};return d.integrity&&(h.integrity=d.integrity),d.referrerPolicy&&(h.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?h.credentials="include":d.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function f(d){if(d.ep)return;d.ep=!0;const h=o(d);fetch(d.href,h)}})();function nv(c){return c&&c.__esModule&&Object.prototype.hasOwnProperty.call(c,"default")?c.default:c}var Mf={exports:{}},Un={};var Pd;function uv(){if(Pd)return Un;Pd=1;var c=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function o(f,d,h){var p=null;if(h!==void 0&&(p=""+h),d.key!==void 0&&(p=""+d.key),"key"in d){h={};for(var _ in d)_!=="key"&&(h[_]=d[_])}else h=d;return d=h.ref,{$$typeof:c,type:f,key:p,ref:d!==void 0?d:null,props:h}}return Un.Fragment=r,Un.jsx=o,Un.jsxs=o,Un}var th;function iv(){return th||(th=1,Mf.exports=uv()),Mf.exports}var M=iv(),Nf={exports:{}},at={};var eh;function cv(){if(eh)return at;eh=1;var c=Symbol.for("react.transitional.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),h=Symbol.for("react.consumer"),p=Symbol.for("react.context"),_=Symbol.for("react.forward_ref"),S=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),N=Symbol.for("react.lazy"),R=Symbol.for("react.activity"),B=Symbol.iterator;function K(v){return v===null||typeof v!="object"?null:(v=B&&v[B]||v["@@iterator"],typeof v=="function"?v:null)}var $={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Q=Object.assign,X={};function H(v,D,Y){this.props=v,this.context=D,this.refs=X,this.updater=Y||$}H.prototype.isReactComponent={},H.prototype.setState=function(v,D){if(typeof v!="object"&&typeof v!="function"&&v!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,v,D,"setState")},H.prototype.forceUpdate=function(v){this.updater.enqueueForceUpdate(this,v,"forceUpdate")};function q(){}q.prototype=H.prototype;function G(v,D,Y){this.props=v,this.context=D,this.refs=X,this.updater=Y||$}var dt=G.prototype=new q;dt.constructor=G,Q(dt,H.prototype),dt.isPureReactComponent=!0;var mt=Array.isArray;function St(){}var et={H:null,A:null,T:null,S:null},xt=Object.prototype.hasOwnProperty;function Rt(v,D,Y){var V=Y.ref;return{$$typeof:c,type:v,key:D,ref:V!==void 0?V:null,props:Y}}function Yt(v,D){return Rt(v.type,D,v.props)}function I(v){return typeof v=="object"&&v!==null&&v.$$typeof===c}function W(v){var D={"=":"=0",":":"=2"};return"$"+v.replace(/[=:]/g,function(Y){return D[Y]})}var tt=/\/+/g;function it(v,D){return typeof v=="object"&&v!==null&&v.key!=null?W(""+v.key):D.toString(36)}function Ht(v){switch(v.status){case"fulfilled":return v.value;case"rejected":throw v.reason;default:switch(typeof v.status=="string"?v.then(St,St):(v.status="pending",v.then(function(D){v.status==="pending"&&(v.status="fulfilled",v.value=D)},function(D){v.status==="pending"&&(v.status="rejected",v.reason=D)})),v.status){case"fulfilled":return v.value;case"rejected":throw v.reason}}throw v}function x(v,D,Y,V,lt){var ct=typeof v;(ct==="undefined"||ct==="boolean")&&(v=null);var bt=!1;if(v===null)bt=!0;else switch(ct){case"bigint":case"string":case"number":bt=!0;break;case"object":switch(v.$$typeof){case c:case r:bt=!0;break;case N:return bt=v._init,x(bt(v._payload),D,Y,V,lt)}}if(bt)return lt=lt(v),bt=V===""?"."+it(v,0):V,mt(lt)?(Y="",bt!=null&&(Y=bt.replace(tt,"$&/")+"/"),x(lt,D,Y,"",function(Ya){return Ya})):lt!=null&&(I(lt)&&(lt=Yt(lt,Y+(lt.key==null||v&&v.key===lt.key?"":(""+lt.key).replace(tt,"$&/")+"/")+bt)),D.push(lt)),1;bt=0;var Pt=V===""?".":V+":";if(mt(v))for(var Bt=0;Bt<v.length;Bt++)V=v[Bt],ct=Pt+it(V,Bt),bt+=x(V,D,Y,ct,lt);else if(Bt=K(v),typeof Bt=="function")for(v=Bt.call(v),Bt=0;!(V=v.next()).done;)V=V.value,ct=Pt+it(V,Bt++),bt+=x(V,D,Y,ct,lt);else if(ct==="object"){if(typeof v.then=="function")return x(Ht(v),D,Y,V,lt);throw D=String(v),Error("Objects are not valid as a React child (found: "+(D==="[object Object]"?"object with keys {"+Object.keys(v).join(", ")+"}":D)+"). If you meant to render a collection of children, use an array instead.")}return bt}function L(v,D,Y){if(v==null)return v;var V=[],lt=0;return x(v,V,"","",function(ct){return D.call(Y,ct,lt++)}),V}function k(v){if(v._status===-1){var D=v._result;D=D(),D.then(function(Y){(v._status===0||v._status===-1)&&(v._status=1,v._result=Y)},function(Y){(v._status===0||v._status===-1)&&(v._status=2,v._result=Y)}),v._status===-1&&(v._status=0,v._result=D)}if(v._status===1)return v._result.default;throw v._result}var yt=typeof reportError=="function"?reportError:function(v){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var D=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof v=="object"&&v!==null&&typeof v.message=="string"?String(v.message):String(v),error:v});if(!window.dispatchEvent(D))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",v);return}console.error(v)},Z={map:L,forEach:function(v,D,Y){L(v,function(){D.apply(this,arguments)},Y)},count:function(v){var D=0;return L(v,function(){D++}),D},toArray:function(v){return L(v,function(D){return D})||[]},only:function(v){if(!I(v))throw Error("React.Children.only expected to receive a single React element child.");return v}};return at.Activity=R,at.Children=Z,at.Component=H,at.Fragment=o,at.Profiler=d,at.PureComponent=G,at.StrictMode=f,at.Suspense=S,at.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=et,at.__COMPILER_RUNTIME={__proto__:null,c:function(v){return et.H.useMemoCache(v)}},at.cache=function(v){return function(){return v.apply(null,arguments)}},at.cacheSignal=function(){return null},at.cloneElement=function(v,D,Y){if(v==null)throw Error("The argument must be a React element, but you passed "+v+".");var V=Q({},v.props),lt=v.key;if(D!=null)for(ct in D.key!==void 0&&(lt=""+D.key),D)!xt.call(D,ct)||ct==="key"||ct==="__self"||ct==="__source"||ct==="ref"&&D.ref===void 0||(V[ct]=D[ct]);var ct=arguments.length-2;if(ct===1)V.children=Y;else if(1<ct){for(var bt=Array(ct),Pt=0;Pt<ct;Pt++)bt[Pt]=arguments[Pt+2];V.children=bt}return Rt(v.type,lt,V)},at.createContext=function(v){return v={$$typeof:p,_currentValue:v,_currentValue2:v,_threadCount:0,Provider:null,Consumer:null},v.Provider=v,v.Consumer={$$typeof:h,_context:v},v},at.createElement=function(v,D,Y){var V,lt={},ct=null;if(D!=null)for(V in D.key!==void 0&&(ct=""+D.key),D)xt.call(D,V)&&V!=="key"&&V!=="__self"&&V!=="__source"&&(lt[V]=D[V]);var bt=arguments.length-2;if(bt===1)lt.children=Y;else if(1<bt){for(var Pt=Array(bt),Bt=0;Bt<bt;Bt++)Pt[Bt]=arguments[Bt+2];lt.children=Pt}if(v&&v.defaultProps)for(V in bt=v.defaultProps,bt)lt[V]===void 0&&(lt[V]=bt[V]);return Rt(v,ct,lt)},at.createRef=function(){return{current:null}},at.forwardRef=function(v){return{$$typeof:_,render:v}},at.isValidElement=I,at.lazy=function(v){return{$$typeof:N,_payload:{_status:-1,_result:v},_init:k}},at.memo=function(v,D){return{$$typeof:y,type:v,compare:D===void 0?null:D}},at.startTransition=function(v){var D=et.T,Y={};et.T=Y;try{var V=v(),lt=et.S;lt!==null&<(Y,V),typeof V=="object"&&V!==null&&typeof V.then=="function"&&V.then(St,yt)}catch(ct){yt(ct)}finally{D!==null&&Y.types!==null&&(D.types=Y.types),et.T=D}},at.unstable_useCacheRefresh=function(){return et.H.useCacheRefresh()},at.use=function(v){return et.H.use(v)},at.useActionState=function(v,D,Y){return et.H.useActionState(v,D,Y)},at.useCallback=function(v,D){return et.H.useCallback(v,D)},at.useContext=function(v){return et.H.useContext(v)},at.useDebugValue=function(){},at.useDeferredValue=function(v,D){return et.H.useDeferredValue(v,D)},at.useEffect=function(v,D){return et.H.useEffect(v,D)},at.useEffectEvent=function(v){return et.H.useEffectEvent(v)},at.useId=function(){return et.H.useId()},at.useImperativeHandle=function(v,D,Y){return et.H.useImperativeHandle(v,D,Y)},at.useInsertionEffect=function(v,D){return et.H.useInsertionEffect(v,D)},at.useLayoutEffect=function(v,D){return et.H.useLayoutEffect(v,D)},at.useMemo=function(v,D){return et.H.useMemo(v,D)},at.useOptimistic=function(v,D){return et.H.useOptimistic(v,D)},at.useReducer=function(v,D,Y){return et.H.useReducer(v,D,Y)},at.useRef=function(v){return et.H.useRef(v)},at.useState=function(v){return et.H.useState(v)},at.useSyncExternalStore=function(v,D,Y){return et.H.useSyncExternalStore(v,D,Y)},at.useTransition=function(){return et.H.useTransition()},at.version="19.2.4",at}var lh;function Zf(){return lh||(lh=1,Nf.exports=cv()),Nf.exports}var E=Zf();const fv=nv(E);var Cf={exports:{}},jn={},Df={exports:{}},Uf={};var ah;function sv(){return ah||(ah=1,(function(c){function r(x,L){var k=x.length;x.push(L);t:for(;0<k;){var yt=k-1>>>1,Z=x[yt];if(0<d(Z,L))x[yt]=L,x[k]=Z,k=yt;else break t}}function o(x){return x.length===0?null:x[0]}function f(x){if(x.length===0)return null;var L=x[0],k=x.pop();if(k!==L){x[0]=k;t:for(var yt=0,Z=x.length,v=Z>>>1;yt<v;){var D=2*(yt+1)-1,Y=x[D],V=D+1,lt=x[V];if(0>d(Y,k))V<Z&&0>d(lt,Y)?(x[yt]=lt,x[V]=k,yt=V):(x[yt]=Y,x[D]=k,yt=D);else if(V<Z&&0>d(lt,k))x[yt]=lt,x[V]=k,yt=V;else break t}}return L}function d(x,L){var k=x.sortIndex-L.sortIndex;return k!==0?k:x.id-L.id}if(c.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var h=performance;c.unstable_now=function(){return h.now()}}else{var p=Date,_=p.now();c.unstable_now=function(){return p.now()-_}}var S=[],y=[],N=1,R=null,B=3,K=!1,$=!1,Q=!1,X=!1,H=typeof setTimeout=="function"?setTimeout:null,q=typeof clearTimeout=="function"?clearTimeout:null,G=typeof setImmediate<"u"?setImmediate:null;function dt(x){for(var L=o(y);L!==null;){if(L.callback===null)f(y);else if(L.startTime<=x)f(y),L.sortIndex=L.expirationTime,r(S,L);else break;L=o(y)}}function mt(x){if(Q=!1,dt(x),!$)if(o(S)!==null)$=!0,St||(St=!0,W());else{var L=o(y);L!==null&&Ht(mt,L.startTime-x)}}var St=!1,et=-1,xt=5,Rt=-1;function Yt(){return X?!0:!(c.unstable_now()-Rt<xt)}function I(){if(X=!1,St){var x=c.unstable_now();Rt=x;var L=!0;try{t:{$=!1,Q&&(Q=!1,q(et),et=-1),K=!0;var k=B;try{e:{for(dt(x),R=o(S);R!==null&&!(R.expirationTime>x&&Yt());){var yt=R.callback;if(typeof yt=="function"){R.callback=null,B=R.priorityLevel;var Z=yt(R.expirationTime<=x);if(x=c.unstable_now(),typeof Z=="function"){R.callback=Z,dt(x),L=!0;break e}R===o(S)&&f(S),dt(x)}else f(S);R=o(S)}if(R!==null)L=!0;else{var v=o(y);v!==null&&Ht(mt,v.startTime-x),L=!1}}break t}finally{R=null,B=k,K=!1}L=void 0}}finally{L?W():St=!1}}}var W;if(typeof G=="function")W=function(){G(I)};else if(typeof MessageChannel<"u"){var tt=new MessageChannel,it=tt.port2;tt.port1.onmessage=I,W=function(){it.postMessage(null)}}else W=function(){H(I,0)};function Ht(x,L){et=H(function(){x(c.unstable_now())},L)}c.unstable_IdlePriority=5,c.unstable_ImmediatePriority=1,c.unstable_LowPriority=4,c.unstable_NormalPriority=3,c.unstable_Profiling=null,c.unstable_UserBlockingPriority=2,c.unstable_cancelCallback=function(x){x.callback=null},c.unstable_forceFrameRate=function(x){0>x||125<x?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):xt=0<x?Math.floor(1e3/x):5},c.unstable_getCurrentPriorityLevel=function(){return B},c.unstable_next=function(x){switch(B){case 1:case 2:case 3:var L=3;break;default:L=B}var k=B;B=L;try{return x()}finally{B=k}},c.unstable_requestPaint=function(){X=!0},c.unstable_runWithPriority=function(x,L){switch(x){case 1:case 2:case 3:case 4:case 5:break;default:x=3}var k=B;B=x;try{return L()}finally{B=k}},c.unstable_scheduleCallback=function(x,L,k){var yt=c.unstable_now();switch(typeof k=="object"&&k!==null?(k=k.delay,k=typeof k=="number"&&0<k?yt+k:yt):k=yt,x){case 1:var Z=-1;break;case 2:Z=250;break;case 5:Z=1073741823;break;case 4:Z=1e4;break;default:Z=5e3}return Z=k+Z,x={id:N++,callback:L,priorityLevel:x,startTime:k,expirationTime:Z,sortIndex:-1},k>yt?(x.sortIndex=k,r(y,x),o(S)===null&&x===o(y)&&(Q?(q(et),et=-1):Q=!0,Ht(mt,k-yt))):(x.sortIndex=Z,r(S,x),$||K||($=!0,St||(St=!0,W()))),x},c.unstable_shouldYield=Yt,c.unstable_wrapCallback=function(x){var L=B;return function(){var k=B;B=L;try{return x.apply(this,arguments)}finally{B=k}}}})(Uf)),Uf}var nh;function rv(){return nh||(nh=1,Df.exports=sv()),Df.exports}var jf={exports:{}},It={};var uh;function ov(){if(uh)return It;uh=1;var c=Zf();function r(S){var y="https://react.dev/errors/"+S;if(1<arguments.length){y+="?args[]="+encodeURIComponent(arguments[1]);for(var N=2;N<arguments.length;N++)y+="&args[]="+encodeURIComponent(arguments[N])}return"Minified React error #"+S+"; visit "+y+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function o(){}var f={d:{f:o,r:function(){throw Error(r(522))},D:o,C:o,L:o,m:o,X:o,S:o,M:o},p:0,findDOMNode:null},d=Symbol.for("react.portal");function h(S,y,N){var R=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:d,key:R==null?null:""+R,children:S,containerInfo:y,implementation:N}}var p=c.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function _(S,y){if(S==="font")return"";if(typeof y=="string")return y==="use-credentials"?y:""}return It.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=f,It.createPortal=function(S,y){var N=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!y||y.nodeType!==1&&y.nodeType!==9&&y.nodeType!==11)throw Error(r(299));return h(S,y,null,N)},It.flushSync=function(S){var y=p.T,N=f.p;try{if(p.T=null,f.p=2,S)return S()}finally{p.T=y,f.p=N,f.d.f()}},It.preconnect=function(S,y){typeof S=="string"&&(y?(y=y.crossOrigin,y=typeof y=="string"?y==="use-credentials"?y:"":void 0):y=null,f.d.C(S,y))},It.prefetchDNS=function(S){typeof S=="string"&&f.d.D(S)},It.preinit=function(S,y){if(typeof S=="string"&&y&&typeof y.as=="string"){var N=y.as,R=_(N,y.crossOrigin),B=typeof y.integrity=="string"?y.integrity:void 0,K=typeof y.fetchPriority=="string"?y.fetchPriority:void 0;N==="style"?f.d.S(S,typeof y.precedence=="string"?y.precedence:void 0,{crossOrigin:R,integrity:B,fetchPriority:K}):N==="script"&&f.d.X(S,{crossOrigin:R,integrity:B,fetchPriority:K,nonce:typeof y.nonce=="string"?y.nonce:void 0})}},It.preinitModule=function(S,y){if(typeof S=="string")if(typeof y=="object"&&y!==null){if(y.as==null||y.as==="script"){var N=_(y.as,y.crossOrigin);f.d.M(S,{crossOrigin:N,integrity:typeof y.integrity=="string"?y.integrity:void 0,nonce:typeof y.nonce=="string"?y.nonce:void 0})}}else y==null&&f.d.M(S)},It.preload=function(S,y){if(typeof S=="string"&&typeof y=="object"&&y!==null&&typeof y.as=="string"){var N=y.as,R=_(N,y.crossOrigin);f.d.L(S,N,{crossOrigin:R,integrity:typeof y.integrity=="string"?y.integrity:void 0,nonce:typeof y.nonce=="string"?y.nonce:void 0,type:typeof y.type=="string"?y.type:void 0,fetchPriority:typeof y.fetchPriority=="string"?y.fetchPriority:void 0,referrerPolicy:typeof y.referrerPolicy=="string"?y.referrerPolicy:void 0,imageSrcSet:typeof y.imageSrcSet=="string"?y.imageSrcSet:void 0,imageSizes:typeof y.imageSizes=="string"?y.imageSizes:void 0,media:typeof y.media=="string"?y.media:void 0})}},It.preloadModule=function(S,y){if(typeof S=="string")if(y){var N=_(y.as,y.crossOrigin);f.d.m(S,{as:typeof y.as=="string"&&y.as!=="script"?y.as:void 0,crossOrigin:N,integrity:typeof y.integrity=="string"?y.integrity:void 0})}else f.d.m(S)},It.requestFormReset=function(S){f.d.r(S)},It.unstable_batchedUpdates=function(S,y){return S(y)},It.useFormState=function(S,y,N){return p.H.useFormState(S,y,N)},It.useFormStatus=function(){return p.H.useHostTransitionStatus()},It.version="19.2.4",It}var ih;function dv(){if(ih)return jf.exports;ih=1;function c(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(r){console.error(r)}}return c(),jf.exports=ov(),jf.exports}var ch;function hv(){if(ch)return jn;ch=1;var c=rv(),r=Zf(),o=dv();function f(t){var e="https://react.dev/errors/"+t;if(1<arguments.length){e+="?args[]="+encodeURIComponent(arguments[1]);for(var l=2;l<arguments.length;l++)e+="&args[]="+encodeURIComponent(arguments[l])}return"Minified React error #"+t+"; visit "+e+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function d(t){return!(!t||t.nodeType!==1&&t.nodeType!==9&&t.nodeType!==11)}function h(t){var e=t,l=t;if(t.alternate)for(;e.return;)e=e.return;else{t=e;do e=t,(e.flags&4098)!==0&&(l=e.return),t=e.return;while(t)}return e.tag===3?l:null}function p(t){if(t.tag===13){var e=t.memoizedState;if(e===null&&(t=t.alternate,t!==null&&(e=t.memoizedState)),e!==null)return e.dehydrated}return null}function _(t){if(t.tag===31){var e=t.memoizedState;if(e===null&&(t=t.alternate,t!==null&&(e=t.memoizedState)),e!==null)return e.dehydrated}return null}function S(t){if(h(t)!==t)throw Error(f(188))}function y(t){var e=t.alternate;if(!e){if(e=h(t),e===null)throw Error(f(188));return e!==t?null:t}for(var l=t,a=e;;){var n=l.return;if(n===null)break;var u=n.alternate;if(u===null){if(a=n.return,a!==null){l=a;continue}break}if(n.child===u.child){for(u=n.child;u;){if(u===l)return S(n),t;if(u===a)return S(n),e;u=u.sibling}throw Error(f(188))}if(l.return!==a.return)l=n,a=u;else{for(var i=!1,s=n.child;s;){if(s===l){i=!0,l=n,a=u;break}if(s===a){i=!0,a=n,l=u;break}s=s.sibling}if(!i){for(s=u.child;s;){if(s===l){i=!0,l=u,a=n;break}if(s===a){i=!0,a=u,l=n;break}s=s.sibling}if(!i)throw Error(f(189))}}if(l.alternate!==a)throw Error(f(190))}if(l.tag!==3)throw Error(f(188));return l.stateNode.current===l?t:e}function N(t){var e=t.tag;if(e===5||e===26||e===27||e===6)return t;for(t=t.child;t!==null;){if(e=N(t),e!==null)return e;t=t.sibling}return null}var R=Object.assign,B=Symbol.for("react.element"),K=Symbol.for("react.transitional.element"),$=Symbol.for("react.portal"),Q=Symbol.for("react.fragment"),X=Symbol.for("react.strict_mode"),H=Symbol.for("react.profiler"),q=Symbol.for("react.consumer"),G=Symbol.for("react.context"),dt=Symbol.for("react.forward_ref"),mt=Symbol.for("react.suspense"),St=Symbol.for("react.suspense_list"),et=Symbol.for("react.memo"),xt=Symbol.for("react.lazy"),Rt=Symbol.for("react.activity"),Yt=Symbol.for("react.memo_cache_sentinel"),I=Symbol.iterator;function W(t){return t===null||typeof t!="object"?null:(t=I&&t[I]||t["@@iterator"],typeof t=="function"?t:null)}var tt=Symbol.for("react.client.reference");function it(t){if(t==null)return null;if(typeof t=="function")return t.$$typeof===tt?null:t.displayName||t.name||null;if(typeof t=="string")return t;switch(t){case Q:return"Fragment";case H:return"Profiler";case X:return"StrictMode";case mt:return"Suspense";case St:return"SuspenseList";case Rt:return"Activity"}if(typeof t=="object")switch(t.$$typeof){case $:return"Portal";case G:return t.displayName||"Context";case q:return(t._context.displayName||"Context")+".Consumer";case dt:var e=t.render;return t=t.displayName,t||(t=e.displayName||e.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case et:return e=t.displayName||null,e!==null?e:it(t.type)||"Memo";case xt:e=t._payload,t=t._init;try{return it(t(e))}catch{}}return null}var Ht=Array.isArray,x=r.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,L=o.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,k={pending:!1,data:null,method:null,action:null},yt=[],Z=-1;function v(t){return{current:t}}function D(t){0>Z||(t.current=yt[Z],yt[Z]=null,Z--)}function Y(t,e){Z++,yt[Z]=t.current,t.current=e}var V=v(null),lt=v(null),ct=v(null),bt=v(null);function Pt(t,e){switch(Y(ct,e),Y(lt,t),Y(V,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?Td(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=Td(e),t=zd(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}D(V),Y(V,t)}function Bt(){D(V),D(lt),D(ct)}function Ya(t){t.memoizedState!==null&&Y(bt,t);var e=V.current,l=zd(e,t.type);e!==l&&(Y(lt,t),Y(V,l))}function Xn(t){lt.current===t&&(D(V),D(lt)),bt.current===t&&(D(bt),Mn._currentValue=k)}var ri,Wf;function Dl(t){if(ri===void 0)try{throw Error()}catch(l){var e=l.stack.trim().match(/\n( *(at )?)/);ri=e&&e[1]||"",Wf=-1<l.stack.indexOf(` - at`)?" (<anonymous>)":-1<l.stack.indexOf("@")?"@unknown:0:0":""}return` -`+ri+t+Wf}var oi=!1;function di(t,e){if(!t||oi)return"";oi=!0;var l=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var a={DetermineComponentFrameRoot:function(){try{if(e){var j=function(){throw Error()};if(Object.defineProperty(j.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(j,[])}catch(O){var A=O}Reflect.construct(t,[],j)}else{try{j.call()}catch(O){A=O}t.call(j.prototype)}}else{try{throw Error()}catch(O){A=O}(j=t())&&typeof j.catch=="function"&&j.catch(function(){})}}catch(O){if(O&&A&&typeof O.stack=="string")return[O.stack,A.stack]}return[null,null]}};a.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var n=Object.getOwnPropertyDescriptor(a.DetermineComponentFrameRoot,"name");n&&n.configurable&&Object.defineProperty(a.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var u=a.DetermineComponentFrameRoot(),i=u[0],s=u[1];if(i&&s){var m=i.split(` -`),z=s.split(` -`);for(n=a=0;a<m.length&&!m[a].includes("DetermineComponentFrameRoot");)a++;for(;n<z.length&&!z[n].includes("DetermineComponentFrameRoot");)n++;if(a===m.length||n===z.length)for(a=m.length-1,n=z.length-1;1<=a&&0<=n&&m[a]!==z[n];)n--;for(;1<=a&&0<=n;a--,n--)if(m[a]!==z[n]){if(a!==1||n!==1)do if(a--,n--,0>n||m[a]!==z[n]){var C=` -`+m[a].replace(" at new "," at ");return t.displayName&&C.includes("<anonymous>")&&(C=C.replace("<anonymous>",t.displayName)),C}while(1<=a&&0<=n);break}}}finally{oi=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?Dl(l):""}function Hh(t,e){switch(t.tag){case 26:case 27:case 5:return Dl(t.type);case 16:return Dl("Lazy");case 13:return t.child!==e&&e!==null?Dl("Suspense Fallback"):Dl("Suspense");case 19:return Dl("SuspenseList");case 0:case 15:return di(t.type,!1);case 11:return di(t.type.render,!1);case 1:return di(t.type,!0);case 31:return Dl("Activity");default:return""}}function If(t){try{var e="",l=null;do e+=Hh(t,l),l=t,t=t.return;while(t);return e}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var hi=Object.prototype.hasOwnProperty,mi=c.unstable_scheduleCallback,yi=c.unstable_cancelCallback,Bh=c.unstable_shouldYield,qh=c.unstable_requestPaint,se=c.unstable_now,Lh=c.unstable_getCurrentPriorityLevel,Pf=c.unstable_ImmediatePriority,ts=c.unstable_UserBlockingPriority,Qn=c.unstable_NormalPriority,Yh=c.unstable_LowPriority,es=c.unstable_IdlePriority,Gh=c.log,Xh=c.unstable_setDisableYieldValue,Ga=null,re=null;function il(t){if(typeof Gh=="function"&&Xh(t),re&&typeof re.setStrictMode=="function")try{re.setStrictMode(Ga,t)}catch{}}var oe=Math.clz32?Math.clz32:Vh,Qh=Math.log,Zh=Math.LN2;function Vh(t){return t>>>=0,t===0?32:31-(Qh(t)/Zh|0)|0}var Zn=256,Vn=262144,wn=4194304;function Ul(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&261888;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function Kn(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var n=0,u=t.suspendedLanes,i=t.pingedLanes;t=t.warmLanes;var s=a&134217727;return s!==0?(a=s&~u,a!==0?n=Ul(a):(i&=s,i!==0?n=Ul(i):l||(l=s&~t,l!==0&&(n=Ul(l))))):(s=a&~u,s!==0?n=Ul(s):i!==0?n=Ul(i):l||(l=a&~t,l!==0&&(n=Ul(l)))),n===0?0:e!==0&&e!==n&&(e&u)===0&&(u=n&-n,l=e&-e,u>=l||u===32&&(l&4194048)!==0)?e:n}function Xa(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function wh(t,e){switch(t){case 1:case 2:case 4:case 8:case 64:return e+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ls(){var t=wn;return wn<<=1,(wn&62914560)===0&&(wn=4194304),t}function vi(t){for(var e=[],l=0;31>l;l++)e.push(t);return e}function Qa(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function Kh(t,e,l,a,n,u){var i=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var s=t.entanglements,m=t.expirationTimes,z=t.hiddenUpdates;for(l=i&~l;0<l;){var C=31-oe(l),j=1<<C;s[C]=0,m[C]=-1;var A=z[C];if(A!==null)for(z[C]=null,C=0;C<A.length;C++){var O=A[C];O!==null&&(O.lane&=-536870913)}l&=~j}a!==0&&as(t,a,0),u!==0&&n===0&&t.tag!==0&&(t.suspendedLanes|=u&~(i&~e))}function as(t,e,l){t.pendingLanes|=e,t.suspendedLanes&=~e;var a=31-oe(e);t.entangledLanes|=e,t.entanglements[a]=t.entanglements[a]|1073741824|l&261930}function ns(t,e){var l=t.entangledLanes|=e;for(t=t.entanglements;l;){var a=31-oe(l),n=1<<a;n&e|t[a]&e&&(t[a]|=e),l&=~n}}function us(t,e){var l=e&-e;return l=(l&42)!==0?1:gi(l),(l&(t.suspendedLanes|e))!==0?0:l}function gi(t){switch(t){case 2:t=1;break;case 8:t=4;break;case 32:t=16;break;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:t=128;break;case 268435456:t=134217728;break;default:t=0}return t}function pi(t){return t&=-t,2<t?8<t?(t&134217727)!==0?32:268435456:8:2}function is(){var t=L.p;return t!==0?t:(t=window.event,t===void 0?32:Kd(t.type))}function cs(t,e){var l=L.p;try{return L.p=t,e()}finally{L.p=l}}var cl=Math.random().toString(36).slice(2),Jt="__reactFiber$"+cl,ee="__reactProps$"+cl,ta="__reactContainer$"+cl,Si="__reactEvents$"+cl,Jh="__reactListeners$"+cl,$h="__reactHandles$"+cl,fs="__reactResources$"+cl,Za="__reactMarker$"+cl;function bi(t){delete t[Jt],delete t[ee],delete t[Si],delete t[Jh],delete t[$h]}function ea(t){var e=t[Jt];if(e)return e;for(var l=t.parentNode;l;){if(e=l[ta]||l[Jt]){if(l=e.alternate,e.child!==null||l!==null&&l.child!==null)for(t=Nd(t);t!==null;){if(l=t[Jt])return l;t=Nd(t)}return e}t=l,l=t.parentNode}return null}function la(t){if(t=t[Jt]||t[ta]){var e=t.tag;if(e===5||e===6||e===13||e===31||e===26||e===27||e===3)return t}return null}function Va(t){var e=t.tag;if(e===5||e===26||e===27||e===6)return t.stateNode;throw Error(f(33))}function aa(t){var e=t[fs];return e||(e=t[fs]={hoistableStyles:new Map,hoistableScripts:new Map}),e}function wt(t){t[Za]=!0}var ss=new Set,rs={};function jl(t,e){na(t,e),na(t+"Capture",e)}function na(t,e){for(rs[t]=e,t=0;t<e.length;t++)ss.add(e[t])}var kh=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),os={},ds={};function Fh(t){return hi.call(ds,t)?!0:hi.call(os,t)?!1:kh.test(t)?ds[t]=!0:(os[t]=!0,!1)}function Jn(t,e,l){if(Fh(e))if(l===null)t.removeAttribute(e);else{switch(typeof l){case"undefined":case"function":case"symbol":t.removeAttribute(e);return;case"boolean":var a=e.toLowerCase().slice(0,5);if(a!=="data-"&&a!=="aria-"){t.removeAttribute(e);return}}t.setAttribute(e,""+l)}}function $n(t,e,l){if(l===null)t.removeAttribute(e);else{switch(typeof l){case"undefined":case"function":case"symbol":case"boolean":t.removeAttribute(e);return}t.setAttribute(e,""+l)}}function Ge(t,e,l,a){if(a===null)t.removeAttribute(l);else{switch(typeof a){case"undefined":case"function":case"symbol":case"boolean":t.removeAttribute(l);return}t.setAttributeNS(e,l,""+a)}}function Ee(t){switch(typeof t){case"bigint":case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function hs(t){var e=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(e==="checkbox"||e==="radio")}function Wh(t,e,l){var a=Object.getOwnPropertyDescriptor(t.constructor.prototype,e);if(!t.hasOwnProperty(e)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var n=a.get,u=a.set;return Object.defineProperty(t,e,{configurable:!0,get:function(){return n.call(this)},set:function(i){l=""+i,u.call(this,i)}}),Object.defineProperty(t,e,{enumerable:a.enumerable}),{getValue:function(){return l},setValue:function(i){l=""+i},stopTracking:function(){t._valueTracker=null,delete t[e]}}}}function Ei(t){if(!t._valueTracker){var e=hs(t)?"checked":"value";t._valueTracker=Wh(t,e,""+t[e])}}function ms(t){if(!t)return!1;var e=t._valueTracker;if(!e)return!0;var l=e.getValue(),a="";return t&&(a=hs(t)?t.checked?"true":"false":t.value),t=a,t!==l?(e.setValue(t),!0):!1}function kn(t){if(t=t||(typeof document<"u"?document:void 0),typeof t>"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var Ih=/[\n"\\]/g;function Te(t){return t.replace(Ih,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function Ti(t,e,l,a,n,u,i,s){t.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?t.type=i:t.removeAttribute("type"),e!=null?i==="number"?(e===0&&t.value===""||t.value!=e)&&(t.value=""+Ee(e)):t.value!==""+Ee(e)&&(t.value=""+Ee(e)):i!=="submit"&&i!=="reset"||t.removeAttribute("value"),e!=null?zi(t,i,Ee(e)):l!=null?zi(t,i,Ee(l)):a!=null&&t.removeAttribute("value"),n==null&&u!=null&&(t.defaultChecked=!!u),n!=null&&(t.checked=n&&typeof n!="function"&&typeof n!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?t.name=""+Ee(s):t.removeAttribute("name")}function ys(t,e,l,a,n,u,i,s){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(t.type=u),e!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||e!=null)){Ei(t);return}l=l!=null?""+Ee(l):"",e=e!=null?""+Ee(e):l,s||e===t.value||(t.value=e),t.defaultValue=e}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,t.checked=s?t.checked:!!a,t.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(t.name=i),Ei(t)}function zi(t,e,l){e==="number"&&kn(t.ownerDocument)===t||t.defaultValue===""+l||(t.defaultValue=""+l)}function ua(t,e,l,a){if(t=t.options,e){e={};for(var n=0;n<l.length;n++)e["$"+l[n]]=!0;for(l=0;l<t.length;l++)n=e.hasOwnProperty("$"+t[l].value),t[l].selected!==n&&(t[l].selected=n),n&&a&&(t[l].defaultSelected=!0)}else{for(l=""+Ee(l),e=null,n=0;n<t.length;n++){if(t[n].value===l){t[n].selected=!0,a&&(t[n].defaultSelected=!0);return}e!==null||t[n].disabled||(e=t[n])}e!==null&&(e.selected=!0)}}function vs(t,e,l){if(e!=null&&(e=""+Ee(e),e!==t.value&&(t.value=e),l==null)){t.defaultValue!==e&&(t.defaultValue=e);return}t.defaultValue=l!=null?""+Ee(l):""}function gs(t,e,l,a){if(e==null){if(a!=null){if(l!=null)throw Error(f(92));if(Ht(a)){if(1<a.length)throw Error(f(93));a=a[0]}l=a}l==null&&(l=""),e=l}l=Ee(e),t.defaultValue=l,a=t.textContent,a===l&&a!==""&&a!==null&&(t.value=a),Ei(t)}function ia(t,e){if(e){var l=t.firstChild;if(l&&l===t.lastChild&&l.nodeType===3){l.nodeValue=e;return}}t.textContent=e}var Ph=new Set("animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp".split(" "));function ps(t,e,l){var a=e.indexOf("--")===0;l==null||typeof l=="boolean"||l===""?a?t.setProperty(e,""):e==="float"?t.cssFloat="":t[e]="":a?t.setProperty(e,l):typeof l!="number"||l===0||Ph.has(e)?e==="float"?t.cssFloat=l:t[e]=(""+l).trim():t[e]=l+"px"}function Ss(t,e,l){if(e!=null&&typeof e!="object")throw Error(f(62));if(t=t.style,l!=null){for(var a in l)!l.hasOwnProperty(a)||e!=null&&e.hasOwnProperty(a)||(a.indexOf("--")===0?t.setProperty(a,""):a==="float"?t.cssFloat="":t[a]="");for(var n in e)a=e[n],e.hasOwnProperty(n)&&l[n]!==a&&ps(t,n,a)}else for(var u in e)e.hasOwnProperty(u)&&ps(t,u,e[u])}function Ai(t){if(t.indexOf("-")===-1)return!1;switch(t){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var tm=new Map([["acceptCharset","accept-charset"],["htmlFor","for"],["httpEquiv","http-equiv"],["crossOrigin","crossorigin"],["accentHeight","accent-height"],["alignmentBaseline","alignment-baseline"],["arabicForm","arabic-form"],["baselineShift","baseline-shift"],["capHeight","cap-height"],["clipPath","clip-path"],["clipRule","clip-rule"],["colorInterpolation","color-interpolation"],["colorInterpolationFilters","color-interpolation-filters"],["colorProfile","color-profile"],["colorRendering","color-rendering"],["dominantBaseline","dominant-baseline"],["enableBackground","enable-background"],["fillOpacity","fill-opacity"],["fillRule","fill-rule"],["floodColor","flood-color"],["floodOpacity","flood-opacity"],["fontFamily","font-family"],["fontSize","font-size"],["fontSizeAdjust","font-size-adjust"],["fontStretch","font-stretch"],["fontStyle","font-style"],["fontVariant","font-variant"],["fontWeight","font-weight"],["glyphName","glyph-name"],["glyphOrientationHorizontal","glyph-orientation-horizontal"],["glyphOrientationVertical","glyph-orientation-vertical"],["horizAdvX","horiz-adv-x"],["horizOriginX","horiz-origin-x"],["imageRendering","image-rendering"],["letterSpacing","letter-spacing"],["lightingColor","lighting-color"],["markerEnd","marker-end"],["markerMid","marker-mid"],["markerStart","marker-start"],["overlinePosition","overline-position"],["overlineThickness","overline-thickness"],["paintOrder","paint-order"],["panose-1","panose-1"],["pointerEvents","pointer-events"],["renderingIntent","rendering-intent"],["shapeRendering","shape-rendering"],["stopColor","stop-color"],["stopOpacity","stop-opacity"],["strikethroughPosition","strikethrough-position"],["strikethroughThickness","strikethrough-thickness"],["strokeDasharray","stroke-dasharray"],["strokeDashoffset","stroke-dashoffset"],["strokeLinecap","stroke-linecap"],["strokeLinejoin","stroke-linejoin"],["strokeMiterlimit","stroke-miterlimit"],["strokeOpacity","stroke-opacity"],["strokeWidth","stroke-width"],["textAnchor","text-anchor"],["textDecoration","text-decoration"],["textRendering","text-rendering"],["transformOrigin","transform-origin"],["underlinePosition","underline-position"],["underlineThickness","underline-thickness"],["unicodeBidi","unicode-bidi"],["unicodeRange","unicode-range"],["unitsPerEm","units-per-em"],["vAlphabetic","v-alphabetic"],["vHanging","v-hanging"],["vIdeographic","v-ideographic"],["vMathematical","v-mathematical"],["vectorEffect","vector-effect"],["vertAdvY","vert-adv-y"],["vertOriginX","vert-origin-x"],["vertOriginY","vert-origin-y"],["wordSpacing","word-spacing"],["writingMode","writing-mode"],["xmlnsXlink","xmlns:xlink"],["xHeight","x-height"]]),em=/^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i;function Fn(t){return em.test(""+t)?"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')":t}function Xe(){}var _i=null;function Ri(t){return t=t.target||t.srcElement||window,t.correspondingUseElement&&(t=t.correspondingUseElement),t.nodeType===3?t.parentNode:t}var ca=null,fa=null;function bs(t){var e=la(t);if(e&&(t=e.stateNode)){var l=t[ee]||null;t:switch(t=e.stateNode,e.type){case"input":if(Ti(t,l.value,l.defaultValue,l.defaultValue,l.checked,l.defaultChecked,l.type,l.name),e=l.name,l.type==="radio"&&e!=null){for(l=t;l.parentNode;)l=l.parentNode;for(l=l.querySelectorAll('input[name="'+Te(""+e)+'"][type="radio"]'),e=0;e<l.length;e++){var a=l[e];if(a!==t&&a.form===t.form){var n=a[ee]||null;if(!n)throw Error(f(90));Ti(a,n.value,n.defaultValue,n.defaultValue,n.checked,n.defaultChecked,n.type,n.name)}}for(e=0;e<l.length;e++)a=l[e],a.form===t.form&&ms(a)}break t;case"textarea":vs(t,l.value,l.defaultValue);break t;case"select":e=l.value,e!=null&&ua(t,!!l.multiple,e,!1)}}}var Oi=!1;function Es(t,e,l){if(Oi)return t(e,l);Oi=!0;try{var a=t(e);return a}finally{if(Oi=!1,(ca!==null||fa!==null)&&(qu(),ca&&(e=ca,t=fa,fa=ca=null,bs(e),t)))for(e=0;e<t.length;e++)bs(t[e])}}function wa(t,e){var l=t.stateNode;if(l===null)return null;var a=l[ee]||null;if(a===null)return null;l=a[e];t:switch(e){case"onClick":case"onClickCapture":case"onDoubleClick":case"onDoubleClickCapture":case"onMouseDown":case"onMouseDownCapture":case"onMouseMove":case"onMouseMoveCapture":case"onMouseUp":case"onMouseUpCapture":case"onMouseEnter":(a=!a.disabled)||(t=t.type,a=!(t==="button"||t==="input"||t==="select"||t==="textarea")),t=!a;break t;default:t=!1}if(t)return null;if(l&&typeof l!="function")throw Error(f(231,e,typeof l));return l}var Qe=!(typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),xi=!1;if(Qe)try{var Ka={};Object.defineProperty(Ka,"passive",{get:function(){xi=!0}}),window.addEventListener("test",Ka,Ka),window.removeEventListener("test",Ka,Ka)}catch{xi=!1}var fl=null,Mi=null,Wn=null;function Ts(){if(Wn)return Wn;var t,e=Mi,l=e.length,a,n="value"in fl?fl.value:fl.textContent,u=n.length;for(t=0;t<l&&e[t]===n[t];t++);var i=l-t;for(a=1;a<=i&&e[l-a]===n[u-a];a++);return Wn=n.slice(t,1<a?1-a:void 0)}function In(t){var e=t.keyCode;return"charCode"in t?(t=t.charCode,t===0&&e===13&&(t=13)):t=e,t===10&&(t=13),32<=t||t===13?t:0}function Pn(){return!0}function zs(){return!1}function le(t){function e(l,a,n,u,i){this._reactName=l,this._targetInst=n,this.type=a,this.nativeEvent=u,this.target=i,this.currentTarget=null;for(var s in t)t.hasOwnProperty(s)&&(l=t[s],this[s]=l?l(u):u[s]);return this.isDefaultPrevented=(u.defaultPrevented!=null?u.defaultPrevented:u.returnValue===!1)?Pn:zs,this.isPropagationStopped=zs,this}return R(e.prototype,{preventDefault:function(){this.defaultPrevented=!0;var l=this.nativeEvent;l&&(l.preventDefault?l.preventDefault():typeof l.returnValue!="unknown"&&(l.returnValue=!1),this.isDefaultPrevented=Pn)},stopPropagation:function(){var l=this.nativeEvent;l&&(l.stopPropagation?l.stopPropagation():typeof l.cancelBubble!="unknown"&&(l.cancelBubble=!0),this.isPropagationStopped=Pn)},persist:function(){},isPersistent:Pn}),e}var Hl={eventPhase:0,bubbles:0,cancelable:0,timeStamp:function(t){return t.timeStamp||Date.now()},defaultPrevented:0,isTrusted:0},tu=le(Hl),Ja=R({},Hl,{view:0,detail:0}),lm=le(Ja),Ni,Ci,$a,eu=R({},Ja,{screenX:0,screenY:0,clientX:0,clientY:0,pageX:0,pageY:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,getModifierState:Ui,button:0,buttons:0,relatedTarget:function(t){return t.relatedTarget===void 0?t.fromElement===t.srcElement?t.toElement:t.fromElement:t.relatedTarget},movementX:function(t){return"movementX"in t?t.movementX:(t!==$a&&($a&&t.type==="mousemove"?(Ni=t.screenX-$a.screenX,Ci=t.screenY-$a.screenY):Ci=Ni=0,$a=t),Ni)},movementY:function(t){return"movementY"in t?t.movementY:Ci}}),As=le(eu),am=R({},eu,{dataTransfer:0}),nm=le(am),um=R({},Ja,{relatedTarget:0}),Di=le(um),im=R({},Hl,{animationName:0,elapsedTime:0,pseudoElement:0}),cm=le(im),fm=R({},Hl,{clipboardData:function(t){return"clipboardData"in t?t.clipboardData:window.clipboardData}}),sm=le(fm),rm=R({},Hl,{data:0}),_s=le(rm),om={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},dm={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"},hm={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};function mm(t){var e=this.nativeEvent;return e.getModifierState?e.getModifierState(t):(t=hm[t])?!!e[t]:!1}function Ui(){return mm}var ym=R({},Ja,{key:function(t){if(t.key){var e=om[t.key]||t.key;if(e!=="Unidentified")return e}return t.type==="keypress"?(t=In(t),t===13?"Enter":String.fromCharCode(t)):t.type==="keydown"||t.type==="keyup"?dm[t.keyCode]||"Unidentified":""},code:0,location:0,ctrlKey:0,shiftKey:0,altKey:0,metaKey:0,repeat:0,locale:0,getModifierState:Ui,charCode:function(t){return t.type==="keypress"?In(t):0},keyCode:function(t){return t.type==="keydown"||t.type==="keyup"?t.keyCode:0},which:function(t){return t.type==="keypress"?In(t):t.type==="keydown"||t.type==="keyup"?t.keyCode:0}}),vm=le(ym),gm=R({},eu,{pointerId:0,width:0,height:0,pressure:0,tangentialPressure:0,tiltX:0,tiltY:0,twist:0,pointerType:0,isPrimary:0}),Rs=le(gm),pm=R({},Ja,{touches:0,targetTouches:0,changedTouches:0,altKey:0,metaKey:0,ctrlKey:0,shiftKey:0,getModifierState:Ui}),Sm=le(pm),bm=R({},Hl,{propertyName:0,elapsedTime:0,pseudoElement:0}),Em=le(bm),Tm=R({},eu,{deltaX:function(t){return"deltaX"in t?t.deltaX:"wheelDeltaX"in t?-t.wheelDeltaX:0},deltaY:function(t){return"deltaY"in t?t.deltaY:"wheelDeltaY"in t?-t.wheelDeltaY:"wheelDelta"in t?-t.wheelDelta:0},deltaZ:0,deltaMode:0}),zm=le(Tm),Am=R({},Hl,{newState:0,oldState:0}),_m=le(Am),Rm=[9,13,27,32],ji=Qe&&"CompositionEvent"in window,ka=null;Qe&&"documentMode"in document&&(ka=document.documentMode);var Om=Qe&&"TextEvent"in window&&!ka,Os=Qe&&(!ji||ka&&8<ka&&11>=ka),xs=" ",Ms=!1;function Ns(t,e){switch(t){case"keyup":return Rm.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Cs(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var sa=!1;function xm(t,e){switch(t){case"compositionend":return Cs(e);case"keypress":return e.which!==32?null:(Ms=!0,xs);case"textInput":return t=e.data,t===xs&&Ms?null:t;default:return null}}function Mm(t,e){if(sa)return t==="compositionend"||!ji&&Ns(t,e)?(t=Ts(),Wn=Mi=fl=null,sa=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1<e.char.length)return e.char;if(e.which)return String.fromCharCode(e.which)}return null;case"compositionend":return Os&&e.locale!=="ko"?null:e.data;default:return null}}var Nm={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Ds(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e==="input"?!!Nm[t.type]:e==="textarea"}function Us(t,e,l,a){ca?fa?fa.push(a):fa=[a]:ca=a,e=Vu(e,"onChange"),0<e.length&&(l=new tu("onChange","change",null,l,a),t.push({event:l,listeners:e}))}var Fa=null,Wa=null;function Cm(t){vd(t,0)}function lu(t){var e=Va(t);if(ms(e))return t}function js(t,e){if(t==="change")return e}var Hs=!1;if(Qe){var Hi;if(Qe){var Bi="oninput"in document;if(!Bi){var Bs=document.createElement("div");Bs.setAttribute("oninput","return;"),Bi=typeof Bs.oninput=="function"}Hi=Bi}else Hi=!1;Hs=Hi&&(!document.documentMode||9<document.documentMode)}function qs(){Fa&&(Fa.detachEvent("onpropertychange",Ls),Wa=Fa=null)}function Ls(t){if(t.propertyName==="value"&&lu(Wa)){var e=[];Us(e,Wa,t,Ri(t)),Es(Cm,e)}}function Dm(t,e,l){t==="focusin"?(qs(),Fa=e,Wa=l,Fa.attachEvent("onpropertychange",Ls)):t==="focusout"&&qs()}function Um(t){if(t==="selectionchange"||t==="keyup"||t==="keydown")return lu(Wa)}function jm(t,e){if(t==="click")return lu(e)}function Hm(t,e){if(t==="input"||t==="change")return lu(e)}function Bm(t,e){return t===e&&(t!==0||1/t===1/e)||t!==t&&e!==e}var de=typeof Object.is=="function"?Object.is:Bm;function Ia(t,e){if(de(t,e))return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;var l=Object.keys(t),a=Object.keys(e);if(l.length!==a.length)return!1;for(a=0;a<l.length;a++){var n=l[a];if(!hi.call(e,n)||!de(t[n],e[n]))return!1}return!0}function Ys(t){for(;t&&t.firstChild;)t=t.firstChild;return t}function Gs(t,e){var l=Ys(t);t=0;for(var a;l;){if(l.nodeType===3){if(a=t+l.textContent.length,t<=e&&a>=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=Ys(l)}}function Xs(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?Xs(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function Qs(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=kn(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=kn(t.document)}return e}function qi(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var qm=Qe&&"documentMode"in document&&11>=document.documentMode,ra=null,Li=null,Pa=null,Yi=!1;function Zs(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Yi||ra==null||ra!==kn(a)||(a=ra,"selectionStart"in a&&qi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Pa&&Ia(Pa,a)||(Pa=a,a=Vu(Li,"onSelect"),0<a.length&&(e=new tu("onSelect","select",null,e,l),t.push({event:e,listeners:a}),e.target=ra)))}function Bl(t,e){var l={};return l[t.toLowerCase()]=e.toLowerCase(),l["Webkit"+t]="webkit"+e,l["Moz"+t]="moz"+e,l}var oa={animationend:Bl("Animation","AnimationEnd"),animationiteration:Bl("Animation","AnimationIteration"),animationstart:Bl("Animation","AnimationStart"),transitionrun:Bl("Transition","TransitionRun"),transitionstart:Bl("Transition","TransitionStart"),transitioncancel:Bl("Transition","TransitionCancel"),transitionend:Bl("Transition","TransitionEnd")},Gi={},Vs={};Qe&&(Vs=document.createElement("div").style,"AnimationEvent"in window||(delete oa.animationend.animation,delete oa.animationiteration.animation,delete oa.animationstart.animation),"TransitionEvent"in window||delete oa.transitionend.transition);function ql(t){if(Gi[t])return Gi[t];if(!oa[t])return t;var e=oa[t],l;for(l in e)if(e.hasOwnProperty(l)&&l in Vs)return Gi[t]=e[l];return t}var ws=ql("animationend"),Ks=ql("animationiteration"),Js=ql("animationstart"),Lm=ql("transitionrun"),Ym=ql("transitionstart"),Gm=ql("transitioncancel"),$s=ql("transitionend"),ks=new Map,Xi="abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");Xi.push("scrollEnd");function De(t,e){ks.set(t,e),jl(e,[t])}var au=typeof reportError=="function"?reportError:function(t){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var e=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof t=="object"&&t!==null&&typeof t.message=="string"?String(t.message):String(t),error:t});if(!window.dispatchEvent(e))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",t);return}console.error(t)},ze=[],da=0,Qi=0;function nu(){for(var t=da,e=Qi=da=0;e<t;){var l=ze[e];ze[e++]=null;var a=ze[e];ze[e++]=null;var n=ze[e];ze[e++]=null;var u=ze[e];if(ze[e++]=null,a!==null&&n!==null){var i=a.pending;i===null?n.next=n:(n.next=i.next,i.next=n),a.pending=n}u!==0&&Fs(l,n,u)}}function uu(t,e,l,a){ze[da++]=t,ze[da++]=e,ze[da++]=l,ze[da++]=a,Qi|=a,t.lanes|=a,t=t.alternate,t!==null&&(t.lanes|=a)}function Zi(t,e,l,a){return uu(t,e,l,a),iu(t)}function Ll(t,e){return uu(t,null,null,e),iu(t)}function Fs(t,e,l){t.lanes|=l;var a=t.alternate;a!==null&&(a.lanes|=l);for(var n=!1,u=t.return;u!==null;)u.childLanes|=l,a=u.alternate,a!==null&&(a.childLanes|=l),u.tag===22&&(t=u.stateNode,t===null||t._visibility&1||(n=!0)),t=u,u=u.return;return t.tag===3?(u=t.stateNode,n&&e!==null&&(n=31-oe(l),t=u.hiddenUpdates,a=t[n],a===null?t[n]=[e]:a.push(e),e.lane=l|536870912),u):null}function iu(t){if(50<Tn)throw Tn=0,Ic=null,Error(f(185));for(var e=t.return;e!==null;)t=e,e=t.return;return t.tag===3?t.stateNode:null}var ha={};function Xm(t,e,l,a){this.tag=t,this.key=l,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.refCleanup=this.ref=null,this.pendingProps=e,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=a,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function he(t,e,l,a){return new Xm(t,e,l,a)}function Vi(t){return t=t.prototype,!(!t||!t.isReactComponent)}function Ze(t,e){var l=t.alternate;return l===null?(l=he(t.tag,e,t.key,t.mode),l.elementType=t.elementType,l.type=t.type,l.stateNode=t.stateNode,l.alternate=t,t.alternate=l):(l.pendingProps=e,l.type=t.type,l.flags=0,l.subtreeFlags=0,l.deletions=null),l.flags=t.flags&65011712,l.childLanes=t.childLanes,l.lanes=t.lanes,l.child=t.child,l.memoizedProps=t.memoizedProps,l.memoizedState=t.memoizedState,l.updateQueue=t.updateQueue,e=t.dependencies,l.dependencies=e===null?null:{lanes:e.lanes,firstContext:e.firstContext},l.sibling=t.sibling,l.index=t.index,l.ref=t.ref,l.refCleanup=t.refCleanup,l}function Ws(t,e){t.flags&=65011714;var l=t.alternate;return l===null?(t.childLanes=0,t.lanes=e,t.child=null,t.subtreeFlags=0,t.memoizedProps=null,t.memoizedState=null,t.updateQueue=null,t.dependencies=null,t.stateNode=null):(t.childLanes=l.childLanes,t.lanes=l.lanes,t.child=l.child,t.subtreeFlags=0,t.deletions=null,t.memoizedProps=l.memoizedProps,t.memoizedState=l.memoizedState,t.updateQueue=l.updateQueue,t.type=l.type,e=l.dependencies,t.dependencies=e===null?null:{lanes:e.lanes,firstContext:e.firstContext}),t}function cu(t,e,l,a,n,u){var i=0;if(a=t,typeof t=="function")Vi(t)&&(i=1);else if(typeof t=="string")i=Ky(t,l,V.current)?26:t==="html"||t==="head"||t==="body"?27:5;else t:switch(t){case Rt:return t=he(31,l,e,n),t.elementType=Rt,t.lanes=u,t;case Q:return Yl(l.children,n,u,e);case X:i=8,n|=24;break;case H:return t=he(12,l,e,n|2),t.elementType=H,t.lanes=u,t;case mt:return t=he(13,l,e,n),t.elementType=mt,t.lanes=u,t;case St:return t=he(19,l,e,n),t.elementType=St,t.lanes=u,t;default:if(typeof t=="object"&&t!==null)switch(t.$$typeof){case G:i=10;break t;case q:i=9;break t;case dt:i=11;break t;case et:i=14;break t;case xt:i=16,a=null;break t}i=29,l=Error(f(130,t===null?"null":typeof t,"")),a=null}return e=he(i,l,e,n),e.elementType=t,e.type=a,e.lanes=u,e}function Yl(t,e,l,a){return t=he(7,t,a,e),t.lanes=l,t}function wi(t,e,l){return t=he(6,t,null,e),t.lanes=l,t}function Is(t){var e=he(18,null,null,0);return e.stateNode=t,e}function Ki(t,e,l){return e=he(4,t.children!==null?t.children:[],t.key,e),e.lanes=l,e.stateNode={containerInfo:t.containerInfo,pendingChildren:null,implementation:t.implementation},e}var Ps=new WeakMap;function Ae(t,e){if(typeof t=="object"&&t!==null){var l=Ps.get(t);return l!==void 0?l:(e={value:t,source:e,stack:If(e)},Ps.set(t,e),e)}return{value:t,source:e,stack:If(e)}}var ma=[],ya=0,fu=null,tn=0,_e=[],Re=0,sl=null,Be=1,qe="";function Ve(t,e){ma[ya++]=tn,ma[ya++]=fu,fu=t,tn=e}function tr(t,e,l){_e[Re++]=Be,_e[Re++]=qe,_e[Re++]=sl,sl=t;var a=Be;t=qe;var n=32-oe(a)-1;a&=~(1<<n),l+=1;var u=32-oe(e)+n;if(30<u){var i=n-n%5;u=(a&(1<<i)-1).toString(32),a>>=i,n-=i,Be=1<<32-oe(e)+n|l<<n|a,qe=u+t}else Be=1<<u|l<<n|a,qe=t}function Ji(t){t.return!==null&&(Ve(t,1),tr(t,1,0))}function $i(t){for(;t===fu;)fu=ma[--ya],ma[ya]=null,tn=ma[--ya],ma[ya]=null;for(;t===sl;)sl=_e[--Re],_e[Re]=null,qe=_e[--Re],_e[Re]=null,Be=_e[--Re],_e[Re]=null}function er(t,e){_e[Re++]=Be,_e[Re++]=qe,_e[Re++]=sl,Be=e.id,qe=e.overflow,sl=t}var $t=null,Mt=null,ht=!1,rl=null,Oe=!1,ki=Error(f(519));function ol(t){var e=Error(f(418,1<arguments.length&&arguments[1]!==void 0&&arguments[1]?"text":"HTML",""));throw en(Ae(e,t)),ki}function lr(t){var e=t.stateNode,l=t.type,a=t.memoizedProps;switch(e[Jt]=t,e[ee]=a,l){case"dialog":st("cancel",e),st("close",e);break;case"iframe":case"object":case"embed":st("load",e);break;case"video":case"audio":for(l=0;l<An.length;l++)st(An[l],e);break;case"source":st("error",e);break;case"img":case"image":case"link":st("error",e),st("load",e);break;case"details":st("toggle",e);break;case"input":st("invalid",e),ys(e,a.value,a.defaultValue,a.checked,a.defaultChecked,a.type,a.name,!0);break;case"select":st("invalid",e);break;case"textarea":st("invalid",e),gs(e,a.value,a.defaultValue,a.children)}l=a.children,typeof l!="string"&&typeof l!="number"&&typeof l!="bigint"||e.textContent===""+l||a.suppressHydrationWarning===!0||bd(e.textContent,l)?(a.popover!=null&&(st("beforetoggle",e),st("toggle",e)),a.onScroll!=null&&st("scroll",e),a.onScrollEnd!=null&&st("scrollend",e),a.onClick!=null&&(e.onclick=Xe),e=!0):e=!1,e||ol(t,!0)}function ar(t){for($t=t.return;$t;)switch($t.tag){case 5:case 31:case 13:Oe=!1;return;case 27:case 3:Oe=!0;return;default:$t=$t.return}}function va(t){if(t!==$t)return!1;if(!ht)return ar(t),ht=!0,!1;var e=t.tag,l;if((l=e!==3&&e!==27)&&((l=e===5)&&(l=t.type,l=!(l!=="form"&&l!=="button")||mf(t.type,t.memoizedProps)),l=!l),l&&Mt&&ol(t),ar(t),e===13){if(t=t.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(f(317));Mt=Md(t)}else if(e===31){if(t=t.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(f(317));Mt=Md(t)}else e===27?(e=Mt,_l(t.type)?(t=Sf,Sf=null,Mt=t):Mt=e):Mt=$t?Me(t.stateNode.nextSibling):null;return!0}function Gl(){Mt=$t=null,ht=!1}function Fi(){var t=rl;return t!==null&&(ie===null?ie=t:ie.push.apply(ie,t),rl=null),t}function en(t){rl===null?rl=[t]:rl.push(t)}var Wi=v(null),Xl=null,we=null;function dl(t,e,l){Y(Wi,e._currentValue),e._currentValue=l}function Ke(t){t._currentValue=Wi.current,D(Wi)}function Ii(t,e,l){for(;t!==null;){var a=t.alternate;if((t.childLanes&e)!==e?(t.childLanes|=e,a!==null&&(a.childLanes|=e)):a!==null&&(a.childLanes&e)!==e&&(a.childLanes|=e),t===l)break;t=t.return}}function Pi(t,e,l,a){var n=t.child;for(n!==null&&(n.return=t);n!==null;){var u=n.dependencies;if(u!==null){var i=n.child;u=u.firstContext;t:for(;u!==null;){var s=u;u=n;for(var m=0;m<e.length;m++)if(s.context===e[m]){u.lanes|=l,s=u.alternate,s!==null&&(s.lanes|=l),Ii(u.return,l,t),a||(i=null);break t}u=s.next}}else if(n.tag===18){if(i=n.return,i===null)throw Error(f(341));i.lanes|=l,u=i.alternate,u!==null&&(u.lanes|=l),Ii(i,l,t),i=null}else i=n.child;if(i!==null)i.return=n;else for(i=n;i!==null;){if(i===t){i=null;break}if(n=i.sibling,n!==null){n.return=i.return,i=n;break}i=i.return}n=i}}function ga(t,e,l,a){t=null;for(var n=e,u=!1;n!==null;){if(!u){if((n.flags&524288)!==0)u=!0;else if((n.flags&262144)!==0)break}if(n.tag===10){var i=n.alternate;if(i===null)throw Error(f(387));if(i=i.memoizedProps,i!==null){var s=n.type;de(n.pendingProps.value,i.value)||(t!==null?t.push(s):t=[s])}}else if(n===bt.current){if(i=n.alternate,i===null)throw Error(f(387));i.memoizedState.memoizedState!==n.memoizedState.memoizedState&&(t!==null?t.push(Mn):t=[Mn])}n=n.return}t!==null&&Pi(e,t,l,a),e.flags|=262144}function su(t){for(t=t.firstContext;t!==null;){if(!de(t.context._currentValue,t.memoizedValue))return!0;t=t.next}return!1}function Ql(t){Xl=t,we=null,t=t.dependencies,t!==null&&(t.firstContext=null)}function kt(t){return nr(Xl,t)}function ru(t,e){return Xl===null&&Ql(t),nr(t,e)}function nr(t,e){var l=e._currentValue;if(e={context:e,memoizedValue:l,next:null},we===null){if(t===null)throw Error(f(308));we=e,t.dependencies={lanes:0,firstContext:e},t.flags|=524288}else we=we.next=e;return l}var Qm=typeof AbortController<"u"?AbortController:function(){var t=[],e=this.signal={aborted:!1,addEventListener:function(l,a){t.push(a)}};this.abort=function(){e.aborted=!0,t.forEach(function(l){return l()})}},Zm=c.unstable_scheduleCallback,Vm=c.unstable_NormalPriority,Gt={$$typeof:G,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function tc(){return{controller:new Qm,data:new Map,refCount:0}}function ln(t){t.refCount--,t.refCount===0&&Zm(Vm,function(){t.controller.abort()})}var an=null,ec=0,pa=0,Sa=null;function wm(t,e){if(an===null){var l=an=[];ec=0,pa=nf(),Sa={status:"pending",value:void 0,then:function(a){l.push(a)}}}return ec++,e.then(ur,ur),e}function ur(){if(--ec===0&&an!==null){Sa!==null&&(Sa.status="fulfilled");var t=an;an=null,pa=0,Sa=null;for(var e=0;e<t.length;e++)(0,t[e])()}}function Km(t,e){var l=[],a={status:"pending",value:null,reason:null,then:function(n){l.push(n)}};return t.then(function(){a.status="fulfilled",a.value=e;for(var n=0;n<l.length;n++)(0,l[n])(e)},function(n){for(a.status="rejected",a.reason=n,n=0;n<l.length;n++)(0,l[n])(void 0)}),a}var ir=x.S;x.S=function(t,e){Vo=se(),typeof e=="object"&&e!==null&&typeof e.then=="function"&&wm(t,e),ir!==null&&ir(t,e)};var Zl=v(null);function lc(){var t=Zl.current;return t!==null?t:Ot.pooledCache}function ou(t,e){e===null?Y(Zl,Zl.current):Y(Zl,e.pool)}function cr(){var t=lc();return t===null?null:{parent:Gt._currentValue,pool:t}}var ba=Error(f(460)),ac=Error(f(474)),du=Error(f(542)),hu={then:function(){}};function fr(t){return t=t.status,t==="fulfilled"||t==="rejected"}function sr(t,e,l){switch(l=t[l],l===void 0?t.push(e):l!==e&&(e.then(Xe,Xe),e=l),e.status){case"fulfilled":return e.value;case"rejected":throw t=e.reason,or(t),t;default:if(typeof e.status=="string")e.then(Xe,Xe);else{if(t=Ot,t!==null&&100<t.shellSuspendCounter)throw Error(f(482));t=e,t.status="pending",t.then(function(a){if(e.status==="pending"){var n=e;n.status="fulfilled",n.value=a}},function(a){if(e.status==="pending"){var n=e;n.status="rejected",n.reason=a}})}switch(e.status){case"fulfilled":return e.value;case"rejected":throw t=e.reason,or(t),t}throw wl=e,ba}}function Vl(t){try{var e=t._init;return e(t._payload)}catch(l){throw l!==null&&typeof l=="object"&&typeof l.then=="function"?(wl=l,ba):l}}var wl=null;function rr(){if(wl===null)throw Error(f(459));var t=wl;return wl=null,t}function or(t){if(t===ba||t===du)throw Error(f(483))}var Ea=null,nn=0;function mu(t){var e=nn;return nn+=1,Ea===null&&(Ea=[]),sr(Ea,t,e)}function un(t,e){e=e.props.ref,t.ref=e!==void 0?e:null}function yu(t,e){throw e.$$typeof===B?Error(f(525)):(t=Object.prototype.toString.call(e),Error(f(31,t==="[object Object]"?"object with keys {"+Object.keys(e).join(", ")+"}":t)))}function dr(t){function e(b,g){if(t){var T=b.deletions;T===null?(b.deletions=[g],b.flags|=16):T.push(g)}}function l(b,g){if(!t)return null;for(;g!==null;)e(b,g),g=g.sibling;return null}function a(b){for(var g=new Map;b!==null;)b.key!==null?g.set(b.key,b):g.set(b.index,b),b=b.sibling;return g}function n(b,g){return b=Ze(b,g),b.index=0,b.sibling=null,b}function u(b,g,T){return b.index=T,t?(T=b.alternate,T!==null?(T=T.index,T<g?(b.flags|=67108866,g):T):(b.flags|=67108866,g)):(b.flags|=1048576,g)}function i(b){return t&&b.alternate===null&&(b.flags|=67108866),b}function s(b,g,T,U){return g===null||g.tag!==6?(g=wi(T,b.mode,U),g.return=b,g):(g=n(g,T),g.return=b,g)}function m(b,g,T,U){var F=T.type;return F===Q?C(b,g,T.props.children,U,T.key):g!==null&&(g.elementType===F||typeof F=="object"&&F!==null&&F.$$typeof===xt&&Vl(F)===g.type)?(g=n(g,T.props),un(g,T),g.return=b,g):(g=cu(T.type,T.key,T.props,null,b.mode,U),un(g,T),g.return=b,g)}function z(b,g,T,U){return g===null||g.tag!==4||g.stateNode.containerInfo!==T.containerInfo||g.stateNode.implementation!==T.implementation?(g=Ki(T,b.mode,U),g.return=b,g):(g=n(g,T.children||[]),g.return=b,g)}function C(b,g,T,U,F){return g===null||g.tag!==7?(g=Yl(T,b.mode,U,F),g.return=b,g):(g=n(g,T),g.return=b,g)}function j(b,g,T){if(typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint")return g=wi(""+g,b.mode,T),g.return=b,g;if(typeof g=="object"&&g!==null){switch(g.$$typeof){case K:return T=cu(g.type,g.key,g.props,null,b.mode,T),un(T,g),T.return=b,T;case $:return g=Ki(g,b.mode,T),g.return=b,g;case xt:return g=Vl(g),j(b,g,T)}if(Ht(g)||W(g))return g=Yl(g,b.mode,T,null),g.return=b,g;if(typeof g.then=="function")return j(b,mu(g),T);if(g.$$typeof===G)return j(b,ru(b,g),T);yu(b,g)}return null}function A(b,g,T,U){var F=g!==null?g.key:null;if(typeof T=="string"&&T!==""||typeof T=="number"||typeof T=="bigint")return F!==null?null:s(b,g,""+T,U);if(typeof T=="object"&&T!==null){switch(T.$$typeof){case K:return T.key===F?m(b,g,T,U):null;case $:return T.key===F?z(b,g,T,U):null;case xt:return T=Vl(T),A(b,g,T,U)}if(Ht(T)||W(T))return F!==null?null:C(b,g,T,U,null);if(typeof T.then=="function")return A(b,g,mu(T),U);if(T.$$typeof===G)return A(b,g,ru(b,T),U);yu(b,T)}return null}function O(b,g,T,U,F){if(typeof U=="string"&&U!==""||typeof U=="number"||typeof U=="bigint")return b=b.get(T)||null,s(g,b,""+U,F);if(typeof U=="object"&&U!==null){switch(U.$$typeof){case K:return b=b.get(U.key===null?T:U.key)||null,m(g,b,U,F);case $:return b=b.get(U.key===null?T:U.key)||null,z(g,b,U,F);case xt:return U=Vl(U),O(b,g,T,U,F)}if(Ht(U)||W(U))return b=b.get(T)||null,C(g,b,U,F,null);if(typeof U.then=="function")return O(b,g,T,mu(U),F);if(U.$$typeof===G)return O(b,g,T,ru(g,U),F);yu(g,U)}return null}function w(b,g,T,U){for(var F=null,vt=null,J=g,ut=g=0,ot=null;J!==null&&ut<T.length;ut++){J.index>ut?(ot=J,J=null):ot=J.sibling;var gt=A(b,J,T[ut],U);if(gt===null){J===null&&(J=ot);break}t&&J&>.alternate===null&&e(b,J),g=u(gt,g,ut),vt===null?F=gt:vt.sibling=gt,vt=gt,J=ot}if(ut===T.length)return l(b,J),ht&&Ve(b,ut),F;if(J===null){for(;ut<T.length;ut++)J=j(b,T[ut],U),J!==null&&(g=u(J,g,ut),vt===null?F=J:vt.sibling=J,vt=J);return ht&&Ve(b,ut),F}for(J=a(J);ut<T.length;ut++)ot=O(J,b,ut,T[ut],U),ot!==null&&(t&&ot.alternate!==null&&J.delete(ot.key===null?ut:ot.key),g=u(ot,g,ut),vt===null?F=ot:vt.sibling=ot,vt=ot);return t&&J.forEach(function(Nl){return e(b,Nl)}),ht&&Ve(b,ut),F}function P(b,g,T,U){if(T==null)throw Error(f(151));for(var F=null,vt=null,J=g,ut=g=0,ot=null,gt=T.next();J!==null&&!gt.done;ut++,gt=T.next()){J.index>ut?(ot=J,J=null):ot=J.sibling;var Nl=A(b,J,gt.value,U);if(Nl===null){J===null&&(J=ot);break}t&&J&&Nl.alternate===null&&e(b,J),g=u(Nl,g,ut),vt===null?F=Nl:vt.sibling=Nl,vt=Nl,J=ot}if(gt.done)return l(b,J),ht&&Ve(b,ut),F;if(J===null){for(;!gt.done;ut++,gt=T.next())gt=j(b,gt.value,U),gt!==null&&(g=u(gt,g,ut),vt===null?F=gt:vt.sibling=gt,vt=gt);return ht&&Ve(b,ut),F}for(J=a(J);!gt.done;ut++,gt=T.next())gt=O(J,b,ut,gt.value,U),gt!==null&&(t&>.alternate!==null&&J.delete(gt.key===null?ut:gt.key),g=u(gt,g,ut),vt===null?F=gt:vt.sibling=gt,vt=gt);return t&&J.forEach(function(av){return e(b,av)}),ht&&Ve(b,ut),F}function _t(b,g,T,U){if(typeof T=="object"&&T!==null&&T.type===Q&&T.key===null&&(T=T.props.children),typeof T=="object"&&T!==null){switch(T.$$typeof){case K:t:{for(var F=T.key;g!==null;){if(g.key===F){if(F=T.type,F===Q){if(g.tag===7){l(b,g.sibling),U=n(g,T.props.children),U.return=b,b=U;break t}}else if(g.elementType===F||typeof F=="object"&&F!==null&&F.$$typeof===xt&&Vl(F)===g.type){l(b,g.sibling),U=n(g,T.props),un(U,T),U.return=b,b=U;break t}l(b,g);break}else e(b,g);g=g.sibling}T.type===Q?(U=Yl(T.props.children,b.mode,U,T.key),U.return=b,b=U):(U=cu(T.type,T.key,T.props,null,b.mode,U),un(U,T),U.return=b,b=U)}return i(b);case $:t:{for(F=T.key;g!==null;){if(g.key===F)if(g.tag===4&&g.stateNode.containerInfo===T.containerInfo&&g.stateNode.implementation===T.implementation){l(b,g.sibling),U=n(g,T.children||[]),U.return=b,b=U;break t}else{l(b,g);break}else e(b,g);g=g.sibling}U=Ki(T,b.mode,U),U.return=b,b=U}return i(b);case xt:return T=Vl(T),_t(b,g,T,U)}if(Ht(T))return w(b,g,T,U);if(W(T)){if(F=W(T),typeof F!="function")throw Error(f(150));return T=F.call(T),P(b,g,T,U)}if(typeof T.then=="function")return _t(b,g,mu(T),U);if(T.$$typeof===G)return _t(b,g,ru(b,T),U);yu(b,T)}return typeof T=="string"&&T!==""||typeof T=="number"||typeof T=="bigint"?(T=""+T,g!==null&&g.tag===6?(l(b,g.sibling),U=n(g,T),U.return=b,b=U):(l(b,g),U=wi(T,b.mode,U),U.return=b,b=U),i(b)):l(b,g)}return function(b,g,T,U){try{nn=0;var F=_t(b,g,T,U);return Ea=null,F}catch(J){if(J===ba||J===du)throw J;var vt=he(29,J,null,b.mode);return vt.lanes=U,vt.return=b,vt}}}var Kl=dr(!0),hr=dr(!1),hl=!1;function nc(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function uc(t,e){t=t.updateQueue,e.updateQueue===t&&(e.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function ml(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function yl(t,e,l){var a=t.updateQueue;if(a===null)return null;if(a=a.shared,(pt&2)!==0){var n=a.pending;return n===null?e.next=e:(e.next=n.next,n.next=e),a.pending=e,e=iu(t),Fs(t,null,l),e}return uu(t,a,e,l),iu(t)}function cn(t,e,l){if(e=e.updateQueue,e!==null&&(e=e.shared,(l&4194048)!==0)){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ns(t,l)}}function ic(t,e){var l=t.updateQueue,a=t.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,l=l.next}while(l!==null);u===null?n=u=e:u=u.next=e}else n=u=e;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},t.updateQueue=l;return}t=l.lastBaseUpdate,t===null?l.firstBaseUpdate=e:t.next=e,l.lastBaseUpdate=e}var cc=!1;function fn(){if(cc){var t=Sa;if(t!==null)throw t}}function sn(t,e,l,a){cc=!1;var n=t.updateQueue;hl=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,s=n.shared.pending;if(s!==null){n.shared.pending=null;var m=s,z=m.next;m.next=null,i===null?u=z:i.next=z,i=m;var C=t.alternate;C!==null&&(C=C.updateQueue,s=C.lastBaseUpdate,s!==i&&(s===null?C.firstBaseUpdate=z:s.next=z,C.lastBaseUpdate=m))}if(u!==null){var j=n.baseState;i=0,C=z=m=null,s=u;do{var A=s.lane&-536870913,O=A!==s.lane;if(O?(rt&A)===A:(a&A)===A){A!==0&&A===pa&&(cc=!0),C!==null&&(C=C.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});t:{var w=t,P=s;A=e;var _t=l;switch(P.tag){case 1:if(w=P.payload,typeof w=="function"){j=w.call(_t,j,A);break t}j=w;break t;case 3:w.flags=w.flags&-65537|128;case 0:if(w=P.payload,A=typeof w=="function"?w.call(_t,j,A):w,A==null)break t;j=R({},j,A);break t;case 2:hl=!0}}A=s.callback,A!==null&&(t.flags|=64,O&&(t.flags|=8192),O=n.callbacks,O===null?n.callbacks=[A]:O.push(A))}else O={lane:A,tag:s.tag,payload:s.payload,callback:s.callback,next:null},C===null?(z=C=O,m=j):C=C.next=O,i|=A;if(s=s.next,s===null){if(s=n.shared.pending,s===null)break;O=s,s=O.next,O.next=null,n.lastBaseUpdate=O,n.shared.pending=null}}while(!0);C===null&&(m=j),n.baseState=m,n.firstBaseUpdate=z,n.lastBaseUpdate=C,u===null&&(n.shared.lanes=0),bl|=i,t.lanes=i,t.memoizedState=j}}function mr(t,e){if(typeof t!="function")throw Error(f(191,t));t.call(e)}function yr(t,e){var l=t.callbacks;if(l!==null)for(t.callbacks=null,t=0;t<l.length;t++)mr(l[t],e)}var Ta=v(null),vu=v(0);function vr(t,e){t=el,Y(vu,t),Y(Ta,e),el=t|e.baseLanes}function fc(){Y(vu,el),Y(Ta,Ta.current)}function sc(){el=vu.current,D(Ta),D(vu)}var me=v(null),xe=null;function vl(t){var e=t.alternate;Y(qt,qt.current&1),Y(me,t),xe===null&&(e===null||Ta.current!==null||e.memoizedState!==null)&&(xe=t)}function rc(t){Y(qt,qt.current),Y(me,t),xe===null&&(xe=t)}function gr(t){t.tag===22?(Y(qt,qt.current),Y(me,t),xe===null&&(xe=t)):gl()}function gl(){Y(qt,qt.current),Y(me,me.current)}function ye(t){D(me),xe===t&&(xe=null),D(qt)}var qt=v(0);function gu(t){for(var e=t;e!==null;){if(e.tag===13){var l=e.memoizedState;if(l!==null&&(l=l.dehydrated,l===null||gf(l)||pf(l)))return e}else if(e.tag===19&&(e.memoizedProps.revealOrder==="forwards"||e.memoizedProps.revealOrder==="backwards"||e.memoizedProps.revealOrder==="unstable_legacy-backwards"||e.memoizedProps.revealOrder==="together")){if((e.flags&128)!==0)return e}else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break;for(;e.sibling===null;){if(e.return===null||e.return===t)return null;e=e.return}e.sibling.return=e.return,e=e.sibling}return null}var Je=0,nt=null,zt=null,Xt=null,pu=!1,za=!1,Jl=!1,Su=0,rn=0,Aa=null,Jm=0;function Ut(){throw Error(f(321))}function oc(t,e){if(e===null)return!1;for(var l=0;l<e.length&&l<t.length;l++)if(!de(t[l],e[l]))return!1;return!0}function dc(t,e,l,a,n,u){return Je=u,nt=e,e.memoizedState=null,e.updateQueue=null,e.lanes=0,x.H=t===null||t.memoizedState===null?to:Oc,Jl=!1,u=l(a,n),Jl=!1,za&&(u=Sr(e,l,a,n)),pr(t),u}function pr(t){x.H=hn;var e=zt!==null&&zt.next!==null;if(Je=0,Xt=zt=nt=null,pu=!1,rn=0,Aa=null,e)throw Error(f(300));t===null||Qt||(t=t.dependencies,t!==null&&su(t)&&(Qt=!0))}function Sr(t,e,l,a){nt=t;var n=0;do{if(za&&(Aa=null),rn=0,za=!1,25<=n)throw Error(f(301));if(n+=1,Xt=zt=null,t.updateQueue!=null){var u=t.updateQueue;u.lastEffect=null,u.events=null,u.stores=null,u.memoCache!=null&&(u.memoCache.index=0)}x.H=eo,u=e(l,a)}while(za);return u}function $m(){var t=x.H,e=t.useState()[0];return e=typeof e.then=="function"?on(e):e,t=t.useState()[0],(zt!==null?zt.memoizedState:null)!==t&&(nt.flags|=1024),e}function hc(){var t=Su!==0;return Su=0,t}function mc(t,e,l){e.updateQueue=t.updateQueue,e.flags&=-2053,t.lanes&=~l}function yc(t){if(pu){for(t=t.memoizedState;t!==null;){var e=t.queue;e!==null&&(e.pending=null),t=t.next}pu=!1}Je=0,Xt=zt=nt=null,za=!1,rn=Su=0,Aa=null}function te(){var t={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return Xt===null?nt.memoizedState=Xt=t:Xt=Xt.next=t,Xt}function Lt(){if(zt===null){var t=nt.alternate;t=t!==null?t.memoizedState:null}else t=zt.next;var e=Xt===null?nt.memoizedState:Xt.next;if(e!==null)Xt=e,zt=t;else{if(t===null)throw nt.alternate===null?Error(f(467)):Error(f(310));zt=t,t={memoizedState:zt.memoizedState,baseState:zt.baseState,baseQueue:zt.baseQueue,queue:zt.queue,next:null},Xt===null?nt.memoizedState=Xt=t:Xt=Xt.next=t}return Xt}function bu(){return{lastEffect:null,events:null,stores:null,memoCache:null}}function on(t){var e=rn;return rn+=1,Aa===null&&(Aa=[]),t=sr(Aa,t,e),e=nt,(Xt===null?e.memoizedState:Xt.next)===null&&(e=e.alternate,x.H=e===null||e.memoizedState===null?to:Oc),t}function Eu(t){if(t!==null&&typeof t=="object"){if(typeof t.then=="function")return on(t);if(t.$$typeof===G)return kt(t)}throw Error(f(438,String(t)))}function vc(t){var e=null,l=nt.updateQueue;if(l!==null&&(e=l.memoCache),e==null){var a=nt.alternate;a!==null&&(a=a.updateQueue,a!==null&&(a=a.memoCache,a!=null&&(e={data:a.data.map(function(n){return n.slice()}),index:0})))}if(e==null&&(e={data:[],index:0}),l===null&&(l=bu(),nt.updateQueue=l),l.memoCache=e,l=e.data[e.index],l===void 0)for(l=e.data[e.index]=Array(t),a=0;a<t;a++)l[a]=Yt;return e.index++,l}function $e(t,e){return typeof e=="function"?e(t):e}function Tu(t){var e=Lt();return gc(e,zt,t)}function gc(t,e,l){var a=t.queue;if(a===null)throw Error(f(311));a.lastRenderedReducer=l;var n=t.baseQueue,u=a.pending;if(u!==null){if(n!==null){var i=n.next;n.next=u.next,u.next=i}e.baseQueue=n=u,a.pending=null}if(u=t.baseState,n===null)t.memoizedState=u;else{e=n.next;var s=i=null,m=null,z=e,C=!1;do{var j=z.lane&-536870913;if(j!==z.lane?(rt&j)===j:(Je&j)===j){var A=z.revertLane;if(A===0)m!==null&&(m=m.next={lane:0,revertLane:0,gesture:null,action:z.action,hasEagerState:z.hasEagerState,eagerState:z.eagerState,next:null}),j===pa&&(C=!0);else if((Je&A)===A){z=z.next,A===pa&&(C=!0);continue}else j={lane:0,revertLane:z.revertLane,gesture:null,action:z.action,hasEagerState:z.hasEagerState,eagerState:z.eagerState,next:null},m===null?(s=m=j,i=u):m=m.next=j,nt.lanes|=A,bl|=A;j=z.action,Jl&&l(u,j),u=z.hasEagerState?z.eagerState:l(u,j)}else A={lane:j,revertLane:z.revertLane,gesture:z.gesture,action:z.action,hasEagerState:z.hasEagerState,eagerState:z.eagerState,next:null},m===null?(s=m=A,i=u):m=m.next=A,nt.lanes|=j,bl|=j;z=z.next}while(z!==null&&z!==e);if(m===null?i=u:m.next=s,!de(u,t.memoizedState)&&(Qt=!0,C&&(l=Sa,l!==null)))throw l;t.memoizedState=u,t.baseState=i,t.baseQueue=m,a.lastRenderedState=u}return n===null&&(a.lanes=0),[t.memoizedState,a.dispatch]}function pc(t){var e=Lt(),l=e.queue;if(l===null)throw Error(f(311));l.lastRenderedReducer=t;var a=l.dispatch,n=l.pending,u=e.memoizedState;if(n!==null){l.pending=null;var i=n=n.next;do u=t(u,i.action),i=i.next;while(i!==n);de(u,e.memoizedState)||(Qt=!0),e.memoizedState=u,e.baseQueue===null&&(e.baseState=u),l.lastRenderedState=u}return[u,a]}function br(t,e,l){var a=nt,n=Lt(),u=ht;if(u){if(l===void 0)throw Error(f(407));l=l()}else l=e();var i=!de((zt||n).memoizedState,l);if(i&&(n.memoizedState=l,Qt=!0),n=n.queue,Ec(zr.bind(null,a,n,t),[t]),n.getSnapshot!==e||i||Xt!==null&&Xt.memoizedState.tag&1){if(a.flags|=2048,_a(9,{destroy:void 0},Tr.bind(null,a,n,l,e),null),Ot===null)throw Error(f(349));u||(Je&127)!==0||Er(a,e,l)}return l}function Er(t,e,l){t.flags|=16384,t={getSnapshot:e,value:l},e=nt.updateQueue,e===null?(e=bu(),nt.updateQueue=e,e.stores=[t]):(l=e.stores,l===null?e.stores=[t]:l.push(t))}function Tr(t,e,l,a){e.value=l,e.getSnapshot=a,Ar(e)&&_r(t)}function zr(t,e,l){return l(function(){Ar(e)&&_r(t)})}function Ar(t){var e=t.getSnapshot;t=t.value;try{var l=e();return!de(t,l)}catch{return!0}}function _r(t){var e=Ll(t,2);e!==null&&ce(e,t,2)}function Sc(t){var e=te();if(typeof t=="function"){var l=t;if(t=l(),Jl){il(!0);try{l()}finally{il(!1)}}}return e.memoizedState=e.baseState=t,e.queue={pending:null,lanes:0,dispatch:null,lastRenderedReducer:$e,lastRenderedState:t},e}function Rr(t,e,l,a){return t.baseState=l,gc(t,zt,typeof a=="function"?a:$e)}function km(t,e,l,a,n){if(_u(t))throw Error(f(485));if(t=e.action,t!==null){var u={payload:n,action:t,next:null,isTransition:!0,status:"pending",value:null,reason:null,listeners:[],then:function(i){u.listeners.push(i)}};x.T!==null?l(!0):u.isTransition=!1,a(u),l=e.pending,l===null?(u.next=e.pending=u,Or(e,u)):(u.next=l.next,e.pending=l.next=u)}}function Or(t,e){var l=e.action,a=e.payload,n=t.state;if(e.isTransition){var u=x.T,i={};x.T=i;try{var s=l(n,a),m=x.S;m!==null&&m(i,s),xr(t,e,s)}catch(z){bc(t,e,z)}finally{u!==null&&i.types!==null&&(u.types=i.types),x.T=u}}else try{u=l(n,a),xr(t,e,u)}catch(z){bc(t,e,z)}}function xr(t,e,l){l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(function(a){Mr(t,e,a)},function(a){return bc(t,e,a)}):Mr(t,e,l)}function Mr(t,e,l){e.status="fulfilled",e.value=l,Nr(e),t.state=l,e=t.pending,e!==null&&(l=e.next,l===e?t.pending=null:(l=l.next,e.next=l,Or(t,l)))}function bc(t,e,l){var a=t.pending;if(t.pending=null,a!==null){a=a.next;do e.status="rejected",e.reason=l,Nr(e),e=e.next;while(e!==a)}t.action=null}function Nr(t){t=t.listeners;for(var e=0;e<t.length;e++)(0,t[e])()}function Cr(t,e){return e}function Dr(t,e){if(ht){var l=Ot.formState;if(l!==null){t:{var a=nt;if(ht){if(Mt){e:{for(var n=Mt,u=Oe;n.nodeType!==8;){if(!u){n=null;break e}if(n=Me(n.nextSibling),n===null){n=null;break e}}u=n.data,n=u==="F!"||u==="F"?n:null}if(n){Mt=Me(n.nextSibling),a=n.data==="F!";break t}}ol(a)}a=!1}a&&(e=l[0])}}return l=te(),l.memoizedState=l.baseState=e,a={pending:null,lanes:0,dispatch:null,lastRenderedReducer:Cr,lastRenderedState:e},l.queue=a,l=Wr.bind(null,nt,a),a.dispatch=l,a=Sc(!1),u=Rc.bind(null,nt,!1,a.queue),a=te(),n={state:e,dispatch:null,action:t,pending:null},a.queue=n,l=km.bind(null,nt,n,u,l),n.dispatch=l,a.memoizedState=t,[e,l,!1]}function Ur(t){var e=Lt();return jr(e,zt,t)}function jr(t,e,l){if(e=gc(t,e,Cr)[0],t=Tu($e)[0],typeof e=="object"&&e!==null&&typeof e.then=="function")try{var a=on(e)}catch(i){throw i===ba?du:i}else a=e;e=Lt();var n=e.queue,u=n.dispatch;return l!==e.memoizedState&&(nt.flags|=2048,_a(9,{destroy:void 0},Fm.bind(null,n,l),null)),[a,u,t]}function Fm(t,e){t.action=e}function Hr(t){var e=Lt(),l=zt;if(l!==null)return jr(e,l,t);Lt(),e=e.memoizedState,l=Lt();var a=l.queue.dispatch;return l.memoizedState=t,[e,a,!1]}function _a(t,e,l,a){return t={tag:t,create:l,deps:a,inst:e,next:null},e=nt.updateQueue,e===null&&(e=bu(),nt.updateQueue=e),l=e.lastEffect,l===null?e.lastEffect=t.next=t:(a=l.next,l.next=t,t.next=a,e.lastEffect=t),t}function Br(){return Lt().memoizedState}function zu(t,e,l,a){var n=te();nt.flags|=t,n.memoizedState=_a(1|e,{destroy:void 0},l,a===void 0?null:a)}function Au(t,e,l,a){var n=Lt();a=a===void 0?null:a;var u=n.memoizedState.inst;zt!==null&&a!==null&&oc(a,zt.memoizedState.deps)?n.memoizedState=_a(e,u,l,a):(nt.flags|=t,n.memoizedState=_a(1|e,u,l,a))}function qr(t,e){zu(8390656,8,t,e)}function Ec(t,e){Au(2048,8,t,e)}function Wm(t){nt.flags|=4;var e=nt.updateQueue;if(e===null)e=bu(),nt.updateQueue=e,e.events=[t];else{var l=e.events;l===null?e.events=[t]:l.push(t)}}function Lr(t){var e=Lt().memoizedState;return Wm({ref:e,nextImpl:t}),function(){if((pt&2)!==0)throw Error(f(440));return e.impl.apply(void 0,arguments)}}function Yr(t,e){return Au(4,2,t,e)}function Gr(t,e){return Au(4,4,t,e)}function Xr(t,e){if(typeof e=="function"){t=t();var l=e(t);return function(){typeof l=="function"?l():e(null)}}if(e!=null)return t=t(),e.current=t,function(){e.current=null}}function Qr(t,e,l){l=l!=null?l.concat([t]):null,Au(4,4,Xr.bind(null,e,t),l)}function Tc(){}function Zr(t,e){var l=Lt();e=e===void 0?null:e;var a=l.memoizedState;return e!==null&&oc(e,a[1])?a[0]:(l.memoizedState=[t,e],t)}function Vr(t,e){var l=Lt();e=e===void 0?null:e;var a=l.memoizedState;if(e!==null&&oc(e,a[1]))return a[0];if(a=t(),Jl){il(!0);try{t()}finally{il(!1)}}return l.memoizedState=[a,e],a}function zc(t,e,l){return l===void 0||(Je&1073741824)!==0&&(rt&261930)===0?t.memoizedState=e:(t.memoizedState=l,t=Ko(),nt.lanes|=t,bl|=t,l)}function wr(t,e,l,a){return de(l,e)?l:Ta.current!==null?(t=zc(t,l,a),de(t,e)||(Qt=!0),t):(Je&42)===0||(Je&1073741824)!==0&&(rt&261930)===0?(Qt=!0,t.memoizedState=l):(t=Ko(),nt.lanes|=t,bl|=t,e)}function Kr(t,e,l,a,n){var u=L.p;L.p=u!==0&&8>u?u:8;var i=x.T,s={};x.T=s,Rc(t,!1,e,l);try{var m=n(),z=x.S;if(z!==null&&z(s,m),m!==null&&typeof m=="object"&&typeof m.then=="function"){var C=Km(m,a);dn(t,e,C,pe(t))}else dn(t,e,a,pe(t))}catch(j){dn(t,e,{then:function(){},status:"rejected",reason:j},pe())}finally{L.p=u,i!==null&&s.types!==null&&(i.types=s.types),x.T=i}}function Im(){}function Ac(t,e,l,a){if(t.tag!==5)throw Error(f(476));var n=Jr(t).queue;Kr(t,n,e,k,l===null?Im:function(){return $r(t),l(a)})}function Jr(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:k,baseState:k,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:$e,lastRenderedState:k},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:$e,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function $r(t){var e=Jr(t);e.next===null&&(e=t.alternate.memoizedState),dn(t,e.next.queue,{},pe())}function _c(){return kt(Mn)}function kr(){return Lt().memoizedState}function Fr(){return Lt().memoizedState}function Pm(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=pe();t=ml(l);var a=yl(e,t,l);a!==null&&(ce(a,e,l),cn(a,e,l)),e={cache:tc()},t.payload=e;return}e=e.return}}function ty(t,e,l){var a=pe();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},_u(t)?Ir(e,l):(l=Zi(t,e,l,a),l!==null&&(ce(l,t,a),Pr(l,e,a)))}function Wr(t,e,l){var a=pe();dn(t,e,l,a)}function dn(t,e,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(_u(t))Ir(e,n);else{var u=t.alternate;if(t.lanes===0&&(u===null||u.lanes===0)&&(u=e.lastRenderedReducer,u!==null))try{var i=e.lastRenderedState,s=u(i,l);if(n.hasEagerState=!0,n.eagerState=s,de(s,i))return uu(t,e,n,0),Ot===null&&nu(),!1}catch{}if(l=Zi(t,e,n,a),l!==null)return ce(l,t,a),Pr(l,e,a),!0}return!1}function Rc(t,e,l,a){if(a={lane:2,revertLane:nf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},_u(t)){if(e)throw Error(f(479))}else e=Zi(t,l,a,2),e!==null&&ce(e,t,2)}function _u(t){var e=t.alternate;return t===nt||e!==null&&e===nt}function Ir(t,e){za=pu=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function Pr(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,ns(t,l)}}var hn={readContext:kt,use:Eu,useCallback:Ut,useContext:Ut,useEffect:Ut,useImperativeHandle:Ut,useLayoutEffect:Ut,useInsertionEffect:Ut,useMemo:Ut,useReducer:Ut,useRef:Ut,useState:Ut,useDebugValue:Ut,useDeferredValue:Ut,useTransition:Ut,useSyncExternalStore:Ut,useId:Ut,useHostTransitionStatus:Ut,useFormState:Ut,useActionState:Ut,useOptimistic:Ut,useMemoCache:Ut,useCacheRefresh:Ut};hn.useEffectEvent=Ut;var to={readContext:kt,use:Eu,useCallback:function(t,e){return te().memoizedState=[t,e===void 0?null:e],t},useContext:kt,useEffect:qr,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,zu(4194308,4,Xr.bind(null,e,t),l)},useLayoutEffect:function(t,e){return zu(4194308,4,t,e)},useInsertionEffect:function(t,e){zu(4,2,t,e)},useMemo:function(t,e){var l=te();e=e===void 0?null:e;var a=t();if(Jl){il(!0);try{t()}finally{il(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=te();if(l!==void 0){var n=l(e);if(Jl){il(!0);try{l(e)}finally{il(!1)}}}else n=e;return a.memoizedState=a.baseState=n,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:n},a.queue=t,t=t.dispatch=ty.bind(null,nt,t),[a.memoizedState,t]},useRef:function(t){var e=te();return t={current:t},e.memoizedState=t},useState:function(t){t=Sc(t);var e=t.queue,l=Wr.bind(null,nt,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Tc,useDeferredValue:function(t,e){var l=te();return zc(l,t,e)},useTransition:function(){var t=Sc(!1);return t=Kr.bind(null,nt,t.queue,!0,!1),te().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=nt,n=te();if(ht){if(l===void 0)throw Error(f(407));l=l()}else{if(l=e(),Ot===null)throw Error(f(349));(rt&127)!==0||Er(a,e,l)}n.memoizedState=l;var u={value:l,getSnapshot:e};return n.queue=u,qr(zr.bind(null,a,u,t),[t]),a.flags|=2048,_a(9,{destroy:void 0},Tr.bind(null,a,u,l,e),null),l},useId:function(){var t=te(),e=Ot.identifierPrefix;if(ht){var l=qe,a=Be;l=(a&~(1<<32-oe(a)-1)).toString(32)+l,e="_"+e+"R_"+l,l=Su++,0<l&&(e+="H"+l.toString(32)),e+="_"}else l=Jm++,e="_"+e+"r_"+l.toString(32)+"_";return t.memoizedState=e},useHostTransitionStatus:_c,useFormState:Dr,useActionState:Dr,useOptimistic:function(t){var e=te();e.memoizedState=e.baseState=t;var l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:null,lastRenderedState:null};return e.queue=l,e=Rc.bind(null,nt,!0,l),l.dispatch=e,[t,e]},useMemoCache:vc,useCacheRefresh:function(){return te().memoizedState=Pm.bind(null,nt)},useEffectEvent:function(t){var e=te(),l={impl:t};return e.memoizedState=l,function(){if((pt&2)!==0)throw Error(f(440));return l.impl.apply(void 0,arguments)}}},Oc={readContext:kt,use:Eu,useCallback:Zr,useContext:kt,useEffect:Ec,useImperativeHandle:Qr,useInsertionEffect:Yr,useLayoutEffect:Gr,useMemo:Vr,useReducer:Tu,useRef:Br,useState:function(){return Tu($e)},useDebugValue:Tc,useDeferredValue:function(t,e){var l=Lt();return wr(l,zt.memoizedState,t,e)},useTransition:function(){var t=Tu($e)[0],e=Lt().memoizedState;return[typeof t=="boolean"?t:on(t),e]},useSyncExternalStore:br,useId:kr,useHostTransitionStatus:_c,useFormState:Ur,useActionState:Ur,useOptimistic:function(t,e){var l=Lt();return Rr(l,zt,t,e)},useMemoCache:vc,useCacheRefresh:Fr};Oc.useEffectEvent=Lr;var eo={readContext:kt,use:Eu,useCallback:Zr,useContext:kt,useEffect:Ec,useImperativeHandle:Qr,useInsertionEffect:Yr,useLayoutEffect:Gr,useMemo:Vr,useReducer:pc,useRef:Br,useState:function(){return pc($e)},useDebugValue:Tc,useDeferredValue:function(t,e){var l=Lt();return zt===null?zc(l,t,e):wr(l,zt.memoizedState,t,e)},useTransition:function(){var t=pc($e)[0],e=Lt().memoizedState;return[typeof t=="boolean"?t:on(t),e]},useSyncExternalStore:br,useId:kr,useHostTransitionStatus:_c,useFormState:Hr,useActionState:Hr,useOptimistic:function(t,e){var l=Lt();return zt!==null?Rr(l,zt,t,e):(l.baseState=t,[t,l.queue.dispatch])},useMemoCache:vc,useCacheRefresh:Fr};eo.useEffectEvent=Lr;function xc(t,e,l,a){e=t.memoizedState,l=l(a,e),l=l==null?e:R({},e,l),t.memoizedState=l,t.lanes===0&&(t.updateQueue.baseState=l)}var Mc={enqueueSetState:function(t,e,l){t=t._reactInternals;var a=pe(),n=ml(a);n.payload=e,l!=null&&(n.callback=l),e=yl(t,n,a),e!==null&&(ce(e,t,a),cn(e,t,a))},enqueueReplaceState:function(t,e,l){t=t._reactInternals;var a=pe(),n=ml(a);n.tag=1,n.payload=e,l!=null&&(n.callback=l),e=yl(t,n,a),e!==null&&(ce(e,t,a),cn(e,t,a))},enqueueForceUpdate:function(t,e){t=t._reactInternals;var l=pe(),a=ml(l);a.tag=2,e!=null&&(a.callback=e),e=yl(t,a,l),e!==null&&(ce(e,t,l),cn(e,t,l))}};function lo(t,e,l,a,n,u,i){return t=t.stateNode,typeof t.shouldComponentUpdate=="function"?t.shouldComponentUpdate(a,u,i):e.prototype&&e.prototype.isPureReactComponent?!Ia(l,a)||!Ia(n,u):!0}function ao(t,e,l,a){t=e.state,typeof e.componentWillReceiveProps=="function"&&e.componentWillReceiveProps(l,a),typeof e.UNSAFE_componentWillReceiveProps=="function"&&e.UNSAFE_componentWillReceiveProps(l,a),e.state!==t&&Mc.enqueueReplaceState(e,e.state,null)}function $l(t,e){var l=e;if("ref"in e){l={};for(var a in e)a!=="ref"&&(l[a]=e[a])}if(t=t.defaultProps){l===e&&(l=R({},l));for(var n in t)l[n]===void 0&&(l[n]=t[n])}return l}function no(t){au(t)}function uo(t){console.error(t)}function io(t){au(t)}function Ru(t,e){try{var l=t.onUncaughtError;l(e.value,{componentStack:e.stack})}catch(a){setTimeout(function(){throw a})}}function co(t,e,l){try{var a=t.onCaughtError;a(l.value,{componentStack:l.stack,errorBoundary:e.tag===1?e.stateNode:null})}catch(n){setTimeout(function(){throw n})}}function Nc(t,e,l){return l=ml(l),l.tag=3,l.payload={element:null},l.callback=function(){Ru(t,e)},l}function fo(t){return t=ml(t),t.tag=3,t}function so(t,e,l,a){var n=l.type.getDerivedStateFromError;if(typeof n=="function"){var u=a.value;t.payload=function(){return n(u)},t.callback=function(){co(e,l,a)}}var i=l.stateNode;i!==null&&typeof i.componentDidCatch=="function"&&(t.callback=function(){co(e,l,a),typeof n!="function"&&(El===null?El=new Set([this]):El.add(this));var s=a.stack;this.componentDidCatch(a.value,{componentStack:s!==null?s:""})})}function ey(t,e,l,a,n){if(l.flags|=32768,a!==null&&typeof a=="object"&&typeof a.then=="function"){if(e=l.alternate,e!==null&&ga(e,l,n,!0),l=me.current,l!==null){switch(l.tag){case 31:case 13:return xe===null?Lu():l.alternate===null&&jt===0&&(jt=3),l.flags&=-257,l.flags|=65536,l.lanes=n,a===hu?l.flags|=16384:(e=l.updateQueue,e===null?l.updateQueue=new Set([a]):e.add(a),ef(t,a,n)),!1;case 22:return l.flags|=65536,a===hu?l.flags|=16384:(e=l.updateQueue,e===null?(e={transitions:null,markerInstances:null,retryQueue:new Set([a])},l.updateQueue=e):(l=e.retryQueue,l===null?e.retryQueue=new Set([a]):l.add(a)),ef(t,a,n)),!1}throw Error(f(435,l.tag))}return ef(t,a,n),Lu(),!1}if(ht)return e=me.current,e!==null?((e.flags&65536)===0&&(e.flags|=256),e.flags|=65536,e.lanes=n,a!==ki&&(t=Error(f(422),{cause:a}),en(Ae(t,l)))):(a!==ki&&(e=Error(f(423),{cause:a}),en(Ae(e,l))),t=t.current.alternate,t.flags|=65536,n&=-n,t.lanes|=n,a=Ae(a,l),n=Nc(t.stateNode,a,n),ic(t,n),jt!==4&&(jt=2)),!1;var u=Error(f(520),{cause:a});if(u=Ae(u,l),En===null?En=[u]:En.push(u),jt!==4&&(jt=2),e===null)return!0;a=Ae(a,l),l=e;do{switch(l.tag){case 3:return l.flags|=65536,t=n&-n,l.lanes|=t,t=Nc(l.stateNode,a,t),ic(l,t),!1;case 1:if(e=l.type,u=l.stateNode,(l.flags&128)===0&&(typeof e.getDerivedStateFromError=="function"||u!==null&&typeof u.componentDidCatch=="function"&&(El===null||!El.has(u))))return l.flags|=65536,n&=-n,l.lanes|=n,n=fo(n),so(n,t,l,a),ic(l,n),!1}l=l.return}while(l!==null);return!1}var Cc=Error(f(461)),Qt=!1;function Ft(t,e,l,a){e.child=t===null?hr(e,null,l,a):Kl(e,t.child,l,a)}function ro(t,e,l,a,n){l=l.render;var u=e.ref;if("ref"in a){var i={};for(var s in a)s!=="ref"&&(i[s]=a[s])}else i=a;return Ql(e),a=dc(t,e,l,i,u,n),s=hc(),t!==null&&!Qt?(mc(t,e,n),ke(t,e,n)):(ht&&s&&Ji(e),e.flags|=1,Ft(t,e,a,n),e.child)}function oo(t,e,l,a,n){if(t===null){var u=l.type;return typeof u=="function"&&!Vi(u)&&u.defaultProps===void 0&&l.compare===null?(e.tag=15,e.type=u,ho(t,e,u,a,n)):(t=cu(l.type,null,a,e,e.mode,n),t.ref=e.ref,t.return=e,e.child=t)}if(u=t.child,!Yc(t,n)){var i=u.memoizedProps;if(l=l.compare,l=l!==null?l:Ia,l(i,a)&&t.ref===e.ref)return ke(t,e,n)}return e.flags|=1,t=Ze(u,a),t.ref=e.ref,t.return=e,e.child=t}function ho(t,e,l,a,n){if(t!==null){var u=t.memoizedProps;if(Ia(u,a)&&t.ref===e.ref)if(Qt=!1,e.pendingProps=a=u,Yc(t,n))(t.flags&131072)!==0&&(Qt=!0);else return e.lanes=t.lanes,ke(t,e,n)}return Dc(t,e,l,a,n)}function mo(t,e,l,a){var n=a.children,u=t!==null?t.memoizedState:null;if(t===null&&e.stateNode===null&&(e.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),a.mode==="hidden"){if((e.flags&128)!==0){if(u=u!==null?u.baseLanes|l:l,t!==null){for(a=e.child=t.child,n=0;a!==null;)n=n|a.lanes|a.childLanes,a=a.sibling;a=n&~u}else a=0,e.child=null;return yo(t,e,u,l,a)}if((l&536870912)!==0)e.memoizedState={baseLanes:0,cachePool:null},t!==null&&ou(e,u!==null?u.cachePool:null),u!==null?vr(e,u):fc(),gr(e);else return a=e.lanes=536870912,yo(t,e,u!==null?u.baseLanes|l:l,l,a)}else u!==null?(ou(e,u.cachePool),vr(e,u),gl(),e.memoizedState=null):(t!==null&&ou(e,null),fc(),gl());return Ft(t,e,n,l),e.child}function mn(t,e){return t!==null&&t.tag===22||e.stateNode!==null||(e.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null}),e.sibling}function yo(t,e,l,a,n){var u=lc();return u=u===null?null:{parent:Gt._currentValue,pool:u},e.memoizedState={baseLanes:l,cachePool:u},t!==null&&ou(e,null),fc(),gr(e),t!==null&&ga(t,e,a,!0),e.childLanes=n,null}function Ou(t,e){return e=Mu({mode:e.mode,children:e.children},t.mode),e.ref=t.ref,t.child=e,e.return=t,e}function vo(t,e,l){return Kl(e,t.child,null,l),t=Ou(e,e.pendingProps),t.flags|=2,ye(e),e.memoizedState=null,t}function ly(t,e,l){var a=e.pendingProps,n=(e.flags&128)!==0;if(e.flags&=-129,t===null){if(ht){if(a.mode==="hidden")return t=Ou(e,a),e.lanes=536870912,mn(null,t);if(rc(e),(t=Mt)?(t=xd(t,Oe),t=t!==null&&t.data==="&"?t:null,t!==null&&(e.memoizedState={dehydrated:t,treeContext:sl!==null?{id:Be,overflow:qe}:null,retryLane:536870912,hydrationErrors:null},l=Is(t),l.return=e,e.child=l,$t=e,Mt=null)):t=null,t===null)throw ol(e);return e.lanes=536870912,null}return Ou(e,a)}var u=t.memoizedState;if(u!==null){var i=u.dehydrated;if(rc(e),n)if(e.flags&256)e.flags&=-257,e=vo(t,e,l);else if(e.memoizedState!==null)e.child=t.child,e.flags|=128,e=null;else throw Error(f(558));else if(Qt||ga(t,e,l,!1),n=(l&t.childLanes)!==0,Qt||n){if(a=Ot,a!==null&&(i=us(a,l),i!==0&&i!==u.retryLane))throw u.retryLane=i,Ll(t,i),ce(a,t,i),Cc;Lu(),e=vo(t,e,l)}else t=u.treeContext,Mt=Me(i.nextSibling),$t=e,ht=!0,rl=null,Oe=!1,t!==null&&er(e,t),e=Ou(e,a),e.flags|=4096;return e}return t=Ze(t.child,{mode:a.mode,children:a.children}),t.ref=e.ref,e.child=t,t.return=e,t}function xu(t,e){var l=e.ref;if(l===null)t!==null&&t.ref!==null&&(e.flags|=4194816);else{if(typeof l!="function"&&typeof l!="object")throw Error(f(284));(t===null||t.ref!==l)&&(e.flags|=4194816)}}function Dc(t,e,l,a,n){return Ql(e),l=dc(t,e,l,a,void 0,n),a=hc(),t!==null&&!Qt?(mc(t,e,n),ke(t,e,n)):(ht&&a&&Ji(e),e.flags|=1,Ft(t,e,l,n),e.child)}function go(t,e,l,a,n,u){return Ql(e),e.updateQueue=null,l=Sr(e,a,l,n),pr(t),a=hc(),t!==null&&!Qt?(mc(t,e,u),ke(t,e,u)):(ht&&a&&Ji(e),e.flags|=1,Ft(t,e,l,u),e.child)}function po(t,e,l,a,n){if(Ql(e),e.stateNode===null){var u=ha,i=l.contextType;typeof i=="object"&&i!==null&&(u=kt(i)),u=new l(a,u),e.memoizedState=u.state!==null&&u.state!==void 0?u.state:null,u.updater=Mc,e.stateNode=u,u._reactInternals=e,u=e.stateNode,u.props=a,u.state=e.memoizedState,u.refs={},nc(e),i=l.contextType,u.context=typeof i=="object"&&i!==null?kt(i):ha,u.state=e.memoizedState,i=l.getDerivedStateFromProps,typeof i=="function"&&(xc(e,l,i,a),u.state=e.memoizedState),typeof l.getDerivedStateFromProps=="function"||typeof u.getSnapshotBeforeUpdate=="function"||typeof u.UNSAFE_componentWillMount!="function"&&typeof u.componentWillMount!="function"||(i=u.state,typeof u.componentWillMount=="function"&&u.componentWillMount(),typeof u.UNSAFE_componentWillMount=="function"&&u.UNSAFE_componentWillMount(),i!==u.state&&Mc.enqueueReplaceState(u,u.state,null),sn(e,a,u,n),fn(),u.state=e.memoizedState),typeof u.componentDidMount=="function"&&(e.flags|=4194308),a=!0}else if(t===null){u=e.stateNode;var s=e.memoizedProps,m=$l(l,s);u.props=m;var z=u.context,C=l.contextType;i=ha,typeof C=="object"&&C!==null&&(i=kt(C));var j=l.getDerivedStateFromProps;C=typeof j=="function"||typeof u.getSnapshotBeforeUpdate=="function",s=e.pendingProps!==s,C||typeof u.UNSAFE_componentWillReceiveProps!="function"&&typeof u.componentWillReceiveProps!="function"||(s||z!==i)&&ao(e,u,a,i),hl=!1;var A=e.memoizedState;u.state=A,sn(e,a,u,n),fn(),z=e.memoizedState,s||A!==z||hl?(typeof j=="function"&&(xc(e,l,j,a),z=e.memoizedState),(m=hl||lo(e,l,m,a,A,z,i))?(C||typeof u.UNSAFE_componentWillMount!="function"&&typeof u.componentWillMount!="function"||(typeof u.componentWillMount=="function"&&u.componentWillMount(),typeof u.UNSAFE_componentWillMount=="function"&&u.UNSAFE_componentWillMount()),typeof u.componentDidMount=="function"&&(e.flags|=4194308)):(typeof u.componentDidMount=="function"&&(e.flags|=4194308),e.memoizedProps=a,e.memoizedState=z),u.props=a,u.state=z,u.context=i,a=m):(typeof u.componentDidMount=="function"&&(e.flags|=4194308),a=!1)}else{u=e.stateNode,uc(t,e),i=e.memoizedProps,C=$l(l,i),u.props=C,j=e.pendingProps,A=u.context,z=l.contextType,m=ha,typeof z=="object"&&z!==null&&(m=kt(z)),s=l.getDerivedStateFromProps,(z=typeof s=="function"||typeof u.getSnapshotBeforeUpdate=="function")||typeof u.UNSAFE_componentWillReceiveProps!="function"&&typeof u.componentWillReceiveProps!="function"||(i!==j||A!==m)&&ao(e,u,a,m),hl=!1,A=e.memoizedState,u.state=A,sn(e,a,u,n),fn();var O=e.memoizedState;i!==j||A!==O||hl||t!==null&&t.dependencies!==null&&su(t.dependencies)?(typeof s=="function"&&(xc(e,l,s,a),O=e.memoizedState),(C=hl||lo(e,l,C,a,A,O,m)||t!==null&&t.dependencies!==null&&su(t.dependencies))?(z||typeof u.UNSAFE_componentWillUpdate!="function"&&typeof u.componentWillUpdate!="function"||(typeof u.componentWillUpdate=="function"&&u.componentWillUpdate(a,O,m),typeof u.UNSAFE_componentWillUpdate=="function"&&u.UNSAFE_componentWillUpdate(a,O,m)),typeof u.componentDidUpdate=="function"&&(e.flags|=4),typeof u.getSnapshotBeforeUpdate=="function"&&(e.flags|=1024)):(typeof u.componentDidUpdate!="function"||i===t.memoizedProps&&A===t.memoizedState||(e.flags|=4),typeof u.getSnapshotBeforeUpdate!="function"||i===t.memoizedProps&&A===t.memoizedState||(e.flags|=1024),e.memoizedProps=a,e.memoizedState=O),u.props=a,u.state=O,u.context=m,a=C):(typeof u.componentDidUpdate!="function"||i===t.memoizedProps&&A===t.memoizedState||(e.flags|=4),typeof u.getSnapshotBeforeUpdate!="function"||i===t.memoizedProps&&A===t.memoizedState||(e.flags|=1024),a=!1)}return u=a,xu(t,e),a=(e.flags&128)!==0,u||a?(u=e.stateNode,l=a&&typeof l.getDerivedStateFromError!="function"?null:u.render(),e.flags|=1,t!==null&&a?(e.child=Kl(e,t.child,null,n),e.child=Kl(e,null,l,n)):Ft(t,e,l,n),e.memoizedState=u.state,t=e.child):t=ke(t,e,n),t}function So(t,e,l,a){return Gl(),e.flags|=256,Ft(t,e,l,a),e.child}var Uc={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function jc(t){return{baseLanes:t,cachePool:cr()}}function Hc(t,e,l){return t=t!==null?t.childLanes&~l:0,e&&(t|=ge),t}function bo(t,e,l){var a=e.pendingProps,n=!1,u=(e.flags&128)!==0,i;if((i=u)||(i=t!==null&&t.memoizedState===null?!1:(qt.current&2)!==0),i&&(n=!0,e.flags&=-129),i=(e.flags&32)!==0,e.flags&=-33,t===null){if(ht){if(n?vl(e):gl(),(t=Mt)?(t=xd(t,Oe),t=t!==null&&t.data!=="&"?t:null,t!==null&&(e.memoizedState={dehydrated:t,treeContext:sl!==null?{id:Be,overflow:qe}:null,retryLane:536870912,hydrationErrors:null},l=Is(t),l.return=e,e.child=l,$t=e,Mt=null)):t=null,t===null)throw ol(e);return pf(t)?e.lanes=32:e.lanes=536870912,null}var s=a.children;return a=a.fallback,n?(gl(),n=e.mode,s=Mu({mode:"hidden",children:s},n),a=Yl(a,n,l,null),s.return=e,a.return=e,s.sibling=a,e.child=s,a=e.child,a.memoizedState=jc(l),a.childLanes=Hc(t,i,l),e.memoizedState=Uc,mn(null,a)):(vl(e),Bc(e,s))}var m=t.memoizedState;if(m!==null&&(s=m.dehydrated,s!==null)){if(u)e.flags&256?(vl(e),e.flags&=-257,e=qc(t,e,l)):e.memoizedState!==null?(gl(),e.child=t.child,e.flags|=128,e=null):(gl(),s=a.fallback,n=e.mode,a=Mu({mode:"visible",children:a.children},n),s=Yl(s,n,l,null),s.flags|=2,a.return=e,s.return=e,a.sibling=s,e.child=a,Kl(e,t.child,null,l),a=e.child,a.memoizedState=jc(l),a.childLanes=Hc(t,i,l),e.memoizedState=Uc,e=mn(null,a));else if(vl(e),pf(s)){if(i=s.nextSibling&&s.nextSibling.dataset,i)var z=i.dgst;i=z,a=Error(f(419)),a.stack="",a.digest=i,en({value:a,source:null,stack:null}),e=qc(t,e,l)}else if(Qt||ga(t,e,l,!1),i=(l&t.childLanes)!==0,Qt||i){if(i=Ot,i!==null&&(a=us(i,l),a!==0&&a!==m.retryLane))throw m.retryLane=a,Ll(t,a),ce(i,t,a),Cc;gf(s)||Lu(),e=qc(t,e,l)}else gf(s)?(e.flags|=192,e.child=t.child,e=null):(t=m.treeContext,Mt=Me(s.nextSibling),$t=e,ht=!0,rl=null,Oe=!1,t!==null&&er(e,t),e=Bc(e,a.children),e.flags|=4096);return e}return n?(gl(),s=a.fallback,n=e.mode,m=t.child,z=m.sibling,a=Ze(m,{mode:"hidden",children:a.children}),a.subtreeFlags=m.subtreeFlags&65011712,z!==null?s=Ze(z,s):(s=Yl(s,n,l,null),s.flags|=2),s.return=e,a.return=e,a.sibling=s,e.child=a,mn(null,a),a=e.child,s=t.child.memoizedState,s===null?s=jc(l):(n=s.cachePool,n!==null?(m=Gt._currentValue,n=n.parent!==m?{parent:m,pool:m}:n):n=cr(),s={baseLanes:s.baseLanes|l,cachePool:n}),a.memoizedState=s,a.childLanes=Hc(t,i,l),e.memoizedState=Uc,mn(t.child,a)):(vl(e),l=t.child,t=l.sibling,l=Ze(l,{mode:"visible",children:a.children}),l.return=e,l.sibling=null,t!==null&&(i=e.deletions,i===null?(e.deletions=[t],e.flags|=16):i.push(t)),e.child=l,e.memoizedState=null,l)}function Bc(t,e){return e=Mu({mode:"visible",children:e},t.mode),e.return=t,t.child=e}function Mu(t,e){return t=he(22,t,null,e),t.lanes=0,t}function qc(t,e,l){return Kl(e,t.child,null,l),t=Bc(e,e.pendingProps.children),t.flags|=2,e.memoizedState=null,t}function Eo(t,e,l){t.lanes|=e;var a=t.alternate;a!==null&&(a.lanes|=e),Ii(t.return,e,l)}function Lc(t,e,l,a,n,u){var i=t.memoizedState;i===null?t.memoizedState={isBackwards:e,rendering:null,renderingStartTime:0,last:a,tail:l,tailMode:n,treeForkCount:u}:(i.isBackwards=e,i.rendering=null,i.renderingStartTime=0,i.last=a,i.tail=l,i.tailMode=n,i.treeForkCount=u)}function To(t,e,l){var a=e.pendingProps,n=a.revealOrder,u=a.tail;a=a.children;var i=qt.current,s=(i&2)!==0;if(s?(i=i&1|2,e.flags|=128):i&=1,Y(qt,i),Ft(t,e,a,l),a=ht?tn:0,!s&&t!==null&&(t.flags&128)!==0)t:for(t=e.child;t!==null;){if(t.tag===13)t.memoizedState!==null&&Eo(t,l,e);else if(t.tag===19)Eo(t,l,e);else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break t;for(;t.sibling===null;){if(t.return===null||t.return===e)break t;t=t.return}t.sibling.return=t.return,t=t.sibling}switch(n){case"forwards":for(l=e.child,n=null;l!==null;)t=l.alternate,t!==null&&gu(t)===null&&(n=l),l=l.sibling;l=n,l===null?(n=e.child,e.child=null):(n=l.sibling,l.sibling=null),Lc(e,!1,n,l,u,a);break;case"backwards":case"unstable_legacy-backwards":for(l=null,n=e.child,e.child=null;n!==null;){if(t=n.alternate,t!==null&&gu(t)===null){e.child=n;break}t=n.sibling,n.sibling=l,l=n,n=t}Lc(e,!0,l,null,u,a);break;case"together":Lc(e,!1,null,null,void 0,a);break;default:e.memoizedState=null}return e.child}function ke(t,e,l){if(t!==null&&(e.dependencies=t.dependencies),bl|=e.lanes,(l&e.childLanes)===0)if(t!==null){if(ga(t,e,l,!1),(l&e.childLanes)===0)return null}else return null;if(t!==null&&e.child!==t.child)throw Error(f(153));if(e.child!==null){for(t=e.child,l=Ze(t,t.pendingProps),e.child=l,l.return=e;t.sibling!==null;)t=t.sibling,l=l.sibling=Ze(t,t.pendingProps),l.return=e;l.sibling=null}return e.child}function Yc(t,e){return(t.lanes&e)!==0?!0:(t=t.dependencies,!!(t!==null&&su(t)))}function ay(t,e,l){switch(e.tag){case 3:Pt(e,e.stateNode.containerInfo),dl(e,Gt,t.memoizedState.cache),Gl();break;case 27:case 5:Ya(e);break;case 4:Pt(e,e.stateNode.containerInfo);break;case 10:dl(e,e.type,e.memoizedProps.value);break;case 31:if(e.memoizedState!==null)return e.flags|=128,rc(e),null;break;case 13:var a=e.memoizedState;if(a!==null)return a.dehydrated!==null?(vl(e),e.flags|=128,null):(l&e.child.childLanes)!==0?bo(t,e,l):(vl(e),t=ke(t,e,l),t!==null?t.sibling:null);vl(e);break;case 19:var n=(t.flags&128)!==0;if(a=(l&e.childLanes)!==0,a||(ga(t,e,l,!1),a=(l&e.childLanes)!==0),n){if(a)return To(t,e,l);e.flags|=128}if(n=e.memoizedState,n!==null&&(n.rendering=null,n.tail=null,n.lastEffect=null),Y(qt,qt.current),a)break;return null;case 22:return e.lanes=0,mo(t,e,l,e.pendingProps);case 24:dl(e,Gt,t.memoizedState.cache)}return ke(t,e,l)}function zo(t,e,l){if(t!==null)if(t.memoizedProps!==e.pendingProps)Qt=!0;else{if(!Yc(t,l)&&(e.flags&128)===0)return Qt=!1,ay(t,e,l);Qt=(t.flags&131072)!==0}else Qt=!1,ht&&(e.flags&1048576)!==0&&tr(e,tn,e.index);switch(e.lanes=0,e.tag){case 16:t:{var a=e.pendingProps;if(t=Vl(e.elementType),e.type=t,typeof t=="function")Vi(t)?(a=$l(t,a),e.tag=1,e=po(null,e,t,a,l)):(e.tag=0,e=Dc(null,e,t,a,l));else{if(t!=null){var n=t.$$typeof;if(n===dt){e.tag=11,e=ro(null,e,t,a,l);break t}else if(n===et){e.tag=14,e=oo(null,e,t,a,l);break t}}throw e=it(t)||t,Error(f(306,e,""))}}return e;case 0:return Dc(t,e,e.type,e.pendingProps,l);case 1:return a=e.type,n=$l(a,e.pendingProps),po(t,e,a,n,l);case 3:t:{if(Pt(e,e.stateNode.containerInfo),t===null)throw Error(f(387));a=e.pendingProps;var u=e.memoizedState;n=u.element,uc(t,e),sn(e,a,null,l);var i=e.memoizedState;if(a=i.cache,dl(e,Gt,a),a!==u.cache&&Pi(e,[Gt],l,!0),fn(),a=i.element,u.isDehydrated)if(u={element:a,isDehydrated:!1,cache:i.cache},e.updateQueue.baseState=u,e.memoizedState=u,e.flags&256){e=So(t,e,a,l);break t}else if(a!==n){n=Ae(Error(f(424)),e),en(n),e=So(t,e,a,l);break t}else for(t=e.stateNode.containerInfo,t.nodeType===9?t=t.body:t=t.nodeName==="HTML"?t.ownerDocument.body:t,Mt=Me(t.firstChild),$t=e,ht=!0,rl=null,Oe=!0,l=hr(e,null,a,l),e.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling;else{if(Gl(),a===n){e=ke(t,e,l);break t}Ft(t,e,a,l)}e=e.child}return e;case 26:return xu(t,e),t===null?(l=jd(e.type,null,e.pendingProps,null))?e.memoizedState=l:ht||(l=e.type,t=e.pendingProps,a=wu(ct.current).createElement(l),a[Jt]=e,a[ee]=t,Wt(a,l,t),wt(a),e.stateNode=a):e.memoizedState=jd(e.type,t.memoizedProps,e.pendingProps,t.memoizedState),null;case 27:return Ya(e),t===null&&ht&&(a=e.stateNode=Cd(e.type,e.pendingProps,ct.current),$t=e,Oe=!0,n=Mt,_l(e.type)?(Sf=n,Mt=Me(a.firstChild)):Mt=n),Ft(t,e,e.pendingProps.children,l),xu(t,e),t===null&&(e.flags|=4194304),e.child;case 5:return t===null&&ht&&((n=a=Mt)&&(a=Uy(a,e.type,e.pendingProps,Oe),a!==null?(e.stateNode=a,$t=e,Mt=Me(a.firstChild),Oe=!1,n=!0):n=!1),n||ol(e)),Ya(e),n=e.type,u=e.pendingProps,i=t!==null?t.memoizedProps:null,a=u.children,mf(n,u)?a=null:i!==null&&mf(n,i)&&(e.flags|=32),e.memoizedState!==null&&(n=dc(t,e,$m,null,null,l),Mn._currentValue=n),xu(t,e),Ft(t,e,a,l),e.child;case 6:return t===null&&ht&&((t=l=Mt)&&(l=jy(l,e.pendingProps,Oe),l!==null?(e.stateNode=l,$t=e,Mt=null,t=!0):t=!1),t||ol(e)),null;case 13:return bo(t,e,l);case 4:return Pt(e,e.stateNode.containerInfo),a=e.pendingProps,t===null?e.child=Kl(e,null,a,l):Ft(t,e,a,l),e.child;case 11:return ro(t,e,e.type,e.pendingProps,l);case 7:return Ft(t,e,e.pendingProps,l),e.child;case 8:return Ft(t,e,e.pendingProps.children,l),e.child;case 12:return Ft(t,e,e.pendingProps.children,l),e.child;case 10:return a=e.pendingProps,dl(e,e.type,a.value),Ft(t,e,a.children,l),e.child;case 9:return n=e.type._context,a=e.pendingProps.children,Ql(e),n=kt(n),a=a(n),e.flags|=1,Ft(t,e,a,l),e.child;case 14:return oo(t,e,e.type,e.pendingProps,l);case 15:return ho(t,e,e.type,e.pendingProps,l);case 19:return To(t,e,l);case 31:return ly(t,e,l);case 22:return mo(t,e,l,e.pendingProps);case 24:return Ql(e),a=kt(Gt),t===null?(n=lc(),n===null&&(n=Ot,u=tc(),n.pooledCache=u,u.refCount++,u!==null&&(n.pooledCacheLanes|=l),n=u),e.memoizedState={parent:a,cache:n},nc(e),dl(e,Gt,n)):((t.lanes&l)!==0&&(uc(t,e),sn(e,null,null,l),fn()),n=t.memoizedState,u=e.memoizedState,n.parent!==a?(n={parent:a,cache:a},e.memoizedState=n,e.lanes===0&&(e.memoizedState=e.updateQueue.baseState=n),dl(e,Gt,a)):(a=u.cache,dl(e,Gt,a),a!==n.cache&&Pi(e,[Gt],l,!0))),Ft(t,e,e.pendingProps.children,l),e.child;case 29:throw e.pendingProps}throw Error(f(156,e.tag))}function Fe(t){t.flags|=4}function Gc(t,e,l,a,n){if((e=(t.mode&32)!==0)&&(e=!1),e){if(t.flags|=16777216,(n&335544128)===n)if(t.stateNode.complete)t.flags|=8192;else if(Fo())t.flags|=8192;else throw wl=hu,ac}else t.flags&=-16777217}function Ao(t,e){if(e.type!=="stylesheet"||(e.state.loading&4)!==0)t.flags&=-16777217;else if(t.flags|=16777216,!Yd(e))if(Fo())t.flags|=8192;else throw wl=hu,ac}function Nu(t,e){e!==null&&(t.flags|=4),t.flags&16384&&(e=t.tag!==22?ls():536870912,t.lanes|=e,Ma|=e)}function yn(t,e){if(!ht)switch(t.tailMode){case"hidden":e=t.tail;for(var l=null;e!==null;)e.alternate!==null&&(l=e),e=e.sibling;l===null?t.tail=null:l.sibling=null;break;case"collapsed":l=t.tail;for(var a=null;l!==null;)l.alternate!==null&&(a=l),l=l.sibling;a===null?e||t.tail===null?t.tail=null:t.tail.sibling=null:a.sibling=null}}function Nt(t){var e=t.alternate!==null&&t.alternate.child===t.child,l=0,a=0;if(e)for(var n=t.child;n!==null;)l|=n.lanes|n.childLanes,a|=n.subtreeFlags&65011712,a|=n.flags&65011712,n.return=t,n=n.sibling;else for(n=t.child;n!==null;)l|=n.lanes|n.childLanes,a|=n.subtreeFlags,a|=n.flags,n.return=t,n=n.sibling;return t.subtreeFlags|=a,t.childLanes=l,e}function ny(t,e,l){var a=e.pendingProps;switch($i(e),e.tag){case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Nt(e),null;case 1:return Nt(e),null;case 3:return l=e.stateNode,a=null,t!==null&&(a=t.memoizedState.cache),e.memoizedState.cache!==a&&(e.flags|=2048),Ke(Gt),Bt(),l.pendingContext&&(l.context=l.pendingContext,l.pendingContext=null),(t===null||t.child===null)&&(va(e)?Fe(e):t===null||t.memoizedState.isDehydrated&&(e.flags&256)===0||(e.flags|=1024,Fi())),Nt(e),null;case 26:var n=e.type,u=e.memoizedState;return t===null?(Fe(e),u!==null?(Nt(e),Ao(e,u)):(Nt(e),Gc(e,n,null,a,l))):u?u!==t.memoizedState?(Fe(e),Nt(e),Ao(e,u)):(Nt(e),e.flags&=-16777217):(t=t.memoizedProps,t!==a&&Fe(e),Nt(e),Gc(e,n,t,a,l)),null;case 27:if(Xn(e),l=ct.current,n=e.type,t!==null&&e.stateNode!=null)t.memoizedProps!==a&&Fe(e);else{if(!a){if(e.stateNode===null)throw Error(f(166));return Nt(e),null}t=V.current,va(e)?lr(e):(t=Cd(n,a,l),e.stateNode=t,Fe(e))}return Nt(e),null;case 5:if(Xn(e),n=e.type,t!==null&&e.stateNode!=null)t.memoizedProps!==a&&Fe(e);else{if(!a){if(e.stateNode===null)throw Error(f(166));return Nt(e),null}if(u=V.current,va(e))lr(e);else{var i=wu(ct.current);switch(u){case 1:u=i.createElementNS("http://www.w3.org/2000/svg",n);break;case 2:u=i.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;default:switch(n){case"svg":u=i.createElementNS("http://www.w3.org/2000/svg",n);break;case"math":u=i.createElementNS("http://www.w3.org/1998/Math/MathML",n);break;case"script":u=i.createElement("div"),u.innerHTML="<script><\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[Jt]=e,u[ee]=a;t:for(i=e.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===e)break t;for(;i.sibling===null;){if(i.return===null||i.return===e)break t;i=i.return}i.sibling.return=i.return,i=i.sibling}e.stateNode=u;t:switch(Wt(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break t;case"img":a=!0;break t;default:a=!1}a&&Fe(e)}}return Nt(e),Gc(e,e.type,t===null?null:t.memoizedProps,e.pendingProps,l),null;case 6:if(t&&e.stateNode!=null)t.memoizedProps!==a&&Fe(e);else{if(typeof a!="string"&&e.stateNode===null)throw Error(f(166));if(t=ct.current,va(e)){if(t=e.stateNode,l=e.memoizedProps,a=null,n=$t,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}t[Jt]=e,t=!!(t.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||bd(t.nodeValue,l)),t||ol(e,!0)}else t=wu(t).createTextNode(a),t[Jt]=e,e.stateNode=t}return Nt(e),null;case 31:if(l=e.memoizedState,t===null||t.memoizedState!==null){if(a=va(e),l!==null){if(t===null){if(!a)throw Error(f(318));if(t=e.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(f(557));t[Jt]=e}else Gl(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Nt(e),t=!1}else l=Fi(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=l),t=!0;if(!t)return e.flags&256?(ye(e),e):(ye(e),null);if((e.flags&128)!==0)throw Error(f(558))}return Nt(e),null;case 13:if(a=e.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(n=va(e),a!==null&&a.dehydrated!==null){if(t===null){if(!n)throw Error(f(318));if(n=e.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(f(317));n[Jt]=e}else Gl(),(e.flags&128)===0&&(e.memoizedState=null),e.flags|=4;Nt(e),n=!1}else n=Fi(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=n),n=!0;if(!n)return e.flags&256?(ye(e),e):(ye(e),null)}return ye(e),(e.flags&128)!==0?(e.lanes=l,e):(l=a!==null,t=t!==null&&t.memoizedState!==null,l&&(a=e.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==t&&l&&(e.child.flags|=8192),Nu(e,e.updateQueue),Nt(e),null);case 4:return Bt(),t===null&&sf(e.stateNode.containerInfo),Nt(e),null;case 10:return Ke(e.type),Nt(e),null;case 19:if(D(qt),a=e.memoizedState,a===null)return Nt(e),null;if(n=(e.flags&128)!==0,u=a.rendering,u===null)if(n)yn(a,!1);else{if(jt!==0||t!==null&&(t.flags&128)!==0)for(t=e.child;t!==null;){if(u=gu(t),u!==null){for(e.flags|=128,yn(a,!1),t=u.updateQueue,e.updateQueue=t,Nu(e,t),e.subtreeFlags=0,t=l,l=e.child;l!==null;)Ws(l,t),l=l.sibling;return Y(qt,qt.current&1|2),ht&&Ve(e,a.treeForkCount),e.child}t=t.sibling}a.tail!==null&&se()>Hu&&(e.flags|=128,n=!0,yn(a,!1),e.lanes=4194304)}else{if(!n)if(t=gu(u),t!==null){if(e.flags|=128,n=!0,t=t.updateQueue,e.updateQueue=t,Nu(e,t),yn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!ht)return Nt(e),null}else 2*se()-a.renderingStartTime>Hu&&l!==536870912&&(e.flags|=128,n=!0,yn(a,!1),e.lanes=4194304);a.isBackwards?(u.sibling=e.child,e.child=u):(t=a.last,t!==null?t.sibling=u:e.child=u,a.last=u)}return a.tail!==null?(t=a.tail,a.rendering=t,a.tail=t.sibling,a.renderingStartTime=se(),t.sibling=null,l=qt.current,Y(qt,n?l&1|2:l&1),ht&&Ve(e,a.treeForkCount),t):(Nt(e),null);case 22:case 23:return ye(e),sc(),a=e.memoizedState!==null,t!==null?t.memoizedState!==null!==a&&(e.flags|=8192):a&&(e.flags|=8192),a?(l&536870912)!==0&&(e.flags&128)===0&&(Nt(e),e.subtreeFlags&6&&(e.flags|=8192)):Nt(e),l=e.updateQueue,l!==null&&Nu(e,l.retryQueue),l=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),a=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(a=e.memoizedState.cachePool.pool),a!==l&&(e.flags|=2048),t!==null&&D(Zl),null;case 24:return l=null,t!==null&&(l=t.memoizedState.cache),e.memoizedState.cache!==l&&(e.flags|=2048),Ke(Gt),Nt(e),null;case 25:return null;case 30:return null}throw Error(f(156,e.tag))}function uy(t,e){switch($i(e),e.tag){case 1:return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 3:return Ke(Gt),Bt(),t=e.flags,(t&65536)!==0&&(t&128)===0?(e.flags=t&-65537|128,e):null;case 26:case 27:case 5:return Xn(e),null;case 31:if(e.memoizedState!==null){if(ye(e),e.alternate===null)throw Error(f(340));Gl()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 13:if(ye(e),t=e.memoizedState,t!==null&&t.dehydrated!==null){if(e.alternate===null)throw Error(f(340));Gl()}return t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 19:return D(qt),null;case 4:return Bt(),null;case 10:return Ke(e.type),null;case 22:case 23:return ye(e),sc(),t!==null&&D(Zl),t=e.flags,t&65536?(e.flags=t&-65537|128,e):null;case 24:return Ke(Gt),null;case 25:return null;default:return null}}function _o(t,e){switch($i(e),e.tag){case 3:Ke(Gt),Bt();break;case 26:case 27:case 5:Xn(e);break;case 4:Bt();break;case 31:e.memoizedState!==null&&ye(e);break;case 13:ye(e);break;case 19:D(qt);break;case 10:Ke(e.type);break;case 22:case 23:ye(e),sc(),t!==null&&D(Zl);break;case 24:Ke(Gt)}}function vn(t,e){try{var l=e.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&t)===t){a=void 0;var u=l.create,i=l.inst;a=u(),i.destroy=a}l=l.next}while(l!==n)}}catch(s){Tt(e,e.return,s)}}function pl(t,e,l){try{var a=e.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&t)===t){var i=a.inst,s=i.destroy;if(s!==void 0){i.destroy=void 0,n=e;var m=l,z=s;try{z()}catch(C){Tt(n,m,C)}}}a=a.next}while(a!==u)}}catch(C){Tt(e,e.return,C)}}function Ro(t){var e=t.updateQueue;if(e!==null){var l=t.stateNode;try{yr(e,l)}catch(a){Tt(t,t.return,a)}}}function Oo(t,e,l){l.props=$l(t.type,t.memoizedProps),l.state=t.memoizedState;try{l.componentWillUnmount()}catch(a){Tt(t,e,a)}}function gn(t,e){try{var l=t.ref;if(l!==null){switch(t.tag){case 26:case 27:case 5:var a=t.stateNode;break;case 30:a=t.stateNode;break;default:a=t.stateNode}typeof l=="function"?t.refCleanup=l(a):l.current=a}}catch(n){Tt(t,e,n)}}function Le(t,e){var l=t.ref,a=t.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){Tt(t,e,n)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){Tt(t,e,n)}else l.current=null}function xo(t){var e=t.type,l=t.memoizedProps,a=t.stateNode;try{t:switch(e){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break t;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){Tt(t,t.return,n)}}function Xc(t,e,l){try{var a=t.stateNode;Oy(a,t.type,l,e),a[ee]=e}catch(n){Tt(t,t.return,n)}}function Mo(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&_l(t.type)||t.tag===4}function Qc(t){t:for(;;){for(;t.sibling===null;){if(t.return===null||Mo(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.tag===27&&_l(t.type)||t.flags&2||t.child===null||t.tag===4)continue t;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function Zc(t,e,l){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(t,e):(e=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,e.appendChild(t),l=l._reactRootContainer,l!=null||e.onclick!==null||(e.onclick=Xe));else if(a!==4&&(a===27&&_l(t.type)&&(l=t.stateNode,e=null),t=t.child,t!==null))for(Zc(t,e,l),t=t.sibling;t!==null;)Zc(t,e,l),t=t.sibling}function Cu(t,e,l){var a=t.tag;if(a===5||a===6)t=t.stateNode,e?l.insertBefore(t,e):l.appendChild(t);else if(a!==4&&(a===27&&_l(t.type)&&(l=t.stateNode),t=t.child,t!==null))for(Cu(t,e,l),t=t.sibling;t!==null;)Cu(t,e,l),t=t.sibling}function No(t){var e=t.stateNode,l=t.memoizedProps;try{for(var a=t.type,n=e.attributes;n.length;)e.removeAttributeNode(n[0]);Wt(e,a,l),e[Jt]=t,e[ee]=l}catch(u){Tt(t,t.return,u)}}var We=!1,Zt=!1,Vc=!1,Co=typeof WeakSet=="function"?WeakSet:Set,Kt=null;function iy(t,e){if(t=t.containerInfo,df=Iu,t=Qs(t),qi(t)){if("selectionStart"in t)var l={start:t.selectionStart,end:t.selectionEnd};else t:{l=(l=t.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break t}var i=0,s=-1,m=-1,z=0,C=0,j=t,A=null;e:for(;;){for(var O;j!==l||n!==0&&j.nodeType!==3||(s=i+n),j!==u||a!==0&&j.nodeType!==3||(m=i+a),j.nodeType===3&&(i+=j.nodeValue.length),(O=j.firstChild)!==null;)A=j,j=O;for(;;){if(j===t)break e;if(A===l&&++z===n&&(s=i),A===u&&++C===a&&(m=i),(O=j.nextSibling)!==null)break;j=A,A=j.parentNode}j=O}l=s===-1||m===-1?null:{start:s,end:m}}else l=null}l=l||{start:0,end:0}}else l=null;for(hf={focusedElem:t,selectionRange:l},Iu=!1,Kt=e;Kt!==null;)if(e=Kt,t=e.child,(e.subtreeFlags&1028)!==0&&t!==null)t.return=e,Kt=t;else for(;Kt!==null;){switch(e=Kt,u=e.alternate,t=e.flags,e.tag){case 0:if((t&4)!==0&&(t=e.updateQueue,t=t!==null?t.events:null,t!==null))for(l=0;l<t.length;l++)n=t[l],n.ref.impl=n.nextImpl;break;case 11:case 15:break;case 1:if((t&1024)!==0&&u!==null){t=void 0,l=e,n=u.memoizedProps,u=u.memoizedState,a=l.stateNode;try{var w=$l(l.type,n);t=a.getSnapshotBeforeUpdate(w,u),a.__reactInternalSnapshotBeforeUpdate=t}catch(P){Tt(l,l.return,P)}}break;case 3:if((t&1024)!==0){if(t=e.stateNode.containerInfo,l=t.nodeType,l===9)vf(t);else if(l===1)switch(t.nodeName){case"HEAD":case"HTML":case"BODY":vf(t);break;default:t.textContent=""}}break;case 5:case 26:case 27:case 6:case 4:case 17:break;default:if((t&1024)!==0)throw Error(f(163))}if(t=e.sibling,t!==null){t.return=e.return,Kt=t;break}Kt=e.return}}function Do(t,e,l){var a=l.flags;switch(l.tag){case 0:case 11:case 15:Pe(t,l),a&4&&vn(5,l);break;case 1:if(Pe(t,l),a&4)if(t=l.stateNode,e===null)try{t.componentDidMount()}catch(i){Tt(l,l.return,i)}else{var n=$l(l.type,e.memoizedProps);e=e.memoizedState;try{t.componentDidUpdate(n,e,t.__reactInternalSnapshotBeforeUpdate)}catch(i){Tt(l,l.return,i)}}a&64&&Ro(l),a&512&&gn(l,l.return);break;case 3:if(Pe(t,l),a&64&&(t=l.updateQueue,t!==null)){if(e=null,l.child!==null)switch(l.child.tag){case 27:case 5:e=l.child.stateNode;break;case 1:e=l.child.stateNode}try{yr(t,e)}catch(i){Tt(l,l.return,i)}}break;case 27:e===null&&a&4&&No(l);case 26:case 5:Pe(t,l),e===null&&a&4&&xo(l),a&512&&gn(l,l.return);break;case 12:Pe(t,l);break;case 31:Pe(t,l),a&4&&Ho(t,l);break;case 13:Pe(t,l),a&4&&Bo(t,l),a&64&&(t=l.memoizedState,t!==null&&(t=t.dehydrated,t!==null&&(l=yy.bind(null,l),Hy(t,l))));break;case 22:if(a=l.memoizedState!==null||We,!a){e=e!==null&&e.memoizedState!==null||Zt,n=We;var u=Zt;We=a,(Zt=e)&&!u?tl(t,l,(l.subtreeFlags&8772)!==0):Pe(t,l),We=n,Zt=u}break;case 30:break;default:Pe(t,l)}}function Uo(t){var e=t.alternate;e!==null&&(t.alternate=null,Uo(e)),t.child=null,t.deletions=null,t.sibling=null,t.tag===5&&(e=t.stateNode,e!==null&&bi(e)),t.stateNode=null,t.return=null,t.dependencies=null,t.memoizedProps=null,t.memoizedState=null,t.pendingProps=null,t.stateNode=null,t.updateQueue=null}var Dt=null,ae=!1;function Ie(t,e,l){for(l=l.child;l!==null;)jo(t,e,l),l=l.sibling}function jo(t,e,l){if(re&&typeof re.onCommitFiberUnmount=="function")try{re.onCommitFiberUnmount(Ga,l)}catch{}switch(l.tag){case 26:Zt||Le(l,e),Ie(t,e,l),l.memoizedState?l.memoizedState.count--:l.stateNode&&(l=l.stateNode,l.parentNode.removeChild(l));break;case 27:Zt||Le(l,e);var a=Dt,n=ae;_l(l.type)&&(Dt=l.stateNode,ae=!1),Ie(t,e,l),Rn(l.stateNode),Dt=a,ae=n;break;case 5:Zt||Le(l,e);case 6:if(a=Dt,n=ae,Dt=null,Ie(t,e,l),Dt=a,ae=n,Dt!==null)if(ae)try{(Dt.nodeType===9?Dt.body:Dt.nodeName==="HTML"?Dt.ownerDocument.body:Dt).removeChild(l.stateNode)}catch(u){Tt(l,e,u)}else try{Dt.removeChild(l.stateNode)}catch(u){Tt(l,e,u)}break;case 18:Dt!==null&&(ae?(t=Dt,Rd(t.nodeType===9?t.body:t.nodeName==="HTML"?t.ownerDocument.body:t,l.stateNode),qa(t)):Rd(Dt,l.stateNode));break;case 4:a=Dt,n=ae,Dt=l.stateNode.containerInfo,ae=!0,Ie(t,e,l),Dt=a,ae=n;break;case 0:case 11:case 14:case 15:pl(2,l,e),Zt||pl(4,l,e),Ie(t,e,l);break;case 1:Zt||(Le(l,e),a=l.stateNode,typeof a.componentWillUnmount=="function"&&Oo(l,e,a)),Ie(t,e,l);break;case 21:Ie(t,e,l);break;case 22:Zt=(a=Zt)||l.memoizedState!==null,Ie(t,e,l),Zt=a;break;default:Ie(t,e,l)}}function Ho(t,e){if(e.memoizedState===null&&(t=e.alternate,t!==null&&(t=t.memoizedState,t!==null))){t=t.dehydrated;try{qa(t)}catch(l){Tt(e,e.return,l)}}}function Bo(t,e){if(e.memoizedState===null&&(t=e.alternate,t!==null&&(t=t.memoizedState,t!==null&&(t=t.dehydrated,t!==null))))try{qa(t)}catch(l){Tt(e,e.return,l)}}function cy(t){switch(t.tag){case 31:case 13:case 19:var e=t.stateNode;return e===null&&(e=t.stateNode=new Co),e;case 22:return t=t.stateNode,e=t._retryCache,e===null&&(e=t._retryCache=new Co),e;default:throw Error(f(435,t.tag))}}function Du(t,e){var l=cy(t);e.forEach(function(a){if(!l.has(a)){l.add(a);var n=vy.bind(null,t,a);a.then(n,n)}})}function ne(t,e){var l=e.deletions;if(l!==null)for(var a=0;a<l.length;a++){var n=l[a],u=t,i=e,s=i;t:for(;s!==null;){switch(s.tag){case 27:if(_l(s.type)){Dt=s.stateNode,ae=!1;break t}break;case 5:Dt=s.stateNode,ae=!1;break t;case 3:case 4:Dt=s.stateNode.containerInfo,ae=!0;break t}s=s.return}if(Dt===null)throw Error(f(160));jo(u,i,n),Dt=null,ae=!1,u=n.alternate,u!==null&&(u.return=null),n.return=null}if(e.subtreeFlags&13886)for(e=e.child;e!==null;)qo(e,t),e=e.sibling}var Ue=null;function qo(t,e){var l=t.alternate,a=t.flags;switch(t.tag){case 0:case 11:case 14:case 15:ne(e,t),ue(t),a&4&&(pl(3,t,t.return),vn(3,t),pl(5,t,t.return));break;case 1:ne(e,t),ue(t),a&512&&(Zt||l===null||Le(l,l.return)),a&64&&We&&(t=t.updateQueue,t!==null&&(a=t.callbacks,a!==null&&(l=t.shared.hiddenCallbacks,t.shared.hiddenCallbacks=l===null?a:l.concat(a))));break;case 26:var n=Ue;if(ne(e,t),ue(t),a&512&&(Zt||l===null||Le(l,l.return)),a&4){var u=l!==null?l.memoizedState:null;if(a=t.memoizedState,l===null)if(a===null)if(t.stateNode===null){t:{a=t.type,l=t.memoizedProps,n=n.ownerDocument||n;e:switch(a){case"title":u=n.getElementsByTagName("title")[0],(!u||u[Za]||u[Jt]||u.namespaceURI==="http://www.w3.org/2000/svg"||u.hasAttribute("itemprop"))&&(u=n.createElement(a),n.head.insertBefore(u,n.querySelector("head > title"))),Wt(u,a,l),u[Jt]=t,wt(u),a=u;break t;case"link":var i=qd("link","href",n).get(a+(l.href||""));if(i){for(var s=0;s<i.length;s++)if(u=i[s],u.getAttribute("href")===(l.href==null||l.href===""?null:l.href)&&u.getAttribute("rel")===(l.rel==null?null:l.rel)&&u.getAttribute("title")===(l.title==null?null:l.title)&&u.getAttribute("crossorigin")===(l.crossOrigin==null?null:l.crossOrigin)){i.splice(s,1);break e}}u=n.createElement(a),Wt(u,a,l),n.head.appendChild(u);break;case"meta":if(i=qd("meta","content",n).get(a+(l.content||""))){for(s=0;s<i.length;s++)if(u=i[s],u.getAttribute("content")===(l.content==null?null:""+l.content)&&u.getAttribute("name")===(l.name==null?null:l.name)&&u.getAttribute("property")===(l.property==null?null:l.property)&&u.getAttribute("http-equiv")===(l.httpEquiv==null?null:l.httpEquiv)&&u.getAttribute("charset")===(l.charSet==null?null:l.charSet)){i.splice(s,1);break e}}u=n.createElement(a),Wt(u,a,l),n.head.appendChild(u);break;default:throw Error(f(468,a))}u[Jt]=t,wt(u),a=u}t.stateNode=a}else Ld(n,t.type,t.stateNode);else t.stateNode=Bd(n,a,t.memoizedProps);else u!==a?(u===null?l.stateNode!==null&&(l=l.stateNode,l.parentNode.removeChild(l)):u.count--,a===null?Ld(n,t.type,t.stateNode):Bd(n,a,t.memoizedProps)):a===null&&t.stateNode!==null&&Xc(t,t.memoizedProps,l.memoizedProps)}break;case 27:ne(e,t),ue(t),a&512&&(Zt||l===null||Le(l,l.return)),l!==null&&a&4&&Xc(t,t.memoizedProps,l.memoizedProps);break;case 5:if(ne(e,t),ue(t),a&512&&(Zt||l===null||Le(l,l.return)),t.flags&32){n=t.stateNode;try{ia(n,"")}catch(w){Tt(t,t.return,w)}}a&4&&t.stateNode!=null&&(n=t.memoizedProps,Xc(t,n,l!==null?l.memoizedProps:n)),a&1024&&(Vc=!0);break;case 6:if(ne(e,t),ue(t),a&4){if(t.stateNode===null)throw Error(f(162));a=t.memoizedProps,l=t.stateNode;try{l.nodeValue=a}catch(w){Tt(t,t.return,w)}}break;case 3:if($u=null,n=Ue,Ue=Ku(e.containerInfo),ne(e,t),Ue=n,ue(t),a&4&&l!==null&&l.memoizedState.isDehydrated)try{qa(e.containerInfo)}catch(w){Tt(t,t.return,w)}Vc&&(Vc=!1,Lo(t));break;case 4:a=Ue,Ue=Ku(t.stateNode.containerInfo),ne(e,t),ue(t),Ue=a;break;case 12:ne(e,t),ue(t);break;case 31:ne(e,t),ue(t),a&4&&(a=t.updateQueue,a!==null&&(t.updateQueue=null,Du(t,a)));break;case 13:ne(e,t),ue(t),t.child.flags&8192&&t.memoizedState!==null!=(l!==null&&l.memoizedState!==null)&&(ju=se()),a&4&&(a=t.updateQueue,a!==null&&(t.updateQueue=null,Du(t,a)));break;case 22:n=t.memoizedState!==null;var m=l!==null&&l.memoizedState!==null,z=We,C=Zt;if(We=z||n,Zt=C||m,ne(e,t),Zt=C,We=z,ue(t),a&8192)t:for(e=t.stateNode,e._visibility=n?e._visibility&-2:e._visibility|1,n&&(l===null||m||We||Zt||kl(t)),l=null,e=t;;){if(e.tag===5||e.tag===26){if(l===null){m=l=e;try{if(u=m.stateNode,n)i=u.style,typeof i.setProperty=="function"?i.setProperty("display","none","important"):i.display="none";else{s=m.stateNode;var j=m.memoizedProps.style,A=j!=null&&j.hasOwnProperty("display")?j.display:null;s.style.display=A==null||typeof A=="boolean"?"":(""+A).trim()}}catch(w){Tt(m,m.return,w)}}}else if(e.tag===6){if(l===null){m=e;try{m.stateNode.nodeValue=n?"":m.memoizedProps}catch(w){Tt(m,m.return,w)}}}else if(e.tag===18){if(l===null){m=e;try{var O=m.stateNode;n?Od(O,!0):Od(m.stateNode,!1)}catch(w){Tt(m,m.return,w)}}}else if((e.tag!==22&&e.tag!==23||e.memoizedState===null||e===t)&&e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break t;for(;e.sibling===null;){if(e.return===null||e.return===t)break t;l===e&&(l=null),e=e.return}l===e&&(l=null),e.sibling.return=e.return,e=e.sibling}a&4&&(a=t.updateQueue,a!==null&&(l=a.retryQueue,l!==null&&(a.retryQueue=null,Du(t,l))));break;case 19:ne(e,t),ue(t),a&4&&(a=t.updateQueue,a!==null&&(t.updateQueue=null,Du(t,a)));break;case 30:break;case 21:break;default:ne(e,t),ue(t)}}function ue(t){var e=t.flags;if(e&2){try{for(var l,a=t.return;a!==null;){if(Mo(a)){l=a;break}a=a.return}if(l==null)throw Error(f(160));switch(l.tag){case 27:var n=l.stateNode,u=Qc(t);Cu(t,u,n);break;case 5:var i=l.stateNode;l.flags&32&&(ia(i,""),l.flags&=-33);var s=Qc(t);Cu(t,s,i);break;case 3:case 4:var m=l.stateNode.containerInfo,z=Qc(t);Zc(t,z,m);break;default:throw Error(f(161))}}catch(C){Tt(t,t.return,C)}t.flags&=-3}e&4096&&(t.flags&=-4097)}function Lo(t){if(t.subtreeFlags&1024)for(t=t.child;t!==null;){var e=t;Lo(e),e.tag===5&&e.flags&1024&&e.stateNode.reset(),t=t.sibling}}function Pe(t,e){if(e.subtreeFlags&8772)for(e=e.child;e!==null;)Do(t,e.alternate,e),e=e.sibling}function kl(t){for(t=t.child;t!==null;){var e=t;switch(e.tag){case 0:case 11:case 14:case 15:pl(4,e,e.return),kl(e);break;case 1:Le(e,e.return);var l=e.stateNode;typeof l.componentWillUnmount=="function"&&Oo(e,e.return,l),kl(e);break;case 27:Rn(e.stateNode);case 26:case 5:Le(e,e.return),kl(e);break;case 22:e.memoizedState===null&&kl(e);break;case 30:kl(e);break;default:kl(e)}t=t.sibling}}function tl(t,e,l){for(l=l&&(e.subtreeFlags&8772)!==0,e=e.child;e!==null;){var a=e.alternate,n=t,u=e,i=u.flags;switch(u.tag){case 0:case 11:case 15:tl(n,u,l),vn(4,u);break;case 1:if(tl(n,u,l),a=u,n=a.stateNode,typeof n.componentDidMount=="function")try{n.componentDidMount()}catch(z){Tt(a,a.return,z)}if(a=u,n=a.updateQueue,n!==null){var s=a.stateNode;try{var m=n.shared.hiddenCallbacks;if(m!==null)for(n.shared.hiddenCallbacks=null,n=0;n<m.length;n++)mr(m[n],s)}catch(z){Tt(a,a.return,z)}}l&&i&64&&Ro(u),gn(u,u.return);break;case 27:No(u);case 26:case 5:tl(n,u,l),l&&a===null&&i&4&&xo(u),gn(u,u.return);break;case 12:tl(n,u,l);break;case 31:tl(n,u,l),l&&i&4&&Ho(n,u);break;case 13:tl(n,u,l),l&&i&4&&Bo(n,u);break;case 22:u.memoizedState===null&&tl(n,u,l),gn(u,u.return);break;case 30:break;default:tl(n,u,l)}e=e.sibling}}function wc(t,e){var l=null;t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(l=t.memoizedState.cachePool.pool),t=null,e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(t=e.memoizedState.cachePool.pool),t!==l&&(t!=null&&t.refCount++,l!=null&&ln(l))}function Kc(t,e){t=null,e.alternate!==null&&(t=e.alternate.memoizedState.cache),e=e.memoizedState.cache,e!==t&&(e.refCount++,t!=null&&ln(t))}function je(t,e,l,a){if(e.subtreeFlags&10256)for(e=e.child;e!==null;)Yo(t,e,l,a),e=e.sibling}function Yo(t,e,l,a){var n=e.flags;switch(e.tag){case 0:case 11:case 15:je(t,e,l,a),n&2048&&vn(9,e);break;case 1:je(t,e,l,a);break;case 3:je(t,e,l,a),n&2048&&(t=null,e.alternate!==null&&(t=e.alternate.memoizedState.cache),e=e.memoizedState.cache,e!==t&&(e.refCount++,t!=null&&ln(t)));break;case 12:if(n&2048){je(t,e,l,a),t=e.stateNode;try{var u=e.memoizedProps,i=u.id,s=u.onPostCommit;typeof s=="function"&&s(i,e.alternate===null?"mount":"update",t.passiveEffectDuration,-0)}catch(m){Tt(e,e.return,m)}}else je(t,e,l,a);break;case 31:je(t,e,l,a);break;case 13:je(t,e,l,a);break;case 23:break;case 22:u=e.stateNode,i=e.alternate,e.memoizedState!==null?u._visibility&2?je(t,e,l,a):pn(t,e):u._visibility&2?je(t,e,l,a):(u._visibility|=2,Ra(t,e,l,a,(e.subtreeFlags&10256)!==0||!1)),n&2048&&wc(i,e);break;case 24:je(t,e,l,a),n&2048&&Kc(e.alternate,e);break;default:je(t,e,l,a)}}function Ra(t,e,l,a,n){for(n=n&&((e.subtreeFlags&10256)!==0||!1),e=e.child;e!==null;){var u=t,i=e,s=l,m=a,z=i.flags;switch(i.tag){case 0:case 11:case 15:Ra(u,i,s,m,n),vn(8,i);break;case 23:break;case 22:var C=i.stateNode;i.memoizedState!==null?C._visibility&2?Ra(u,i,s,m,n):pn(u,i):(C._visibility|=2,Ra(u,i,s,m,n)),n&&z&2048&&wc(i.alternate,i);break;case 24:Ra(u,i,s,m,n),n&&z&2048&&Kc(i.alternate,i);break;default:Ra(u,i,s,m,n)}e=e.sibling}}function pn(t,e){if(e.subtreeFlags&10256)for(e=e.child;e!==null;){var l=t,a=e,n=a.flags;switch(a.tag){case 22:pn(l,a),n&2048&&wc(a.alternate,a);break;case 24:pn(l,a),n&2048&&Kc(a.alternate,a);break;default:pn(l,a)}e=e.sibling}}var Sn=8192;function Oa(t,e,l){if(t.subtreeFlags&Sn)for(t=t.child;t!==null;)Go(t,e,l),t=t.sibling}function Go(t,e,l){switch(t.tag){case 26:Oa(t,e,l),t.flags&Sn&&t.memoizedState!==null&&Jy(l,Ue,t.memoizedState,t.memoizedProps);break;case 5:Oa(t,e,l);break;case 3:case 4:var a=Ue;Ue=Ku(t.stateNode.containerInfo),Oa(t,e,l),Ue=a;break;case 22:t.memoizedState===null&&(a=t.alternate,a!==null&&a.memoizedState!==null?(a=Sn,Sn=16777216,Oa(t,e,l),Sn=a):Oa(t,e,l));break;default:Oa(t,e,l)}}function Xo(t){var e=t.alternate;if(e!==null&&(t=e.child,t!==null)){e.child=null;do e=t.sibling,t.sibling=null,t=e;while(t!==null)}}function bn(t){var e=t.deletions;if((t.flags&16)!==0){if(e!==null)for(var l=0;l<e.length;l++){var a=e[l];Kt=a,Zo(a,t)}Xo(t)}if(t.subtreeFlags&10256)for(t=t.child;t!==null;)Qo(t),t=t.sibling}function Qo(t){switch(t.tag){case 0:case 11:case 15:bn(t),t.flags&2048&&pl(9,t,t.return);break;case 3:bn(t);break;case 12:bn(t);break;case 22:var e=t.stateNode;t.memoizedState!==null&&e._visibility&2&&(t.return===null||t.return.tag!==13)?(e._visibility&=-3,Uu(t)):bn(t);break;default:bn(t)}}function Uu(t){var e=t.deletions;if((t.flags&16)!==0){if(e!==null)for(var l=0;l<e.length;l++){var a=e[l];Kt=a,Zo(a,t)}Xo(t)}for(t=t.child;t!==null;){switch(e=t,e.tag){case 0:case 11:case 15:pl(8,e,e.return),Uu(e);break;case 22:l=e.stateNode,l._visibility&2&&(l._visibility&=-3,Uu(e));break;default:Uu(e)}t=t.sibling}}function Zo(t,e){for(;Kt!==null;){var l=Kt;switch(l.tag){case 0:case 11:case 15:pl(8,l,e);break;case 23:case 22:if(l.memoizedState!==null&&l.memoizedState.cachePool!==null){var a=l.memoizedState.cachePool.pool;a!=null&&a.refCount++}break;case 24:ln(l.memoizedState.cache)}if(a=l.child,a!==null)a.return=l,Kt=a;else t:for(l=t;Kt!==null;){a=Kt;var n=a.sibling,u=a.return;if(Uo(a),a===l){Kt=null;break t}if(n!==null){n.return=u,Kt=n;break t}Kt=u}}}var fy={getCacheForType:function(t){var e=kt(Gt),l=e.data.get(t);return l===void 0&&(l=t(),e.data.set(t,l)),l},cacheSignal:function(){return kt(Gt).controller.signal}},sy=typeof WeakMap=="function"?WeakMap:Map,pt=0,Ot=null,ft=null,rt=0,Et=0,ve=null,Sl=!1,xa=!1,Jc=!1,el=0,jt=0,bl=0,Fl=0,$c=0,ge=0,Ma=0,En=null,ie=null,kc=!1,ju=0,Vo=0,Hu=1/0,Bu=null,El=null,Vt=0,Tl=null,Na=null,ll=0,Fc=0,Wc=null,wo=null,Tn=0,Ic=null;function pe(){return(pt&2)!==0&&rt!==0?rt&-rt:x.T!==null?nf():is()}function Ko(){if(ge===0)if((rt&536870912)===0||ht){var t=Vn;Vn<<=1,(Vn&3932160)===0&&(Vn=262144),ge=t}else ge=536870912;return t=me.current,t!==null&&(t.flags|=32),ge}function ce(t,e,l){(t===Ot&&(Et===2||Et===9)||t.cancelPendingCommit!==null)&&(Ca(t,0),zl(t,rt,ge,!1)),Qa(t,l),((pt&2)===0||t!==Ot)&&(t===Ot&&((pt&2)===0&&(Fl|=l),jt===4&&zl(t,rt,ge,!1)),Ye(t))}function Jo(t,e,l){if((pt&6)!==0)throw Error(f(327));var a=!l&&(e&127)===0&&(e&t.expiredLanes)===0||Xa(t,e),n=a?dy(t,e):tf(t,e,!0),u=a;do{if(n===0){xa&&!a&&zl(t,e,0,!1);break}else{if(l=t.current.alternate,u&&!ry(l)){n=tf(t,e,!1),u=!1;continue}if(n===2){if(u=e,t.errorRecoveryDisabledLanes&u)var i=0;else i=t.pendingLanes&-536870913,i=i!==0?i:i&536870912?536870912:0;if(i!==0){e=i;t:{var s=t;n=En;var m=s.current.memoizedState.isDehydrated;if(m&&(Ca(s,i).flags|=256),i=tf(s,i,!1),i!==2){if(Jc&&!m){s.errorRecoveryDisabledLanes|=u,Fl|=u,n=4;break t}u=ie,ie=n,u!==null&&(ie===null?ie=u:ie.push.apply(ie,u))}n=i}if(u=!1,n!==2)continue}}if(n===1){Ca(t,0),zl(t,e,0,!0);break}t:{switch(a=t,u=n,u){case 0:case 1:throw Error(f(345));case 4:if((e&4194048)!==e)break;case 6:zl(a,e,ge,!Sl);break t;case 2:ie=null;break;case 3:case 5:break;default:throw Error(f(329))}if((e&62914560)===e&&(n=ju+300-se(),10<n)){if(zl(a,e,ge,!Sl),Kn(a,0,!0)!==0)break t;ll=e,a.timeoutHandle=Ad($o.bind(null,a,l,ie,Bu,kc,e,ge,Fl,Ma,Sl,u,"Throttled",-0,0),n);break t}$o(a,l,ie,Bu,kc,e,ge,Fl,Ma,Sl,u,null,-0,0)}}break}while(!0);Ye(t)}function $o(t,e,l,a,n,u,i,s,m,z,C,j,A,O){if(t.timeoutHandle=-1,j=e.subtreeFlags,j&8192||(j&16785408)===16785408){j={stylesheets:null,count:0,imgCount:0,imgBytes:0,suspenseyImages:[],waitingForImages:!0,waitingForViewTransition:!1,unsuspend:Xe},Go(e,u,j);var w=(u&62914560)===u?ju-se():(u&4194048)===u?Vo-se():0;if(w=$y(j,w),w!==null){ll=u,t.cancelPendingCommit=w(ld.bind(null,t,e,u,l,a,n,i,s,m,C,j,null,A,O)),zl(t,u,i,!z);return}}ld(t,e,u,l,a,n,i,s,m)}function ry(t){for(var e=t;;){var l=e.tag;if((l===0||l===11||l===15)&&e.flags&16384&&(l=e.updateQueue,l!==null&&(l=l.stores,l!==null)))for(var a=0;a<l.length;a++){var n=l[a],u=n.getSnapshot;n=n.value;try{if(!de(u(),n))return!1}catch{return!1}}if(l=e.child,e.subtreeFlags&16384&&l!==null)l.return=e,e=l;else{if(e===t)break;for(;e.sibling===null;){if(e.return===null||e.return===t)return!0;e=e.return}e.sibling.return=e.return,e=e.sibling}}return!0}function zl(t,e,l,a){e&=~$c,e&=~Fl,t.suspendedLanes|=e,t.pingedLanes&=~e,a&&(t.warmLanes|=e),a=t.expirationTimes;for(var n=e;0<n;){var u=31-oe(n),i=1<<u;a[u]=-1,n&=~i}l!==0&&as(t,l,e)}function qu(){return(pt&6)===0?(zn(0),!1):!0}function Pc(){if(ft!==null){if(Et===0)var t=ft.return;else t=ft,we=Xl=null,yc(t),Ea=null,nn=0,t=ft;for(;t!==null;)_o(t.alternate,t),t=t.return;ft=null}}function Ca(t,e){var l=t.timeoutHandle;l!==-1&&(t.timeoutHandle=-1,Ny(l)),l=t.cancelPendingCommit,l!==null&&(t.cancelPendingCommit=null,l()),ll=0,Pc(),Ot=t,ft=l=Ze(t.current,null),rt=e,Et=0,ve=null,Sl=!1,xa=Xa(t,e),Jc=!1,Ma=ge=$c=Fl=bl=jt=0,ie=En=null,kc=!1,(e&8)!==0&&(e|=e&32);var a=t.entangledLanes;if(a!==0)for(t=t.entanglements,a&=e;0<a;){var n=31-oe(a),u=1<<n;e|=t[n],a&=~u}return el=e,nu(),l}function ko(t,e){nt=null,x.H=hn,e===ba||e===du?(e=rr(),Et=3):e===ac?(e=rr(),Et=4):Et=e===Cc?8:e!==null&&typeof e=="object"&&typeof e.then=="function"?6:1,ve=e,ft===null&&(jt=1,Ru(t,Ae(e,t.current)))}function Fo(){var t=me.current;return t===null?!0:(rt&4194048)===rt?xe===null:(rt&62914560)===rt||(rt&536870912)!==0?t===xe:!1}function Wo(){var t=x.H;return x.H=hn,t===null?hn:t}function Io(){var t=x.A;return x.A=fy,t}function Lu(){jt=4,Sl||(rt&4194048)!==rt&&me.current!==null||(xa=!0),(bl&134217727)===0&&(Fl&134217727)===0||Ot===null||zl(Ot,rt,ge,!1)}function tf(t,e,l){var a=pt;pt|=2;var n=Wo(),u=Io();(Ot!==t||rt!==e)&&(Bu=null,Ca(t,e)),e=!1;var i=jt;t:do try{if(Et!==0&&ft!==null){var s=ft,m=ve;switch(Et){case 8:Pc(),i=6;break t;case 3:case 2:case 9:case 6:me.current===null&&(e=!0);var z=Et;if(Et=0,ve=null,Da(t,s,m,z),l&&xa){i=0;break t}break;default:z=Et,Et=0,ve=null,Da(t,s,m,z)}}oy(),i=jt;break}catch(C){ko(t,C)}while(!0);return e&&t.shellSuspendCounter++,we=Xl=null,pt=a,x.H=n,x.A=u,ft===null&&(Ot=null,rt=0,nu()),i}function oy(){for(;ft!==null;)Po(ft)}function dy(t,e){var l=pt;pt|=2;var a=Wo(),n=Io();Ot!==t||rt!==e?(Bu=null,Hu=se()+500,Ca(t,e)):xa=Xa(t,e);t:do try{if(Et!==0&&ft!==null){e=ft;var u=ve;e:switch(Et){case 1:Et=0,ve=null,Da(t,e,u,1);break;case 2:case 9:if(fr(u)){Et=0,ve=null,td(e);break}e=function(){Et!==2&&Et!==9||Ot!==t||(Et=7),Ye(t)},u.then(e,e);break t;case 3:Et=7;break t;case 4:Et=5;break t;case 7:fr(u)?(Et=0,ve=null,td(e)):(Et=0,ve=null,Da(t,e,u,7));break;case 5:var i=null;switch(ft.tag){case 26:i=ft.memoizedState;case 5:case 27:var s=ft;if(i?Yd(i):s.stateNode.complete){Et=0,ve=null;var m=s.sibling;if(m!==null)ft=m;else{var z=s.return;z!==null?(ft=z,Yu(z)):ft=null}break e}}Et=0,ve=null,Da(t,e,u,5);break;case 6:Et=0,ve=null,Da(t,e,u,6);break;case 8:Pc(),jt=6;break t;default:throw Error(f(462))}}hy();break}catch(C){ko(t,C)}while(!0);return we=Xl=null,x.H=a,x.A=n,pt=l,ft!==null?0:(Ot=null,rt=0,nu(),jt)}function hy(){for(;ft!==null&&!Bh();)Po(ft)}function Po(t){var e=zo(t.alternate,t,el);t.memoizedProps=t.pendingProps,e===null?Yu(t):ft=e}function td(t){var e=t,l=e.alternate;switch(e.tag){case 15:case 0:e=go(l,e,e.pendingProps,e.type,void 0,rt);break;case 11:e=go(l,e,e.pendingProps,e.type.render,e.ref,rt);break;case 5:yc(e);default:_o(l,e),e=ft=Ws(e,el),e=zo(l,e,el)}t.memoizedProps=t.pendingProps,e===null?Yu(t):ft=e}function Da(t,e,l,a){we=Xl=null,yc(e),Ea=null,nn=0;var n=e.return;try{if(ey(t,n,e,l,rt)){jt=1,Ru(t,Ae(l,t.current)),ft=null;return}}catch(u){if(n!==null)throw ft=n,u;jt=1,Ru(t,Ae(l,t.current)),ft=null;return}e.flags&32768?(ht||a===1?t=!0:xa||(rt&536870912)!==0?t=!1:(Sl=t=!0,(a===2||a===9||a===3||a===6)&&(a=me.current,a!==null&&a.tag===13&&(a.flags|=16384))),ed(e,t)):Yu(e)}function Yu(t){var e=t;do{if((e.flags&32768)!==0){ed(e,Sl);return}t=e.return;var l=ny(e.alternate,e,el);if(l!==null){ft=l;return}if(e=e.sibling,e!==null){ft=e;return}ft=e=t}while(e!==null);jt===0&&(jt=5)}function ed(t,e){do{var l=uy(t.alternate,t);if(l!==null){l.flags&=32767,ft=l;return}if(l=t.return,l!==null&&(l.flags|=32768,l.subtreeFlags=0,l.deletions=null),!e&&(t=t.sibling,t!==null)){ft=t;return}ft=t=l}while(t!==null);jt=6,ft=null}function ld(t,e,l,a,n,u,i,s,m){t.cancelPendingCommit=null;do Gu();while(Vt!==0);if((pt&6)!==0)throw Error(f(327));if(e!==null){if(e===t.current)throw Error(f(177));if(u=e.lanes|e.childLanes,u|=Qi,Kh(t,l,u,i,s,m),t===Ot&&(ft=Ot=null,rt=0),Na=e,Tl=t,ll=l,Fc=u,Wc=n,wo=a,(e.subtreeFlags&10256)!==0||(e.flags&10256)!==0?(t.callbackNode=null,t.callbackPriority=0,gy(Qn,function(){return cd(),null})):(t.callbackNode=null,t.callbackPriority=0),a=(e.flags&13878)!==0,(e.subtreeFlags&13878)!==0||a){a=x.T,x.T=null,n=L.p,L.p=2,i=pt,pt|=4;try{iy(t,e,l)}finally{pt=i,L.p=n,x.T=a}}Vt=1,ad(),nd(),ud()}}function ad(){if(Vt===1){Vt=0;var t=Tl,e=Na,l=(e.flags&13878)!==0;if((e.subtreeFlags&13878)!==0||l){l=x.T,x.T=null;var a=L.p;L.p=2;var n=pt;pt|=4;try{qo(e,t);var u=hf,i=Qs(t.containerInfo),s=u.focusedElem,m=u.selectionRange;if(i!==s&&s&&s.ownerDocument&&Xs(s.ownerDocument.documentElement,s)){if(m!==null&&qi(s)){var z=m.start,C=m.end;if(C===void 0&&(C=z),"selectionStart"in s)s.selectionStart=z,s.selectionEnd=Math.min(C,s.value.length);else{var j=s.ownerDocument||document,A=j&&j.defaultView||window;if(A.getSelection){var O=A.getSelection(),w=s.textContent.length,P=Math.min(m.start,w),_t=m.end===void 0?P:Math.min(m.end,w);!O.extend&&P>_t&&(i=_t,_t=P,P=i);var b=Gs(s,P),g=Gs(s,_t);if(b&&g&&(O.rangeCount!==1||O.anchorNode!==b.node||O.anchorOffset!==b.offset||O.focusNode!==g.node||O.focusOffset!==g.offset)){var T=j.createRange();T.setStart(b.node,b.offset),O.removeAllRanges(),P>_t?(O.addRange(T),O.extend(g.node,g.offset)):(T.setEnd(g.node,g.offset),O.addRange(T))}}}}for(j=[],O=s;O=O.parentNode;)O.nodeType===1&&j.push({element:O,left:O.scrollLeft,top:O.scrollTop});for(typeof s.focus=="function"&&s.focus(),s=0;s<j.length;s++){var U=j[s];U.element.scrollLeft=U.left,U.element.scrollTop=U.top}}Iu=!!df,hf=df=null}finally{pt=n,L.p=a,x.T=l}}t.current=e,Vt=2}}function nd(){if(Vt===2){Vt=0;var t=Tl,e=Na,l=(e.flags&8772)!==0;if((e.subtreeFlags&8772)!==0||l){l=x.T,x.T=null;var a=L.p;L.p=2;var n=pt;pt|=4;try{Do(t,e.alternate,e)}finally{pt=n,L.p=a,x.T=l}}Vt=3}}function ud(){if(Vt===4||Vt===3){Vt=0,qh();var t=Tl,e=Na,l=ll,a=wo;(e.subtreeFlags&10256)!==0||(e.flags&10256)!==0?Vt=5:(Vt=0,Na=Tl=null,id(t,t.pendingLanes));var n=t.pendingLanes;if(n===0&&(El=null),pi(l),e=e.stateNode,re&&typeof re.onCommitFiberRoot=="function")try{re.onCommitFiberRoot(Ga,e,void 0,(e.current.flags&128)===128)}catch{}if(a!==null){e=x.T,n=L.p,L.p=2,x.T=null;try{for(var u=t.onRecoverableError,i=0;i<a.length;i++){var s=a[i];u(s.value,{componentStack:s.stack})}}finally{x.T=e,L.p=n}}(ll&3)!==0&&Gu(),Ye(t),n=t.pendingLanes,(l&261930)!==0&&(n&42)!==0?t===Ic?Tn++:(Tn=0,Ic=t):Tn=0,zn(0)}}function id(t,e){(t.pooledCacheLanes&=e)===0&&(e=t.pooledCache,e!=null&&(t.pooledCache=null,ln(e)))}function Gu(){return ad(),nd(),ud(),cd()}function cd(){if(Vt!==5)return!1;var t=Tl,e=Fc;Fc=0;var l=pi(ll),a=x.T,n=L.p;try{L.p=32>l?32:l,x.T=null,l=Wc,Wc=null;var u=Tl,i=ll;if(Vt=0,Na=Tl=null,ll=0,(pt&6)!==0)throw Error(f(331));var s=pt;if(pt|=4,Qo(u.current),Yo(u,u.current,i,l),pt=s,zn(0,!1),re&&typeof re.onPostCommitFiberRoot=="function")try{re.onPostCommitFiberRoot(Ga,u)}catch{}return!0}finally{L.p=n,x.T=a,id(t,e)}}function fd(t,e,l){e=Ae(l,e),e=Nc(t.stateNode,e,2),t=yl(t,e,2),t!==null&&(Qa(t,2),Ye(t))}function Tt(t,e,l){if(t.tag===3)fd(t,t,l);else for(;e!==null;){if(e.tag===3){fd(e,t,l);break}else if(e.tag===1){var a=e.stateNode;if(typeof e.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(El===null||!El.has(a))){t=Ae(l,t),l=fo(2),a=yl(e,l,2),a!==null&&(so(l,a,e,t),Qa(a,2),Ye(a));break}}e=e.return}}function ef(t,e,l){var a=t.pingCache;if(a===null){a=t.pingCache=new sy;var n=new Set;a.set(e,n)}else n=a.get(e),n===void 0&&(n=new Set,a.set(e,n));n.has(l)||(Jc=!0,n.add(l),t=my.bind(null,t,e,l),e.then(t,t))}function my(t,e,l){var a=t.pingCache;a!==null&&a.delete(e),t.pingedLanes|=t.suspendedLanes&l,t.warmLanes&=~l,Ot===t&&(rt&l)===l&&(jt===4||jt===3&&(rt&62914560)===rt&&300>se()-ju?(pt&2)===0&&Ca(t,0):$c|=l,Ma===rt&&(Ma=0)),Ye(t)}function sd(t,e){e===0&&(e=ls()),t=Ll(t,e),t!==null&&(Qa(t,e),Ye(t))}function yy(t){var e=t.memoizedState,l=0;e!==null&&(l=e.retryLane),sd(t,l)}function vy(t,e){var l=0;switch(t.tag){case 31:case 13:var a=t.stateNode,n=t.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=t.stateNode;break;case 22:a=t.stateNode._retryCache;break;default:throw Error(f(314))}a!==null&&a.delete(e),sd(t,l)}function gy(t,e){return mi(t,e)}var Xu=null,Ua=null,lf=!1,Qu=!1,af=!1,Al=0;function Ye(t){t!==Ua&&t.next===null&&(Ua===null?Xu=Ua=t:Ua=Ua.next=t),Qu=!0,lf||(lf=!0,Sy())}function zn(t,e){if(!af&&Qu){af=!0;do for(var l=!1,a=Xu;a!==null;){if(t!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,s=a.pingedLanes;u=(1<<31-oe(42|t)+1)-1,u&=n&~(i&~s),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,hd(a,u))}else u=rt,u=Kn(a,a===Ot?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Xa(a,u)||(l=!0,hd(a,u));a=a.next}while(l);af=!1}}function py(){rd()}function rd(){Qu=lf=!1;var t=0;Al!==0&&My()&&(t=Al);for(var e=se(),l=null,a=Xu;a!==null;){var n=a.next,u=od(a,e);u===0?(a.next=null,l===null?Xu=n:l.next=n,n===null&&(Ua=l)):(l=a,(t!==0||(u&3)!==0)&&(Qu=!0)),a=n}Vt!==0&&Vt!==5||zn(t),Al!==0&&(Al=0)}function od(t,e){for(var l=t.suspendedLanes,a=t.pingedLanes,n=t.expirationTimes,u=t.pendingLanes&-62914561;0<u;){var i=31-oe(u),s=1<<i,m=n[i];m===-1?((s&l)===0||(s&a)!==0)&&(n[i]=wh(s,e)):m<=e&&(t.expiredLanes|=s),u&=~s}if(e=Ot,l=rt,l=Kn(t,t===e?l:0,t.cancelPendingCommit!==null||t.timeoutHandle!==-1),a=t.callbackNode,l===0||t===e&&(Et===2||Et===9)||t.cancelPendingCommit!==null)return a!==null&&a!==null&&yi(a),t.callbackNode=null,t.callbackPriority=0;if((l&3)===0||Xa(t,l)){if(e=l&-l,e===t.callbackPriority)return e;switch(a!==null&&yi(a),pi(l)){case 2:case 8:l=ts;break;case 32:l=Qn;break;case 268435456:l=es;break;default:l=Qn}return a=dd.bind(null,t),l=mi(l,a),t.callbackPriority=e,t.callbackNode=l,e}return a!==null&&a!==null&&yi(a),t.callbackPriority=2,t.callbackNode=null,2}function dd(t,e){if(Vt!==0&&Vt!==5)return t.callbackNode=null,t.callbackPriority=0,null;var l=t.callbackNode;if(Gu()&&t.callbackNode!==l)return null;var a=rt;return a=Kn(t,t===Ot?a:0,t.cancelPendingCommit!==null||t.timeoutHandle!==-1),a===0?null:(Jo(t,a,e),od(t,se()),t.callbackNode!=null&&t.callbackNode===l?dd.bind(null,t):null)}function hd(t,e){if(Gu())return null;Jo(t,e,!0)}function Sy(){Cy(function(){(pt&6)!==0?mi(Pf,py):rd()})}function nf(){if(Al===0){var t=pa;t===0&&(t=Zn,Zn<<=1,(Zn&261888)===0&&(Zn=256)),Al=t}return Al}function md(t){return t==null||typeof t=="symbol"||typeof t=="boolean"?null:typeof t=="function"?t:Fn(""+t)}function yd(t,e){var l=e.ownerDocument.createElement("input");return l.name=e.name,l.value=e.value,t.id&&l.setAttribute("form",t.id),e.parentNode.insertBefore(l,e),t=new FormData(t),l.parentNode.removeChild(l),t}function by(t,e,l,a,n){if(e==="submit"&&l&&l.stateNode===n){var u=md((n[ee]||null).action),i=a.submitter;i&&(e=(e=i[ee]||null)?md(e.formAction):i.getAttribute("formAction"),e!==null&&(u=e,i=null));var s=new tu("action","action",null,a,n);t.push({event:s,listeners:[{instance:null,listener:function(){if(a.defaultPrevented){if(Al!==0){var m=i?yd(n,i):new FormData(n);Ac(l,{pending:!0,data:m,method:n.method,action:u},null,m)}}else typeof u=="function"&&(s.preventDefault(),m=i?yd(n,i):new FormData(n),Ac(l,{pending:!0,data:m,method:n.method,action:u},u,m))},currentTarget:n}]})}}for(var uf=0;uf<Xi.length;uf++){var cf=Xi[uf],Ey=cf.toLowerCase(),Ty=cf[0].toUpperCase()+cf.slice(1);De(Ey,"on"+Ty)}De(ws,"onAnimationEnd"),De(Ks,"onAnimationIteration"),De(Js,"onAnimationStart"),De("dblclick","onDoubleClick"),De("focusin","onFocus"),De("focusout","onBlur"),De(Lm,"onTransitionRun"),De(Ym,"onTransitionStart"),De(Gm,"onTransitionCancel"),De($s,"onTransitionEnd"),na("onMouseEnter",["mouseout","mouseover"]),na("onMouseLeave",["mouseout","mouseover"]),na("onPointerEnter",["pointerout","pointerover"]),na("onPointerLeave",["pointerout","pointerover"]),jl("onChange","change click focusin focusout input keydown keyup selectionchange".split(" ")),jl("onSelect","focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")),jl("onBeforeInput",["compositionend","keypress","textInput","paste"]),jl("onCompositionEnd","compositionend focusout keydown keypress keyup mousedown".split(" ")),jl("onCompositionStart","compositionstart focusout keydown keypress keyup mousedown".split(" ")),jl("onCompositionUpdate","compositionupdate focusout keydown keypress keyup mousedown".split(" "));var An="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),zy=new Set("beforetoggle cancel close invalid load scroll scrollend toggle".split(" ").concat(An));function vd(t,e){e=(e&4)!==0;for(var l=0;l<t.length;l++){var a=t[l],n=a.event;a=a.listeners;t:{var u=void 0;if(e)for(var i=a.length-1;0<=i;i--){var s=a[i],m=s.instance,z=s.currentTarget;if(s=s.listener,m!==u&&n.isPropagationStopped())break t;u=s,n.currentTarget=z;try{u(n)}catch(C){au(C)}n.currentTarget=null,u=m}else for(i=0;i<a.length;i++){if(s=a[i],m=s.instance,z=s.currentTarget,s=s.listener,m!==u&&n.isPropagationStopped())break t;u=s,n.currentTarget=z;try{u(n)}catch(C){au(C)}n.currentTarget=null,u=m}}}}function st(t,e){var l=e[Si];l===void 0&&(l=e[Si]=new Set);var a=t+"__bubble";l.has(a)||(gd(e,t,2,!1),l.add(a))}function ff(t,e,l){var a=0;e&&(a|=4),gd(l,t,a,e)}var Zu="_reactListening"+Math.random().toString(36).slice(2);function sf(t){if(!t[Zu]){t[Zu]=!0,ss.forEach(function(l){l!=="selectionchange"&&(zy.has(l)||ff(l,!1,t),ff(l,!0,t))});var e=t.nodeType===9?t:t.ownerDocument;e===null||e[Zu]||(e[Zu]=!0,ff("selectionchange",!1,e))}}function gd(t,e,l,a){switch(Kd(e)){case 2:var n=Wy;break;case 8:n=Iy;break;default:n=Af}l=n.bind(null,e,l,t),n=void 0,!xi||e!=="touchstart"&&e!=="touchmove"&&e!=="wheel"||(n=!0),a?n!==void 0?t.addEventListener(e,l,{capture:!0,passive:n}):t.addEventListener(e,l,!0):n!==void 0?t.addEventListener(e,l,{passive:n}):t.addEventListener(e,l,!1)}function rf(t,e,l,a,n){var u=a;if((e&1)===0&&(e&2)===0&&a!==null)t:for(;;){if(a===null)return;var i=a.tag;if(i===3||i===4){var s=a.stateNode.containerInfo;if(s===n)break;if(i===4)for(i=a.return;i!==null;){var m=i.tag;if((m===3||m===4)&&i.stateNode.containerInfo===n)return;i=i.return}for(;s!==null;){if(i=ea(s),i===null)return;if(m=i.tag,m===5||m===6||m===26||m===27){a=u=i;continue t}s=s.parentNode}}a=a.return}Es(function(){var z=u,C=Ri(l),j=[];t:{var A=ks.get(t);if(A!==void 0){var O=tu,w=t;switch(t){case"keypress":if(In(l)===0)break t;case"keydown":case"keyup":O=vm;break;case"focusin":w="focus",O=Di;break;case"focusout":w="blur",O=Di;break;case"beforeblur":case"afterblur":O=Di;break;case"click":if(l.button===2)break t;case"auxclick":case"dblclick":case"mousedown":case"mousemove":case"mouseup":case"mouseout":case"mouseover":case"contextmenu":O=As;break;case"drag":case"dragend":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"dragstart":case"drop":O=nm;break;case"touchcancel":case"touchend":case"touchmove":case"touchstart":O=Sm;break;case ws:case Ks:case Js:O=cm;break;case $s:O=Em;break;case"scroll":case"scrollend":O=lm;break;case"wheel":O=zm;break;case"copy":case"cut":case"paste":O=sm;break;case"gotpointercapture":case"lostpointercapture":case"pointercancel":case"pointerdown":case"pointermove":case"pointerout":case"pointerover":case"pointerup":O=Rs;break;case"toggle":case"beforetoggle":O=_m}var P=(e&4)!==0,_t=!P&&(t==="scroll"||t==="scrollend"),b=P?A!==null?A+"Capture":null:A;P=[];for(var g=z,T;g!==null;){var U=g;if(T=U.stateNode,U=U.tag,U!==5&&U!==26&&U!==27||T===null||b===null||(U=wa(g,b),U!=null&&P.push(_n(g,U,T))),_t)break;g=g.return}0<P.length&&(A=new O(A,w,null,l,C),j.push({event:A,listeners:P}))}}if((e&7)===0){t:{if(A=t==="mouseover"||t==="pointerover",O=t==="mouseout"||t==="pointerout",A&&l!==_i&&(w=l.relatedTarget||l.fromElement)&&(ea(w)||w[ta]))break t;if((O||A)&&(A=C.window===C?C:(A=C.ownerDocument)?A.defaultView||A.parentWindow:window,O?(w=l.relatedTarget||l.toElement,O=z,w=w?ea(w):null,w!==null&&(_t=h(w),P=w.tag,w!==_t||P!==5&&P!==27&&P!==6)&&(w=null)):(O=null,w=z),O!==w)){if(P=As,U="onMouseLeave",b="onMouseEnter",g="mouse",(t==="pointerout"||t==="pointerover")&&(P=Rs,U="onPointerLeave",b="onPointerEnter",g="pointer"),_t=O==null?A:Va(O),T=w==null?A:Va(w),A=new P(U,g+"leave",O,l,C),A.target=_t,A.relatedTarget=T,U=null,ea(C)===z&&(P=new P(b,g+"enter",w,l,C),P.target=T,P.relatedTarget=_t,U=P),_t=U,O&&w)e:{for(P=Ay,b=O,g=w,T=0,U=b;U;U=P(U))T++;U=0;for(var F=g;F;F=P(F))U++;for(;0<T-U;)b=P(b),T--;for(;0<U-T;)g=P(g),U--;for(;T--;){if(b===g||g!==null&&b===g.alternate){P=b;break e}b=P(b),g=P(g)}P=null}else P=null;O!==null&&pd(j,A,O,P,!1),w!==null&&_t!==null&&pd(j,_t,w,P,!0)}}t:{if(A=z?Va(z):window,O=A.nodeName&&A.nodeName.toLowerCase(),O==="select"||O==="input"&&A.type==="file")var vt=js;else if(Ds(A))if(Hs)vt=Hm;else{vt=Um;var J=Dm}else O=A.nodeName,!O||O.toLowerCase()!=="input"||A.type!=="checkbox"&&A.type!=="radio"?z&&Ai(z.elementType)&&(vt=js):vt=jm;if(vt&&(vt=vt(t,z))){Us(j,vt,l,C);break t}J&&J(t,A,z),t==="focusout"&&z&&A.type==="number"&&z.memoizedProps.value!=null&&zi(A,"number",A.value)}switch(J=z?Va(z):window,t){case"focusin":(Ds(J)||J.contentEditable==="true")&&(ra=J,Li=z,Pa=null);break;case"focusout":Pa=Li=ra=null;break;case"mousedown":Yi=!0;break;case"contextmenu":case"mouseup":case"dragend":Yi=!1,Zs(j,l,C);break;case"selectionchange":if(qm)break;case"keydown":case"keyup":Zs(j,l,C)}var ut;if(ji)t:{switch(t){case"compositionstart":var ot="onCompositionStart";break t;case"compositionend":ot="onCompositionEnd";break t;case"compositionupdate":ot="onCompositionUpdate";break t}ot=void 0}else sa?Ns(t,l)&&(ot="onCompositionEnd"):t==="keydown"&&l.keyCode===229&&(ot="onCompositionStart");ot&&(Os&&l.locale!=="ko"&&(sa||ot!=="onCompositionStart"?ot==="onCompositionEnd"&&sa&&(ut=Ts()):(fl=C,Mi="value"in fl?fl.value:fl.textContent,sa=!0)),J=Vu(z,ot),0<J.length&&(ot=new _s(ot,t,null,l,C),j.push({event:ot,listeners:J}),ut?ot.data=ut:(ut=Cs(l),ut!==null&&(ot.data=ut)))),(ut=Om?xm(t,l):Mm(t,l))&&(ot=Vu(z,"onBeforeInput"),0<ot.length&&(J=new _s("onBeforeInput","beforeinput",null,l,C),j.push({event:J,listeners:ot}),J.data=ut)),by(j,t,z,l,C)}vd(j,e)})}function _n(t,e,l){return{instance:t,listener:e,currentTarget:l}}function Vu(t,e){for(var l=e+"Capture",a=[];t!==null;){var n=t,u=n.stateNode;if(n=n.tag,n!==5&&n!==26&&n!==27||u===null||(n=wa(t,l),n!=null&&a.unshift(_n(t,n,u)),n=wa(t,e),n!=null&&a.push(_n(t,n,u))),t.tag===3)return a;t=t.return}return[]}function Ay(t){if(t===null)return null;do t=t.return;while(t&&t.tag!==5&&t.tag!==27);return t||null}function pd(t,e,l,a,n){for(var u=e._reactName,i=[];l!==null&&l!==a;){var s=l,m=s.alternate,z=s.stateNode;if(s=s.tag,m!==null&&m===a)break;s!==5&&s!==26&&s!==27||z===null||(m=z,n?(z=wa(l,u),z!=null&&i.unshift(_n(l,z,m))):n||(z=wa(l,u),z!=null&&i.push(_n(l,z,m)))),l=l.return}i.length!==0&&t.push({event:e,listeners:i})}var _y=/\r\n?/g,Ry=/\u0000|\uFFFD/g;function Sd(t){return(typeof t=="string"?t:""+t).replace(_y,` -`).replace(Ry,"")}function bd(t,e){return e=Sd(e),Sd(t)===e}function At(t,e,l,a,n,u){switch(l){case"children":typeof a=="string"?e==="body"||e==="textarea"&&a===""||ia(t,a):(typeof a=="number"||typeof a=="bigint")&&e!=="body"&&ia(t,""+a);break;case"className":$n(t,"class",a);break;case"tabIndex":$n(t,"tabindex",a);break;case"dir":case"role":case"viewBox":case"width":case"height":$n(t,l,a);break;case"style":Ss(t,a,u);break;case"data":if(e!=="object"){$n(t,"data",a);break}case"src":case"href":if(a===""&&(e!=="a"||l!=="href")){t.removeAttribute(l);break}if(a==null||typeof a=="function"||typeof a=="symbol"||typeof a=="boolean"){t.removeAttribute(l);break}a=Fn(""+a),t.setAttribute(l,a);break;case"action":case"formAction":if(typeof a=="function"){t.setAttribute(l,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof u=="function"&&(l==="formAction"?(e!=="input"&&At(t,e,"name",n.name,n,null),At(t,e,"formEncType",n.formEncType,n,null),At(t,e,"formMethod",n.formMethod,n,null),At(t,e,"formTarget",n.formTarget,n,null)):(At(t,e,"encType",n.encType,n,null),At(t,e,"method",n.method,n,null),At(t,e,"target",n.target,n,null)));if(a==null||typeof a=="symbol"||typeof a=="boolean"){t.removeAttribute(l);break}a=Fn(""+a),t.setAttribute(l,a);break;case"onClick":a!=null&&(t.onclick=Xe);break;case"onScroll":a!=null&&st("scroll",t);break;case"onScrollEnd":a!=null&&st("scrollend",t);break;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(f(61));if(l=a.__html,l!=null){if(n.children!=null)throw Error(f(60));t.innerHTML=l}}break;case"multiple":t.multiple=a&&typeof a!="function"&&typeof a!="symbol";break;case"muted":t.muted=a&&typeof a!="function"&&typeof a!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(a==null||typeof a=="function"||typeof a=="boolean"||typeof a=="symbol"){t.removeAttribute("xlink:href");break}l=Fn(""+a),t.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",l);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":a!=null&&typeof a!="function"&&typeof a!="symbol"?t.setAttribute(l,""+a):t.removeAttribute(l);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":a&&typeof a!="function"&&typeof a!="symbol"?t.setAttribute(l,""):t.removeAttribute(l);break;case"capture":case"download":a===!0?t.setAttribute(l,""):a!==!1&&a!=null&&typeof a!="function"&&typeof a!="symbol"?t.setAttribute(l,a):t.removeAttribute(l);break;case"cols":case"rows":case"size":case"span":a!=null&&typeof a!="function"&&typeof a!="symbol"&&!isNaN(a)&&1<=a?t.setAttribute(l,a):t.removeAttribute(l);break;case"rowSpan":case"start":a==null||typeof a=="function"||typeof a=="symbol"||isNaN(a)?t.removeAttribute(l):t.setAttribute(l,a);break;case"popover":st("beforetoggle",t),st("toggle",t),Jn(t,"popover",a);break;case"xlinkActuate":Ge(t,"http://www.w3.org/1999/xlink","xlink:actuate",a);break;case"xlinkArcrole":Ge(t,"http://www.w3.org/1999/xlink","xlink:arcrole",a);break;case"xlinkRole":Ge(t,"http://www.w3.org/1999/xlink","xlink:role",a);break;case"xlinkShow":Ge(t,"http://www.w3.org/1999/xlink","xlink:show",a);break;case"xlinkTitle":Ge(t,"http://www.w3.org/1999/xlink","xlink:title",a);break;case"xlinkType":Ge(t,"http://www.w3.org/1999/xlink","xlink:type",a);break;case"xmlBase":Ge(t,"http://www.w3.org/XML/1998/namespace","xml:base",a);break;case"xmlLang":Ge(t,"http://www.w3.org/XML/1998/namespace","xml:lang",a);break;case"xmlSpace":Ge(t,"http://www.w3.org/XML/1998/namespace","xml:space",a);break;case"is":Jn(t,"is",a);break;case"innerText":case"textContent":break;default:(!(2<l.length)||l[0]!=="o"&&l[0]!=="O"||l[1]!=="n"&&l[1]!=="N")&&(l=tm.get(l)||l,Jn(t,l,a))}}function of(t,e,l,a,n,u){switch(l){case"style":Ss(t,a,u);break;case"dangerouslySetInnerHTML":if(a!=null){if(typeof a!="object"||!("__html"in a))throw Error(f(61));if(l=a.__html,l!=null){if(n.children!=null)throw Error(f(60));t.innerHTML=l}}break;case"children":typeof a=="string"?ia(t,a):(typeof a=="number"||typeof a=="bigint")&&ia(t,""+a);break;case"onScroll":a!=null&&st("scroll",t);break;case"onScrollEnd":a!=null&&st("scrollend",t);break;case"onClick":a!=null&&(t.onclick=Xe);break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"innerHTML":case"ref":break;case"innerText":case"textContent":break;default:if(!rs.hasOwnProperty(l))t:{if(l[0]==="o"&&l[1]==="n"&&(n=l.endsWith("Capture"),e=l.slice(2,n?l.length-7:void 0),u=t[ee]||null,u=u!=null?u[l]:null,typeof u=="function"&&t.removeEventListener(e,u,n),typeof a=="function")){typeof u!="function"&&u!==null&&(l in t?t[l]=null:t.hasAttribute(l)&&t.removeAttribute(l)),t.addEventListener(e,a,n);break t}l in t?t[l]=a:a===!0?t.setAttribute(l,""):Jn(t,l,a)}}}function Wt(t,e,l){switch(e){case"div":case"span":case"svg":case"path":case"a":case"g":case"p":case"li":break;case"img":st("error",t),st("load",t);var a=!1,n=!1,u;for(u in l)if(l.hasOwnProperty(u)){var i=l[u];if(i!=null)switch(u){case"src":a=!0;break;case"srcSet":n=!0;break;case"children":case"dangerouslySetInnerHTML":throw Error(f(137,e));default:At(t,e,u,i,l,null)}}n&&At(t,e,"srcSet",l.srcSet,l,null),a&&At(t,e,"src",l.src,l,null);return;case"input":st("invalid",t);var s=u=i=n=null,m=null,z=null;for(a in l)if(l.hasOwnProperty(a)){var C=l[a];if(C!=null)switch(a){case"name":n=C;break;case"type":i=C;break;case"checked":m=C;break;case"defaultChecked":z=C;break;case"value":u=C;break;case"defaultValue":s=C;break;case"children":case"dangerouslySetInnerHTML":if(C!=null)throw Error(f(137,e));break;default:At(t,e,a,C,l,null)}}ys(t,u,s,m,z,i,n,!1);return;case"select":st("invalid",t),a=i=u=null;for(n in l)if(l.hasOwnProperty(n)&&(s=l[n],s!=null))switch(n){case"value":u=s;break;case"defaultValue":i=s;break;case"multiple":a=s;default:At(t,e,n,s,l,null)}e=u,l=i,t.multiple=!!a,e!=null?ua(t,!!a,e,!1):l!=null&&ua(t,!!a,l,!0);return;case"textarea":st("invalid",t),u=n=a=null;for(i in l)if(l.hasOwnProperty(i)&&(s=l[i],s!=null))switch(i){case"value":a=s;break;case"defaultValue":n=s;break;case"children":u=s;break;case"dangerouslySetInnerHTML":if(s!=null)throw Error(f(91));break;default:At(t,e,i,s,l,null)}gs(t,a,n,u);return;case"option":for(m in l)l.hasOwnProperty(m)&&(a=l[m],a!=null)&&(m==="selected"?t.selected=a&&typeof a!="function"&&typeof a!="symbol":At(t,e,m,a,l,null));return;case"dialog":st("beforetoggle",t),st("toggle",t),st("cancel",t),st("close",t);break;case"iframe":case"object":st("load",t);break;case"video":case"audio":for(a=0;a<An.length;a++)st(An[a],t);break;case"image":st("error",t),st("load",t);break;case"details":st("toggle",t);break;case"embed":case"source":case"link":st("error",t),st("load",t);case"area":case"base":case"br":case"col":case"hr":case"keygen":case"meta":case"param":case"track":case"wbr":case"menuitem":for(z in l)if(l.hasOwnProperty(z)&&(a=l[z],a!=null))switch(z){case"children":case"dangerouslySetInnerHTML":throw Error(f(137,e));default:At(t,e,z,a,l,null)}return;default:if(Ai(e)){for(C in l)l.hasOwnProperty(C)&&(a=l[C],a!==void 0&&of(t,e,C,a,l,void 0));return}}for(s in l)l.hasOwnProperty(s)&&(a=l[s],a!=null&&At(t,e,s,a,l,null))}function Oy(t,e,l,a){switch(e){case"div":case"span":case"svg":case"path":case"a":case"g":case"p":case"li":break;case"input":var n=null,u=null,i=null,s=null,m=null,z=null,C=null;for(O in l){var j=l[O];if(l.hasOwnProperty(O)&&j!=null)switch(O){case"checked":break;case"value":break;case"defaultValue":m=j;default:a.hasOwnProperty(O)||At(t,e,O,null,a,j)}}for(var A in a){var O=a[A];if(j=l[A],a.hasOwnProperty(A)&&(O!=null||j!=null))switch(A){case"type":u=O;break;case"name":n=O;break;case"checked":z=O;break;case"defaultChecked":C=O;break;case"value":i=O;break;case"defaultValue":s=O;break;case"children":case"dangerouslySetInnerHTML":if(O!=null)throw Error(f(137,e));break;default:O!==j&&At(t,e,A,O,a,j)}}Ti(t,i,s,m,z,C,u,n);return;case"select":O=i=s=A=null;for(u in l)if(m=l[u],l.hasOwnProperty(u)&&m!=null)switch(u){case"value":break;case"multiple":O=m;default:a.hasOwnProperty(u)||At(t,e,u,null,a,m)}for(n in a)if(u=a[n],m=l[n],a.hasOwnProperty(n)&&(u!=null||m!=null))switch(n){case"value":A=u;break;case"defaultValue":s=u;break;case"multiple":i=u;default:u!==m&&At(t,e,n,u,a,m)}e=s,l=i,a=O,A!=null?ua(t,!!l,A,!1):!!a!=!!l&&(e!=null?ua(t,!!l,e,!0):ua(t,!!l,l?[]:"",!1));return;case"textarea":O=A=null;for(s in l)if(n=l[s],l.hasOwnProperty(s)&&n!=null&&!a.hasOwnProperty(s))switch(s){case"value":break;case"children":break;default:At(t,e,s,null,a,n)}for(i in a)if(n=a[i],u=l[i],a.hasOwnProperty(i)&&(n!=null||u!=null))switch(i){case"value":A=n;break;case"defaultValue":O=n;break;case"children":break;case"dangerouslySetInnerHTML":if(n!=null)throw Error(f(91));break;default:n!==u&&At(t,e,i,n,a,u)}vs(t,A,O);return;case"option":for(var w in l)A=l[w],l.hasOwnProperty(w)&&A!=null&&!a.hasOwnProperty(w)&&(w==="selected"?t.selected=!1:At(t,e,w,null,a,A));for(m in a)A=a[m],O=l[m],a.hasOwnProperty(m)&&A!==O&&(A!=null||O!=null)&&(m==="selected"?t.selected=A&&typeof A!="function"&&typeof A!="symbol":At(t,e,m,A,a,O));return;case"img":case"link":case"area":case"base":case"br":case"col":case"embed":case"hr":case"keygen":case"meta":case"param":case"source":case"track":case"wbr":case"menuitem":for(var P in l)A=l[P],l.hasOwnProperty(P)&&A!=null&&!a.hasOwnProperty(P)&&At(t,e,P,null,a,A);for(z in a)if(A=a[z],O=l[z],a.hasOwnProperty(z)&&A!==O&&(A!=null||O!=null))switch(z){case"children":case"dangerouslySetInnerHTML":if(A!=null)throw Error(f(137,e));break;default:At(t,e,z,A,a,O)}return;default:if(Ai(e)){for(var _t in l)A=l[_t],l.hasOwnProperty(_t)&&A!==void 0&&!a.hasOwnProperty(_t)&&of(t,e,_t,void 0,a,A);for(C in a)A=a[C],O=l[C],!a.hasOwnProperty(C)||A===O||A===void 0&&O===void 0||of(t,e,C,A,a,O);return}}for(var b in l)A=l[b],l.hasOwnProperty(b)&&A!=null&&!a.hasOwnProperty(b)&&At(t,e,b,null,a,A);for(j in a)A=a[j],O=l[j],!a.hasOwnProperty(j)||A===O||A==null&&O==null||At(t,e,j,A,a,O)}function Ed(t){switch(t){case"css":case"script":case"font":case"img":case"image":case"input":case"link":return!0;default:return!1}}function xy(){if(typeof performance.getEntriesByType=="function"){for(var t=0,e=0,l=performance.getEntriesByType("resource"),a=0;a<l.length;a++){var n=l[a],u=n.transferSize,i=n.initiatorType,s=n.duration;if(u&&s&&Ed(i)){for(i=0,s=n.responseEnd,a+=1;a<l.length;a++){var m=l[a],z=m.startTime;if(z>s)break;var C=m.transferSize,j=m.initiatorType;C&&Ed(j)&&(m=m.responseEnd,i+=C*(m<s?1:(s-z)/(m-z)))}if(--a,e+=8*(u+i)/(n.duration/1e3),t++,10<t)break}}if(0<t)return e/t/1e6}return navigator.connection&&(t=navigator.connection.downlink,typeof t=="number")?t:5}var df=null,hf=null;function wu(t){return t.nodeType===9?t:t.ownerDocument}function Td(t){switch(t){case"http://www.w3.org/2000/svg":return 1;case"http://www.w3.org/1998/Math/MathML":return 2;default:return 0}}function zd(t,e){if(t===0)switch(e){case"svg":return 1;case"math":return 2;default:return 0}return t===1&&e==="foreignObject"?0:t}function mf(t,e){return t==="textarea"||t==="noscript"||typeof e.children=="string"||typeof e.children=="number"||typeof e.children=="bigint"||typeof e.dangerouslySetInnerHTML=="object"&&e.dangerouslySetInnerHTML!==null&&e.dangerouslySetInnerHTML.__html!=null}var yf=null;function My(){var t=window.event;return t&&t.type==="popstate"?t===yf?!1:(yf=t,!0):(yf=null,!1)}var Ad=typeof setTimeout=="function"?setTimeout:void 0,Ny=typeof clearTimeout=="function"?clearTimeout:void 0,_d=typeof Promise=="function"?Promise:void 0,Cy=typeof queueMicrotask=="function"?queueMicrotask:typeof _d<"u"?function(t){return _d.resolve(null).then(t).catch(Dy)}:Ad;function Dy(t){setTimeout(function(){throw t})}function _l(t){return t==="head"}function Rd(t,e){var l=e,a=0;do{var n=l.nextSibling;if(t.removeChild(l),n&&n.nodeType===8)if(l=n.data,l==="/$"||l==="/&"){if(a===0){t.removeChild(n),qa(e);return}a--}else if(l==="$"||l==="$?"||l==="$~"||l==="$!"||l==="&")a++;else if(l==="html")Rn(t.ownerDocument.documentElement);else if(l==="head"){l=t.ownerDocument.head,Rn(l);for(var u=l.firstChild;u;){var i=u.nextSibling,s=u.nodeName;u[Za]||s==="SCRIPT"||s==="STYLE"||s==="LINK"&&u.rel.toLowerCase()==="stylesheet"||l.removeChild(u),u=i}}else l==="body"&&Rn(t.ownerDocument.body);l=n}while(l);qa(e)}function Od(t,e){var l=t;t=0;do{var a=l.nextSibling;if(l.nodeType===1?e?(l._stashedDisplay=l.style.display,l.style.display="none"):(l.style.display=l._stashedDisplay||"",l.getAttribute("style")===""&&l.removeAttribute("style")):l.nodeType===3&&(e?(l._stashedText=l.nodeValue,l.nodeValue=""):l.nodeValue=l._stashedText||""),a&&a.nodeType===8)if(l=a.data,l==="/$"){if(t===0)break;t--}else l!=="$"&&l!=="$?"&&l!=="$~"&&l!=="$!"||t++;l=a}while(l)}function vf(t){var e=t.firstChild;for(e&&e.nodeType===10&&(e=e.nextSibling);e;){var l=e;switch(e=e.nextSibling,l.nodeName){case"HTML":case"HEAD":case"BODY":vf(l),bi(l);continue;case"SCRIPT":case"STYLE":continue;case"LINK":if(l.rel.toLowerCase()==="stylesheet")continue}t.removeChild(l)}}function Uy(t,e,l,a){for(;t.nodeType===1;){var n=l;if(t.nodeName.toLowerCase()!==e.toLowerCase()){if(!a&&(t.nodeName!=="INPUT"||t.type!=="hidden"))break}else if(a){if(!t[Za])switch(e){case"meta":if(!t.hasAttribute("itemprop"))break;return t;case"link":if(u=t.getAttribute("rel"),u==="stylesheet"&&t.hasAttribute("data-precedence"))break;if(u!==n.rel||t.getAttribute("href")!==(n.href==null||n.href===""?null:n.href)||t.getAttribute("crossorigin")!==(n.crossOrigin==null?null:n.crossOrigin)||t.getAttribute("title")!==(n.title==null?null:n.title))break;return t;case"style":if(t.hasAttribute("data-precedence"))break;return t;case"script":if(u=t.getAttribute("src"),(u!==(n.src==null?null:n.src)||t.getAttribute("type")!==(n.type==null?null:n.type)||t.getAttribute("crossorigin")!==(n.crossOrigin==null?null:n.crossOrigin))&&u&&t.hasAttribute("async")&&!t.hasAttribute("itemprop"))break;return t;default:return t}}else if(e==="input"&&t.type==="hidden"){var u=n.name==null?null:""+n.name;if(n.type==="hidden"&&t.getAttribute("name")===u)return t}else return t;if(t=Me(t.nextSibling),t===null)break}return null}function jy(t,e,l){if(e==="")return null;for(;t.nodeType!==3;)if((t.nodeType!==1||t.nodeName!=="INPUT"||t.type!=="hidden")&&!l||(t=Me(t.nextSibling),t===null))return null;return t}function xd(t,e){for(;t.nodeType!==8;)if((t.nodeType!==1||t.nodeName!=="INPUT"||t.type!=="hidden")&&!e||(t=Me(t.nextSibling),t===null))return null;return t}function gf(t){return t.data==="$?"||t.data==="$~"}function pf(t){return t.data==="$!"||t.data==="$?"&&t.ownerDocument.readyState!=="loading"}function Hy(t,e){var l=t.ownerDocument;if(t.data==="$~")t._reactRetry=e;else if(t.data!=="$?"||l.readyState!=="loading")e();else{var a=function(){e(),l.removeEventListener("DOMContentLoaded",a)};l.addEventListener("DOMContentLoaded",a),t._reactRetry=a}}function Me(t){for(;t!=null;t=t.nextSibling){var e=t.nodeType;if(e===1||e===3)break;if(e===8){if(e=t.data,e==="$"||e==="$!"||e==="$?"||e==="$~"||e==="&"||e==="F!"||e==="F")break;if(e==="/$"||e==="/&")return null}}return t}var Sf=null;function Md(t){t=t.nextSibling;for(var e=0;t;){if(t.nodeType===8){var l=t.data;if(l==="/$"||l==="/&"){if(e===0)return Me(t.nextSibling);e--}else l!=="$"&&l!=="$!"&&l!=="$?"&&l!=="$~"&&l!=="&"||e++}t=t.nextSibling}return null}function Nd(t){t=t.previousSibling;for(var e=0;t;){if(t.nodeType===8){var l=t.data;if(l==="$"||l==="$!"||l==="$?"||l==="$~"||l==="&"){if(e===0)return t;e--}else l!=="/$"&&l!=="/&"||e++}t=t.previousSibling}return null}function Cd(t,e,l){switch(e=wu(l),t){case"html":if(t=e.documentElement,!t)throw Error(f(452));return t;case"head":if(t=e.head,!t)throw Error(f(453));return t;case"body":if(t=e.body,!t)throw Error(f(454));return t;default:throw Error(f(451))}}function Rn(t){for(var e=t.attributes;e.length;)t.removeAttributeNode(e[0]);bi(t)}var Ne=new Map,Dd=new Set;function Ku(t){return typeof t.getRootNode=="function"?t.getRootNode():t.nodeType===9?t:t.ownerDocument}var al=L.d;L.d={f:By,r:qy,D:Ly,C:Yy,L:Gy,m:Xy,X:Zy,S:Qy,M:Vy};function By(){var t=al.f(),e=qu();return t||e}function qy(t){var e=la(t);e!==null&&e.tag===5&&e.type==="form"?$r(e):al.r(t)}var ja=typeof document>"u"?null:document;function Ud(t,e,l){var a=ja;if(a&&typeof e=="string"&&e){var n=Te(e);n='link[rel="'+t+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Dd.has(n)||(Dd.add(n),t={rel:t,crossOrigin:l,href:e},a.querySelector(n)===null&&(e=a.createElement("link"),Wt(e,"link",t),wt(e),a.head.appendChild(e)))}}function Ly(t){al.D(t),Ud("dns-prefetch",t,null)}function Yy(t,e){al.C(t,e),Ud("preconnect",t,e)}function Gy(t,e,l){al.L(t,e,l);var a=ja;if(a&&t&&e){var n='link[rel="preload"][as="'+Te(e)+'"]';e==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+Te(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+Te(l.imageSizes)+'"]')):n+='[href="'+Te(t)+'"]';var u=n;switch(e){case"style":u=Ha(t);break;case"script":u=Ba(t)}Ne.has(u)||(t=R({rel:"preload",href:e==="image"&&l&&l.imageSrcSet?void 0:t,as:e},l),Ne.set(u,t),a.querySelector(n)!==null||e==="style"&&a.querySelector(On(u))||e==="script"&&a.querySelector(xn(u))||(e=a.createElement("link"),Wt(e,"link",t),wt(e),a.head.appendChild(e)))}}function Xy(t,e){al.m(t,e);var l=ja;if(l&&t){var a=e&&typeof e.as=="string"?e.as:"script",n='link[rel="modulepreload"][as="'+Te(a)+'"][href="'+Te(t)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ba(t)}if(!Ne.has(u)&&(t=R({rel:"modulepreload",href:t},e),Ne.set(u,t),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(xn(u)))return}a=l.createElement("link"),Wt(a,"link",t),wt(a),l.head.appendChild(a)}}}function Qy(t,e,l){al.S(t,e,l);var a=ja;if(a&&t){var n=aa(a).hoistableStyles,u=Ha(t);e=e||"default";var i=n.get(u);if(!i){var s={loading:0,preload:null};if(i=a.querySelector(On(u)))s.loading=5;else{t=R({rel:"stylesheet",href:t,"data-precedence":e},l),(l=Ne.get(u))&&bf(t,l);var m=i=a.createElement("link");wt(m),Wt(m,"link",t),m._p=new Promise(function(z,C){m.onload=z,m.onerror=C}),m.addEventListener("load",function(){s.loading|=1}),m.addEventListener("error",function(){s.loading|=2}),s.loading|=4,Ju(i,e,a)}i={type:"stylesheet",instance:i,count:1,state:s},n.set(u,i)}}}function Zy(t,e){al.X(t,e);var l=ja;if(l&&t){var a=aa(l).hoistableScripts,n=Ba(t),u=a.get(n);u||(u=l.querySelector(xn(n)),u||(t=R({src:t,async:!0},e),(e=Ne.get(n))&&Ef(t,e),u=l.createElement("script"),wt(u),Wt(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Vy(t,e){al.M(t,e);var l=ja;if(l&&t){var a=aa(l).hoistableScripts,n=Ba(t),u=a.get(n);u||(u=l.querySelector(xn(n)),u||(t=R({src:t,async:!0,type:"module"},e),(e=Ne.get(n))&&Ef(t,e),u=l.createElement("script"),wt(u),Wt(u,"link",t),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function jd(t,e,l,a){var n=(n=ct.current)?Ku(n):null;if(!n)throw Error(f(446));switch(t){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(e=Ha(l.href),l=aa(n).hoistableStyles,a=l.get(e),a||(a={type:"style",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){t=Ha(l.href);var u=aa(n).hoistableStyles,i=u.get(t);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(t,i),(u=n.querySelector(On(t)))&&!u._p&&(i.instance=u,i.state.loading=5),Ne.has(t)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Ne.set(t,l),u||wy(n,t,l,i.state))),e&&a===null)throw Error(f(528,""));return i}if(e&&a!==null)throw Error(f(529,""));return null;case"script":return e=l.async,l=l.src,typeof l=="string"&&e&&typeof e!="function"&&typeof e!="symbol"?(e=Ba(l),l=aa(n).hoistableScripts,a=l.get(e),a||(a={type:"script",instance:null,count:0,state:null},l.set(e,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(f(444,t))}}function Ha(t){return'href="'+Te(t)+'"'}function On(t){return'link[rel="stylesheet"]['+t+"]"}function Hd(t){return R({},t,{"data-precedence":t.precedence,precedence:null})}function wy(t,e,l,a){t.querySelector('link[rel="preload"][as="style"]['+e+"]")?a.loading=1:(e=t.createElement("link"),a.preload=e,e.addEventListener("load",function(){return a.loading|=1}),e.addEventListener("error",function(){return a.loading|=2}),Wt(e,"link",l),wt(e),t.head.appendChild(e))}function Ba(t){return'[src="'+Te(t)+'"]'}function xn(t){return"script[async]"+t}function Bd(t,e,l){if(e.count++,e.instance===null)switch(e.type){case"style":var a=t.querySelector('style[data-href~="'+Te(l.href)+'"]');if(a)return e.instance=a,wt(a),a;var n=R({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(t.ownerDocument||t).createElement("style"),wt(a),Wt(a,"style",n),Ju(a,l.precedence,t),e.instance=a;case"stylesheet":n=Ha(l.href);var u=t.querySelector(On(n));if(u)return e.state.loading|=4,e.instance=u,wt(u),u;a=Hd(l),(n=Ne.get(n))&&bf(a,n),u=(t.ownerDocument||t).createElement("link"),wt(u);var i=u;return i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Wt(u,"link",a),e.state.loading|=4,Ju(u,l.precedence,t),e.instance=u;case"script":return u=Ba(l.src),(n=t.querySelector(xn(u)))?(e.instance=n,wt(n),n):(a=l,(n=Ne.get(u))&&(a=R({},l),Ef(a,n)),t=t.ownerDocument||t,n=t.createElement("script"),wt(n),Wt(n,"link",a),t.head.appendChild(n),e.instance=n);case"void":return null;default:throw Error(f(443,e.type))}else e.type==="stylesheet"&&(e.state.loading&4)===0&&(a=e.instance,e.state.loading|=4,Ju(a,l.precedence,t));return e.instance}function Ju(t,e,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i<a.length;i++){var s=a[i];if(s.dataset.precedence===e)u=s;else if(u!==n)break}u?u.parentNode.insertBefore(t,u.nextSibling):(e=l.nodeType===9?l.head:l,e.insertBefore(t,e.firstChild))}function bf(t,e){t.crossOrigin==null&&(t.crossOrigin=e.crossOrigin),t.referrerPolicy==null&&(t.referrerPolicy=e.referrerPolicy),t.title==null&&(t.title=e.title)}function Ef(t,e){t.crossOrigin==null&&(t.crossOrigin=e.crossOrigin),t.referrerPolicy==null&&(t.referrerPolicy=e.referrerPolicy),t.integrity==null&&(t.integrity=e.integrity)}var $u=null;function qd(t,e,l){if($u===null){var a=new Map,n=$u=new Map;n.set(l,a)}else n=$u,a=n.get(l),a||(a=new Map,n.set(l,a));if(a.has(t))return a;for(a.set(t,null),l=l.getElementsByTagName(t),n=0;n<l.length;n++){var u=l[n];if(!(u[Za]||u[Jt]||t==="link"&&u.getAttribute("rel")==="stylesheet")&&u.namespaceURI!=="http://www.w3.org/2000/svg"){var i=u.getAttribute(e)||"";i=t+i;var s=a.get(i);s?s.push(u):a.set(i,[u])}}return a}function Ld(t,e,l){t=t.ownerDocument||t,t.head.insertBefore(l,e==="title"?t.querySelector("head > title"):null)}function Ky(t,e,l){if(l===1||e.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof e.precedence!="string"||typeof e.href!="string"||e.href==="")break;return!0;case"link":if(typeof e.rel!="string"||typeof e.href!="string"||e.href===""||e.onLoad||e.onError)break;return e.rel==="stylesheet"?(t=e.disabled,typeof e.precedence=="string"&&t==null):!0;case"script":if(e.async&&typeof e.async!="function"&&typeof e.async!="symbol"&&!e.onLoad&&!e.onError&&e.src&&typeof e.src=="string")return!0}return!1}function Yd(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Jy(t,e,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Ha(a.href),u=e.querySelector(On(n));if(u){e=u._p,e!==null&&typeof e=="object"&&typeof e.then=="function"&&(t.count++,t=ku.bind(t),e.then(t,t)),l.state.loading|=4,l.instance=u,wt(u);return}u=e.ownerDocument||e,a=Hd(a),(n=Ne.get(n))&&bf(a,n),u=u.createElement("link"),wt(u);var i=u;i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Wt(u,"link",a),l.instance=u}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(l,e),(e=l.state.preload)&&(l.state.loading&3)===0&&(t.count++,l=ku.bind(t),e.addEventListener("load",l),e.addEventListener("error",l))}}var Tf=0;function $y(t,e){return t.stylesheets&&t.count===0&&Wu(t,t.stylesheets),0<t.count||0<t.imgCount?function(l){var a=setTimeout(function(){if(t.stylesheets&&Wu(t,t.stylesheets),t.unsuspend){var u=t.unsuspend;t.unsuspend=null,u()}},6e4+e);0<t.imgBytes&&Tf===0&&(Tf=62500*xy());var n=setTimeout(function(){if(t.waitingForImages=!1,t.count===0&&(t.stylesheets&&Wu(t,t.stylesheets),t.unsuspend)){var u=t.unsuspend;t.unsuspend=null,u()}},(t.imgBytes>Tf?50:800)+e);return t.unsuspend=l,function(){t.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function ku(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Wu(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Fu=null;function Wu(t,e){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Fu=new Map,e.forEach(ky,t),Fu=null,ku.call(t))}function ky(t,e){if(!(e.state.loading&4)){var l=Fu.get(t);if(l)var a=l.get(null);else{l=new Map,Fu.set(t,l);for(var n=t.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u<n.length;u++){var i=n[u];(i.nodeName==="LINK"||i.getAttribute("media")!=="not all")&&(l.set(i.dataset.precedence,i),a=i)}a&&l.set(null,a)}n=e.instance,i=n.getAttribute("data-precedence"),u=l.get(i)||a,u===a&&l.set(null,n),l.set(i,n),this.count++,a=ku.bind(this),n.addEventListener("load",a),n.addEventListener("error",a),u?u.parentNode.insertBefore(n,u.nextSibling):(t=t.nodeType===9?t.head:t,t.insertBefore(n,t.firstChild)),e.state.loading|=4}}var Mn={$$typeof:G,Provider:null,Consumer:null,_currentValue:k,_currentValue2:k,_threadCount:0};function Fy(t,e,l,a,n,u,i,s,m){this.tag=1,this.containerInfo=t,this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.next=this.pendingContext=this.context=this.cancelPendingCommit=null,this.callbackPriority=0,this.expirationTimes=vi(-1),this.entangledLanes=this.shellSuspendCounter=this.errorRecoveryDisabledLanes=this.expiredLanes=this.warmLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=vi(0),this.hiddenUpdates=vi(null),this.identifierPrefix=a,this.onUncaughtError=n,this.onCaughtError=u,this.onRecoverableError=i,this.pooledCache=null,this.pooledCacheLanes=0,this.formState=m,this.incompleteTransitions=new Map}function Gd(t,e,l,a,n,u,i,s,m,z,C,j){return t=new Fy(t,e,l,i,m,z,C,j,s),e=1,u===!0&&(e|=24),u=he(3,null,null,e),t.current=u,u.stateNode=t,e=tc(),e.refCount++,t.pooledCache=e,e.refCount++,u.memoizedState={element:a,isDehydrated:l,cache:e},nc(u),t}function Xd(t){return t?(t=ha,t):ha}function Qd(t,e,l,a,n,u){n=Xd(n),a.context===null?a.context=n:a.pendingContext=n,a=ml(e),a.payload={element:l},u=u===void 0?null:u,u!==null&&(a.callback=u),l=yl(t,a,e),l!==null&&(ce(l,t,e),cn(l,t,e))}function Zd(t,e){if(t=t.memoizedState,t!==null&&t.dehydrated!==null){var l=t.retryLane;t.retryLane=l!==0&&l<e?l:e}}function zf(t,e){Zd(t,e),(t=t.alternate)&&Zd(t,e)}function Vd(t){if(t.tag===13||t.tag===31){var e=Ll(t,67108864);e!==null&&ce(e,t,67108864),zf(t,67108864)}}function wd(t){if(t.tag===13||t.tag===31){var e=pe();e=gi(e);var l=Ll(t,e);l!==null&&ce(l,t,e),zf(t,e)}}var Iu=!0;function Wy(t,e,l,a){var n=x.T;x.T=null;var u=L.p;try{L.p=2,Af(t,e,l,a)}finally{L.p=u,x.T=n}}function Iy(t,e,l,a){var n=x.T;x.T=null;var u=L.p;try{L.p=8,Af(t,e,l,a)}finally{L.p=u,x.T=n}}function Af(t,e,l,a){if(Iu){var n=_f(a);if(n===null)rf(t,e,a,Pu,l),Jd(t,a);else if(tv(n,t,e,l,a))a.stopPropagation();else if(Jd(t,a),e&4&&-1<Py.indexOf(t)){for(;n!==null;){var u=la(n);if(u!==null)switch(u.tag){case 3:if(u=u.stateNode,u.current.memoizedState.isDehydrated){var i=Ul(u.pendingLanes);if(i!==0){var s=u;for(s.pendingLanes|=2,s.entangledLanes|=2;i;){var m=1<<31-oe(i);s.entanglements[1]|=m,i&=~m}Ye(u),(pt&6)===0&&(Hu=se()+500,zn(0))}}break;case 31:case 13:s=Ll(u,2),s!==null&&ce(s,u,2),qu(),zf(u,2)}if(u=_f(a),u===null&&rf(t,e,a,Pu,l),u===n)break;n=u}n!==null&&a.stopPropagation()}else rf(t,e,a,null,l)}}function _f(t){return t=Ri(t),Rf(t)}var Pu=null;function Rf(t){if(Pu=null,t=ea(t),t!==null){var e=h(t);if(e===null)t=null;else{var l=e.tag;if(l===13){if(t=p(e),t!==null)return t;t=null}else if(l===31){if(t=_(e),t!==null)return t;t=null}else if(l===3){if(e.stateNode.current.memoizedState.isDehydrated)return e.tag===3?e.stateNode.containerInfo:null;t=null}else e!==t&&(t=null)}}return Pu=t,null}function Kd(t){switch(t){case"beforetoggle":case"cancel":case"click":case"close":case"contextmenu":case"copy":case"cut":case"auxclick":case"dblclick":case"dragend":case"dragstart":case"drop":case"focusin":case"focusout":case"input":case"invalid":case"keydown":case"keypress":case"keyup":case"mousedown":case"mouseup":case"paste":case"pause":case"play":case"pointercancel":case"pointerdown":case"pointerup":case"ratechange":case"reset":case"resize":case"seeked":case"submit":case"toggle":case"touchcancel":case"touchend":case"touchstart":case"volumechange":case"change":case"selectionchange":case"textInput":case"compositionstart":case"compositionend":case"compositionupdate":case"beforeblur":case"afterblur":case"beforeinput":case"blur":case"fullscreenchange":case"focus":case"hashchange":case"popstate":case"select":case"selectstart":return 2;case"drag":case"dragenter":case"dragexit":case"dragleave":case"dragover":case"mousemove":case"mouseout":case"mouseover":case"pointermove":case"pointerout":case"pointerover":case"scroll":case"touchmove":case"wheel":case"mouseenter":case"mouseleave":case"pointerenter":case"pointerleave":return 8;case"message":switch(Lh()){case Pf:return 2;case ts:return 8;case Qn:case Yh:return 32;case es:return 268435456;default:return 32}default:return 32}}var Of=!1,Rl=null,Ol=null,xl=null,Nn=new Map,Cn=new Map,Ml=[],Py="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset".split(" ");function Jd(t,e){switch(t){case"focusin":case"focusout":Rl=null;break;case"dragenter":case"dragleave":Ol=null;break;case"mouseover":case"mouseout":xl=null;break;case"pointerover":case"pointerout":Nn.delete(e.pointerId);break;case"gotpointercapture":case"lostpointercapture":Cn.delete(e.pointerId)}}function Dn(t,e,l,a,n,u){return t===null||t.nativeEvent!==u?(t={blockedOn:e,domEventName:l,eventSystemFlags:a,nativeEvent:u,targetContainers:[n]},e!==null&&(e=la(e),e!==null&&Vd(e)),t):(t.eventSystemFlags|=a,e=t.targetContainers,n!==null&&e.indexOf(n)===-1&&e.push(n),t)}function tv(t,e,l,a,n){switch(e){case"focusin":return Rl=Dn(Rl,t,e,l,a,n),!0;case"dragenter":return Ol=Dn(Ol,t,e,l,a,n),!0;case"mouseover":return xl=Dn(xl,t,e,l,a,n),!0;case"pointerover":var u=n.pointerId;return Nn.set(u,Dn(Nn.get(u)||null,t,e,l,a,n)),!0;case"gotpointercapture":return u=n.pointerId,Cn.set(u,Dn(Cn.get(u)||null,t,e,l,a,n)),!0}return!1}function $d(t){var e=ea(t.target);if(e!==null){var l=h(e);if(l!==null){if(e=l.tag,e===13){if(e=p(l),e!==null){t.blockedOn=e,cs(t.priority,function(){wd(l)});return}}else if(e===31){if(e=_(l),e!==null){t.blockedOn=e,cs(t.priority,function(){wd(l)});return}}else if(e===3&&l.stateNode.current.memoizedState.isDehydrated){t.blockedOn=l.tag===3?l.stateNode.containerInfo:null;return}}}t.blockedOn=null}function ti(t){if(t.blockedOn!==null)return!1;for(var e=t.targetContainers;0<e.length;){var l=_f(t.nativeEvent);if(l===null){l=t.nativeEvent;var a=new l.constructor(l.type,l);_i=a,l.target.dispatchEvent(a),_i=null}else return e=la(l),e!==null&&Vd(e),t.blockedOn=l,!1;e.shift()}return!0}function kd(t,e,l){ti(t)&&l.delete(e)}function ev(){Of=!1,Rl!==null&&ti(Rl)&&(Rl=null),Ol!==null&&ti(Ol)&&(Ol=null),xl!==null&&ti(xl)&&(xl=null),Nn.forEach(kd),Cn.forEach(kd)}function ei(t,e){t.blockedOn===e&&(t.blockedOn=null,Of||(Of=!0,c.unstable_scheduleCallback(c.unstable_NormalPriority,ev)))}var li=null;function Fd(t){li!==t&&(li=t,c.unstable_scheduleCallback(c.unstable_NormalPriority,function(){li===t&&(li=null);for(var e=0;e<t.length;e+=3){var l=t[e],a=t[e+1],n=t[e+2];if(typeof a!="function"){if(Rf(a||l)===null)continue;break}var u=la(l);u!==null&&(t.splice(e,3),e-=3,Ac(u,{pending:!0,data:n,method:l.method,action:a},a,n))}}))}function qa(t){function e(m){return ei(m,t)}Rl!==null&&ei(Rl,t),Ol!==null&&ei(Ol,t),xl!==null&&ei(xl,t),Nn.forEach(e),Cn.forEach(e);for(var l=0;l<Ml.length;l++){var a=Ml[l];a.blockedOn===t&&(a.blockedOn=null)}for(;0<Ml.length&&(l=Ml[0],l.blockedOn===null);)$d(l),l.blockedOn===null&&Ml.shift();if(l=(t.ownerDocument||t).$$reactFormReplay,l!=null)for(a=0;a<l.length;a+=3){var n=l[a],u=l[a+1],i=n[ee]||null;if(typeof u=="function")i||Fd(l);else if(i){var s=null;if(u&&u.hasAttribute("formAction")){if(n=u,i=u[ee]||null)s=i.formAction;else if(Rf(n)!==null)continue}else s=i.action;typeof s=="function"?l[a+1]=s:(l.splice(a,3),a-=3),Fd(l)}}}function Wd(){function t(u){u.canIntercept&&u.info==="react-transition"&&u.intercept({handler:function(){return new Promise(function(i){return n=i})},focusReset:"manual",scroll:"manual"})}function e(){n!==null&&(n(),n=null),a||setTimeout(l,20)}function l(){if(!a&&!navigation.transition){var u=navigation.currentEntry;u&&u.url!=null&&navigation.navigate(u.url,{state:u.getState(),info:"react-transition",history:"replace"})}}if(typeof navigation=="object"){var a=!1,n=null;return navigation.addEventListener("navigate",t),navigation.addEventListener("navigatesuccess",e),navigation.addEventListener("navigateerror",e),setTimeout(l,100),function(){a=!0,navigation.removeEventListener("navigate",t),navigation.removeEventListener("navigatesuccess",e),navigation.removeEventListener("navigateerror",e),n!==null&&(n(),n=null)}}}function xf(t){this._internalRoot=t}ai.prototype.render=xf.prototype.render=function(t){var e=this._internalRoot;if(e===null)throw Error(f(409));var l=e.current,a=pe();Qd(l,a,t,e,null,null)},ai.prototype.unmount=xf.prototype.unmount=function(){var t=this._internalRoot;if(t!==null){this._internalRoot=null;var e=t.containerInfo;Qd(t.current,2,null,t,null,null),qu(),e[ta]=null}};function ai(t){this._internalRoot=t}ai.prototype.unstable_scheduleHydration=function(t){if(t){var e=is();t={blockedOn:null,target:t,priority:e};for(var l=0;l<Ml.length&&e!==0&&e<Ml[l].priority;l++);Ml.splice(l,0,t),l===0&&$d(t)}};var Id=r.version;if(Id!=="19.2.4")throw Error(f(527,Id,"19.2.4"));L.findDOMNode=function(t){var e=t._reactInternals;if(e===void 0)throw typeof t.render=="function"?Error(f(188)):(t=Object.keys(t).join(","),Error(f(268,t)));return t=y(e),t=t!==null?N(t):null,t=t===null?null:t.stateNode,t};var lv={bundleType:0,version:"19.2.4",rendererPackageName:"react-dom",currentDispatcherRef:x,reconcilerVersion:"19.2.4"};if(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"){var ni=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!ni.isDisabled&&ni.supportsFiber)try{Ga=ni.inject(lv),re=ni}catch{}}return jn.createRoot=function(t,e){if(!d(t))throw Error(f(299));var l=!1,a="",n=no,u=uo,i=io;return e!=null&&(e.unstable_strictMode===!0&&(l=!0),e.identifierPrefix!==void 0&&(a=e.identifierPrefix),e.onUncaughtError!==void 0&&(n=e.onUncaughtError),e.onCaughtError!==void 0&&(u=e.onCaughtError),e.onRecoverableError!==void 0&&(i=e.onRecoverableError)),e=Gd(t,1,!1,null,null,l,a,null,n,u,i,Wd),t[ta]=e.current,sf(t),new xf(e)},jn.hydrateRoot=function(t,e,l){if(!d(t))throw Error(f(299));var a=!1,n="",u=no,i=uo,s=io,m=null;return l!=null&&(l.unstable_strictMode===!0&&(a=!0),l.identifierPrefix!==void 0&&(n=l.identifierPrefix),l.onUncaughtError!==void 0&&(u=l.onUncaughtError),l.onCaughtError!==void 0&&(i=l.onCaughtError),l.onRecoverableError!==void 0&&(s=l.onRecoverableError),l.formState!==void 0&&(m=l.formState)),e=Gd(t,1,!0,e,l??null,a,n,m,u,i,s,Wd),e.context=Xd(null),l=e.current,a=pe(),a=gi(a),n=ml(a),n.callback=null,yl(l,n,a),l=a,e.current.lanes=l,Qa(e,l),Ye(e),t[ta]=e.current,sf(t),new ai(e)},jn.version="19.2.4",jn}var fh;function mv(){if(fh)return Cf.exports;fh=1;function c(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(c)}catch(r){console.error(r)}}return c(),Cf.exports=hv(),Cf.exports}var yv=mv();var sh="popstate";function vv(c={}){function r(d,h){let{pathname:p="/",search:_="",hash:S=""}=Il(d.location.hash.substring(1));return!p.startsWith("/")&&!p.startsWith(".")&&(p="/"+p),Gf("",{pathname:p,search:_,hash:S},h.state&&h.state.usr||null,h.state&&h.state.key||"default")}function o(d,h){let p=d.document.querySelector("base"),_="";if(p&&p.getAttribute("href")){let S=d.location.href,y=S.indexOf("#");_=y===-1?S:S.slice(0,y)}return _+"#"+(typeof h=="string"?h:Bn(h))}function f(d,h){Se(d.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(h)})`)}return pv(r,o,f,c)}function Ct(c,r){if(c===!1||c===null||typeof c>"u")throw new Error(r)}function Se(c,r){if(!c){typeof console<"u"&&console.warn(r);try{throw new Error(r)}catch{}}}function gv(){return Math.random().toString(36).substring(2,10)}function rh(c,r){return{usr:c.state,key:c.key,idx:r}}function Gf(c,r,o=null,f){return{pathname:typeof c=="string"?c:c.pathname,search:"",hash:"",...typeof r=="string"?Il(r):r,state:o,key:r&&r.key||f||gv()}}function Bn({pathname:c="/",search:r="",hash:o=""}){return r&&r!=="?"&&(c+=r.charAt(0)==="?"?r:"?"+r),o&&o!=="#"&&(c+=o.charAt(0)==="#"?o:"#"+o),c}function Il(c){let r={};if(c){let o=c.indexOf("#");o>=0&&(r.hash=c.substring(o),c=c.substring(0,o));let f=c.indexOf("?");f>=0&&(r.search=c.substring(f),c=c.substring(0,f)),c&&(r.pathname=c)}return r}function pv(c,r,o,f={}){let{window:d=document.defaultView,v5Compat:h=!1}=f,p=d.history,_="POP",S=null,y=N();y==null&&(y=0,p.replaceState({...p.state,idx:y},""));function N(){return(p.state||{idx:null}).idx}function R(){_="POP";let X=N(),H=X==null?null:X-y;y=X,S&&S({action:_,location:Q.location,delta:H})}function B(X,H){_="PUSH";let q=Gf(Q.location,X,H);o&&o(q,X),y=N()+1;let G=rh(q,y),dt=Q.createHref(q);try{p.pushState(G,"",dt)}catch(mt){if(mt instanceof DOMException&&mt.name==="DataCloneError")throw mt;d.location.assign(dt)}h&&S&&S({action:_,location:Q.location,delta:1})}function K(X,H){_="REPLACE";let q=Gf(Q.location,X,H);o&&o(q,X),y=N();let G=rh(q,y),dt=Q.createHref(q);p.replaceState(G,"",dt),h&&S&&S({action:_,location:Q.location,delta:0})}function $(X){return Sv(X)}let Q={get action(){return _},get location(){return c(d,p)},listen(X){if(S)throw new Error("A history only accepts one active listener");return d.addEventListener(sh,R),S=X,()=>{d.removeEventListener(sh,R),S=null}},createHref(X){return r(d,X)},createURL:$,encodeLocation(X){let H=$(X);return{pathname:H.pathname,search:H.search,hash:H.hash}},push:B,replace:K,go(X){return p.go(X)}};return Q}function Sv(c,r=!1){let o="http://localhost";typeof window<"u"&&(o=window.location.origin!=="null"?window.location.origin:window.location.href),Ct(o,"No window.location.(origin|href) available to create URL");let f=typeof c=="string"?c:Bn(c);return f=f.replace(/ $/,"%20"),!r&&f.startsWith("//")&&(f=o+f),new URL(f,o)}function yh(c,r,o="/"){return bv(c,r,o,!1)}function bv(c,r,o,f){let d=typeof r=="string"?Il(r):r,h=ul(d.pathname||"/",o);if(h==null)return null;let p=vh(c);Ev(p);let _=null;for(let S=0;_==null&&S<p.length;++S){let y=ph(h);_=Nv(p[S],y,f)}return _}function vh(c,r=[],o=[],f="",d=!1){let h=(p,_,S=d,y)=>{let N={relativePath:y===void 0?p.path||"":y,caseSensitive:p.caseSensitive===!0,childrenIndex:_,route:p};if(N.relativePath.startsWith("/")){if(!N.relativePath.startsWith(f)&&S)return;Ct(N.relativePath.startsWith(f),`Absolute route path "${N.relativePath}" nested under path "${f}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),N.relativePath=N.relativePath.slice(f.length)}let R=nl([f,N.relativePath]),B=o.concat(N);p.children&&p.children.length>0&&(Ct(p.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${R}".`),vh(p.children,r,B,R,S)),!(p.path==null&&!p.index)&&r.push({path:R,score:xv(R,p.index),routesMeta:B})};return c.forEach((p,_)=>{if(p.path===""||!p.path?.includes("?"))h(p,_);else for(let S of gh(p.path))h(p,_,!0,S)}),r}function gh(c){let r=c.split("/");if(r.length===0)return[];let[o,...f]=r,d=o.endsWith("?"),h=o.replace(/\?$/,"");if(f.length===0)return d?[h,""]:[h];let p=gh(f.join("/")),_=[];return _.push(...p.map(S=>S===""?h:[h,S].join("/"))),d&&_.push(...p),_.map(S=>c.startsWith("/")&&S===""?"/":S)}function Ev(c){c.sort((r,o)=>r.score!==o.score?o.score-r.score:Mv(r.routesMeta.map(f=>f.childrenIndex),o.routesMeta.map(f=>f.childrenIndex)))}var Tv=/^:[\w-]+$/,zv=3,Av=2,_v=1,Rv=10,Ov=-2,oh=c=>c==="*";function xv(c,r){let o=c.split("/"),f=o.length;return o.some(oh)&&(f+=Ov),r&&(f+=Av),o.filter(d=>!oh(d)).reduce((d,h)=>d+(Tv.test(h)?zv:h===""?_v:Rv),f)}function Mv(c,r){return c.length===r.length&&c.slice(0,-1).every((f,d)=>f===r[d])?c[c.length-1]-r[r.length-1]:0}function Nv(c,r,o=!1){let{routesMeta:f}=c,d={},h="/",p=[];for(let _=0;_<f.length;++_){let S=f[_],y=_===f.length-1,N=h==="/"?r:r.slice(h.length)||"/",R=qn({path:S.relativePath,caseSensitive:S.caseSensitive,end:y},N),B=S.route;if(!R&&y&&o&&!f[f.length-1].route.index&&(R=qn({path:S.relativePath,caseSensitive:S.caseSensitive,end:!1},N)),!R)return null;Object.assign(d,R.params),p.push({params:d,pathname:nl([h,R.pathname]),pathnameBase:Hv(nl([h,R.pathnameBase])),route:B}),R.pathnameBase!=="/"&&(h=nl([h,R.pathnameBase]))}return p}function qn(c,r){typeof c=="string"&&(c={path:c,caseSensitive:!1,end:!0});let[o,f]=Cv(c.path,c.caseSensitive,c.end),d=r.match(o);if(!d)return null;let h=d[0],p=h.replace(/(.)\/+$/,"$1"),_=d.slice(1);return{params:f.reduce((y,{paramName:N,isOptional:R},B)=>{if(N==="*"){let $=_[B]||"";p=h.slice(0,h.length-$.length).replace(/(.)\/+$/,"$1")}const K=_[B];return R&&!K?y[N]=void 0:y[N]=(K||"").replace(/%2F/g,"/"),y},{}),pathname:h,pathnameBase:p,pattern:c}}function Cv(c,r=!1,o=!0){Se(c==="*"||!c.endsWith("*")||c.endsWith("/*"),`Route path "${c}" will be treated as if it were "${c.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${c.replace(/\*$/,"/*")}".`);let f=[],d="^"+c.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(p,_,S)=>(f.push({paramName:_,isOptional:S!=null}),S?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return c.endsWith("*")?(f.push({paramName:"*"}),d+=c==="*"||c==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):o?d+="\\/*$":c!==""&&c!=="/"&&(d+="(?:(?=\\/|$))"),[new RegExp(d,r?void 0:"i"),f]}function ph(c){try{return c.split("/").map(r=>decodeURIComponent(r).replace(/\//g,"%2F")).join("/")}catch(r){return Se(!1,`The URL path "${c}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${r}).`),c}}function ul(c,r){if(r==="/")return c;if(!c.toLowerCase().startsWith(r.toLowerCase()))return null;let o=r.endsWith("/")?r.length-1:r.length,f=c.charAt(o);return f&&f!=="/"?null:c.slice(o)||"/"}var Dv=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Uv(c,r="/"){let{pathname:o,search:f="",hash:d=""}=typeof c=="string"?Il(c):c,h;return o?(o=o.replace(/\/\/+/g,"/"),o.startsWith("/")?h=dh(o.substring(1),"/"):h=dh(o,r)):h=r,{pathname:h,search:Bv(f),hash:qv(d)}}function dh(c,r){let o=r.replace(/\/+$/,"").split("/");return c.split("/").forEach(d=>{d===".."?o.length>1&&o.pop():d!=="."&&o.push(d)}),o.length>1?o.join("/"):"/"}function Hf(c,r,o,f){return`Cannot include a '${c}' character in a manually specified \`to.${r}\` field [${JSON.stringify(f)}]. Please separate it out to the \`to.${o}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function jv(c){return c.filter((r,o)=>o===0||r.route.path&&r.route.path.length>0)}function Vf(c){let r=jv(c);return r.map((o,f)=>f===r.length-1?o.pathname:o.pathnameBase)}function wf(c,r,o,f=!1){let d;typeof c=="string"?d=Il(c):(d={...c},Ct(!d.pathname||!d.pathname.includes("?"),Hf("?","pathname","search",d)),Ct(!d.pathname||!d.pathname.includes("#"),Hf("#","pathname","hash",d)),Ct(!d.search||!d.search.includes("#"),Hf("#","search","hash",d)));let h=c===""||d.pathname==="",p=h?"/":d.pathname,_;if(p==null)_=o;else{let R=r.length-1;if(!f&&p.startsWith("..")){let B=p.split("/");for(;B[0]==="..";)B.shift(),R-=1;d.pathname=B.join("/")}_=R>=0?r[R]:"/"}let S=Uv(d,_),y=p&&p!=="/"&&p.endsWith("/"),N=(h||p===".")&&o.endsWith("/");return!S.pathname.endsWith("/")&&(y||N)&&(S.pathname+="/"),S}var nl=c=>c.join("/").replace(/\/\/+/g,"/"),Hv=c=>c.replace(/\/+$/,"").replace(/^\/*/,"/"),Bv=c=>!c||c==="?"?"":c.startsWith("?")?c:"?"+c,qv=c=>!c||c==="#"?"":c.startsWith("#")?c:"#"+c,Lv=class{constructor(c,r,o,f=!1){this.status=c,this.statusText=r||"",this.internal=f,o instanceof Error?(this.data=o.toString(),this.error=o):this.data=o}};function Yv(c){return c!=null&&typeof c.status=="number"&&typeof c.statusText=="string"&&typeof c.internal=="boolean"&&"data"in c}function Gv(c){return c.map(r=>r.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var Sh=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function bh(c,r){let o=c;if(typeof o!="string"||!Dv.test(o))return{absoluteURL:void 0,isExternal:!1,to:o};let f=o,d=!1;if(Sh)try{let h=new URL(window.location.href),p=o.startsWith("//")?new URL(h.protocol+o):new URL(o),_=ul(p.pathname,r);p.origin===h.origin&&_!=null?o=_+p.search+p.hash:d=!0}catch{Se(!1,`<Link to="${o}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:f,isExternal:d,to:o}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Eh=["POST","PUT","PATCH","DELETE"];new Set(Eh);var Xv=["GET",...Eh];new Set(Xv);var La=E.createContext(null);La.displayName="DataRouter";var fi=E.createContext(null);fi.displayName="DataRouterState";var Qv=E.createContext(!1),Th=E.createContext({isTransitioning:!1});Th.displayName="ViewTransition";var Zv=E.createContext(new Map);Zv.displayName="Fetchers";var Vv=E.createContext(null);Vv.displayName="Await";var be=E.createContext(null);be.displayName="Navigation";var Ln=E.createContext(null);Ln.displayName="Location";var He=E.createContext({outlet:null,matches:[],isDataRoute:!1});He.displayName="Route";var Kf=E.createContext(null);Kf.displayName="RouteError";var zh="REACT_ROUTER_ERROR",wv="REDIRECT",Kv="ROUTE_ERROR_RESPONSE";function Jv(c){if(c.startsWith(`${zh}:${wv}:{`))try{let r=JSON.parse(c.slice(28));if(typeof r=="object"&&r&&typeof r.status=="number"&&typeof r.statusText=="string"&&typeof r.location=="string"&&typeof r.reloadDocument=="boolean"&&typeof r.replace=="boolean")return r}catch{}}function $v(c){if(c.startsWith(`${zh}:${Kv}:{`))try{let r=JSON.parse(c.slice(40));if(typeof r=="object"&&r&&typeof r.status=="number"&&typeof r.statusText=="string")return new Lv(r.status,r.statusText,r.data)}catch{}}function kv(c,{relative:r}={}){Ct(Pl(),"useHref() may be used only in the context of a <Router> component.");let{basename:o,navigator:f}=E.useContext(be),{hash:d,pathname:h,search:p}=Gn(c,{relative:r}),_=h;return o!=="/"&&(_=h==="/"?o:nl([o,h])),f.createHref({pathname:_,search:p,hash:d})}function Pl(){return E.useContext(Ln)!=null}function Ce(){return Ct(Pl(),"useLocation() may be used only in the context of a <Router> component."),E.useContext(Ln).location}function Bf(c){Ct(Pl(),"useMatch() may be used only in the context of a <Router> component.");let{pathname:r}=Ce();return E.useMemo(()=>qn(c,ph(r)),[r,c])}var Ah="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function _h(c){E.useContext(be).static||E.useLayoutEffect(c)}function Yn(){let{isDataRoute:c}=E.useContext(He);return c?s0():Fv()}function Fv(){Ct(Pl(),"useNavigate() may be used only in the context of a <Router> component.");let c=E.useContext(La),{basename:r,navigator:o}=E.useContext(be),{matches:f}=E.useContext(He),{pathname:d}=Ce(),h=JSON.stringify(Vf(f)),p=E.useRef(!1);return _h(()=>{p.current=!0}),E.useCallback((S,y={})=>{if(Se(p.current,Ah),!p.current)return;if(typeof S=="number"){o.go(S);return}let N=wf(S,JSON.parse(h),d,y.relative==="path");c==null&&r!=="/"&&(N.pathname=N.pathname==="/"?r:nl([r,N.pathname])),(y.replace?o.replace:o.push)(N,y.state,y)},[r,o,h,d,c])}E.createContext(null);function Wv(){let{matches:c}=E.useContext(He),r=c[c.length-1];return r?r.params:{}}function Gn(c,{relative:r}={}){let{matches:o}=E.useContext(He),{pathname:f}=Ce(),d=JSON.stringify(Vf(o));return E.useMemo(()=>wf(c,JSON.parse(d),f,r==="path"),[c,d,f,r])}function Iv(c,r){return Rh(c,r)}function Rh(c,r,o,f,d){Ct(Pl(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:h}=E.useContext(be),{matches:p}=E.useContext(He),_=p[p.length-1],S=_?_.params:{},y=_?_.pathname:"/",N=_?_.pathnameBase:"/",R=_&&_.route;{let q=R&&R.path||"";xh(y,!R||q.endsWith("*")||q.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${y}" (under <Route path="${q}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. - -Please change the parent <Route path="${q}"> to <Route path="${q==="/"?"*":`${q}/*`}">.`)}let B=Ce(),K;if(r){let q=typeof r=="string"?Il(r):r;Ct(N==="/"||q.pathname?.startsWith(N),`When overriding the location using \`<Routes location>\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${N}" but pathname "${q.pathname}" was given in the \`location\` prop.`),K=q}else K=B;let $=K.pathname||"/",Q=$;if(N!=="/"){let q=N.replace(/^\//,"").split("/");Q="/"+$.replace(/^\//,"").split("/").slice(q.length).join("/")}let X=yh(c,{pathname:Q});Se(R||X!=null,`No routes matched location "${K.pathname}${K.search}${K.hash}" `),Se(X==null||X[X.length-1].route.element!==void 0||X[X.length-1].route.Component!==void 0||X[X.length-1].route.lazy!==void 0,`Matched leaf route at location "${K.pathname}${K.search}${K.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`);let H=a0(X&&X.map(q=>Object.assign({},q,{params:Object.assign({},S,q.params),pathname:nl([N,h.encodeLocation?h.encodeLocation(q.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:q.pathname]),pathnameBase:q.pathnameBase==="/"?N:nl([N,h.encodeLocation?h.encodeLocation(q.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:q.pathnameBase])})),p,o,f,d);return r&&H?E.createElement(Ln.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...K},navigationType:"POP"}},H):H}function Pv(){let c=f0(),r=Yv(c)?`${c.status} ${c.statusText}`:c instanceof Error?c.message:JSON.stringify(c),o=c instanceof Error?c.stack:null,f="rgba(200,200,200, 0.5)",d={padding:"0.5rem",backgroundColor:f},h={padding:"2px 4px",backgroundColor:f},p=null;return console.error("Error handled by React Router default ErrorBoundary:",c),p=E.createElement(E.Fragment,null,E.createElement("p",null,"💿 Hey developer 👋"),E.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",E.createElement("code",{style:h},"ErrorBoundary")," or"," ",E.createElement("code",{style:h},"errorElement")," prop on your route.")),E.createElement(E.Fragment,null,E.createElement("h2",null,"Unexpected Application Error!"),E.createElement("h3",{style:{fontStyle:"italic"}},r),o?E.createElement("pre",{style:d},o):null,p)}var t0=E.createElement(Pv,null),Oh=class extends E.Component{constructor(c){super(c),this.state={location:c.location,revalidation:c.revalidation,error:c.error}}static getDerivedStateFromError(c){return{error:c}}static getDerivedStateFromProps(c,r){return r.location!==c.location||r.revalidation!=="idle"&&c.revalidation==="idle"?{error:c.error,location:c.location,revalidation:c.revalidation}:{error:c.error!==void 0?c.error:r.error,location:r.location,revalidation:c.revalidation||r.revalidation}}componentDidCatch(c,r){this.props.onError?this.props.onError(c,r):console.error("React Router caught the following error during render",c)}render(){let c=this.state.error;if(this.context&&typeof c=="object"&&c&&"digest"in c&&typeof c.digest=="string"){const o=$v(c.digest);o&&(c=o)}let r=c!==void 0?E.createElement(He.Provider,{value:this.props.routeContext},E.createElement(Kf.Provider,{value:c,children:this.props.component})):this.props.children;return this.context?E.createElement(e0,{error:c},r):r}};Oh.contextType=Qv;var qf=new WeakMap;function e0({children:c,error:r}){let{basename:o}=E.useContext(be);if(typeof r=="object"&&r&&"digest"in r&&typeof r.digest=="string"){let f=Jv(r.digest);if(f){let d=qf.get(r);if(d)throw d;let h=bh(f.location,o);if(Sh&&!qf.get(r))if(h.isExternal||f.reloadDocument)window.location.href=h.absoluteURL||h.to;else{const p=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(h.to,{replace:f.replace}));throw qf.set(r,p),p}return E.createElement("meta",{httpEquiv:"refresh",content:`0;url=${h.absoluteURL||h.to}`})}}return c}function l0({routeContext:c,match:r,children:o}){let f=E.useContext(La);return f&&f.static&&f.staticContext&&(r.route.errorElement||r.route.ErrorBoundary)&&(f.staticContext._deepestRenderedBoundaryId=r.route.id),E.createElement(He.Provider,{value:c},o)}function a0(c,r=[],o=null,f=null,d=null){if(c==null){if(!o)return null;if(o.errors)c=o.matches;else if(r.length===0&&!o.initialized&&o.matches.length>0)c=o.matches;else return null}let h=c,p=o?.errors;if(p!=null){let N=h.findIndex(R=>R.route.id&&p?.[R.route.id]!==void 0);Ct(N>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(p).join(",")}`),h=h.slice(0,Math.min(h.length,N+1))}let _=!1,S=-1;if(o)for(let N=0;N<h.length;N++){let R=h[N];if((R.route.HydrateFallback||R.route.hydrateFallbackElement)&&(S=N),R.route.id){let{loaderData:B,errors:K}=o,$=R.route.loader&&!B.hasOwnProperty(R.route.id)&&(!K||K[R.route.id]===void 0);if(R.route.lazy||$){_=!0,S>=0?h=h.slice(0,S+1):h=[h[0]];break}}}let y=o&&f?(N,R)=>{f(N,{location:o.location,params:o.matches?.[0]?.params??{},unstable_pattern:Gv(o.matches),errorInfo:R})}:void 0;return h.reduceRight((N,R,B)=>{let K,$=!1,Q=null,X=null;o&&(K=p&&R.route.id?p[R.route.id]:void 0,Q=R.route.errorElement||t0,_&&(S<0&&B===0?(xh("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),$=!0,X=null):S===B&&($=!0,X=R.route.hydrateFallbackElement||null)));let H=r.concat(h.slice(0,B+1)),q=()=>{let G;return K?G=Q:$?G=X:R.route.Component?G=E.createElement(R.route.Component,null):R.route.element?G=R.route.element:G=N,E.createElement(l0,{match:R,routeContext:{outlet:N,matches:H,isDataRoute:o!=null},children:G})};return o&&(R.route.ErrorBoundary||R.route.errorElement||B===0)?E.createElement(Oh,{location:o.location,revalidation:o.revalidation,component:Q,error:K,children:q(),routeContext:{outlet:null,matches:H,isDataRoute:!0},onError:y}):q()},null)}function Jf(c){return`${c} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function n0(c){let r=E.useContext(La);return Ct(r,Jf(c)),r}function u0(c){let r=E.useContext(fi);return Ct(r,Jf(c)),r}function i0(c){let r=E.useContext(He);return Ct(r,Jf(c)),r}function $f(c){let r=i0(c),o=r.matches[r.matches.length-1];return Ct(o.route.id,`${c} can only be used on routes that contain a unique "id"`),o.route.id}function c0(){return $f("useRouteId")}function f0(){let c=E.useContext(Kf),r=u0("useRouteError"),o=$f("useRouteError");return c!==void 0?c:r.errors?.[o]}function s0(){let{router:c}=n0("useNavigate"),r=$f("useNavigate"),o=E.useRef(!1);return _h(()=>{o.current=!0}),E.useCallback(async(d,h={})=>{Se(o.current,Ah),o.current&&(typeof d=="number"?await c.navigate(d):await c.navigate(d,{fromRouteId:r,...h}))},[c,r])}var hh={};function xh(c,r,o){!r&&!hh[c]&&(hh[c]=!0,Se(!1,o))}E.memo(r0);function r0({routes:c,future:r,state:o,onError:f}){return Rh(c,void 0,o,f,r)}function o0({to:c,replace:r,state:o,relative:f}){Ct(Pl(),"<Navigate> may be used only in the context of a <Router> component.");let{static:d}=E.useContext(be);Se(!d,"<Navigate> must not be used on the initial render in a <StaticRouter>. This is a no-op, but you should modify your code so the <Navigate> is only ever rendered in response to some user interaction or state change.");let{matches:h}=E.useContext(He),{pathname:p}=Ce(),_=Yn(),S=wf(c,Vf(h),p,f==="path"),y=JSON.stringify(S);return E.useEffect(()=>{_(JSON.parse(y),{replace:r,state:o,relative:f})},[_,y,f,r,o]),null}function Wl(c){Ct(!1,"A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.")}function d0({basename:c="/",children:r=null,location:o,navigationType:f="POP",navigator:d,static:h=!1,unstable_useTransitions:p}){Ct(!Pl(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let _=c.replace(/^\/*/,"/"),S=E.useMemo(()=>({basename:_,navigator:d,static:h,unstable_useTransitions:p,future:{}}),[_,d,h,p]);typeof o=="string"&&(o=Il(o));let{pathname:y="/",search:N="",hash:R="",state:B=null,key:K="default"}=o,$=E.useMemo(()=>{let Q=ul(y,_);return Q==null?null:{location:{pathname:Q,search:N,hash:R,state:B,key:K},navigationType:f}},[_,y,N,R,B,K,f]);return Se($!=null,`<Router basename="${_}"> is not able to match the URL "${y}${N}${R}" because it does not start with the basename, so the <Router> won't render anything.`),$==null?null:E.createElement(be.Provider,{value:S},E.createElement(Ln.Provider,{children:r,value:$}))}function Mh({children:c,location:r}){return Iv(Xf(c),r)}function Xf(c,r=[]){let o=[];return E.Children.forEach(c,(f,d)=>{if(!E.isValidElement(f))return;let h=[...r,d];if(f.type===E.Fragment){o.push.apply(o,Xf(f.props.children,h));return}Ct(f.type===Wl,`[${typeof f.type=="string"?f.type:f.type.name}] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>`),Ct(!f.props.index||!f.props.children,"An index route cannot have child routes.");let p={id:f.props.id||h.join("-"),caseSensitive:f.props.caseSensitive,element:f.props.element,Component:f.props.Component,index:f.props.index,path:f.props.path,middleware:f.props.middleware,loader:f.props.loader,action:f.props.action,hydrateFallbackElement:f.props.hydrateFallbackElement,HydrateFallback:f.props.HydrateFallback,errorElement:f.props.errorElement,ErrorBoundary:f.props.ErrorBoundary,hasErrorBoundary:f.props.hasErrorBoundary===!0||f.props.ErrorBoundary!=null||f.props.errorElement!=null,shouldRevalidate:f.props.shouldRevalidate,handle:f.props.handle,lazy:f.props.lazy};f.props.children&&(p.children=Xf(f.props.children,h)),o.push(p)}),o}var ii="get",ci="application/x-www-form-urlencoded";function si(c){return typeof HTMLElement<"u"&&c instanceof HTMLElement}function h0(c){return si(c)&&c.tagName.toLowerCase()==="button"}function m0(c){return si(c)&&c.tagName.toLowerCase()==="form"}function y0(c){return si(c)&&c.tagName.toLowerCase()==="input"}function v0(c){return!!(c.metaKey||c.altKey||c.ctrlKey||c.shiftKey)}function g0(c,r){return c.button===0&&(!r||r==="_self")&&!v0(c)}function Qf(c=""){return new URLSearchParams(typeof c=="string"||Array.isArray(c)||c instanceof URLSearchParams?c:Object.keys(c).reduce((r,o)=>{let f=c[o];return r.concat(Array.isArray(f)?f.map(d=>[o,d]):[[o,f]])},[]))}function p0(c,r){let o=Qf(c);return r&&r.forEach((f,d)=>{o.has(d)||r.getAll(d).forEach(h=>{o.append(d,h)})}),o}var ui=null;function S0(){if(ui===null)try{new FormData(document.createElement("form"),0),ui=!1}catch{ui=!0}return ui}var b0=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Lf(c){return c!=null&&!b0.has(c)?(Se(!1,`"${c}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${ci}"`),null):c}function E0(c,r){let o,f,d,h,p;if(m0(c)){let _=c.getAttribute("action");f=_?ul(_,r):null,o=c.getAttribute("method")||ii,d=Lf(c.getAttribute("enctype"))||ci,h=new FormData(c)}else if(h0(c)||y0(c)&&(c.type==="submit"||c.type==="image")){let _=c.form;if(_==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let S=c.getAttribute("formaction")||_.getAttribute("action");if(f=S?ul(S,r):null,o=c.getAttribute("formmethod")||_.getAttribute("method")||ii,d=Lf(c.getAttribute("formenctype"))||Lf(_.getAttribute("enctype"))||ci,h=new FormData(_,c),!S0()){let{name:y,type:N,value:R}=c;if(N==="image"){let B=y?`${y}.`:"";h.append(`${B}x`,"0"),h.append(`${B}y`,"0")}else y&&h.append(y,R)}}else{if(si(c))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');o=ii,f=null,d=ci,p=c}return h&&d==="text/plain"&&(p=h,h=void 0),{action:f,method:o.toLowerCase(),encType:d,formData:h,body:p}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function kf(c,r){if(c===!1||c===null||typeof c>"u")throw new Error(r)}function T0(c,r,o,f){let d=typeof c=="string"?new URL(c,typeof window>"u"?"server://singlefetch/":window.location.origin):c;return o?d.pathname.endsWith("/")?d.pathname=`${d.pathname}_.${f}`:d.pathname=`${d.pathname}.${f}`:d.pathname==="/"?d.pathname=`_root.${f}`:r&&ul(d.pathname,r)==="/"?d.pathname=`${r.replace(/\/$/,"")}/_root.${f}`:d.pathname=`${d.pathname.replace(/\/$/,"")}.${f}`,d}async function z0(c,r){if(c.id in r)return r[c.id];try{let o=await import(c.module);return r[c.id]=o,o}catch(o){return console.error(`Error loading route module \`${c.module}\`, reloading page...`),console.error(o),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function A0(c){return c==null?!1:c.href==null?c.rel==="preload"&&typeof c.imageSrcSet=="string"&&typeof c.imageSizes=="string":typeof c.rel=="string"&&typeof c.href=="string"}async function _0(c,r,o){let f=await Promise.all(c.map(async d=>{let h=r.routes[d.route.id];if(h){let p=await z0(h,o);return p.links?p.links():[]}return[]}));return M0(f.flat(1).filter(A0).filter(d=>d.rel==="stylesheet"||d.rel==="preload").map(d=>d.rel==="stylesheet"?{...d,rel:"prefetch",as:"style"}:{...d,rel:"prefetch"}))}function mh(c,r,o,f,d,h){let p=(S,y)=>o[y]?S.route.id!==o[y].route.id:!0,_=(S,y)=>o[y].pathname!==S.pathname||o[y].route.path?.endsWith("*")&&o[y].params["*"]!==S.params["*"];return h==="assets"?r.filter((S,y)=>p(S,y)||_(S,y)):h==="data"?r.filter((S,y)=>{let N=f.routes[S.route.id];if(!N||!N.hasLoader)return!1;if(p(S,y)||_(S,y))return!0;if(S.route.shouldRevalidate){let R=S.route.shouldRevalidate({currentUrl:new URL(d.pathname+d.search+d.hash,window.origin),currentParams:o[0]?.params||{},nextUrl:new URL(c,window.origin),nextParams:S.params,defaultShouldRevalidate:!0});if(typeof R=="boolean")return R}return!0}):[]}function R0(c,r,{includeHydrateFallback:o}={}){return O0(c.map(f=>{let d=r.routes[f.route.id];if(!d)return[];let h=[d.module];return d.clientActionModule&&(h=h.concat(d.clientActionModule)),d.clientLoaderModule&&(h=h.concat(d.clientLoaderModule)),o&&d.hydrateFallbackModule&&(h=h.concat(d.hydrateFallbackModule)),d.imports&&(h=h.concat(d.imports)),h}).flat(1))}function O0(c){return[...new Set(c)]}function x0(c){let r={},o=Object.keys(c).sort();for(let f of o)r[f]=c[f];return r}function M0(c,r){let o=new Set;return new Set(r),c.reduce((f,d)=>{let h=JSON.stringify(x0(d));return o.has(h)||(o.add(h),f.push({key:h,link:d})),f},[])}function Nh(){let c=E.useContext(La);return kf(c,"You must render this element inside a <DataRouterContext.Provider> element"),c}function N0(){let c=E.useContext(fi);return kf(c,"You must render this element inside a <DataRouterStateContext.Provider> element"),c}var Ff=E.createContext(void 0);Ff.displayName="FrameworkContext";function Ch(){let c=E.useContext(Ff);return kf(c,"You must render this element inside a <HydratedRouter> element"),c}function C0(c,r){let o=E.useContext(Ff),[f,d]=E.useState(!1),[h,p]=E.useState(!1),{onFocus:_,onBlur:S,onMouseEnter:y,onMouseLeave:N,onTouchStart:R}=r,B=E.useRef(null);E.useEffect(()=>{if(c==="render"&&p(!0),c==="viewport"){let Q=H=>{H.forEach(q=>{p(q.isIntersecting)})},X=new IntersectionObserver(Q,{threshold:.5});return B.current&&X.observe(B.current),()=>{X.disconnect()}}},[c]),E.useEffect(()=>{if(f){let Q=setTimeout(()=>{p(!0)},100);return()=>{clearTimeout(Q)}}},[f]);let K=()=>{d(!0)},$=()=>{d(!1),p(!1)};return o?c!=="intent"?[h,B,{}]:[h,B,{onFocus:Hn(_,K),onBlur:Hn(S,$),onMouseEnter:Hn(y,K),onMouseLeave:Hn(N,$),onTouchStart:Hn(R,K)}]:[!1,B,{}]}function Hn(c,r){return o=>{c&&c(o),o.defaultPrevented||r(o)}}function D0({page:c,...r}){let{router:o}=Nh(),f=E.useMemo(()=>yh(o.routes,c,o.basename),[o.routes,c,o.basename]);return f?E.createElement(j0,{page:c,matches:f,...r}):null}function U0(c){let{manifest:r,routeModules:o}=Ch(),[f,d]=E.useState([]);return E.useEffect(()=>{let h=!1;return _0(c,r,o).then(p=>{h||d(p)}),()=>{h=!0}},[c,r,o]),f}function j0({page:c,matches:r,...o}){let f=Ce(),{future:d,manifest:h,routeModules:p}=Ch(),{basename:_}=Nh(),{loaderData:S,matches:y}=N0(),N=E.useMemo(()=>mh(c,r,y,h,f,"data"),[c,r,y,h,f]),R=E.useMemo(()=>mh(c,r,y,h,f,"assets"),[c,r,y,h,f]),B=E.useMemo(()=>{if(c===f.pathname+f.search+f.hash)return[];let Q=new Set,X=!1;if(r.forEach(q=>{let G=h.routes[q.route.id];!G||!G.hasLoader||(!N.some(dt=>dt.route.id===q.route.id)&&q.route.id in S&&p[q.route.id]?.shouldRevalidate||G.hasClientLoader?X=!0:Q.add(q.route.id))}),Q.size===0)return[];let H=T0(c,_,d.unstable_trailingSlashAwareDataRequests,"data");return X&&Q.size>0&&H.searchParams.set("_routes",r.filter(q=>Q.has(q.route.id)).map(q=>q.route.id).join(",")),[H.pathname+H.search]},[_,d.unstable_trailingSlashAwareDataRequests,S,f,h,N,r,c,p]),K=E.useMemo(()=>R0(R,h),[R,h]),$=U0(R);return E.createElement(E.Fragment,null,B.map(Q=>E.createElement("link",{key:Q,rel:"prefetch",as:"fetch",href:Q,...o})),K.map(Q=>E.createElement("link",{key:Q,rel:"modulepreload",href:Q,...o})),$.map(({key:Q,link:X})=>E.createElement("link",{key:Q,nonce:o.nonce,...X,crossOrigin:X.crossOrigin??o.crossOrigin})))}function H0(...c){return r=>{c.forEach(o=>{typeof o=="function"?o(r):o!=null&&(o.current=r)})}}var B0=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{B0&&(window.__reactRouterVersion="7.13.0")}catch{}function q0({basename:c,children:r,unstable_useTransitions:o,window:f}){let d=E.useRef();d.current==null&&(d.current=vv({window:f,v5Compat:!0}));let h=d.current,[p,_]=E.useState({action:h.action,location:h.location}),S=E.useCallback(y=>{o===!1?_(y):E.startTransition(()=>_(y))},[o]);return E.useLayoutEffect(()=>h.listen(S),[h,S]),E.createElement(d0,{basename:c,children:r,location:p.location,navigationType:p.action,navigator:h,unstable_useTransitions:o})}var Dh=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Cl=E.forwardRef(function({onClick:r,discover:o="render",prefetch:f="none",relative:d,reloadDocument:h,replace:p,state:_,target:S,to:y,preventScrollReset:N,viewTransition:R,unstable_defaultShouldRevalidate:B,...K},$){let{basename:Q,unstable_useTransitions:X}=E.useContext(be),H=typeof y=="string"&&Dh.test(y),q=bh(y,Q);y=q.to;let G=kv(y,{relative:d}),[dt,mt,St]=C0(f,K),et=X0(y,{replace:p,state:_,target:S,preventScrollReset:N,relative:d,viewTransition:R,unstable_defaultShouldRevalidate:B,unstable_useTransitions:X});function xt(Yt){r&&r(Yt),Yt.defaultPrevented||et(Yt)}let Rt=E.createElement("a",{...K,...St,href:q.absoluteURL||G,onClick:q.isExternal||h?r:xt,ref:H0($,mt),target:S,"data-discover":!H&&o==="render"?"true":void 0});return dt&&!H?E.createElement(E.Fragment,null,Rt,E.createElement(D0,{page:G})):Rt});Cl.displayName="Link";var L0=E.forwardRef(function({"aria-current":r="page",caseSensitive:o=!1,className:f="",end:d=!1,style:h,to:p,viewTransition:_,children:S,...y},N){let R=Gn(p,{relative:y.relative}),B=Ce(),K=E.useContext(fi),{navigator:$,basename:Q}=E.useContext(be),X=K!=null&&K0(R)&&_===!0,H=$.encodeLocation?$.encodeLocation(R).pathname:R.pathname,q=B.pathname,G=K&&K.navigation&&K.navigation.location?K.navigation.location.pathname:null;o||(q=q.toLowerCase(),G=G?G.toLowerCase():null,H=H.toLowerCase()),G&&Q&&(G=ul(G,Q)||G);const dt=H!=="/"&&H.endsWith("/")?H.length-1:H.length;let mt=q===H||!d&&q.startsWith(H)&&q.charAt(dt)==="/",St=G!=null&&(G===H||!d&&G.startsWith(H)&&G.charAt(H.length)==="/"),et={isActive:mt,isPending:St,isTransitioning:X},xt=mt?r:void 0,Rt;typeof f=="function"?Rt=f(et):Rt=[f,mt?"active":null,St?"pending":null,X?"transitioning":null].filter(Boolean).join(" ");let Yt=typeof h=="function"?h(et):h;return E.createElement(Cl,{...y,"aria-current":xt,className:Rt,ref:N,style:Yt,to:p,viewTransition:_},typeof S=="function"?S(et):S)});L0.displayName="NavLink";var Y0=E.forwardRef(({discover:c="render",fetcherKey:r,navigate:o,reloadDocument:f,replace:d,state:h,method:p=ii,action:_,onSubmit:S,relative:y,preventScrollReset:N,viewTransition:R,unstable_defaultShouldRevalidate:B,...K},$)=>{let{unstable_useTransitions:Q}=E.useContext(be),X=V0(),H=w0(_,{relative:y}),q=p.toLowerCase()==="get"?"get":"post",G=typeof _=="string"&&Dh.test(_),dt=mt=>{if(S&&S(mt),mt.defaultPrevented)return;mt.preventDefault();let St=mt.nativeEvent.submitter,et=St?.getAttribute("formmethod")||p,xt=()=>X(St||mt.currentTarget,{fetcherKey:r,method:et,navigate:o,replace:d,state:h,relative:y,preventScrollReset:N,viewTransition:R,unstable_defaultShouldRevalidate:B});Q&&o!==!1?E.startTransition(()=>xt()):xt()};return E.createElement("form",{ref:$,method:q,action:H,onSubmit:f?S:dt,...K,"data-discover":!G&&c==="render"?"true":void 0})});Y0.displayName="Form";function G0(c){return`${c} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Uh(c){let r=E.useContext(La);return Ct(r,G0(c)),r}function X0(c,{target:r,replace:o,state:f,preventScrollReset:d,relative:h,viewTransition:p,unstable_defaultShouldRevalidate:_,unstable_useTransitions:S}={}){let y=Yn(),N=Ce(),R=Gn(c,{relative:h});return E.useCallback(B=>{if(g0(B,r)){B.preventDefault();let K=o!==void 0?o:Bn(N)===Bn(R),$=()=>y(c,{replace:K,state:f,preventScrollReset:d,relative:h,viewTransition:p,unstable_defaultShouldRevalidate:_});S?E.startTransition(()=>$()):$()}},[N,y,R,o,f,r,c,d,h,p,_,S])}function jh(c){Se(typeof URLSearchParams<"u","You cannot use the `useSearchParams` hook in a browser that does not support the URLSearchParams API. If you need to support Internet Explorer 11, we recommend you load a polyfill such as https://github.com/ungap/url-search-params.");let r=E.useRef(Qf(c)),o=E.useRef(!1),f=Ce(),d=E.useMemo(()=>p0(f.search,o.current?null:r.current),[f.search]),h=Yn(),p=E.useCallback((_,S)=>{const y=Qf(typeof _=="function"?_(new URLSearchParams(d)):_);o.current=!0,h("?"+y,S)},[h,d]);return[d,p]}var Q0=0,Z0=()=>`__${String(++Q0)}__`;function V0(){let{router:c}=Uh("useSubmit"),{basename:r}=E.useContext(be),o=c0(),f=c.fetch,d=c.navigate;return E.useCallback(async(h,p={})=>{let{action:_,method:S,encType:y,formData:N,body:R}=E0(h,r);if(p.navigate===!1){let B=p.fetcherKey||Z0();await f(B,o,p.action||_,{unstable_defaultShouldRevalidate:p.unstable_defaultShouldRevalidate,preventScrollReset:p.preventScrollReset,formData:N,body:R,formMethod:p.method||S,formEncType:p.encType||y,flushSync:p.flushSync})}else await d(p.action||_,{unstable_defaultShouldRevalidate:p.unstable_defaultShouldRevalidate,preventScrollReset:p.preventScrollReset,formData:N,body:R,formMethod:p.method||S,formEncType:p.encType||y,replace:p.replace,state:p.state,fromRouteId:o,flushSync:p.flushSync,viewTransition:p.viewTransition})},[f,d,r,o])}function w0(c,{relative:r}={}){let{basename:o}=E.useContext(be),f=E.useContext(He);Ct(f,"useFormAction must be used inside a RouteContext");let[d]=f.matches.slice(-1),h={...Gn(c||".",{relative:r})},p=Ce();if(c==null){h.search=p.search;let _=new URLSearchParams(h.search),S=_.getAll("index");if(S.some(N=>N==="")){_.delete("index"),S.filter(R=>R).forEach(R=>_.append("index",R));let N=_.toString();h.search=N?`?${N}`:""}}return(!c||c===".")&&d.route.index&&(h.search=h.search?h.search.replace(/^\?/,"?index&"):"?index"),o!=="/"&&(h.pathname=h.pathname==="/"?o:nl([o,h.pathname])),Bn(h)}function K0(c,{relative:r}={}){let o=E.useContext(Th);Ct(o!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:f}=Uh("useViewTransitionState"),d=Gn(c,{relative:r});if(!o.isTransitioning)return!1;let h=ul(o.currentLocation.pathname,f)||o.currentLocation.pathname,p=ul(o.nextLocation.pathname,f)||o.nextLocation.pathname;return qn(d.pathname,p)!=null||qn(d.pathname,h)!=null}function J0(c){const o=`; ${document.cookie}`.split(`; ${c}=`);if(o.length===2)return o.pop()?.split(";").shift()}async function fe(c,r){const o=r?.method?.toUpperCase()||"GET",f=["POST","PUT","DELETE"].includes(o),d=new Headers(r?.headers||{});if(f){const h=J0("csrf_token");h&&d.set("X-CSRF-Token",h)}return fetch(c,{...r,headers:d,credentials:"include"})}function $0(){const[c,r]=E.useState("neko"),[o,f]=E.useState(""),[d,h]=E.useState(""),p=Yn(),_=async S=>{S.preventDefault(),h("");try{const y=new URLSearchParams;y.append("username",c),y.append("password",o);const N=await fe("/api/login",{method:"POST",body:y});if(N.ok)p("/");else{const R=await N.json();h(R.message||"Login failed")}}catch{h("Network error")}};return M.jsx("div",{className:"login-container",children:M.jsxs("form",{onSubmit:_,className:"login-form",children:[M.jsx("h1",{children:"neko rss mode"}),M.jsxs("div",{className:"form-group",children:[M.jsx("label",{htmlFor:"username",children:"username"}),M.jsx("input",{id:"username",type:"text",value:c,onChange:S=>r(S.target.value)})]}),M.jsxs("div",{className:"form-group",children:[M.jsx("label",{htmlFor:"password",children:"password"}),M.jsx("input",{id:"password",type:"password",value:o,onChange:S=>f(S.target.value),autoFocus:!0})]}),d&&M.jsx("div",{className:"error-message",children:d}),M.jsx("button",{type:"submit",children:"login"})]})})}function k0({theme:c,setTheme:r,setSidebarVisible:o,isMobile:f}){const[d,h]=E.useState([]),[p,_]=E.useState([]),[S,y]=E.useState(!0),[N,R]=E.useState(""),[B,K]=E.useState(!1),[$,Q]=E.useState(!0),[X,H]=E.useState(""),q=Yn(),[G]=jh(),dt=Ce(),mt=Bf("/feed/:feedId"),St=Bf("/tag/:tagName"),xt=!!(Bf("/")||mt||St),Rt=mt?.params.feedId,Yt=St?.params.tagName,I=G.get("sidebar")||localStorage.getItem("neko-sidebar-variant")||"glass";E.useEffect(()=>{const Z=G.get("sidebar");Z&&localStorage.setItem("neko-sidebar-variant",Z)},[G]);const W=G.get("filter")||(xt?"unread":""),tt=Z=>{const v=xt?dt.pathname:"/",D=new URLSearchParams(G);return D.set("filter",Z),`${v}?${D.toString()}`},it=Z=>{const v=new URLSearchParams(G);!v.has("filter")&&W&&v.set("filter",W);const D=v.toString();return`${Z}${D?"?"+D:""}`},Ht=Z=>{if(Z.preventDefault(),X.trim()){const v=new URLSearchParams(G);v.set("q",X.trim()),W&&v.set("filter",W),q(`/?${v.toString()}`)}},x=()=>{K(!B)},L=()=>{Q(!$)},k=()=>{f&&o(!1)};if(E.useEffect(()=>{Promise.all([fe("/api/feed/").then(Z=>{if(!Z.ok)throw new Error("Failed to fetch feeds");return Z.json()}),fe("/api/tag").then(Z=>{if(!Z.ok)throw new Error("Failed to fetch tags");return Z.json()})]).then(([Z,v])=>{h(Z),_(v),y(!1)}).catch(Z=>{R(Z.message),y(!1)})},[]),S)return M.jsx("div",{className:"feed-list-loading",children:"Loading feeds..."});if(N)return M.jsxs("div",{className:"feed-list-error",children:["Error: ",N]});const yt=()=>{fe("/api/logout",{method:"POST"}).then(()=>window.location.href="/v2/#/login")};return M.jsxs("div",{className:`feed-list variant-${I}`,children:[M.jsx("h1",{className:"logo",onClick:()=>o(!1),children:"🐱"}),M.jsx("div",{className:"search-section",children:M.jsx("form",{onSubmit:Ht,className:"search-form",children:M.jsx("input",{type:"search",placeholder:"search...",value:X,onChange:Z=>H(Z.target.value),className:"search-input"})})}),M.jsx("div",{className:"filter-section",children:M.jsxs("ul",{className:"filter-list",children:[M.jsx("li",{className:"unread_filter",children:M.jsx(Cl,{to:tt("unread"),className:W==="unread"?"active":"",onClick:k,children:"unread"})}),M.jsx("li",{className:"all_filter",children:M.jsx(Cl,{to:tt("all"),className:W==="all"?"active":"",onClick:k,children:"all"})}),M.jsx("li",{className:"starred_filter",children:M.jsx(Cl,{to:tt("starred"),className:W==="starred"?"active":"",onClick:k,children:"starred"})})]})}),M.jsxs("div",{className:"tag-section",children:[M.jsxs("h4",{onClick:L,className:"section-header",children:[M.jsx("span",{className:`caret ${$?"expanded":""}`,children:"▶"})," Tags"]}),$&&M.jsx("ul",{className:"tag-list-items",children:p.map(Z=>M.jsx("li",{className:"tag-item",children:M.jsx(Cl,{to:it(`/tag/${encodeURIComponent(Z.title)}`),className:`tag-link ${Yt===Z.title?"active":""}`,onClick:k,children:Z.title})},Z.title))})]}),M.jsxs("div",{className:"feed-section",children:[M.jsxs("h4",{onClick:x,className:"section-header",children:[M.jsx("span",{className:`caret ${B?"expanded":""}`,children:"▶"})," Feeds"]}),B&&(d.length===0?M.jsx("p",{children:"No feeds found."}):M.jsx("ul",{className:"feed-list-items",children:d.map(Z=>{const v=Rt?.split(",").includes(String(Z._id)),D=Y=>{Y.preventDefault(),Y.stopPropagation();const V=Rt?Rt.split(","):[];let lt;v?lt=V.filter(ct=>ct!==String(Z._id)):lt=[...V,String(Z._id)],lt.length===0?q(it("/")):q(it(`/feed/${lt.join(",")}`))};return M.jsx("li",{className:"sidebar-feed-item",children:M.jsxs("div",{className:"feed-item-row",children:[M.jsx("input",{type:"checkbox",checked:!!v,onChange:()=>{},onClick:D,className:"feed-checkbox"}),M.jsx(Cl,{to:it(`/feed/${Z._id}`),className:`feed-title ${v?"active":""}`,onClick:k,children:Z.title||Z.url})]})},Z._id)})}))]}),M.jsx("div",{className:"nav-section",children:M.jsxs("ul",{className:"nav-list",children:[M.jsx("li",{children:M.jsx(Cl,{to:"/settings",className:"nav-link",onClick:k,children:"settings"})}),M.jsx("li",{children:M.jsx("button",{onClick:yt,className:"logout-link",children:"logout"})})]})}),M.jsx("div",{className:"theme-section",children:M.jsxs("div",{className:"theme-selector",children:[M.jsx("button",{onClick:()=>r("light"),className:c==="light"?"active":"",title:"Light Theme",children:"☀️"}),M.jsx("button",{onClick:()=>r("dark"),className:c==="dark"?"active":"",title:"Dark Theme",children:"🌙"})]})})]})}const F0=E.memo(function({item:r,onToggleStar:o,onUpdate:f}){const[d,h]=E.useState(!1),p=S=>{S.stopPropagation(),o&&o(r)},_=S=>{S.stopPropagation(),h(!0),fe(`/api/item/${r._id}`).then(y=>{if(!y.ok)throw new Error("Failed to fetch full content");return y.json()}).then(y=>{const N={...r,...y};f&&f(N),h(!1)}).catch(y=>{console.error("Error fetching full content:",y),h(!1)})};return M.jsxs("li",{className:`feed-item ${r.read?"read":"unread"} ${d?"loading":""}`,children:[M.jsxs("div",{className:"item-header",children:[M.jsx("a",{href:r.url,target:"_blank",rel:"noopener noreferrer",className:"item-title",children:r.title||"(No Title)"}),M.jsx("button",{onClick:p,className:`star-btn ${r.starred?"is-starred":"is-unstarred"}`,title:r.starred?"Unstar":"Star",children:"★"})]}),M.jsxs("div",{className:"dateline",children:[M.jsxs("a",{href:r.url,target:"_blank",rel:"noopener noreferrer",children:[new Date(r.publish_date).toLocaleDateString(),r.feed_title&&` - ${r.feed_title}`]}),M.jsx("div",{className:"item-actions",style:{display:"inline-block",float:"right"},children:!r.full_content&&M.jsx("button",{onClick:_,className:"scrape-btn",title:"Load Full Content",children:"text"})})]}),(r.full_content||r.description)&&M.jsx("div",{className:"item-description",dangerouslySetInnerHTML:{__html:r.full_content||r.description}})]})});function Yf(){const{feedId:c,tagName:r}=Wv(),[o]=jh(),f=o.get("filter")||"unread",[d,h]=E.useState([]),p=E.useRef([]),[_,S]=E.useState(!0),[y,N]=E.useState(!1),R=E.useRef(y),[B,K]=E.useState(!0),$=E.useRef(B),[Q,X]=E.useState(""),[H,q]=E.useState(-1),G=E.useRef(H);E.useEffect(()=>{p.current=d},[d]),E.useEffect(()=>{R.current=y},[y]),E.useEffect(()=>{$.current=B},[B]),E.useEffect(()=>{G.current=H},[H]);const dt=E.useCallback(I=>{I?N(!0):(S(!0),h([])),X("");let W="/api/stream";const tt=new URLSearchParams;c?c.includes(",")?tt.append("feed_ids",c):tt.append("feed_id",c):r&&tt.append("tag",r),I&&tt.append("max_id",I);const it=o.get("q");it&&tt.append("q",it),f==="all"?tt.append("read_filter","all"):f==="starred"?(tt.append("starred","true"),tt.append("read_filter","all")):it||tt.append("read_filter","unread");const Ht=tt.toString();Ht&&(W+=`?${Ht}`),fe(W).then(x=>{if(!x.ok)throw new Error("Failed to fetch items");return x.json()}).then(x=>{h(I?L=>{const k=new Set(L.map(Z=>Z._id)),yt=x.filter(Z=>!k.has(Z._id));return[...L,...yt]}:x),K(x.length>0),S(!1),N(!1)}).catch(x=>{X(x.message),S(!1),N(!1)})},[c,r,f,o]);E.useEffect(()=>{dt(),q(-1)},[dt]);const mt=E.useCallback(I=>{const W=document.getElementById(`item-${I}`);W&&W.scrollIntoView({behavior:"auto",block:"start"})},[]),St=E.useCallback(I=>{const W={...I,read:!0};h(tt=>tt.map(it=>it._id===I._id?W:it)),fe(`/api/item/${I._id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({read:!0,starred:I.starred})}).catch(tt=>console.error("Failed to mark read",tt))},[]),et=E.useCallback(I=>{const W={...I,starred:!I.starred};h(tt=>tt.map(it=>it._id===I._id?W:it)),fe(`/api/item/${I._id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({read:I.read,starred:!I.starred})}).catch(tt=>console.error("Failed to toggle star",tt))},[]),xt=E.useCallback(I=>{h(W=>W.map(tt=>tt._id===I._id?I:tt))},[]);E.useEffect(()=>{const I=W=>{const tt=p.current;if(tt.length!==0)if(W.key==="j"){const it=Math.min(G.current+1,tt.length-1);if(it!==G.current){G.current=it,q(it);const Ht=tt[it];Ht.read||St(Ht),mt(it),it===tt.length-1&&$.current&&!R.current&&dt(String(tt[tt.length-1]._id))}else $.current&&!R.current&&dt(String(tt[tt.length-1]._id))}else if(W.key==="k"){const it=Math.max(G.current-1,0);it!==G.current&&(G.current=it,q(it),mt(it))}else W.key==="s"&&G.current>=0&&G.current<tt.length&&et(tt[G.current])};return window.addEventListener("keydown",I),()=>window.removeEventListener("keydown",I)},[St,mt,et,dt]);const Rt=E.useRef(null),Yt=E.useCallback(()=>{const I=document.querySelector(".dashboard-main");if(!I)return;const W=I.getBoundingClientRect();p.current.forEach((it,Ht)=>{if(it.read)return;const x=document.getElementById(`item-${Ht}`);if(!x)return;x.getBoundingClientRect().top<W.top&&St(it)})},[St]);return E.useEffect(()=>{const I=document.querySelector(".dashboard-main");if(!I)return;let W=null;const tt=()=>{W===null&&(W=window.setTimeout(()=>{Yt(),W=null},250))};return I.addEventListener("scroll",tt),Yt(),()=>{W&&clearTimeout(W),I.removeEventListener("scroll",tt)}},[Yt]),E.useEffect(()=>{Yt()},[d,Yt]),E.useEffect(()=>{Rt.current&&Rt.current.disconnect(),Rt.current=new IntersectionObserver(W=>{W.forEach(tt=>{tt.isIntersecting&&!R.current&&$.current&&p.current.length>0&&dt(String(p.current[p.current.length-1]._id))})},{root:null,threshold:0,rootMargin:"100px"});const I=document.getElementById("load-more-sentinel");return I&&Rt.current.observe(I),()=>Rt.current?.disconnect()},[B,dt]),_?M.jsx("div",{className:"feed-items-loading",children:"Loading items..."}):Q?M.jsxs("div",{className:"feed-items-error",children:["Error: ",Q]}):M.jsx("div",{className:"feed-items",children:d.length===0?M.jsx("p",{children:"No items found."}):M.jsxs("ul",{className:"item-list",children:[d.map((I,W)=>M.jsx("div",{id:`item-${W}`,"data-index":W,"data-selected":W===H,onClick:()=>q(W),children:M.jsx(F0,{item:I,onToggleStar:()=>et(I),onUpdate:xt})},I._id)),B&&M.jsx("li",{id:"load-more-sentinel",className:"loading-more",children:y?"Loading more...":""})]})})}function W0({fontTheme:c,setFontTheme:r}){const[o,f]=E.useState([]),[d,h]=E.useState(""),[p,_]=E.useState(!1),[S,y]=E.useState(null),[N,R]=E.useState(null),B=fv.useCallback(()=>{_(!0),fe("/api/feed/").then(H=>{if(!H.ok)throw new Error("Failed to fetch feeds");return H.json()}).then(H=>{f(H),_(!1)}).catch(H=>{y(H.message),_(!1)})},[]);E.useEffect(()=>{B()},[B]);const K=H=>{H.preventDefault(),d&&(_(!0),fe("/api/feed/",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:d})}).then(q=>{if(!q.ok)throw new Error("Failed to add feed");return q.json()}).then(()=>{h(""),B()}).catch(q=>{y(q.message),_(!1)}))},$=H=>{globalThis.confirm("Are you sure you want to delete this feed?")&&(_(!0),fe(`/api/feed/${H}`,{method:"DELETE"}).then(q=>{if(!q.ok)throw new Error("Failed to delete feed");f(o.filter(G=>G._id!==H)),_(!1)}).catch(q=>{y(q.message),_(!1)}))},Q=H=>{if(H.preventDefault(),!N)return;_(!0);const q=new FormData;q.append("file",N),q.append("format","opml"),fe("/api/import",{method:"POST",body:q}).then(G=>{if(!G.ok)throw new Error("Failed to import feeds");return G.json()}).then(()=>{R(null),B(),alert("Import successful!")}).catch(G=>{y(G.message),_(!1)})},X=()=>{_(!0),fe("/api/crawl",{method:"POST"}).then(H=>{if(!H.ok)throw new Error("Failed to start crawl");return H.json()}).then(()=>{_(!1),alert("Crawl started!")}).catch(H=>{y(H.message),_(!1)})};return M.jsxs("div",{className:"settings-page variant-glass",children:[M.jsx("h2",{children:"Settings"}),r&&M.jsxs("div",{className:"appearance-section",children:[M.jsx("h3",{children:"Appearance"}),M.jsxs("div",{className:"font-selector",children:[M.jsx("label",{htmlFor:"font-theme-select",children:"Font Theme:"}),M.jsxs("select",{id:"font-theme-select",value:c||"default",onChange:H=>r(H.target.value),className:"font-select",children:[M.jsx("option",{value:"default",children:"Default"}),M.jsx("option",{value:"serif",children:"Serif"}),M.jsx("option",{value:"sans",children:"Sans-Serif"}),M.jsx("option",{value:"mono",children:"Monospace"})]})]})]}),M.jsxs("div",{className:"add-feed-section",children:[M.jsx("h3",{children:"Add New Feed"}),M.jsxs("form",{onSubmit:K,className:"add-feed-form",children:[M.jsx("input",{type:"url",value:d,onChange:H=>h(H.target.value),placeholder:"https://example.com/feed.xml",required:!0,className:"feed-input",disabled:p}),M.jsx("button",{type:"submit",disabled:p,children:"Add Feed"})]})]}),M.jsxs("div",{className:"import-export-section",children:[M.jsxs("div",{className:"import-section",children:[M.jsx("h3",{children:"Import Feeds (OPML)"}),M.jsxs("form",{onSubmit:Q,className:"import-form",children:[M.jsx("input",{type:"file",accept:".opml,.xml,.txt","aria-label":"Import Feeds",onChange:H=>R(H.target.files?.[0]||null),className:"file-input",disabled:p}),M.jsx("button",{type:"submit",disabled:!N||p,children:"Import"})]})]}),M.jsxs("div",{className:"export-section",children:[M.jsx("h3",{children:"Export Feeds"}),M.jsxs("div",{className:"export-buttons",children:[M.jsx("a",{href:"/api/export/opml",className:"export-btn",children:"OPML"}),M.jsx("a",{href:"/api/export/text",className:"export-btn",children:"Text"}),M.jsx("a",{href:"/api/export/json",className:"export-btn",children:"JSON"})]})]}),M.jsxs("div",{className:"crawl-section",children:[M.jsx("h3",{children:"Actions"}),M.jsx("button",{onClick:X,disabled:p,className:"crawl-btn",children:"Crawl All Feeds Now"})]})]}),S&&M.jsx("p",{className:"error-message",children:S}),M.jsxs("div",{className:"feed-list-section",children:[M.jsx("h3",{children:"Manage Feeds"}),p&&M.jsx("p",{children:"Loading..."}),M.jsx("ul",{className:"settings-feed-list",children:o.map(H=>M.jsxs("li",{className:"settings-feed-item",children:[M.jsxs("div",{className:"feed-info",children:[M.jsx("span",{className:"feed-title",children:H.title||"(No Title)"}),M.jsx("span",{className:"feed-url",children:H.url})]}),M.jsx("button",{onClick:()=>$(H._id),className:"delete-btn",disabled:p,title:"Delete Feed",children:"Delete"})]},H._id))})]})]})}function I0({children:c}){const[r,o]=E.useState(null),f=Ce();return E.useEffect(()=>{fe("/api/auth").then(d=>{d.ok?o(!0):o(!1)}).catch(()=>o(!1))},[]),r===null?M.jsx("div",{children:"Loading..."}):r?c:M.jsx(o0,{to:"/login",state:{from:f},replace:!0})}function P0({theme:c,setTheme:r,fontTheme:o,setFontTheme:f}){const[d,h]=E.useState(window.innerWidth>768);return E.useEffect(()=>{const p=()=>{window.innerWidth>768?h(!0):h(!1)};return window.addEventListener("resize",p),()=>window.removeEventListener("resize",p)},[]),M.jsx("div",{className:`dashboard ${d?"sidebar-visible":"sidebar-hidden"} theme-${c} font-${o}`,children:M.jsxs("div",{className:"dashboard-content",children:[(!d||window.innerWidth<=768)&&M.jsx("button",{className:"sidebar-toggle fixed-toggle",onClick:()=>h(!d),title:d?"Hide Sidebar":"Show Sidebar",children:"🐱"}),d&&M.jsx("div",{className:"sidebar-backdrop",onClick:()=>h(!1)}),M.jsx("aside",{className:`dashboard-sidebar ${d?"":"hidden"}`,children:M.jsx(k0,{theme:c,setTheme:r,setSidebarVisible:h,isMobile:window.innerWidth<=768})}),M.jsx("main",{className:"dashboard-main",children:M.jsxs(Mh,{children:[M.jsx(Wl,{path:"/feed/:feedId",element:M.jsx(Yf,{})}),M.jsx(Wl,{path:"/tag/:tagName",element:M.jsx(Yf,{})}),M.jsx(Wl,{path:"/settings",element:M.jsx(W0,{fontTheme:o,setFontTheme:f})}),M.jsx(Wl,{path:"/",element:M.jsx(Yf,{})})]})})]})})}function tg(){const[c,r]=E.useState(localStorage.getItem("neko-theme")||"light"),[o,f]=E.useState(localStorage.getItem("neko-font-theme")||"default"),d=p=>{r(p),localStorage.setItem("neko-theme",p)},h=p=>{f(p),localStorage.setItem("neko-font-theme",p)};return M.jsx(q0,{children:M.jsxs(Mh,{children:[M.jsx(Wl,{path:"/login",element:M.jsx($0,{})}),M.jsx(Wl,{path:"/*",element:M.jsx(I0,{children:M.jsx(P0,{theme:c,setTheme:d,fontTheme:o,setFontTheme:h})})})]})})}yv.createRoot(document.getElementById("root")).render(M.jsx(E.StrictMode,{children:M.jsx(tg,{})})); diff --git a/web/dist/v2/index.html b/web/dist/v2/index.html deleted file mode 100644 index b0baff7..0000000 --- a/web/dist/v2/index.html +++ /dev/null @@ -1,14 +0,0 @@ -<!doctype html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="/v2/vite.svg" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, viewport-fit=cover" /> - <title>Neko Reader</title> - <script type="module" crossorigin src="/v2/assets/index-Dh9FpypQ.js"></script> - <link rel="stylesheet" crossorigin href="/v2/assets/index-BIMig4wW.css"> - </head> - <body> - <div id="root"></div> - </body> -</html> diff --git a/web/dist/v2/vite.svg b/web/dist/v2/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/web/dist/v2/vite.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
\ No newline at end of file diff --git a/web/routing_test.go b/web/routing_test.go index a7c5c37..ce5e671 100644 --- a/web/routing_test.go +++ b/web/routing_test.go @@ -22,19 +22,13 @@ func TestRouting(t *testing.T) { containsBody string }{ { - name: "Root serves new UI", + name: "Root serves V3 UI", path: "/", method: "GET", expectedStatus: http.StatusOK, - containsBody: "<!doctype html>", // from React dist/v2 - }, - { - name: "/v2/ serves new UI", - path: "/v2/", - method: "GET", - expectedStatus: http.StatusOK, - containsBody: "<!doctype html>", + containsBody: "<!doctype html>", // from V3 dist/v3 }, + { name: "/v3/ serves v3 UI", path: "/v3/", @@ -35,7 +35,7 @@ var ( //go:embed static/* staticFiles embed.FS - //go:embed dist/v2/* dist/v3/* + //go:embed dist/v3/* frontendFiles embed.FS ) diff --git a/web/web_test.go b/web/web_test.go index a40e073..f900d07 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -632,7 +632,7 @@ func TestImageProxyHandlerInvalidBase64(t *testing.T) { func TestServeFrontendNotFound(t *testing.T) { req := httptest.NewRequest("GET", "/not-actually-a-file", nil) rr := httptest.NewRecorder() - ServeFrontend("dist/v2")(rr, req) + ServeFrontend("dist/v3")(rr, req) // Should fallback to index.html if it's not a dot-extension file if rr.Code != http.StatusOK { t.Errorf("Expected %d (fallback to index.html), got %d", http.StatusOK, rr.Code) |
