aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/coverage/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/coverage/src/components')
-rw-r--r--frontend/coverage/src/components/FeedItem.css.html74
-rw-r--r--frontend/coverage/src/components/FeedItem.tsx.html18
-rw-r--r--frontend/coverage/src/components/FeedItems.css.html2
-rw-r--r--frontend/coverage/src/components/FeedItems.tsx.html254
-rw-r--r--frontend/coverage/src/components/FeedList.css.html150
-rw-r--r--frontend/coverage/src/components/FeedList.tsx.html215
-rw-r--r--frontend/coverage/src/components/Login.css.html2
-rw-r--r--frontend/coverage/src/components/Login.tsx.html55
-rw-r--r--frontend/coverage/src/components/Settings.css.html361
-rw-r--r--frontend/coverage/src/components/Settings.tsx.html316
-rw-r--r--frontend/coverage/src/components/index.html105
11 files changed, 1163 insertions, 389 deletions
diff --git a/frontend/coverage/src/components/FeedItem.css.html b/frontend/coverage/src/components/FeedItem.css.html
index 213077f..192959f 100644
--- a/frontend/coverage/src/components/FeedItem.css.html
+++ b/frontend/coverage/src/components/FeedItem.css.html
@@ -188,7 +188,51 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -330,7 +374,7 @@
}
&nbsp;
.item-title {
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-family: var(--font-heading);
font-size: 1.8rem;
font-weight: bold;
text-decoration: none;
@@ -429,7 +473,7 @@
border: 1px solid var(--border-color, #ccc);
color: blue;
cursor: pointer;
- font-family: 'Helvetica Neue';
+ font-family: var(--font-heading);
font-weight: bold;
font-size: 0.8rem;
padding: 2px 6px;
@@ -438,6 +482,28 @@
&nbsp;
.scrape-btn:hover {
background: var(--sidebar-bg);
+}
+&nbsp;
+@media (max-width: 768px) {
+ .feed-item {
+ margin-top: 2rem;
+ padding: 0.5rem;
+ }
+&nbsp;
+ .item-title {
+ font-size: 1.4rem;
+ word-break: break-word;
+ }
+&nbsp;
+ .item-header {
+ flex-direction: column;
+ gap: 0.5rem;
+ }
+&nbsp;
+ .item-actions {
+ margin-left: 0;
+ margin-bottom: 0.5rem;
+ }
}</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
@@ -445,7 +511,7 @@
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/FeedItem.tsx.html b/frontend/coverage/src/components/FeedItem.tsx.html
index 6e76131..6df1fec 100644
--- a/frontend/coverage/src/components/FeedItem.tsx.html
+++ b/frontend/coverage/src/components/FeedItem.tsx.html
@@ -189,18 +189,18 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</span>
-<span class="cline-any cline-yes">33x</span>
+<span class="cline-any cline-yes">56x</span>
+<span class="cline-any cline-yes">56x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</span>
-<span class="cline-any cline-yes">16x</span>
+<span class="cline-any cline-yes">56x</span>
+<span class="cline-any cline-yes">22x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</span>
+<span class="cline-any cline-yes">56x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</span>
+<span class="cline-any cline-yes">56x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
@@ -236,7 +236,7 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</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>
@@ -254,7 +254,7 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">33x</span>
+<span class="cline-any cline-yes">56x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -415,7 +415,7 @@ export default function FeedItem({ item: initialItem }: FeedItemProps) {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/FeedItems.css.html b/frontend/coverage/src/components/FeedItems.css.html
index 7a971c6..66a3307 100644
--- a/frontend/coverage/src/components/FeedItems.css.html
+++ b/frontend/coverage/src/components/FeedItems.css.html
@@ -136,7 +136,7 @@
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/FeedItems.tsx.html b/frontend/coverage/src/components/FeedItems.tsx.html
index f6b7493..9811743 100644
--- a/frontend/coverage/src/components/FeedItems.tsx.html
+++ b/frontend/coverage/src/components/FeedItems.tsx.html
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
- <span class="strong">88.97% </span>
+ <span class="strong">89.23% </span>
<span class="quiet">Statements</span>
- <span class='fraction'>113/127</span>
+ <span class='fraction'>116/130</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">75.3% </span>
+ <span class="strong">76.19% </span>
<span class="quiet">Branches</span>
- <span class='fraction'>61/81</span>
+ <span class='fraction'>64/84</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">86.2% </span>
+ <span class="strong">87.09% </span>
<span class="quiet">Functions</span>
- <span class='fraction'>25/29</span>
+ <span class='fraction'>27/31</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">88.69% </span>
+ <span class="strong">89.07% </span>
<span class="quiet">Lines</span>
- <span class='fraction'>102/115</span>
+ <span class='fraction'>106/119</span>
</div>
@@ -296,7 +296,25 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -304,78 +322,78 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</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">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">27x</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">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">1x</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">7x</span>
-<span class="cline-any cline-yes">7x</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</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">&nbsp;</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-yes">8x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">6x</span>
+<span class="cline-any cline-yes">9x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">8x</span>
-<span class="cline-any cline-yes">8x</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">8x</span>
+<span class="cline-any cline-yes">11x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">7x</span>
+<span class="cline-any cline-yes">10x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">7x</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">10x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">6x</span>
-<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">5x</span>
+<span class="cline-any cline-yes">9x</span>
+<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">6x</span>
-<span class="cline-any cline-yes">6x</span>
-<span class="cline-any cline-yes">6x</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
@@ -384,20 +402,21 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">7x</span>
-<span class="cline-any cline-yes">7x</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">36x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">3x</span>
@@ -409,7 +428,7 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
+<span class="cline-any cline-yes">36x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
@@ -421,22 +440,29 @@
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">23x</span>
-<span class="cline-any cline-yes">3x</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">&nbsp;</span>
-<span class="cline-any cline-yes">3x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">2x</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">&nbsp;</span>
-<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-yes">5x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">5x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">5x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
@@ -455,25 +481,19 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">23x</span>
-<span class="cline-any cline-yes">23x</span>
+<span class="cline-any cline-yes">31x</span>
+<span class="cline-any cline-yes">31x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-yes">36x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-yes">1x</span>
-<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-yes">31x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-neutral">&nbsp;</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>
@@ -488,29 +508,45 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">24x</span>
-<span class="cline-any cline-yes">15x</span>
-<span class="cline-any cline-yes">15x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">31x</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">24x</span>
-<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">24x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">27x</span>
-<span class="cline-any cline-yes">14x</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">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">31x</span>
+<span class="cline-any cline-yes">31x</span>
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">36x</span>
<span class="cline-any cline-yes">21x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">20x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">44x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -620,6 +656,7 @@ export default function FeedItems() {
useEffect(() =&gt; {
fetchItems();
setSelectedIndex(-1);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [feedId, tagName, filterFn, searchParams]);
&nbsp;
&nbsp;
@@ -668,6 +705,13 @@ export default function FeedItems() {
}
scrollToItem(nextIndex);
}
+&nbsp;
+ // 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 &amp;&amp; hasMore &amp;&amp; !loadingMore) {
+ fetchItems(String(items[items.length - 1]._id));
+ }
+&nbsp;
return nextIndex;
});
<span class="missing-if-branch" title="if path not taken" >I</span>} else if (e.key === 'k') {
@@ -690,22 +734,16 @@ export default function FeedItems() {
&nbsp;
window.addEventListener('keydown', handleKeyDown);
return () =&gt; window.removeEventListener('keydown', handleKeyDown);
- }, [items]);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [items, hasMore, loadingMore]);
&nbsp;
&nbsp;
&nbsp;
useEffect(() =&gt; {
- const observer = new IntersectionObserver(
+ // Observer for marking items as read
+ const itemObserver = new IntersectionObserver(
(entries) =&gt; {
entries.forEach((entry) =&gt; {
- // Infinity scroll sentinel
- if (entry.target.id === 'load-more-sentinel') {
- <span class="missing-if-branch" title="else path not taken" >E</span>if (entry.isIntersecting &amp;&amp; !loadingMore &amp;&amp; hasMore &amp;&amp; items.length &gt; 0) {
- fetchItems(String(items[items.length - 1]._id));
- }
- return;
- }
-&nbsp;
// 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 &amp;&amp; entry.boundingClientRect.top &lt; 0) {
const index = Number(entry.target.getAttribute('data-index'));
@@ -721,15 +759,31 @@ export default function FeedItems() {
{ root: null, threshold: 0 }
);
&nbsp;
+ // Observer for infinite scroll (less aggressive, must be fully visible)
+ const sentinelObserver = new IntersectionObserver(
+ (entries) =&gt; {
+ entries.forEach((entry) =&gt; {
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (entry.isIntersecting &amp;&amp; !loadingMore &amp;&amp; hasMore &amp;&amp; items.length &gt; 0) {
+ fetchItems(String(items[items.length - 1]._id));
+ }
+ });
+ },
+ { root: null, threshold: 1.0 }
+ );
+&nbsp;
items.forEach((_, index) =&gt; {
const el = document.getElementById(`item-${index}`);
- <span class="missing-if-branch" title="else path not taken" >E</span>if (el) observer.observe(el);
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (el) itemObserver.observe(el);
});
&nbsp;
const sentinel = document.getElementById('load-more-sentinel');
- if (sentinel) observer.observe(sentinel);
+ if (sentinel) sentinelObserver.observe(sentinel);
&nbsp;
- return () =&gt; observer.disconnect();
+ return () =&gt; {
+ itemObserver.disconnect();
+ sentinelObserver.disconnect();
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [items, loadingMore, hasMore]);
&nbsp;
if (loading) return &lt;div className="feed-items-loading"&gt;Loading items...&lt;/div&gt;;
@@ -769,7 +823,7 @@ export default function FeedItems() {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/FeedList.css.html b/frontend/coverage/src/components/FeedList.css.html
index 2b93e18..d892e77 100644
--- a/frontend/coverage/src/components/FeedList.css.html
+++ b/frontend/coverage/src/components/FeedList.css.html
@@ -236,7 +236,87 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -411,10 +491,13 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">.feed-list {
padding: 1rem;
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-family: var(--font-heading);
color: #777;
/* specific v1 color */
font-size: 0.8rem;
+ background: var(--sidebar-bg);
+ min-height: 100%;
+ flex: 1;
}
&nbsp;
.feed-list h1.logo {
@@ -429,9 +512,6 @@
z-index: 10;
padding-bottom: 0.5rem;
color: var(--text-color);
- /* Usually dark/white depending on theme, v1 was white on blue? No, white on fixed header? No, v1 logo class says color: white. But sidebar is #ccc. */
- /* In v1 logo was fixed top left (blue header bar?). In v2 sidebar is #ccc.
- Let's use theme text color but maybe bolder? */
}
&nbsp;
/* Override logo color if necessary for themes */
@@ -466,11 +546,25 @@
margin: 1rem 0 0.25rem 0;
cursor: pointer;
user-select: none;
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ 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;
+}
+&nbsp;
+.caret {
+ display: inline-block;
+ font-size: 0.6rem;
+ transition: transform 0.2s ease;
+ color: #777;
+}
+&nbsp;
+.caret.expanded {
+ transform: rotate(90deg);
}
&nbsp;
.filter-list,
@@ -537,19 +631,25 @@
&nbsp;
.nav-section {
margin-top: 2rem;
- border-top: 1px solid var(--border-color, #999);
- padding-top: 0.5rem;
+ border-top: 1px solid var(--border-color, #eee);
+ padding-top: 1rem;
}
&nbsp;
.logout-link {
text-align: left;
width: 100%;
color: #777;
- /* Make logout less prominent */
+ display: block;
+}
+&nbsp;
+.nav-link,
+.logout-link {
+ padding: 0.25rem 0;
}
&nbsp;
.logout-link:hover {
color: var(--link-color, blue);
+ text-decoration: underline;
}
&nbsp;
.theme-section {
@@ -559,20 +659,40 @@
.theme-selector {
display: flex;
gap: 0.5rem;
+ margin-top: 0.5rem;
}
&nbsp;
.theme-selector button {
- background: transparent;
- border: 1px solid var(--border-color, #999);
+ background: rgba(0, 0, 0, 0.05);
+ border: none;
cursor: pointer;
- padding: 0.1rem 0.3rem;
- font-size: 0.9rem;
- border-radius: 0;
+ 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;
+}
+&nbsp;
+.theme-selector button:hover {
+ background: rgba(0, 0, 0, 0.1);
+ transform: translateY(-2px);
}
&nbsp;
.theme-selector button.active {
background: var(--border-color, #999);
color: white;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+&nbsp;
+.theme-dark .theme-selector button {
+ background: rgba(255, 255, 255, 0.1);
+}
+&nbsp;
+.theme-dark .theme-selector button:hover {
+ background: rgba(255, 255, 255, 0.2);
}
&nbsp;
/* Scrollbar styling for webkit */
@@ -589,7 +709,7 @@
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/FeedList.tsx.html b/frontend/coverage/src/components/FeedList.tsx.html
index acb2ede..4061422 100644
--- a/frontend/coverage/src/components/FeedList.tsx.html
+++ b/frontend/coverage/src/components/FeedList.tsx.html
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
- <span class="strong">79.54% </span>
+ <span class="strong">87.27% </span>
<span class="quiet">Statements</span>
- <span class='fraction'>35/44</span>
+ <span class='fraction'>48/55</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">64.86% </span>
+ <span class="strong">70% </span>
<span class="quiet">Branches</span>
- <span class='fraction'>24/37</span>
+ <span class='fraction'>35/50</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">64.7% </span>
+ <span class="strong">78.94% </span>
<span class="quiet">Functions</span>
- <span class='fraction'>11/17</span>
+ <span class='fraction'>15/19</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">82.05% </span>
+ <span class="strong">90% </span>
<span class="quiet">Lines</span>
- <span class='fraction'>32/39</span>
+ <span class='fraction'>45/50</span>
</div>
@@ -61,7 +61,7 @@
</div>
</template>
</div>
- <div class='status-line medium'></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>
@@ -248,7 +248,34 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -263,62 +290,85 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-yes">22x</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">22x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
-<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">22x</span>
+<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
+<span class="cline-any cline-yes">22x</span>
+<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">13x</span>
+<span class="cline-any cline-yes">22x</span>
+<span class="cline-any cline-yes">9x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">7x</span>
+<span class="cline-any cline-yes">7x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">7x</span>
+<span class="cline-any cline-yes">7x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
-<span class="cline-any cline-yes">6x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">6x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">22x</span>
+<span class="cline-any cline-yes">13x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">12x</span>
+<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">12x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -330,7 +380,8 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -384,6 +435,8 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -415,6 +468,7 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -437,36 +491,49 @@
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';
&nbsp;
export default function FeedList({
theme,
setTheme,
setSidebarVisible,
+ isMobile,
}: {
theme: string;
setTheme: (t: string) =&gt; void;
setSidebarVisible: (visible: boolean) =&gt; void;
+ isMobile: boolean;
}) {
const [feeds, setFeeds] = useState&lt;Feed[]&gt;([]);
const [tags, setTags] = useState&lt;Category[]&gt;([]);
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();
&nbsp;
+ const sidebarVariant = searchParams.get('sidebar') || localStorage.getItem('neko-sidebar-variant') || 'glass';
+&nbsp;
+ useEffect(() =&gt; {
+ 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]);
+&nbsp;
const currentFilter =
searchParams.get('filter') ||
(location.pathname === '/' &amp;&amp; !feedId &amp;&amp; !tagName ? 'unread' : <span class="branch-1 cbranch-no" title="branch not covered" >'');</span>
&nbsp;
- const handleSearch = <span class="fstat-no" title="function not covered" >(e</span>: React.FormEvent) =&gt; {
-<span class="cstat-no" title="statement not covered" > e.preventDefault();</span>
-<span class="cstat-no" title="statement not covered" > if (searchQuery.trim()) {</span>
-<span class="cstat-no" title="statement not covered" > navigate(`/?q=${encodeURIComponent(searchQuery.trim())}`);</span>
+ const handleSearch = (e: React.FormEvent) =&gt; {
+ e.preventDefault();
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (searchQuery.trim()) {
+ navigate(`/?q=${encodeURIComponent(searchQuery.trim())}`);
}
};
&nbsp;
@@ -474,15 +541,25 @@ export default function FeedList({
setFeedsExpanded(!feedsExpanded);
};
&nbsp;
+ const toggleTags = <span class="fstat-no" title="function not covered" >() =&gt; {</span>
+<span class="cstat-no" title="statement not covered" > setTagsExpanded(!tagsExpanded);</span>
+ };
+&nbsp;
+ const handleLinkClick = () =&gt; {
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (isMobile) {
+ setSidebarVisible(false);
+ }
+ };
+&nbsp;
useEffect(() =&gt; {
Promise.all([
apiFetch('/api/feed/').then((res) =&gt; {
<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();
+ return res.json() as Promise&lt;Feed[]&gt;;
}),
apiFetch('/api/tag').then((res) =&gt; {
<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();
+ return res.json() as Promise&lt;Category[]&gt;;
}),
])
.then(([feedsData, tagsData]) =&gt; {
@@ -504,7 +581,7 @@ export default function FeedList({
};
&nbsp;
return (
- &lt;div className="feed-list"&gt;
+ &lt;div className={`feed-list variant-${sidebarVariant}`}&gt;
&lt;h1 className="logo" onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(false)}&gt;</span>
🐱
&lt;/h1&gt;
@@ -515,7 +592,7 @@ export default function FeedList({
type="search"
placeholder="search..."
value={searchQuery}
- onChange={<span class="fstat-no" title="function not covered" >(e</span>) =&gt; <span class="cstat-no" title="statement not covered" >setSearchQuery(e.target.value)}</span>
+ onChange={(e) =&gt; setSearchQuery(e.target.value)}
className="search-input"
/&gt;
&lt;/form&gt;
@@ -524,17 +601,17 @@ export default function FeedList({
&lt;div className="filter-section"&gt;
&lt;ul className="filter-list"&gt;
&lt;li className="unread_filter"&gt;
- &lt;Link to="/?filter=unread" className={currentFilter === 'unread' ? 'active' : <span class="branch-1 cbranch-no" title="branch not covered" >''}&gt;</span>
+ &lt;Link to="/?filter=unread" className={currentFilter === 'unread' ? 'active' : <span class="branch-1 cbranch-no" title="branch not covered" >''} o</span>nClick={handleLinkClick}&gt;
unread
&lt;/Link&gt;
&lt;/li&gt;
&lt;li className="all_filter"&gt;
- &lt;Link to="/?filter=all" className={currentFilter === 'all' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}&gt;
+ &lt;Link to="/?filter=all" className={currentFilter === 'all' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'} onClick={handleLinkClick}&gt;
all
&lt;/Link&gt;
&lt;/li&gt;
&lt;li className="starred_filter"&gt;
- &lt;Link to="/?filter=starred" className={currentFilter === 'starred' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}&gt;
+ &lt;Link to="/?filter=starred" className={currentFilter === 'starred' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'} onClick={handleLinkClick}&gt;
starred
&lt;/Link&gt;
&lt;/li&gt;
@@ -542,26 +619,29 @@ export default function FeedList({
&lt;/div&gt;
&nbsp;
&lt;div className="tag-section"&gt;
- &lt;h4 onClick={<span class="fstat-no" title="function not covered" >() =&gt; {</span> }} className="section-header"&gt;
- Tags
+ &lt;h4 onClick={toggleTags} className="section-header"&gt;
+ &lt;span className={`caret ${tagsExpanded ? 'expanded' : <span class="branch-1 cbranch-no" title="branch not covered" >''}</span>`}&gt;▶&lt;/span&gt; Tags
&lt;/h4&gt;
- &lt;ul className="tag-list-items"&gt;
- {tags.map((tag) =&gt; (
- &lt;li key={tag.title} className="tag-item"&gt;
- &lt;Link
- to={`/tag/${encodeURIComponent(tag.title)}`}
- className={`tag-link ${tagName === tag.title ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}`}
- &gt;
- {tag.title}
- &lt;/Link&gt;
- &lt;/li&gt;
- ))}
- &lt;/ul&gt;
+ {tagsExpanded &amp;&amp; (
+ &lt;ul className="tag-list-items"&gt;
+ {tags.map((tag) =&gt; (
+ &lt;li key={tag.title} className="tag-item"&gt;
+ &lt;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}
+ &gt;
+ {tag.title}
+ &lt;/Link&gt;
+ &lt;/li&gt;
+ ))}
+ &lt;/ul&gt;
+ )}
&lt;/div&gt;
&nbsp;
&lt;div className="feed-section"&gt;
&lt;h4 onClick={toggleFeeds} className="section-header"&gt;
- Feeds
+ &lt;span className={`caret ${feedsExpanded ? 'expanded' : ''}`}&gt;▶&lt;/span&gt; Feeds
&lt;/h4&gt;
{feedsExpanded &amp;&amp;
(feeds.length === 0 ? (
@@ -573,6 +653,7 @@ export default function FeedList({
&lt;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}
&gt;
{feed.title || <span class="branch-1 cbranch-no" title="branch not covered" >feed.url}</span>
&lt;/Link&gt;
@@ -585,7 +666,7 @@ export default function FeedList({
&lt;div className="nav-section"&gt;
&lt;ul className="nav-list"&gt;
&lt;li&gt;
- &lt;Link to="/settings" className="nav-link"&gt;
+ &lt;Link to="/settings" className="nav-link" onClick={handleLinkClick}&gt;
settings
&lt;/Link&gt;
&lt;/li&gt;
@@ -625,7 +706,7 @@ export default function FeedList({
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/Login.css.html b/frontend/coverage/src/components/Login.css.html
index 031618b..140a86b 100644
--- a/frontend/coverage/src/components/Login.css.html
+++ b/frontend/coverage/src/components/Login.css.html
@@ -259,7 +259,7 @@ button[type='submit']:hover {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/Login.tsx.html b/frontend/coverage/src/components/Login.tsx.html
index 43fb613..111dcba 100644
--- a/frontend/coverage/src/components/Login.tsx.html
+++ b/frontend/coverage/src/components/Login.tsx.html
@@ -25,7 +25,7 @@
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Statements</span>
- <span class='fraction'>17/17</span>
+ <span class='fraction'>20/20</span>
</div>
@@ -39,14 +39,14 @@
<div class='fl pad1y space-right2'>
<span class="strong">100% </span>
<span class="quiet">Functions</span>
- <span class='fraction'>3/3</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'>17/17</span>
+ <span class='fraction'>20/20</span>
</div>
@@ -119,18 +119,30 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">14x</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">&nbsp;</span>
-<span class="cline-any cline-yes">14x</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">&nbsp;</span>
@@ -138,6 +150,7 @@
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
<span class="cline-any cline-yes">3x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -155,10 +168,19 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
+<span class="cline-any cline-yes">17x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">3x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -182,6 +204,7 @@ import './Login.css';
import { apiFetch } from '../utils';
&nbsp;
export default function Login() {
+ const [username, setUsername] = useState('neko');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const navigate = useNavigate();
@@ -193,6 +216,7 @@ export default function Login() {
try {
// Use URLSearchParams to send as form-urlencoded, matching backend expectation
const params = new URLSearchParams();
+ params.append('username', username);
params.append('password', password);
&nbsp;
const res = await apiFetch('/api/login', {
@@ -206,7 +230,7 @@ export default function Login() {
const data = await res.json();
setError(data.message || <span class="branch-1 cbranch-no" title="branch not covered" >'Login failed')</span>;
}
- } catch (err) {
+ } catch (_err) {
setError('Network error');
}
};
@@ -216,6 +240,15 @@ export default function Login() {
&lt;form onSubmit={handleSubmit} className="login-form"&gt;
&lt;h1&gt;neko rss mode&lt;/h1&gt;
&lt;div className="form-group"&gt;
+ &lt;label htmlFor="username"&gt;username&lt;/label&gt;
+ &lt;input
+ id="username"
+ type="text"
+ value={username}
+ onChange={(e) =&gt; setUsername(e.target.value)}
+ /&gt;
+ &lt;/div&gt;
+ &lt;div className="form-group"&gt;
&lt;label htmlFor="password"&gt;password&lt;/label&gt;
&lt;input
id="password"
@@ -238,7 +271,7 @@ export default function Login() {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/Settings.css.html b/frontend/coverage/src/components/Settings.css.html
index 28a1915..4109bba 100644
--- a/frontend/coverage/src/components/Settings.css.html
+++ b/frontend/coverage/src/components/Settings.css.html
@@ -223,7 +223,86 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -383,18 +462,151 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">.settings-page {
- padding: 2rem;
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</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;
+}
+&nbsp;
+.settings-page.variant-glass h2,
+.settings-page.variant-glass h3 {
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ color: var(--text-color);
+ opacity: 0.9;
}
&nbsp;
-.add-feed-section {
- background: var(--sidebar-bg);
+.add-feed-section,
+.appearance-section,
+.import-section,
+.export-section,
+.feed-list-section {
+ background: rgba(255, 255, 255, 0.03);
padding: 1.5rem;
- border-radius: 8px;
+ border-radius: 16px;
margin-bottom: 2rem;
- border: 1px solid var(--border-color);
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ transition: all 0.3s ease;
+}
+&nbsp;
+.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);
+}
+&nbsp;
+.font-selector {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
+&nbsp;
+.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;
+}
+&nbsp;
+.font-select:focus {
+ border-color: rgba(255, 255, 255, 0.3);
}
&nbsp;
.add-feed-form {
@@ -404,32 +616,45 @@
&nbsp;
.feed-input {
flex: 1;
- padding: 0.5rem;
- border: 1px solid var(--border-color);
- background: var(--bg-color);
+ 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: 4px;
+ border-radius: 20px;
font-size: 1rem;
+ outline: none;
+ transition: border-color 0.2s;
+}
+&nbsp;
+.feed-input:focus {
+ border-color: rgba(255, 255, 255, 0.3);
}
&nbsp;
.error-message {
- color: #d32f2f;
+ color: #ff5252;
margin-top: 1rem;
+ font-weight: 600;
}
&nbsp;
.settings-feed-list {
list-style: none;
padding: 0;
- border: 1px solid var(--border-color);
- border-radius: 8px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+ border-radius: 12px;
+ overflow: hidden;
}
&nbsp;
.settings-feed-item {
display: flex;
justify-content: space-between;
align-items: center;
- padding: 1rem;
- border-bottom: 1px solid var(--border-color);
+ padding: 1.2rem;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
+ transition: background 0.2s;
+}
+&nbsp;
+.settings-feed-item:hover {
+ background: rgba(255, 255, 255, 0.02);
}
&nbsp;
.settings-feed-item:last-child {
@@ -439,109 +664,121 @@
.feed-info {
display: flex;
flex-direction: column;
+ gap: 0.2rem;
}
&nbsp;
.feed-title {
- font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
- font-weight: bold;
- font-size: 1.1rem;
+ font-weight: 600;
+ font-size: 1.05rem;
+ opacity: 0.9;
}
&nbsp;
.feed-url {
color: var(--text-color);
- opacity: 0.6;
- font-size: 0.9rem;
+ opacity: 0.5;
+ font-size: 0.85rem;
}
&nbsp;
.delete-btn {
- background: #ff5252;
- color: white;
- border: none;
+ background: rgba(255, 82, 82, 0.15);
+ color: #ff8a80;
+ border: 1px solid rgba(255, 82, 82, 0.2);
padding: 0.5rem 1rem;
- border-radius: 4px;
+ border-radius: 12px;
cursor: pointer;
+ font-weight: 600;
+ transition: all 0.2s;
}
&nbsp;
-.delete-btn:hover {
- background: #ff1744;
-}
-&nbsp;
-.delete-btn:disabled {
- background: #ffcdd2;
- cursor: not-allowed;
+.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);
}
&nbsp;
.import-export-section {
display: flex;
gap: 2rem;
- margin-bottom: 2rem;
}
&nbsp;
@media (max-width: 600px) {
+ .settings-page.variant-glass {
+ padding: 1.5rem;
+ margin-top: 1rem;
+ }
+&nbsp;
+ .add-feed-form {
+ flex-direction: column;
+ }
+&nbsp;
.import-export-section {
flex-direction: column;
+ gap: 1rem;
}
-}
&nbsp;
-.import-section,
-.export-section {
- flex: 1;
- background: var(--sidebar-bg);
- padding: 1.5rem;
- border-radius: 8px;
- border: 1px solid var(--border-color);
+ .settings-feed-item {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
}
&nbsp;
.import-form {
display: flex;
flex-direction: column;
- gap: 1rem;
+ gap: 1.2rem;
}
&nbsp;
.file-input {
font-size: 0.9rem;
max-width: 100%;
+ color: var(--text-color);
+ opacity: 0.8;
}
&nbsp;
.export-buttons {
display: flex;
- gap: 1rem;
+ gap: 0.8rem;
flex-wrap: wrap;
}
&nbsp;
.export-btn {
display: inline-block;
- padding: 0.5rem 1rem;
- background: var(--bg-color);
- color: var(--link-color);
+ padding: 0.6rem 1.2rem;
+ background: rgba(255, 255, 255, 0.05);
+ color: var(--text-color);
text-decoration: none;
- border: 1px solid var(--border-color);
- border-radius: 4px;
- font-weight: bold;
- text-align: center;
- min-width: 70px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 12px;
+ font-weight: 600;
+ transition: all 0.2s;
}
&nbsp;
.export-btn:hover {
- background: var(--sidebar-bg);
+ background: rgba(255, 255, 255, 0.1);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
&nbsp;
-button {
+button:not(.delete-btn) {
cursor: pointer;
- padding: 0.5rem 1rem;
- border-radius: 4px;
- border: 1px solid var(--border-color);
- background: var(--bg-color);
+ 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: bold;
+ font-weight: 600;
+ transition: all 0.2s;
}
&nbsp;
-button:hover:not(:disabled) {
- background: var(--sidebar-bg);
+button:not(.delete-btn):hover:not(:disabled) {
+ background: rgba(255, 255, 255, 0.2);
+ transform: scale(1.02);
}
&nbsp;
button:disabled {
- opacity: 0.5;
+ opacity: 0.4;
cursor: not-allowed;
}</pre></td></tr></table></pre>
@@ -550,7 +787,7 @@ button:disabled {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/Settings.tsx.html b/frontend/coverage/src/components/Settings.tsx.html
index 3d8d219..892218e 100644
--- a/frontend/coverage/src/components/Settings.tsx.html
+++ b/frontend/coverage/src/components/Settings.tsx.html
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
- <span class="strong">56.25% </span>
+ <span class="strong">80% </span>
<span class="quiet">Statements</span>
- <span class='fraction'>36/64</span>
+ <span class='fraction'>60/75</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">41.66% </span>
+ <span class="strong">66.66% </span>
<span class="quiet">Branches</span>
- <span class='fraction'>10/24</span>
+ <span class='fraction'>20/30</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">63.63% </span>
+ <span class="strong">85.18% </span>
<span class="quiet">Functions</span>
- <span class='fraction'>14/22</span>
+ <span class='fraction'>23/27</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">62.5% </span>
+ <span class="strong">87.87% </span>
<span class="quiet">Lines</span>
- <span class='fraction'>35/56</span>
+ <span class='fraction'>58/66</span>
</div>
@@ -61,7 +61,7 @@
</div>
</template>
</div>
- <div class='status-line medium'></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>
@@ -243,55 +243,138 @@
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
+<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">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">34x</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
+<span class="cline-any cline-yes">34x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
+<span class="cline-any cline-yes">9x</span>
+<span class="cline-any cline-yes">9x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">9x</span>
+<span class="cline-any cline-yes">9x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">14x</span>
+<span class="cline-any cline-yes">34x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
+<span class="cline-any cline-yes">7x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
-<span class="cline-any cline-yes">4x</span>
-<span class="cline-any cline-yes">4x</span>
+<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-yes">3x</span>
+<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">34x</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</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">&nbsp;</span>
@@ -301,12 +384,22 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</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">&nbsp;</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">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-yes">1x</span>
@@ -319,35 +412,28 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</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">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-yes">1x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">34x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">14x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -375,8 +461,32 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">2x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">1x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -403,7 +513,9 @@
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">5x</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-neutral">&nbsp;</span>
+<span class="cline-any cline-yes">6x</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
@@ -428,15 +540,22 @@ import type { Feed } from '../types';
import './Settings.css';
import { apiFetch } from '../utils';
&nbsp;
-export default function Settings() {
+interface SettingsProps {
+ fontTheme?: string;
+ setFontTheme?: (t: string) =&gt; void;
+}
+&nbsp;
+export default function Settings({ fontTheme, setFontTheme }: SettingsProps) {
const [feeds, setFeeds] = useState&lt;Feed[]&gt;([]);
+ /* ... existing state ... */
const [newFeedUrl, setNewFeedUrl] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState&lt;string | null&gt;(null);
&nbsp;
const [importFile, setImportFile] = useState&lt;File | null&gt;(null);
&nbsp;
- const fetchFeeds = () =&gt; {
+ /* ... existing fetchFeeds ... */
+ const fetchFeeds = React.useCallback(() =&gt; {
setLoading(true);
apiFetch('/api/feed/')
.then((res) =&gt; {
@@ -451,12 +570,14 @@ export default function Settings() {
<span class="cstat-no" title="statement not covered" > setError(err.message);</span>
<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
});
- };
+ }, []);
&nbsp;
useEffect(() =&gt; {
+ // eslint-disable-next-line
fetchFeeds();
- }, []);
+ }, [fetchFeeds]);
&nbsp;
+ /* ... existing handlers ... */
const handleAddFeed = (e: React.FormEvent) =&gt; {
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>
@@ -468,16 +589,16 @@ export default function Settings() {
body: JSON.stringify({ url: newFeedUrl }),
})
.then((res) =&gt; {
- <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 add feed');</span>
+ if (!res.ok) throw new Error('Failed to add feed');
return res.json();
})
.then(() =&gt; {
setNewFeedUrl('');
fetchFeeds();
})
- .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; {
-<span class="cstat-no" title="statement not covered" > setError(err.message);</span>
-<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
+ .catch((err) =&gt; {
+ setError(err.message);
+ setLoading(false);
});
};
&nbsp;
@@ -499,27 +620,46 @@ export default function Settings() {
});
};
&nbsp;
- const handleImport = <span class="fstat-no" title="function not covered" >(e</span>: React.FormEvent) =&gt; {
-<span class="cstat-no" title="statement not covered" > e.preventDefault();</span>
-<span class="cstat-no" title="statement not covered" > if (!importFile) <span class="cstat-no" title="statement not covered" >return;</span></span>
+ const handleImport = (e: React.FormEvent) =&gt; {
+ 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>
&nbsp;
-<span class="cstat-no" title="statement not covered" > setLoading(true);</span>
- const formData = <span class="cstat-no" title="statement not covered" >new FormData();</span>
-<span class="cstat-no" title="statement not covered" > formData.append('file', importFile);</span>
-<span class="cstat-no" title="statement not covered" > formData.append('format', 'opml');</span>
+ setLoading(true);
+ const formData = new FormData();
+ formData.append('file', importFile);
+ formData.append('format', 'opml');
&nbsp;
-<span class="cstat-no" title="statement not covered" > apiFetch('/api/import', {</span>
+ apiFetch('/api/import', {
method: 'POST',
body: formData,
})
- .then(<span class="fstat-no" title="function not covered" >(r</span>es) =&gt; {
-<span class="cstat-no" title="statement not covered" > if (!res.ok) <span class="cstat-no" title="statement not covered" >throw new Error('Failed to import feeds');</span></span>
-<span class="cstat-no" title="statement not covered" > return res.json();</span>
+ .then((res) =&gt; {
+ <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(<span class="fstat-no" title="function not covered" >() =&gt; {</span>
-<span class="cstat-no" title="statement not covered" > setImportFile(null);</span>
-<span class="cstat-no" title="statement not covered" > fetchFeeds();</span>
-<span class="cstat-no" title="statement not covered" > alert('Import successful!');</span>
+ .then(() =&gt; {
+ setImportFile(null);
+ fetchFeeds();
+ alert('Import successful!');
+ })
+ .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; {
+<span class="cstat-no" title="statement not covered" > setError(err.message);</span>
+<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
+ });
+ };
+&nbsp;
+ const handleCrawl = () =&gt; {
+ setLoading(true);
+ apiFetch('/api/crawl', {
+ method: 'POST',
+ })
+ .then((res) =&gt; {
+ <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(() =&gt; {
+ setLoading(false);
+ alert('Crawl started!');
})
.catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; {
<span class="cstat-no" title="statement not covered" > setError(err.message);</span>
@@ -528,9 +668,29 @@ export default function Settings() {
};
&nbsp;
return (
- &lt;div className="settings-page"&gt;
+ &lt;div className="settings-page variant-glass"&gt;
&lt;h2&gt;Settings&lt;/h2&gt;
&nbsp;
+ {setFontTheme &amp;&amp; (
+ &lt;div className="appearance-section"&gt;
+ &lt;h3&gt;Appearance&lt;/h3&gt;
+ &lt;div className="font-selector"&gt;
+ &lt;label htmlFor="font-theme-select"&gt;Font Theme:&lt;/label&gt;
+ &lt;select
+ id="font-theme-select"
+ value={fontTheme || <span class="branch-1 cbranch-no" title="branch not covered" >'default'}</span>
+ onChange={(e) =&gt; setFontTheme(e.target.value)}
+ className="font-select"
+ &gt;
+ &lt;option value="default"&gt;Default&lt;/option&gt;
+ &lt;option value="serif"&gt;Serif&lt;/option&gt;
+ &lt;option value="sans"&gt;Sans-Serif&lt;/option&gt;
+ &lt;option value="mono"&gt;Monospace&lt;/option&gt;
+ &lt;/select&gt;
+ &lt;/div&gt;
+ &lt;/div&gt;
+ )}
+&nbsp;
&lt;div className="add-feed-section"&gt;
&lt;h3&gt;Add New Feed&lt;/h3&gt;
&lt;form onSubmit={handleAddFeed} className="add-feed-form"&gt;
@@ -556,11 +716,12 @@ export default function Settings() {
&lt;input
type="file"
accept=".opml,.xml,.txt"
- onChange={<span class="fstat-no" title="function not covered" >(e</span>) =&gt; <span class="cstat-no" title="statement not covered" >setImportFile(e.target.files?.[0] || null)}</span>
+ aria-label="Import Feeds"
+ onChange={(e) =&gt; setImportFile(e.target.files?.[0] || <span class="branch-1 cbranch-no" title="branch not covered" >null)</span>}
className="file-input"
disabled={loading}
/&gt;
- &lt;button type="submit" disabled={!importFile || <span class="branch-1 cbranch-no" title="branch not covered" >loading}&gt;</span>
+ &lt;button type="submit" disabled={!importFile || loading}&gt;
Import
&lt;/button&gt;
&lt;/form&gt;
@@ -574,9 +735,16 @@ export default function Settings() {
&lt;a href="/api/export/json" className="export-btn"&gt;JSON&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
+&nbsp;
+ &lt;div className="crawl-section"&gt;
+ &lt;h3&gt;Actions&lt;/h3&gt;
+ &lt;button onClick={handleCrawl} disabled={loading} className="crawl-btn"&gt;
+ Crawl All Feeds Now
+ &lt;/button&gt;
+ &lt;/div&gt;
&lt;/div&gt;
&nbsp;
- {error &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >&lt;p className="error-message"&gt;{error}&lt;/p&gt;}</span>
+ {error &amp;&amp; &lt;p className="error-message"&gt;{error}&lt;/p&gt;}
&nbsp;
&lt;div className="feed-list-section"&gt;
&lt;h3&gt;Manage Feeds&lt;/h3&gt;
@@ -610,7 +778,7 @@ export default function Settings() {
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>
diff --git a/frontend/coverage/src/components/index.html b/frontend/coverage/src/components/index.html
index 66ca900..fc333bb 100644
--- a/frontend/coverage/src/components/index.html
+++ b/frontend/coverage/src/components/index.html
@@ -23,30 +23,30 @@
<div class='clearfix'>
<div class='fl pad1y space-right2'>
- <span class="strong">79.57% </span>
+ <span class="strong">86.21% </span>
<span class="quiet">Statements</span>
- <span class='fraction'>226/284</span>
+ <span class='fraction'>269/312</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">70.17% </span>
+ <span class="strong">74.61% </span>
<span class="quiet">Branches</span>
- <span class='fraction'>120/171</span>
+ <span class='fraction'>144/193</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">75.9% </span>
+ <span class="strong">84.94% </span>
<span class="quiet">Functions</span>
- <span class='fraction'>63/83</span>
+ <span class='fraction'>79/93</span>
</div>
<div class='fl pad1y space-right2'>
- <span class="strong">81.78% </span>
+ <span class="strong">88.81% </span>
<span class="quiet">Lines</span>
- <span class='fraction'>211/258</span>
+ <span class='fraction'>254/286</span>
</div>
@@ -61,7 +61,7 @@
</div>
</template>
</div>
- <div class='status-line medium'></div>
+ <div class='status-line high'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
@@ -125,17 +125,17 @@
<tr>
<td class="file high" data-value="FeedItems.tsx"><a href="FeedItems.tsx.html">FeedItems.tsx</a></td>
- <td data-value="88.97" class="pic high">
- <div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
+ <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="88.97" class="pct high">88.97%</td>
- <td data-value="127" class="abs high">113/127</td>
- <td data-value="75.3" class="pct medium">75.3%</td>
- <td data-value="81" class="abs medium">61/81</td>
- <td data-value="86.2" class="pct high">86.2%</td>
- <td data-value="29" class="abs high">25/29</td>
- <td data-value="88.69" class="pct high">88.69%</td>
- <td data-value="115" class="abs high">102/115</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>
@@ -154,18 +154,33 @@
</tr>
<tr>
- <td class="file medium" data-value="FeedList.tsx"><a href="FeedList.tsx.html">FeedList.tsx</a></td>
- <td data-value="79.54" class="pic medium">
- <div class="chart"><div class="cover-fill" style="width: 79%"></div><div class="cover-empty" style="width: 21%"></div></div>
+ <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="79.54" class="pct medium">79.54%</td>
- <td data-value="44" class="abs medium">35/44</td>
- <td data-value="64.86" class="pct medium">64.86%</td>
- <td data-value="37" class="abs medium">24/37</td>
- <td data-value="64.7" class="pct medium">64.7%</td>
- <td data-value="17" class="abs medium">11/17</td>
- <td data-value="82.05" class="pct high">82.05%</td>
- <td data-value="39" class="abs high">32/39</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>
@@ -189,13 +204,13 @@
<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="17" class="abs high">17/17</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="3" class="abs high">3/3</td>
+ <td data-value="4" class="abs high">4/4</td>
<td data-value="100" class="pct high">100%</td>
- <td data-value="17" class="abs high">17/17</td>
+ <td data-value="20" class="abs high">20/20</td>
</tr>
<tr>
@@ -214,18 +229,18 @@
</tr>
<tr>
- <td class="file medium" data-value="Settings.tsx"><a href="Settings.tsx.html">Settings.tsx</a></td>
- <td data-value="56.25" class="pic medium">
- <div class="chart"><div class="cover-fill" style="width: 56%"></div><div class="cover-empty" style="width: 44%"></div></div>
+ <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="56.25" class="pct medium">56.25%</td>
- <td data-value="64" class="abs medium">36/64</td>
- <td data-value="41.66" class="pct low">41.66%</td>
- <td data-value="24" class="abs low">10/24</td>
- <td data-value="63.63" class="pct medium">63.63%</td>
- <td data-value="22" class="abs medium">14/22</td>
- <td data-value="62.5" class="pct medium">62.5%</td>
- <td data-value="56" class="abs medium">35/56</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>
@@ -236,7 +251,7 @@
<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-14T18:02:09.004Z
+ at 2026-02-15T05:30:50.842Z
</div>
<script src="../../prettify.js"></script>
<script>