aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/coverage/src
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-16 19:37:50 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-16 19:40:10 -0800
commitcba29e6aae637b04ff6eaf28f74bc15b6242b9ea (patch)
tree226753a3fcd18a6d45089dafcb1ee72557140aa8 /frontend/coverage/src
parentcb6d0c9e330c27ff85ff065c2ea6dd1a756cbf6d (diff)
downloadneko-cba29e6aae637b04ff6eaf28f74bc15b6242b9ea.tar.gz
neko-cba29e6aae637b04ff6eaf28f74bc15b6242b9ea.tar.bz2
neko-cba29e6aae637b04ff6eaf28f74bc15b6242b9ea.zip
Remove legacy V2 React frontend and update build/test scripts to focus on Vanilla JS (V3)
Diffstat (limited to 'frontend/coverage/src')
-rw-r--r--frontend/coverage/src/App.css.html478
-rw-r--r--frontend/coverage/src/App.tsx.html505
-rw-r--r--frontend/coverage/src/components/FeedItem.css.html526
-rw-r--r--frontend/coverage/src/components/FeedItem.tsx.html430
-rw-r--r--frontend/coverage/src/components/FeedItems.css.html151
-rw-r--r--frontend/coverage/src/components/FeedItems.tsx.html838
-rw-r--r--frontend/coverage/src/components/FeedList.css.html724
-rw-r--r--frontend/coverage/src/components/FeedList.tsx.html721
-rw-r--r--frontend/coverage/src/components/Login.css.html274
-rw-r--r--frontend/coverage/src/components/Login.tsx.html286
-rw-r--r--frontend/coverage/src/components/Settings.css.html802
-rw-r--r--frontend/coverage/src/components/Settings.tsx.html793
-rw-r--r--frontend/coverage/src/components/index.html266
-rw-r--r--frontend/coverage/src/index.html146
14 files changed, 0 insertions, 6940 deletions
diff --git a/frontend/coverage/src/App.css.html b/frontend/coverage/src/App.css.html
deleted file mode 100644
index d23e87b..0000000
--- a/frontend/coverage/src/App.css.html
+++ /dev/null
@@ -1,478 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/App.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../prettify.css" />
- <link rel="stylesheet" href="../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> App.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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>
-<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">/* Resets and Base Styles */
-* {
- box-sizing: border-box;
-}
-&nbsp;
-body {
- margin: 0;
-}
-&nbsp;
-/* Dashboard Layout */
-.dashboard {
- display: flex;
- flex-direction: column;
- height: 100vh;
- overflow: hidden;
- /* Prevent body scroll */
-}
-&nbsp;
-/* Header styles removed as we moved to sidebar navigation */
-&nbsp;
-.dashboard-content {
- display: flex;
- flex: 1;
- overflow: hidden;
- position: relative;
-}
-&nbsp;
-.dashboard-sidebar {
- width: 11rem;
- background: transparent;
- border-right: 1px solid var(--border-color);
- display: flex;
- flex-direction: column;
- overflow-y: auto;
- transition: margin-left 0.4s ease;
- /* No padding here, handled in FeedList */
-}
-&nbsp;
-.dashboard-sidebar.hidden {
- margin-left: -11rem;
-}
-&nbsp;
-.dashboard-main {
- flex: 1;
- padding: 2rem;
- overflow-y: auto;
- background: var(--bg-color);
- margin-left: 0;
-}
-&nbsp;
-.dashboard-main&gt;* {
- max-width: 35em;
- margin: 0 auto;
-}
-&nbsp;
-.fixed-toggle {
- position: absolute;
- top: 1rem;
- left: 1rem;
- z-index: 1000;
- background: var(--bg-color);
- /* Added bg to be visible over content if needed */
- border: none;
- font-size: 2rem;
- line-height: 1;
- cursor: pointer;
- padding: 0.2rem;
- color: var(--text-color);
- border-radius: 50%;
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
- display: flex;
- align-items: center;
- justify-content: center;
-}
-&nbsp;
-.fixed-toggle:hover {
- transform: scale(1.1);
-}
-&nbsp;
-/* Mobile Responsiveness */
-@media (max-width: 768px) {
- .dashboard-sidebar {
- position: fixed;
- top: 0;
- left: 0;
- bottom: 0;
- z-index: 1100;
- box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2);
- width: 14rem;
- /* Slightly wider on mobile for better target area */
- }
-&nbsp;
- .dashboard-sidebar.hidden {
- margin-left: -14rem;
- }
-&nbsp;
- .dashboard-main {
- padding: 1rem;
- padding-top: 4rem;
- /* Space for the toggle button */
- }
-&nbsp;
- .dashboard-main&gt;* {
- max-width: 100%;
- }
-&nbsp;
- /* When sidebar is visible on mobile, we show a backdrop */
- .sidebar-backdrop {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.4);
- z-index: 1050;
- animation: fadeIn 0.3s ease;
- }
-&nbsp;
- .dashboard.sidebar-visible::after {
- display: none;
- }
-}
-&nbsp;
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
-&nbsp;
- to {
- opacity: 1;
- }
-}</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../sorter.js"></script>
- <script src="../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/App.tsx.html b/frontend/coverage/src/App.tsx.html
deleted file mode 100644
index 6ec66af..0000000
--- a/frontend/coverage/src/App.tsx.html
+++ /dev/null
@@ -1,505 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/App.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../prettify.css" />
- <link rel="stylesheet" href="../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> App.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">65.71% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>23/35</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">60% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>15/25</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">53.84% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>7/13</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">64.7% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>22/34</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line medium'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">2x</span>
-<span class="cline-any cline-yes">2x</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-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-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-neutral">&nbsp;</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-neutral">&nbsp;</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-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-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-yes">1x</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>
-<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-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-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>
-<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>
-<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-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">2x</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">2x</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">2x</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-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">import React, { useEffect, useState } from 'react';
-import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom';
-import Login from './components/Login';
-import './App.css';
-import { apiFetch } from './utils';
-&nbsp;
-// Protected Route wrapper
-function RequireAuth({ children }: { children: React.ReactElement }) {
- const [auth, setAuth] = useState&lt;boolean | null&gt;(null);
- const location = useLocation();
-&nbsp;
- useEffect(() =&gt; {
- apiFetch('/api/auth')
- .then((res) =&gt; {
- if (res.ok) {
- setAuth(true);
- } else <span class="missing-if-branch" title="else path not taken" >E</span>{
-<span class="cstat-no" title="statement not covered" > setAuth(false);</span>
- }
- })
- .catch(<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etAuth(false))</span>;
- }, []);
-&nbsp;
- if (auth === null) {
- return &lt;div&gt;Loading...&lt;/div&gt;;
- }
-&nbsp;
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!auth) {
-<span class="cstat-no" title="statement not covered" > return &lt;Navigate to="/login" state={{ from: location }} replace /&gt;;</span>
- }
-&nbsp;
- return children;
-}
-&nbsp;
-import FeedList from './components/FeedList';
-import FeedItems from './components/FeedItems';
-import Settings from './components/Settings';
-&nbsp;
-interface DashboardProps {
- theme: string;
- setTheme: (t: string) =&gt; void;
- fontTheme: string;
- setFontTheme: (t: string) =&gt; void;
-}
-&nbsp;
-function Dashboard({ theme, setTheme, fontTheme, setFontTheme }: DashboardProps) {
- const [sidebarVisible, setSidebarVisible] = useState(window.innerWidth &gt; 768);
-&nbsp;
- useEffect(() =&gt; {
- const handleResize = <span class="fstat-no" title="function not covered" >() =&gt; {</span>
-<span class="cstat-no" title="statement not covered" > if (window.innerWidth &gt; 768) {</span>
-<span class="cstat-no" title="statement not covered" > setSidebarVisible(true);</span>
- } else {
-<span class="cstat-no" title="statement not covered" > setSidebarVisible(false);</span>
- }
- };
- window.addEventListener('resize', handleResize);
- return () =&gt; window.removeEventListener('resize', handleResize);
- }, []);
-&nbsp;
- return (
- &lt;div
- className={`dashboard ${sidebarVisible ? 'sidebar-visible' : <span class="branch-1 cbranch-no" title="branch not covered" >'sidebar-hidden'}</span> theme-${theme} font-${fontTheme}`}
- &gt;
- &lt;div className="dashboard-content"&gt;
- {(!sidebarVisible || window.innerWidth &lt;= 768) &amp;&amp; (
-<span class="branch-2 cbranch-no" title="branch not covered" > &lt;button</span>
- className="sidebar-toggle fixed-toggle"
- onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(!sidebarVisible)}</span>
- title={sidebarVisible ? "Hide Sidebar" : "Show Sidebar"}
- &gt;
- 🐱
- &lt;/button&gt;
- )}
- {sidebarVisible &amp;&amp; (
- &lt;div
- className="sidebar-backdrop"
- onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etSidebarVisible(false)}</span>
- /&gt;
- )}
- &lt;aside className={`dashboard-sidebar ${sidebarVisible ? '' : <span class="branch-1 cbranch-no" title="branch not covered" >'hidden'}</span>`}&gt;
- &lt;FeedList
- theme={theme}
- setTheme={setTheme}
- setSidebarVisible={setSidebarVisible}
- isMobile={window.innerWidth &lt;= 768}
- /&gt;
- &lt;/aside&gt;
- &lt;main className="dashboard-main"&gt;
- &lt;Routes&gt;
- &lt;Route path="/feed/:feedId" element={&lt;FeedItems /&gt;} /&gt;
- &lt;Route path="/tag/:tagName" element={&lt;FeedItems /&gt;} /&gt;
- &lt;Route path="/settings" element={&lt;Settings fontTheme={fontTheme} setFontTheme={setFontTheme} /&gt;} /&gt;
- &lt;Route path="/" element={&lt;FeedItems /&gt;} /&gt;
- &lt;/Routes&gt;
- &lt;/main&gt;
- &lt;/div&gt;
- &lt;/div&gt;
- );
-}
-&nbsp;
-function App() {
- const [theme, setTheme] = useState(localStorage.getItem('neko-theme') || 'light');
- const [fontTheme, setFontTheme] = useState(localStorage.getItem('neko-font-theme') || 'default');
-&nbsp;
- const handleSetTheme = <span class="fstat-no" title="function not covered" >(n</span>ewTheme: string) =&gt; {
-<span class="cstat-no" title="statement not covered" > setTheme(newTheme);</span>
-<span class="cstat-no" title="statement not covered" > localStorage.setItem('neko-theme', newTheme);</span>
- };
-&nbsp;
- const handleSetFontTheme = <span class="fstat-no" title="function not covered" >(n</span>ewFontTheme: string) =&gt; {
-<span class="cstat-no" title="statement not covered" > setFontTheme(newFontTheme);</span>
-<span class="cstat-no" title="statement not covered" > localStorage.setItem('neko-font-theme', newFontTheme);</span>
- };
-&nbsp;
- const basename = window.location.pathname.startsWith('/v2') ? '/v2' : <span class="branch-1 cbranch-no" title="branch not covered" >'/';</span>
-&nbsp;
- return (
- &lt;BrowserRouter basename={basename}&gt;
- &lt;Routes&gt;
- &lt;Route path="/login" element={&lt;Login /&gt;} /&gt;
- &lt;Route
- path="/*"
- element={
- &lt;RequireAuth&gt;
- &lt;Dashboard
- theme={theme}
- setTheme={handleSetTheme}
- fontTheme={fontTheme}
- setFontTheme={handleSetFontTheme}
- /&gt;
- &lt;/RequireAuth&gt;
- }
- /&gt;
- &lt;/Routes&gt;
- &lt;/BrowserRouter&gt;
- );
-}
-&nbsp;
-export default App;
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../sorter.js"></script>
- <script src="../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedItem.css.html b/frontend/coverage/src/components/FeedItem.css.html
deleted file mode 100644
index 192959f..0000000
--- a/frontend/coverage/src/components/FeedItem.css.html
+++ /dev/null
@@ -1,526 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedItem.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItem.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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>
-<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">.feed-item {
- padding: 1rem;
- margin-top: 5rem;
- list-style: none;
- border-bottom: none;
-}
-&nbsp;
-/* removed read/unread specific font-weight to keep it always bold as requested */
-&nbsp;
-.item-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- margin-bottom: 0.5rem;
-}
-&nbsp;
-.item-title {
- font-family: var(--font-heading);
- font-size: 1.8rem;
- font-weight: bold;
- text-decoration: none;
- color: var(--link-color);
- display: block;
- flex: 1;
-}
-&nbsp;
-.item-title:hover {
- text-decoration: none;
- color: var(--link-color);
-}
-&nbsp;
-.item-actions {
- display: flex;
- gap: 0.5rem;
- margin-left: 1rem;
-}
-&nbsp;
-/* Legacy controls were simple text/links, but buttons are fine if minimal */
-.star-btn {
- background: none;
- border: none;
- cursor: pointer;
- font-size: 1.25rem;
- padding: 0 0 0 0.5rem;
- vertical-align: middle;
- transition: color 0.2s;
- line-height: 1;
-}
-&nbsp;
-.star-btn.is-starred {
- color: blue;
-}
-&nbsp;
-.star-btn.is-unstarred {
- color: var(--text-color);
- opacity: 0.3;
-}
-&nbsp;
-.star-btn:hover {
- color: blue;
-}
-&nbsp;
-.action-btn {
- background: var(--sidebar-bg);
- border: 1px solid var(--border-color, #ccc);
- cursor: pointer;
- padding: 2px 6px;
- font-size: 1rem;
- color: blue;
- font-weight: bold;
-}
-&nbsp;
-.action-btn:hover {
- background-color: #eee;
-}
-&nbsp;
-.dateline {
- margin-top: 0;
- font-weight: normal;
- font-size: 0.75em;
- color: #ccc;
- margin-bottom: 1rem;
-}
-&nbsp;
-.dateline a {
- color: #ccc;
- text-decoration: none;
-}
-&nbsp;
-.item-description {
- color: var(--text-color);
- line-height: 1.5;
- font-size: 1rem;
- margin-top: 1rem;
-}
-&nbsp;
-.item-description img {
- max-width: 100%;
- height: auto;
- display: block;
- margin: 1rem 0;
-}
-&nbsp;
-.item-description blockquote {
- padding: 1rem 1rem 0 1rem;
- border-left: 4px solid var(--sidebar-bg);
- color: var(--text-color);
- opacity: 0.8;
- margin-left: 0;
-}
-&nbsp;
-.scrape-btn {
- background: var(--bg-color);
- border: 1px solid var(--border-color, #ccc);
- color: blue;
- cursor: pointer;
- font-family: var(--font-heading);
- font-weight: bold;
- font-size: 0.8rem;
- padding: 2px 6px;
- margin-left: 0.5rem;
-}
-&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 -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedItem.tsx.html b/frontend/coverage/src/components/FeedItem.tsx.html
deleted file mode 100644
index 6df1fec..0000000
--- a/frontend/coverage/src/components/FeedItem.tsx.html
+++ /dev/null
@@ -1,430 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedItem.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItem.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">78.12% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>25/32</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">86.95% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>20/23</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">83.33% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>10/12</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">80.64% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>25/31</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line medium'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">56x</span>
-<span class="cline-any cline-yes">56x</span>
-<span class="cline-any cline-neutral">&nbsp;</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">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">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>
-<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-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-no">&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-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-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">56x</span>
-<span class="cline-any cline-yes">1x</span>
-<span class="cline-any cline-yes">1x</span>
-<span class="cline-any cline-yes">1x</span>
-<span class="cline-any cline-neutral">&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>
-<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-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">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>
-<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-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">import { useState, useEffect } from 'react';
-import type { Item } from '../types';
-import './FeedItem.css';
-&nbsp;
-import { apiFetch } from '../utils';
-&nbsp;
-interface FeedItemProps {
- item: Item;
-}
-&nbsp;
-export default function FeedItem({ item: initialItem }: FeedItemProps) {
- const [item, setItem] = useState(initialItem);
- const [loading, setLoading] = useState(false);
-&nbsp;
- useEffect(() =&gt; {
- setItem(initialItem);
- }, [initialItem]);
-&nbsp;
- const toggleStar = () =&gt; {
- updateItem({ ...item, starred: !item.starred });
- };
-&nbsp;
- const updateItem = (newItem: Item) =&gt; {
- setLoading(true);
- // Optimistic update
- const previousItem = item;
- setItem(newItem);
-&nbsp;
- apiFetch(`/api/item/${newItem._id}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- _id: newItem._id,
- read: newItem.read,
- starred: newItem.starred,
- }),
- })
- .then((res) =&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 update item');</span>
- }
- return res.json();
- })
- .then(() =&gt; {
- // Confirm with server response if needed, but for now we trust the optimistic update
- // or we could setItem(updated) if the server returns the full object
- setLoading(false);
- })
- .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; {
-<span class="cstat-no" title="statement not covered" > console.error('Error updating item:', err);</span>
- // Revert on error
-<span class="cstat-no" title="statement not covered" > setItem(previousItem);</span>
-<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
- });
- };
-&nbsp;
- const loadFullContent = (e: React.MouseEvent) =&gt; {
- e.stopPropagation();
- setLoading(true);
- apiFetch(`/api/item/${item._id}`)
- .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 full content');</span>
- return res.json();
- })
- .then((data) =&gt; {
- setItem({ ...item, ...data });
- setLoading(false);
- })
- .catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; {
-<span class="cstat-no" title="statement not covered" > console.error('Error fetching full content:', err);</span>
-<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
- });
- };
-&nbsp;
- return (
- &lt;li className={`feed-item ${item.read ? 'read' : 'unread'} ${loading ? 'loading' : ''}`}&gt;
- &lt;div className="item-header"&gt;
- &lt;a href={item.url} target="_blank" rel="noopener noreferrer" className="item-title"&gt;
- {item.title || <span class="branch-1 cbranch-no" title="branch not covered" >'(No Title)'}</span>
- &lt;/a&gt;
- &lt;button
- onClick={(e) =&gt; {
- e.stopPropagation();
- toggleStar();
- }}
- className={`star-btn ${item.starred ? 'is-starred' : 'is-unstarred'}`}
- title={item.starred ? 'Unstar' : 'Star'}
- &gt;
- ★
- &lt;/button&gt;
- &lt;/div&gt;
- &lt;div className="dateline"&gt;
- &lt;a href={item.url} target="_blank" rel="noopener noreferrer"&gt;
- {new Date(item.publish_date).toLocaleDateString()}
- {item.feed_title &amp;&amp; ` - ${item.feed_title}`}
- &lt;/a&gt;
- &lt;div className="item-actions" style={{ display: 'inline-block', float: 'right' }}&gt;
- {!item.full_content &amp;&amp; (
- &lt;button onClick={loadFullContent} className="scrape-btn" title="Load Full Content"&gt;
- text
- &lt;/button&gt;
- )}
- &lt;/div&gt;
- &lt;/div&gt;
- {(item.full_content || item.description) &amp;&amp; (
- &lt;div
- className="item-description"
- dangerouslySetInnerHTML={{ __html: item.full_content || item.description }}
- /&gt;
- )}
- &lt;/li&gt;
- );
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedItems.css.html b/frontend/coverage/src/components/FeedItems.css.html
deleted file mode 100644
index 66a3307..0000000
--- a/frontend/coverage/src/components/FeedItems.css.html
+++ /dev/null
@@ -1,151 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedItems.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItems.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">.feed-items {
- padding: 1rem 0;
- /* Removing horizontal padding to avoid double-padding with FeedItem */
-}
-&nbsp;
-.feed-items h2 {
- margin-top: 0;
- border-bottom: 2px solid var(--border-color);
- padding-bottom: 0.5rem;
-}
-&nbsp;
-.item-list {
- list-style: none;
- padding: 0;
-}
-&nbsp;
-.loading-more {
- padding: 2rem;
- text-align: center;
- color: #888;
- font-size: 0.9rem;
- min-height: 50px;
-}</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedItems.tsx.html b/frontend/coverage/src/components/FeedItems.tsx.html
deleted file mode 100644
index 9811743..0000000
--- a/frontend/coverage/src/components/FeedItems.tsx.html
+++ /dev/null
@@ -1,838 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedItems.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedItems.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">89.23% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>116/130</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">76.19% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>64/84</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">87.09% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>27/31</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">89.07% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>106/119</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line high'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a>
-<a name='L149'></a><a href='#L149'>149</a>
-<a name='L150'></a><a href='#L150'>150</a>
-<a name='L151'></a><a href='#L151'>151</a>
-<a name='L152'></a><a href='#L152'>152</a>
-<a name='L153'></a><a href='#L153'>153</a>
-<a name='L154'></a><a href='#L154'>154</a>
-<a name='L155'></a><a href='#L155'>155</a>
-<a name='L156'></a><a href='#L156'>156</a>
-<a name='L157'></a><a href='#L157'>157</a>
-<a name='L158'></a><a href='#L158'>158</a>
-<a name='L159'></a><a href='#L159'>159</a>
-<a name='L160'></a><a href='#L160'>160</a>
-<a name='L161'></a><a href='#L161'>161</a>
-<a name='L162'></a><a href='#L162'>162</a>
-<a name='L163'></a><a href='#L163'>163</a>
-<a name='L164'></a><a href='#L164'>164</a>
-<a name='L165'></a><a href='#L165'>165</a>
-<a name='L166'></a><a href='#L166'>166</a>
-<a name='L167'></a><a href='#L167'>167</a>
-<a name='L168'></a><a href='#L168'>168</a>
-<a name='L169'></a><a href='#L169'>169</a>
-<a name='L170'></a><a href='#L170'>170</a>
-<a name='L171'></a><a href='#L171'>171</a>
-<a name='L172'></a><a href='#L172'>172</a>
-<a name='L173'></a><a href='#L173'>173</a>
-<a name='L174'></a><a href='#L174'>174</a>
-<a name='L175'></a><a href='#L175'>175</a>
-<a name='L176'></a><a href='#L176'>176</a>
-<a name='L177'></a><a href='#L177'>177</a>
-<a name='L178'></a><a href='#L178'>178</a>
-<a name='L179'></a><a href='#L179'>179</a>
-<a name='L180'></a><a href='#L180'>180</a>
-<a name='L181'></a><a href='#L181'>181</a>
-<a name='L182'></a><a href='#L182'>182</a>
-<a name='L183'></a><a href='#L183'>183</a>
-<a name='L184'></a><a href='#L184'>184</a>
-<a name='L185'></a><a href='#L185'>185</a>
-<a name='L186'></a><a href='#L186'>186</a>
-<a name='L187'></a><a href='#L187'>187</a>
-<a name='L188'></a><a href='#L188'>188</a>
-<a name='L189'></a><a href='#L189'>189</a>
-<a name='L190'></a><a href='#L190'>190</a>
-<a name='L191'></a><a href='#L191'>191</a>
-<a name='L192'></a><a href='#L192'>192</a>
-<a name='L193'></a><a href='#L193'>193</a>
-<a name='L194'></a><a href='#L194'>194</a>
-<a name='L195'></a><a href='#L195'>195</a>
-<a name='L196'></a><a href='#L196'>196</a>
-<a name='L197'></a><a href='#L197'>197</a>
-<a name='L198'></a><a href='#L198'>198</a>
-<a name='L199'></a><a href='#L199'>199</a>
-<a name='L200'></a><a href='#L200'>200</a>
-<a name='L201'></a><a href='#L201'>201</a>
-<a name='L202'></a><a href='#L202'>202</a>
-<a name='L203'></a><a href='#L203'>203</a>
-<a name='L204'></a><a href='#L204'>204</a>
-<a name='L205'></a><a href='#L205'>205</a>
-<a name='L206'></a><a href='#L206'>206</a>
-<a name='L207'></a><a href='#L207'>207</a>
-<a name='L208'></a><a href='#L208'>208</a>
-<a name='L209'></a><a href='#L209'>209</a>
-<a name='L210'></a><a href='#L210'>210</a>
-<a name='L211'></a><a href='#L211'>211</a>
-<a name='L212'></a><a href='#L212'>212</a>
-<a name='L213'></a><a href='#L213'>213</a>
-<a name='L214'></a><a href='#L214'>214</a>
-<a name='L215'></a><a href='#L215'>215</a>
-<a name='L216'></a><a href='#L216'>216</a>
-<a name='L217'></a><a href='#L217'>217</a>
-<a name='L218'></a><a href='#L218'>218</a>
-<a name='L219'></a><a href='#L219'>219</a>
-<a name='L220'></a><a href='#L220'>220</a>
-<a name='L221'></a><a href='#L221'>221</a>
-<a name='L222'></a><a href='#L222'>222</a>
-<a name='L223'></a><a href='#L223'>223</a>
-<a name='L224'></a><a href='#L224'>224</a>
-<a name='L225'></a><a href='#L225'>225</a>
-<a name='L226'></a><a href='#L226'>226</a>
-<a name='L227'></a><a href='#L227'>227</a>
-<a name='L228'></a><a href='#L228'>228</a>
-<a name='L229'></a><a href='#L229'>229</a>
-<a name='L230'></a><a href='#L230'>230</a>
-<a name='L231'></a><a href='#L231'>231</a>
-<a name='L232'></a><a href='#L232'>232</a>
-<a name='L233'></a><a href='#L233'>233</a>
-<a name='L234'></a><a href='#L234'>234</a>
-<a name='L235'></a><a href='#L235'>235</a>
-<a name='L236'></a><a href='#L236'>236</a>
-<a name='L237'></a><a href='#L237'>237</a>
-<a name='L238'></a><a href='#L238'>238</a>
-<a name='L239'></a><a href='#L239'>239</a>
-<a name='L240'></a><a href='#L240'>240</a>
-<a name='L241'></a><a href='#L241'>241</a>
-<a name='L242'></a><a href='#L242'>242</a>
-<a name='L243'></a><a href='#L243'>243</a>
-<a name='L244'></a><a href='#L244'>244</a>
-<a name='L245'></a><a href='#L245'>245</a>
-<a name='L246'></a><a href='#L246'>246</a>
-<a name='L247'></a><a href='#L247'>247</a>
-<a name='L248'></a><a href='#L248'>248</a>
-<a name='L249'></a><a href='#L249'>249</a>
-<a name='L250'></a><a href='#L250'>250</a>
-<a name='L251'></a><a href='#L251'>251</a>
-<a name='L252'></a><a href='#L252'>252</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">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">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">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">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">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">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">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">11x</span>
-<span class="cline-any cline-no">&nbsp;</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">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">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">11x</span>
-<span class="cline-any cline-neutral">&nbsp;</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">10x</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">3x</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">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>
-<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">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-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-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>
-<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-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">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>
-<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-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">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">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">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>
-<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-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">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-neutral">&nbsp;</span>
-<span class="cline-any cline-yes">36x</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-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-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-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">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-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">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-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>
-<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-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">import { useEffect, useState } from 'react';
-import { useParams, useSearchParams } from 'react-router-dom';
-import type { Item } from '../types';
-import FeedItem from './FeedItem';
-import './FeedItems.css';
-import { apiFetch } from '../utils';
-&nbsp;
-export default function FeedItems() {
- const { feedId, tagName } = useParams&lt;{ feedId: string; tagName: string }&gt;();
- const [searchParams] = useSearchParams();
- const filterFn = searchParams.get('filter') || 'unread';
-&nbsp;
- const [items, setItems] = useState&lt;Item[]&gt;([]);
- const [loading, setLoading] = useState(true);
- const [loadingMore, setLoadingMore] = useState(false);
- const [hasMore, setHasMore] = useState(true);
- const [error, setError] = useState('');
- const [selectedIndex, setSelectedIndex] = useState(-1);
-&nbsp;
- const fetchItems = (maxId?: string) =&gt; {
- if (maxId) {
- setLoadingMore(true);
- } else {
- setLoading(true);
- setItems([]);
- }
- setError('');
-&nbsp;
- let url = '/api/stream';
- const params = new URLSearchParams();
-&nbsp;
- if (feedId) {
- params.append('feed_id', feedId);
- } else if (tagName) {
- params.append('tag', tagName);
- }
-&nbsp;
- if (maxId) {
- params.append('max_id', maxId);
- }
-&nbsp;
- // Apply filters
- const searchQuery = searchParams.get('q');
- <span class="missing-if-branch" title="if path not taken" >I</span>if (searchQuery) {
-<span class="cstat-no" title="statement not covered" > params.append('q', searchQuery);</span>
- }
-&nbsp;
- <span class="missing-if-branch" title="if path not taken" >I</span>if (filterFn === 'all') {
-<span class="cstat-no" title="statement not covered" > params.append('read_filter', 'all');</span>
- <span class="missing-if-branch" title="if path not taken" >I</span>} else if (filterFn === 'starred') {
-<span class="cstat-no" title="statement not covered" > params.append('starred', 'true');</span>
-<span class="cstat-no" title="statement not covered" > params.append('read_filter', 'all');</span>
- } else {
- // default to unread
- <span class="missing-if-branch" title="else path not taken" >E</span>if (!searchQuery) {
- params.append('read_filter', 'unread');
- }
- }
-&nbsp;
- const queryString = params.toString();
- <span class="missing-if-branch" title="else path not taken" >E</span>if (queryString) {
- url += `?${queryString}`;
- }
-&nbsp;
- apiFetch(url)
- .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 items');</span>
- }
- return res.json();
- })
- .then((data) =&gt; {
- if (maxId) {
- setItems((prev) =&gt; [...prev, ...data]);
- } else {
- setItems(data);
- }
- setHasMore(data.length &gt; 0);
- setLoading(false);
- setLoadingMore(false);
- })
- .catch((err) =&gt; {
- setError(err.message);
- setLoading(false);
- setLoadingMore(false);
- });
- };
-&nbsp;
- useEffect(() =&gt; {
- fetchItems();
- setSelectedIndex(-1);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [feedId, tagName, filterFn, searchParams]);
-&nbsp;
-&nbsp;
- const scrollToItem = (index: number) =&gt; {
- const element = document.getElementById(`item-${index}`);
- <span class="missing-if-branch" title="else path not taken" >E</span>if (element) {
- element.scrollIntoView({ behavior: 'auto', block: 'start' });
- }
- };
-&nbsp;
- const markAsRead = (item: Item) =&gt; {
- const updatedItem = { ...item, read: true };
- // Optimistic update
- setItems((prevItems) =&gt; prevItems.map((i) =&gt; (i._id === item._id ? updatedItem : i)));
-&nbsp;
- apiFetch(`/api/item/${item._id}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ read: true, starred: item.starred }),
- }).catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; <span class="cstat-no" title="statement not covered" >console.error('Failed to mark read', err))</span>;
- };
-&nbsp;
- const toggleStar = (item: Item) =&gt; {
- const updatedItem = { ...item, starred: !item.starred };
- // Optimistic update
- setItems((prevItems) =&gt; prevItems.map((i) =&gt; (i._id === item._id ? updatedItem : i)));
-&nbsp;
- apiFetch(`/api/item/${item._id}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ read: item.read, starred: !item.starred }),
- }).catch(<span class="fstat-no" title="function not covered" >(e</span>rr) =&gt; <span class="cstat-no" title="statement not covered" >console.error('Failed to toggle star', err))</span>;
- };
-&nbsp;
- useEffect(() =&gt; {
- const handleKeyDown = (e: KeyboardEvent) =&gt; {
- <span class="missing-if-branch" title="if path not taken" >I</span>if (items.length === 0) <span class="cstat-no" title="statement not covered" >return;</span>
-&nbsp;
- if (e.key === 'j') {
- setSelectedIndex((prev) =&gt; {
- const nextIndex = Math.min(prev + 1, items.length - 1);
- <span class="missing-if-branch" title="else path not taken" >E</span>if (nextIndex !== prev) {
- const item = items[nextIndex];
- if (!item.read) {
- markAsRead(item);
- }
- scrollToItem(nextIndex);
- }
-&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') {
-<span class="cstat-no" title="statement not covered" > setSelectedIndex(<span class="fstat-no" title="function not covered" >(p</span>rev) =&gt; {</span>
- const nextIndex = <span class="cstat-no" title="statement not covered" >Math.max(prev - 1, 0);</span>
-<span class="cstat-no" title="statement not covered" > if (nextIndex !== prev) {</span>
-<span class="cstat-no" title="statement not covered" > scrollToItem(nextIndex);</span>
- }
-<span class="cstat-no" title="statement not covered" > return nextIndex;</span>
- });
- <span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 's') {
- setSelectedIndex((currentIndex) =&gt; {
- <span class="missing-if-branch" title="else path not taken" >E</span>if (currentIndex &gt;= 0 &amp;&amp; currentIndex &lt; items.length) {
- toggleStar(items[currentIndex]);
- }
- return currentIndex;
- });
- }
- };
-&nbsp;
- window.addEventListener('keydown', handleKeyDown);
- return () =&gt; window.removeEventListener('keydown', handleKeyDown);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [items, hasMore, loadingMore]);
-&nbsp;
-&nbsp;
-&nbsp;
- useEffect(() =&gt; {
- // Observer for marking items as read
- const itemObserver = new IntersectionObserver(
- (entries) =&gt; {
- entries.forEach((entry) =&gt; {
- // 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'));
- <span class="missing-if-branch" title="else path not taken" >E</span>if (!isNaN(index) &amp;&amp; index &gt;= 0 &amp;&amp; index &lt; items.length) {
- const item = items[index];
- <span class="missing-if-branch" title="else path not taken" >E</span>if (!item.read) {
- markAsRead(item);
- }
- }
- }
- });
- },
- { root: null, threshold: 0 }
- );
-&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) itemObserver.observe(el);
- });
-&nbsp;
- const sentinel = document.getElementById('load-more-sentinel');
- if (sentinel) sentinelObserver.observe(sentinel);
-&nbsp;
- 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;;
- if (error) return &lt;div className="feed-items-error"&gt;Error: {error}&lt;/div&gt;;
-&nbsp;
- return (
- &lt;div className="feed-items"&gt;
- {items.length === 0 ? (
-<span class="branch-0 cbranch-no" title="branch not covered" > &lt;p&gt;No items found.&lt;/p&gt;</span>
- ) : (
- &lt;ul className="item-list"&gt;
- {items.map((item, index) =&gt; (
- &lt;div
- id={`item-${index}`}
- key={item._id}
- data-index={index}
- data-selected={index === selectedIndex}
- onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etSelectedIndex(index)}</span>
- &gt;
- &lt;FeedItem item={item} /&gt;
- &lt;/div&gt;
- ))}
- {hasMore &amp;&amp; (
- &lt;div id="load-more-sentinel" className="loading-more"&gt;
- {loadingMore ? 'Loading more...' : ''}
- &lt;/div&gt;
- )}
- &lt;/ul&gt;
- )}
- &lt;/div&gt;
- );
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedList.css.html b/frontend/coverage/src/components/FeedList.css.html
deleted file mode 100644
index d892e77..0000000
--- a/frontend/coverage/src/components/FeedList.css.html
+++ /dev/null
@@ -1,724 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedList.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedList.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a>
-<a name='L149'></a><a href='#L149'>149</a>
-<a name='L150'></a><a href='#L150'>150</a>
-<a name='L151'></a><a href='#L151'>151</a>
-<a name='L152'></a><a href='#L152'>152</a>
-<a name='L153'></a><a href='#L153'>153</a>
-<a name='L154'></a><a href='#L154'>154</a>
-<a name='L155'></a><a href='#L155'>155</a>
-<a name='L156'></a><a href='#L156'>156</a>
-<a name='L157'></a><a href='#L157'>157</a>
-<a name='L158'></a><a href='#L158'>158</a>
-<a name='L159'></a><a href='#L159'>159</a>
-<a name='L160'></a><a href='#L160'>160</a>
-<a name='L161'></a><a href='#L161'>161</a>
-<a name='L162'></a><a href='#L162'>162</a>
-<a name='L163'></a><a href='#L163'>163</a>
-<a name='L164'></a><a href='#L164'>164</a>
-<a name='L165'></a><a href='#L165'>165</a>
-<a name='L166'></a><a href='#L166'>166</a>
-<a name='L167'></a><a href='#L167'>167</a>
-<a name='L168'></a><a href='#L168'>168</a>
-<a name='L169'></a><a href='#L169'>169</a>
-<a name='L170'></a><a href='#L170'>170</a>
-<a name='L171'></a><a href='#L171'>171</a>
-<a name='L172'></a><a href='#L172'>172</a>
-<a name='L173'></a><a href='#L173'>173</a>
-<a name='L174'></a><a href='#L174'>174</a>
-<a name='L175'></a><a href='#L175'>175</a>
-<a name='L176'></a><a href='#L176'>176</a>
-<a name='L177'></a><a href='#L177'>177</a>
-<a name='L178'></a><a href='#L178'>178</a>
-<a name='L179'></a><a href='#L179'>179</a>
-<a name='L180'></a><a href='#L180'>180</a>
-<a name='L181'></a><a href='#L181'>181</a>
-<a name='L182'></a><a href='#L182'>182</a>
-<a name='L183'></a><a href='#L183'>183</a>
-<a name='L184'></a><a href='#L184'>184</a>
-<a name='L185'></a><a href='#L185'>185</a>
-<a name='L186'></a><a href='#L186'>186</a>
-<a name='L187'></a><a href='#L187'>187</a>
-<a name='L188'></a><a href='#L188'>188</a>
-<a name='L189'></a><a href='#L189'>189</a>
-<a name='L190'></a><a href='#L190'>190</a>
-<a name='L191'></a><a href='#L191'>191</a>
-<a name='L192'></a><a href='#L192'>192</a>
-<a name='L193'></a><a href='#L193'>193</a>
-<a name='L194'></a><a href='#L194'>194</a>
-<a name='L195'></a><a href='#L195'>195</a>
-<a name='L196'></a><a href='#L196'>196</a>
-<a name='L197'></a><a href='#L197'>197</a>
-<a name='L198'></a><a href='#L198'>198</a>
-<a name='L199'></a><a href='#L199'>199</a>
-<a name='L200'></a><a href='#L200'>200</a>
-<a name='L201'></a><a href='#L201'>201</a>
-<a name='L202'></a><a href='#L202'>202</a>
-<a name='L203'></a><a href='#L203'>203</a>
-<a name='L204'></a><a href='#L204'>204</a>
-<a name='L205'></a><a href='#L205'>205</a>
-<a name='L206'></a><a href='#L206'>206</a>
-<a name='L207'></a><a href='#L207'>207</a>
-<a name='L208'></a><a href='#L208'>208</a>
-<a name='L209'></a><a href='#L209'>209</a>
-<a name='L210'></a><a href='#L210'>210</a>
-<a name='L211'></a><a href='#L211'>211</a>
-<a name='L212'></a><a href='#L212'>212</a>
-<a name='L213'></a><a href='#L213'>213</a>
-<a name='L214'></a><a href='#L214'>214</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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>
-<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>
-<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">.feed-list {
- padding: 1rem;
- font-family: var(--font-heading);
- color: #777;
- /* specific v1 color */
- font-size: 0.8rem;
- background: var(--sidebar-bg);
- min-height: 100%;
- flex: 1;
-}
-&nbsp;
-.feed-list h1.logo {
- font-size: 2rem;
- /* match v1 */
- margin: 0 0 1rem 0;
- line-height: 1;
- cursor: pointer;
- position: sticky;
- top: 0;
- background: var(--sidebar-bg);
- z-index: 10;
- padding-bottom: 0.5rem;
- color: var(--text-color);
-}
-&nbsp;
-/* Override logo color if necessary for themes */
-.theme-light .feed-list h1.logo {
- color: #333;
-}
-&nbsp;
-.theme-dark .feed-list h1.logo {
- color: #eee;
-}
-&nbsp;
-.search-section {
- margin-bottom: 1rem;
-}
-&nbsp;
-.search-input {
- width: 100%;
- padding: 0.25rem;
- border: 1px solid var(--border-color, #999);
- background: var(--bg-color);
- color: var(--text-color);
- font-size: 0.8rem;
- font-family: inherit;
- border-radius: 0;
- /* v1 didn't have rounded inputs usually */
-}
-&nbsp;
-.section-header {
- font-size: 1rem;
- /* v1 h4 size? */
- font-weight: bold;
- margin: 1rem 0 0.25rem 0;
- cursor: pointer;
- user-select: none;
- font-family: var(--font-heading);
- color: #333;
- /* Darker than list items */
- text-transform: lowercase;
- font-variant: small-caps;
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-&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,
-.tag-list-items,
-.feed-list-items,
-.nav-list {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-&nbsp;
-.filter-list li,
-.nav-list li {
- margin-bottom: 0.1rem;
-}
-&nbsp;
-.filter-list a,
-.nav-list a,
-.tag-link,
-.feed-title,
-.logout-link {
- text-decoration: none;
- color: var(--link-color, blue);
- font-size: 0.8rem;
- /* Matches v1 .75em approx */
- display: block;
- cursor: pointer;
- background: none;
- border: none;
- padding: 0;
- font-family: inherit;
- font-variant: small-caps;
- text-transform: lowercase;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-&nbsp;
-.filter-list a:hover,
-.nav-list a:hover,
-.tag-link:hover,
-.feed-title:hover,
-.logout-link:hover {
- text-decoration: underline;
- color: var(--link-color, blue);
-}
-&nbsp;
-.filter-list a.active,
-.tag-link.active,
-.feed-title.active {
- font-weight: bold;
- color: #000;
- /* Active state black */
-}
-&nbsp;
-.tag-item,
-.sidebar-feed-item {
- margin-bottom: 0;
-}
-&nbsp;
-.feed-category {
- display: none;
-}
-&nbsp;
-.nav-section {
- margin-top: 2rem;
- border-top: 1px solid var(--border-color, #eee);
- padding-top: 1rem;
-}
-&nbsp;
-.logout-link {
- text-align: left;
- width: 100%;
- color: #777;
- 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 {
- margin-top: 1rem;
-}
-&nbsp;
-.theme-selector {
- display: flex;
- gap: 0.5rem;
- margin-top: 0.5rem;
-}
-&nbsp;
-.theme-selector button {
- background: rgba(0, 0, 0, 0.05);
- border: none;
- cursor: pointer;
- padding: 0.4rem;
- font-size: 1rem;
- border-radius: 8px;
- line-height: 1;
- transition: all 0.2s ease;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-&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 */
-.dashboard-sidebar::-webkit-scrollbar {
- width: 4px;
-}
-&nbsp;
-.dashboard-sidebar::-webkit-scrollbar-thumb {
- background-color: var(--border-color, #999);
-}</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/FeedList.tsx.html b/frontend/coverage/src/components/FeedList.tsx.html
deleted file mode 100644
index 4061422..0000000
--- a/frontend/coverage/src/components/FeedList.tsx.html
+++ /dev/null
@@ -1,721 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/FeedList.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> FeedList.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">87.27% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>48/55</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">70% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>35/50</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">78.94% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>15/19</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">90% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>45/50</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line high'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a>
-<a name='L149'></a><a href='#L149'>149</a>
-<a name='L150'></a><a href='#L150'>150</a>
-<a name='L151'></a><a href='#L151'>151</a>
-<a name='L152'></a><a href='#L152'>152</a>
-<a name='L153'></a><a href='#L153'>153</a>
-<a name='L154'></a><a href='#L154'>154</a>
-<a name='L155'></a><a href='#L155'>155</a>
-<a name='L156'></a><a href='#L156'>156</a>
-<a name='L157'></a><a href='#L157'>157</a>
-<a name='L158'></a><a href='#L158'>158</a>
-<a name='L159'></a><a href='#L159'>159</a>
-<a name='L160'></a><a href='#L160'>160</a>
-<a name='L161'></a><a href='#L161'>161</a>
-<a name='L162'></a><a href='#L162'>162</a>
-<a name='L163'></a><a href='#L163'>163</a>
-<a name='L164'></a><a href='#L164'>164</a>
-<a name='L165'></a><a href='#L165'>165</a>
-<a name='L166'></a><a href='#L166'>166</a>
-<a name='L167'></a><a href='#L167'>167</a>
-<a name='L168'></a><a href='#L168'>168</a>
-<a name='L169'></a><a href='#L169'>169</a>
-<a name='L170'></a><a href='#L170'>170</a>
-<a name='L171'></a><a href='#L171'>171</a>
-<a name='L172'></a><a href='#L172'>172</a>
-<a name='L173'></a><a href='#L173'>173</a>
-<a name='L174'></a><a href='#L174'>174</a>
-<a name='L175'></a><a href='#L175'>175</a>
-<a name='L176'></a><a href='#L176'>176</a>
-<a name='L177'></a><a href='#L177'>177</a>
-<a name='L178'></a><a href='#L178'>178</a>
-<a name='L179'></a><a href='#L179'>179</a>
-<a name='L180'></a><a href='#L180'>180</a>
-<a name='L181'></a><a href='#L181'>181</a>
-<a name='L182'></a><a href='#L182'>182</a>
-<a name='L183'></a><a href='#L183'>183</a>
-<a name='L184'></a><a href='#L184'>184</a>
-<a name='L185'></a><a href='#L185'>185</a>
-<a name='L186'></a><a href='#L186'>186</a>
-<a name='L187'></a><a href='#L187'>187</a>
-<a name='L188'></a><a href='#L188'>188</a>
-<a name='L189'></a><a href='#L189'>189</a>
-<a name='L190'></a><a href='#L190'>190</a>
-<a name='L191'></a><a href='#L191'>191</a>
-<a name='L192'></a><a href='#L192'>192</a>
-<a name='L193'></a><a href='#L193'>193</a>
-<a name='L194'></a><a href='#L194'>194</a>
-<a name='L195'></a><a href='#L195'>195</a>
-<a name='L196'></a><a href='#L196'>196</a>
-<a name='L197'></a><a href='#L197'>197</a>
-<a name='L198'></a><a href='#L198'>198</a>
-<a name='L199'></a><a href='#L199'>199</a>
-<a name='L200'></a><a href='#L200'>200</a>
-<a name='L201'></a><a href='#L201'>201</a>
-<a name='L202'></a><a href='#L202'>202</a>
-<a name='L203'></a><a href='#L203'>203</a>
-<a name='L204'></a><a href='#L204'>204</a>
-<a name='L205'></a><a href='#L205'>205</a>
-<a name='L206'></a><a href='#L206'>206</a>
-<a name='L207'></a><a href='#L207'>207</a>
-<a name='L208'></a><a href='#L208'>208</a>
-<a name='L209'></a><a href='#L209'>209</a>
-<a name='L210'></a><a href='#L210'>210</a>
-<a name='L211'></a><a href='#L211'>211</a>
-<a name='L212'></a><a href='#L212'>212</a>
-<a name='L213'></a><a href='#L213'>213</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">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">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-neutral">&nbsp;</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">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-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">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">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-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">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>
-<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-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-yes">4x</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-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-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-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-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>
-<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">import { useEffect, useState } from 'react';
-import { Link, useNavigate, useSearchParams, useLocation, useParams } from 'react-router-dom';
-import type { Feed, Category } from '../types';
-import './FeedList.css';
-import './FeedListVariants.css';
-import { apiFetch } from '../utils';
-&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 = (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;
- const toggleFeeds = () =&gt; {
- 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() 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() as Promise&lt;Category[]&gt;;
- }),
- ])
- .then(([feedsData, tagsData]) =&gt; {
- setFeeds(feedsData);
- setTags(tagsData);
- setLoading(false);
- })
- .catch((err) =&gt; {
- setError(err.message);
- setLoading(false);
- });
- }, []);
-&nbsp;
- if (loading) return &lt;div className="feed-list-loading"&gt;Loading feeds...&lt;/div&gt;;
- if (error) return &lt;div className="feed-list-error"&gt;Error: {error}&lt;/div&gt;;
-&nbsp;
- const handleLogout = () =&gt; {
- apiFetch('/api/logout', { method: 'POST' }).then(() =&gt; (window.location.href = '/v2/login'));
- };
-&nbsp;
- return (
- &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;
-&nbsp;
- &lt;div className="search-section"&gt;
- &lt;form onSubmit={handleSearch} className="search-form"&gt;
- &lt;input
- type="search"
- placeholder="search..."
- value={searchQuery}
- onChange={(e) =&gt; setSearchQuery(e.target.value)}
- className="search-input"
- /&gt;
- &lt;/form&gt;
- &lt;/div&gt;
-&nbsp;
- &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" >''} 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>'} 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>'} onClick={handleLinkClick}&gt;
- starred
- &lt;/Link&gt;
- &lt;/li&gt;
- &lt;/ul&gt;
- &lt;/div&gt;
-&nbsp;
- &lt;div className="tag-section"&gt;
- &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;
- {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;
- &lt;span className={`caret ${feedsExpanded ? 'expanded' : ''}`}&gt;▶&lt;/span&gt; Feeds
- &lt;/h4&gt;
- {feedsExpanded &amp;&amp;
- (feeds.length === 0 ? (
- &lt;p&gt;No feeds found.&lt;/p&gt;
- ) : (
- &lt;ul className="feed-list-items"&gt;
- {feeds.map((feed) =&gt; (
- &lt;li key={feed._id} className="sidebar-feed-item"&gt;
- &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;
- &lt;/li&gt;
- ))}
- &lt;/ul&gt;
- ))}
- &lt;/div&gt;
-&nbsp;
- &lt;div className="nav-section"&gt;
- &lt;ul className="nav-list"&gt;
- &lt;li&gt;
- &lt;Link to="/settings" className="nav-link" onClick={handleLinkClick}&gt;
- settings
- &lt;/Link&gt;
- &lt;/li&gt;
- &lt;li&gt;
- &lt;button onClick={handleLogout} className="logout-link"&gt;
- logout
- &lt;/button&gt;
- &lt;/li&gt;
- &lt;/ul&gt;
- &lt;/div&gt;
-&nbsp;
- &lt;div className="theme-section"&gt;
- &lt;div className="theme-selector"&gt;
- &lt;button
- onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etTheme('light')}</span>
- className={theme === 'light' ? 'active' : <span class="branch-1 cbranch-no" title="branch not covered" >''}</span>
- title="Light Theme"
- &gt;
- ☀️
- &lt;/button&gt;
- &lt;button
- onClick={<span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >s</span>etTheme('dark')}</span>
- className={theme === 'dark' ? <span class="branch-0 cbranch-no" title="branch not covered" >'active' : '</span>'}
- title="Dark Theme"
- &gt;
- 🌙
- &lt;/button&gt;
- &lt;/div&gt;
- &lt;/div&gt;
- &lt;/div&gt;
- );
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/Login.css.html b/frontend/coverage/src/components/Login.css.html
deleted file mode 100644
index 140a86b..0000000
--- a/frontend/coverage/src/components/Login.css.html
+++ /dev/null
@@ -1,274 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/Login.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Login.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">.login-container {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh;
- background-color: #f5f5f5;
-}
-&nbsp;
-.login-form {
- background: white;
- padding: 2rem;
- border-radius: 8px;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
- width: 100%;
- max-width: 400px;
-}
-&nbsp;
-.login-form h1 {
- margin-bottom: 2rem;
- text-align: center;
- color: #333;
-}
-&nbsp;
-.form-group {
- margin-bottom: 1.5rem;
-}
-&nbsp;
-.form-group label {
- display: block;
- margin-bottom: 0.5rem;
- font-weight: bold;
- color: #555;
-}
-&nbsp;
-.form-group input {
- width: 100%;
- padding: 0.75rem;
- border: 1px solid #ddd;
- border-radius: 4px;
- font-size: 1rem;
-}
-&nbsp;
-.error-message {
- color: #dc3545;
- margin-bottom: 1rem;
- text-align: center;
-}
-&nbsp;
-button[type='submit'] {
- width: 100%;
- padding: 0.75rem;
- background-color: #007bff;
- color: white;
- border: none;
- border-radius: 4px;
- font-size: 1rem;
- cursor: pointer;
- transition: background-color 0.2s;
-}
-&nbsp;
-button[type='submit']:hover {
- background-color: #0056b3;
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/Login.tsx.html b/frontend/coverage/src/components/Login.tsx.html
deleted file mode 100644
index 111dcba..0000000
--- a/frontend/coverage/src/components/Login.tsx.html
+++ /dev/null
@@ -1,286 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/Login.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Login.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">100% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>20/20</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">83.33% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>5/6</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">100% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>4/4</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">100% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>20/20</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line high'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">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">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>
-<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-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>
-<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-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-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">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>
-<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>
-<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">import { useState, type FormEvent } from 'react';
-import { useNavigate } from 'react-router-dom';
-import './Login.css';
-&nbsp;
-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();
-&nbsp;
- const handleSubmit = async (e: FormEvent) =&gt; {
- e.preventDefault();
- setError('');
-&nbsp;
- 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', {
- method: 'POST',
- body: params,
- });
-&nbsp;
- if (res.ok) {
- navigate('/');
- } else {
- const data = await res.json();
- setError(data.message || <span class="branch-1 cbranch-no" title="branch not covered" >'Login failed')</span>;
- }
- } catch (_err) {
- setError('Network error');
- }
- };
-&nbsp;
- return (
- &lt;div className="login-container"&gt;
- &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"
- type="password"
- value={password}
- onChange={(e) =&gt; setPassword(e.target.value)}
- autoFocus
- /&gt;
- &lt;/div&gt;
- {error &amp;&amp; &lt;div className="error-message"&gt;{error}&lt;/div&gt;}
- &lt;button type="submit"&gt;login&lt;/button&gt;
- &lt;/form&gt;
- &lt;/div&gt;
- );
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/Settings.css.html b/frontend/coverage/src/components/Settings.css.html
deleted file mode 100644
index 4109bba..0000000
--- a/frontend/coverage/src/components/Settings.css.html
+++ /dev/null
@@ -1,802 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/Settings.css</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Settings.css</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">0% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>0/0</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line low'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a>
-<a name='L149'></a><a href='#L149'>149</a>
-<a name='L150'></a><a href='#L150'>150</a>
-<a name='L151'></a><a href='#L151'>151</a>
-<a name='L152'></a><a href='#L152'>152</a>
-<a name='L153'></a><a href='#L153'>153</a>
-<a name='L154'></a><a href='#L154'>154</a>
-<a name='L155'></a><a href='#L155'>155</a>
-<a name='L156'></a><a href='#L156'>156</a>
-<a name='L157'></a><a href='#L157'>157</a>
-<a name='L158'></a><a href='#L158'>158</a>
-<a name='L159'></a><a href='#L159'>159</a>
-<a name='L160'></a><a href='#L160'>160</a>
-<a name='L161'></a><a href='#L161'>161</a>
-<a name='L162'></a><a href='#L162'>162</a>
-<a name='L163'></a><a href='#L163'>163</a>
-<a name='L164'></a><a href='#L164'>164</a>
-<a name='L165'></a><a href='#L165'>165</a>
-<a name='L166'></a><a href='#L166'>166</a>
-<a name='L167'></a><a href='#L167'>167</a>
-<a name='L168'></a><a href='#L168'>168</a>
-<a name='L169'></a><a href='#L169'>169</a>
-<a name='L170'></a><a href='#L170'>170</a>
-<a name='L171'></a><a href='#L171'>171</a>
-<a name='L172'></a><a href='#L172'>172</a>
-<a name='L173'></a><a href='#L173'>173</a>
-<a name='L174'></a><a href='#L174'>174</a>
-<a name='L175'></a><a href='#L175'>175</a>
-<a name='L176'></a><a href='#L176'>176</a>
-<a name='L177'></a><a href='#L177'>177</a>
-<a name='L178'></a><a href='#L178'>178</a>
-<a name='L179'></a><a href='#L179'>179</a>
-<a name='L180'></a><a href='#L180'>180</a>
-<a name='L181'></a><a href='#L181'>181</a>
-<a name='L182'></a><a href='#L182'>182</a>
-<a name='L183'></a><a href='#L183'>183</a>
-<a name='L184'></a><a href='#L184'>184</a>
-<a name='L185'></a><a href='#L185'>185</a>
-<a name='L186'></a><a href='#L186'>186</a>
-<a name='L187'></a><a href='#L187'>187</a>
-<a name='L188'></a><a href='#L188'>188</a>
-<a name='L189'></a><a href='#L189'>189</a>
-<a name='L190'></a><a href='#L190'>190</a>
-<a name='L191'></a><a href='#L191'>191</a>
-<a name='L192'></a><a href='#L192'>192</a>
-<a name='L193'></a><a href='#L193'>193</a>
-<a name='L194'></a><a href='#L194'>194</a>
-<a name='L195'></a><a href='#L195'>195</a>
-<a name='L196'></a><a href='#L196'>196</a>
-<a name='L197'></a><a href='#L197'>197</a>
-<a name='L198'></a><a href='#L198'>198</a>
-<a name='L199'></a><a href='#L199'>199</a>
-<a name='L200'></a><a href='#L200'>200</a>
-<a name='L201'></a><a href='#L201'>201</a>
-<a name='L202'></a><a href='#L202'>202</a>
-<a name='L203'></a><a href='#L203'>203</a>
-<a name='L204'></a><a href='#L204'>204</a>
-<a name='L205'></a><a href='#L205'>205</a>
-<a name='L206'></a><a href='#L206'>206</a>
-<a name='L207'></a><a href='#L207'>207</a>
-<a name='L208'></a><a href='#L208'>208</a>
-<a name='L209'></a><a href='#L209'>209</a>
-<a name='L210'></a><a href='#L210'>210</a>
-<a name='L211'></a><a href='#L211'>211</a>
-<a name='L212'></a><a href='#L212'>212</a>
-<a name='L213'></a><a href='#L213'>213</a>
-<a name='L214'></a><a href='#L214'>214</a>
-<a name='L215'></a><a href='#L215'>215</a>
-<a name='L216'></a><a href='#L216'>216</a>
-<a name='L217'></a><a href='#L217'>217</a>
-<a name='L218'></a><a href='#L218'>218</a>
-<a name='L219'></a><a href='#L219'>219</a>
-<a name='L220'></a><a href='#L220'>220</a>
-<a name='L221'></a><a href='#L221'>221</a>
-<a name='L222'></a><a href='#L222'>222</a>
-<a name='L223'></a><a href='#L223'>223</a>
-<a name='L224'></a><a href='#L224'>224</a>
-<a name='L225'></a><a href='#L225'>225</a>
-<a name='L226'></a><a href='#L226'>226</a>
-<a name='L227'></a><a href='#L227'>227</a>
-<a name='L228'></a><a href='#L228'>228</a>
-<a name='L229'></a><a href='#L229'>229</a>
-<a name='L230'></a><a href='#L230'>230</a>
-<a name='L231'></a><a href='#L231'>231</a>
-<a name='L232'></a><a href='#L232'>232</a>
-<a name='L233'></a><a href='#L233'>233</a>
-<a name='L234'></a><a href='#L234'>234</a>
-<a name='L235'></a><a href='#L235'>235</a>
-<a name='L236'></a><a href='#L236'>236</a>
-<a name='L237'></a><a href='#L237'>237</a>
-<a name='L238'></a><a href='#L238'>238</a>
-<a name='L239'></a><a href='#L239'>239</a>
-<a name='L240'></a><a href='#L240'>240</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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>
-<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>
-<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,
-.appearance-section,
-.import-section,
-.export-section,
-.feed-list-section {
- background: rgba(255, 255, 255, 0.03);
- padding: 1.5rem;
- border-radius: 16px;
- margin-bottom: 2rem;
- border: 1px solid rgba(255, 255, 255, 0.05);
- transition: all 0.3s ease;
-}
-&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 {
- display: flex;
- gap: 1rem;
-}
-&nbsp;
-.feed-input {
- flex: 1;
- padding: 0.6rem 1.2rem;
- border: 1px solid rgba(255, 255, 255, 0.1);
- background: rgba(0, 0, 0, 0.1);
- color: var(--text-color);
- border-radius: 20px;
- font-size: 1rem;
- outline: none;
- transition: border-color 0.2s;
-}
-&nbsp;
-.feed-input:focus {
- border-color: rgba(255, 255, 255, 0.3);
-}
-&nbsp;
-.error-message {
- color: #ff5252;
- margin-top: 1rem;
- font-weight: 600;
-}
-&nbsp;
-.settings-feed-list {
- list-style: none;
- padding: 0;
- 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: 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 {
- border-bottom: none;
-}
-&nbsp;
-.feed-info {
- display: flex;
- flex-direction: column;
- gap: 0.2rem;
-}
-&nbsp;
-.feed-title {
- font-weight: 600;
- font-size: 1.05rem;
- opacity: 0.9;
-}
-&nbsp;
-.feed-url {
- color: var(--text-color);
- opacity: 0.5;
- font-size: 0.85rem;
-}
-&nbsp;
-.delete-btn {
- background: rgba(255, 82, 82, 0.15);
- color: #ff8a80;
- border: 1px solid rgba(255, 82, 82, 0.2);
- padding: 0.5rem 1rem;
- border-radius: 12px;
- cursor: pointer;
- font-weight: 600;
- transition: all 0.2s;
-}
-&nbsp;
-.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;
-}
-&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;
- .settings-feed-item {
- flex-direction: column;
- align-items: flex-start;
- gap: 1rem;
- }
-}
-&nbsp;
-.import-form {
- display: flex;
- flex-direction: column;
- 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: 0.8rem;
- flex-wrap: wrap;
-}
-&nbsp;
-.export-btn {
- display: inline-block;
- padding: 0.6rem 1.2rem;
- background: rgba(255, 255, 255, 0.05);
- color: var(--text-color);
- text-decoration: none;
- border: 1px solid rgba(255, 255, 255, 0.1);
- border-radius: 12px;
- font-weight: 600;
- transition: all 0.2s;
-}
-&nbsp;
-.export-btn:hover {
- background: rgba(255, 255, 255, 0.1);
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-}
-&nbsp;
-button:not(.delete-btn) {
- cursor: pointer;
- padding: 0.6rem 1.2rem;
- border-radius: 12px;
- border: 1px solid rgba(255, 255, 255, 0.1);
- background: rgba(255, 255, 255, 0.1);
- color: var(--text-color);
- font-weight: 600;
- transition: all 0.2s;
-}
-&nbsp;
-button:not(.delete-btn):hover:not(:disabled) {
- background: rgba(255, 255, 255, 0.2);
- transform: scale(1.02);
-}
-&nbsp;
-button:disabled {
- opacity: 0.4;
- cursor: not-allowed;
-}</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/Settings.tsx.html b/frontend/coverage/src/components/Settings.tsx.html
deleted file mode 100644
index 892218e..0000000
--- a/frontend/coverage/src/components/Settings.tsx.html
+++ /dev/null
@@ -1,793 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components/Settings.tsx</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> / <a href="index.html">src/components</a> Settings.tsx</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">80% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>60/75</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">66.66% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>20/30</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">85.18% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>23/27</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">87.87% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>58/66</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line high'></div>
- <pre><table class="coverage">
-<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
-<a name='L2'></a><a href='#L2'>2</a>
-<a name='L3'></a><a href='#L3'>3</a>
-<a name='L4'></a><a href='#L4'>4</a>
-<a name='L5'></a><a href='#L5'>5</a>
-<a name='L6'></a><a href='#L6'>6</a>
-<a name='L7'></a><a href='#L7'>7</a>
-<a name='L8'></a><a href='#L8'>8</a>
-<a name='L9'></a><a href='#L9'>9</a>
-<a name='L10'></a><a href='#L10'>10</a>
-<a name='L11'></a><a href='#L11'>11</a>
-<a name='L12'></a><a href='#L12'>12</a>
-<a name='L13'></a><a href='#L13'>13</a>
-<a name='L14'></a><a href='#L14'>14</a>
-<a name='L15'></a><a href='#L15'>15</a>
-<a name='L16'></a><a href='#L16'>16</a>
-<a name='L17'></a><a href='#L17'>17</a>
-<a name='L18'></a><a href='#L18'>18</a>
-<a name='L19'></a><a href='#L19'>19</a>
-<a name='L20'></a><a href='#L20'>20</a>
-<a name='L21'></a><a href='#L21'>21</a>
-<a name='L22'></a><a href='#L22'>22</a>
-<a name='L23'></a><a href='#L23'>23</a>
-<a name='L24'></a><a href='#L24'>24</a>
-<a name='L25'></a><a href='#L25'>25</a>
-<a name='L26'></a><a href='#L26'>26</a>
-<a name='L27'></a><a href='#L27'>27</a>
-<a name='L28'></a><a href='#L28'>28</a>
-<a name='L29'></a><a href='#L29'>29</a>
-<a name='L30'></a><a href='#L30'>30</a>
-<a name='L31'></a><a href='#L31'>31</a>
-<a name='L32'></a><a href='#L32'>32</a>
-<a name='L33'></a><a href='#L33'>33</a>
-<a name='L34'></a><a href='#L34'>34</a>
-<a name='L35'></a><a href='#L35'>35</a>
-<a name='L36'></a><a href='#L36'>36</a>
-<a name='L37'></a><a href='#L37'>37</a>
-<a name='L38'></a><a href='#L38'>38</a>
-<a name='L39'></a><a href='#L39'>39</a>
-<a name='L40'></a><a href='#L40'>40</a>
-<a name='L41'></a><a href='#L41'>41</a>
-<a name='L42'></a><a href='#L42'>42</a>
-<a name='L43'></a><a href='#L43'>43</a>
-<a name='L44'></a><a href='#L44'>44</a>
-<a name='L45'></a><a href='#L45'>45</a>
-<a name='L46'></a><a href='#L46'>46</a>
-<a name='L47'></a><a href='#L47'>47</a>
-<a name='L48'></a><a href='#L48'>48</a>
-<a name='L49'></a><a href='#L49'>49</a>
-<a name='L50'></a><a href='#L50'>50</a>
-<a name='L51'></a><a href='#L51'>51</a>
-<a name='L52'></a><a href='#L52'>52</a>
-<a name='L53'></a><a href='#L53'>53</a>
-<a name='L54'></a><a href='#L54'>54</a>
-<a name='L55'></a><a href='#L55'>55</a>
-<a name='L56'></a><a href='#L56'>56</a>
-<a name='L57'></a><a href='#L57'>57</a>
-<a name='L58'></a><a href='#L58'>58</a>
-<a name='L59'></a><a href='#L59'>59</a>
-<a name='L60'></a><a href='#L60'>60</a>
-<a name='L61'></a><a href='#L61'>61</a>
-<a name='L62'></a><a href='#L62'>62</a>
-<a name='L63'></a><a href='#L63'>63</a>
-<a name='L64'></a><a href='#L64'>64</a>
-<a name='L65'></a><a href='#L65'>65</a>
-<a name='L66'></a><a href='#L66'>66</a>
-<a name='L67'></a><a href='#L67'>67</a>
-<a name='L68'></a><a href='#L68'>68</a>
-<a name='L69'></a><a href='#L69'>69</a>
-<a name='L70'></a><a href='#L70'>70</a>
-<a name='L71'></a><a href='#L71'>71</a>
-<a name='L72'></a><a href='#L72'>72</a>
-<a name='L73'></a><a href='#L73'>73</a>
-<a name='L74'></a><a href='#L74'>74</a>
-<a name='L75'></a><a href='#L75'>75</a>
-<a name='L76'></a><a href='#L76'>76</a>
-<a name='L77'></a><a href='#L77'>77</a>
-<a name='L78'></a><a href='#L78'>78</a>
-<a name='L79'></a><a href='#L79'>79</a>
-<a name='L80'></a><a href='#L80'>80</a>
-<a name='L81'></a><a href='#L81'>81</a>
-<a name='L82'></a><a href='#L82'>82</a>
-<a name='L83'></a><a href='#L83'>83</a>
-<a name='L84'></a><a href='#L84'>84</a>
-<a name='L85'></a><a href='#L85'>85</a>
-<a name='L86'></a><a href='#L86'>86</a>
-<a name='L87'></a><a href='#L87'>87</a>
-<a name='L88'></a><a href='#L88'>88</a>
-<a name='L89'></a><a href='#L89'>89</a>
-<a name='L90'></a><a href='#L90'>90</a>
-<a name='L91'></a><a href='#L91'>91</a>
-<a name='L92'></a><a href='#L92'>92</a>
-<a name='L93'></a><a href='#L93'>93</a>
-<a name='L94'></a><a href='#L94'>94</a>
-<a name='L95'></a><a href='#L95'>95</a>
-<a name='L96'></a><a href='#L96'>96</a>
-<a name='L97'></a><a href='#L97'>97</a>
-<a name='L98'></a><a href='#L98'>98</a>
-<a name='L99'></a><a href='#L99'>99</a>
-<a name='L100'></a><a href='#L100'>100</a>
-<a name='L101'></a><a href='#L101'>101</a>
-<a name='L102'></a><a href='#L102'>102</a>
-<a name='L103'></a><a href='#L103'>103</a>
-<a name='L104'></a><a href='#L104'>104</a>
-<a name='L105'></a><a href='#L105'>105</a>
-<a name='L106'></a><a href='#L106'>106</a>
-<a name='L107'></a><a href='#L107'>107</a>
-<a name='L108'></a><a href='#L108'>108</a>
-<a name='L109'></a><a href='#L109'>109</a>
-<a name='L110'></a><a href='#L110'>110</a>
-<a name='L111'></a><a href='#L111'>111</a>
-<a name='L112'></a><a href='#L112'>112</a>
-<a name='L113'></a><a href='#L113'>113</a>
-<a name='L114'></a><a href='#L114'>114</a>
-<a name='L115'></a><a href='#L115'>115</a>
-<a name='L116'></a><a href='#L116'>116</a>
-<a name='L117'></a><a href='#L117'>117</a>
-<a name='L118'></a><a href='#L118'>118</a>
-<a name='L119'></a><a href='#L119'>119</a>
-<a name='L120'></a><a href='#L120'>120</a>
-<a name='L121'></a><a href='#L121'>121</a>
-<a name='L122'></a><a href='#L122'>122</a>
-<a name='L123'></a><a href='#L123'>123</a>
-<a name='L124'></a><a href='#L124'>124</a>
-<a name='L125'></a><a href='#L125'>125</a>
-<a name='L126'></a><a href='#L126'>126</a>
-<a name='L127'></a><a href='#L127'>127</a>
-<a name='L128'></a><a href='#L128'>128</a>
-<a name='L129'></a><a href='#L129'>129</a>
-<a name='L130'></a><a href='#L130'>130</a>
-<a name='L131'></a><a href='#L131'>131</a>
-<a name='L132'></a><a href='#L132'>132</a>
-<a name='L133'></a><a href='#L133'>133</a>
-<a name='L134'></a><a href='#L134'>134</a>
-<a name='L135'></a><a href='#L135'>135</a>
-<a name='L136'></a><a href='#L136'>136</a>
-<a name='L137'></a><a href='#L137'>137</a>
-<a name='L138'></a><a href='#L138'>138</a>
-<a name='L139'></a><a href='#L139'>139</a>
-<a name='L140'></a><a href='#L140'>140</a>
-<a name='L141'></a><a href='#L141'>141</a>
-<a name='L142'></a><a href='#L142'>142</a>
-<a name='L143'></a><a href='#L143'>143</a>
-<a name='L144'></a><a href='#L144'>144</a>
-<a name='L145'></a><a href='#L145'>145</a>
-<a name='L146'></a><a href='#L146'>146</a>
-<a name='L147'></a><a href='#L147'>147</a>
-<a name='L148'></a><a href='#L148'>148</a>
-<a name='L149'></a><a href='#L149'>149</a>
-<a name='L150'></a><a href='#L150'>150</a>
-<a name='L151'></a><a href='#L151'>151</a>
-<a name='L152'></a><a href='#L152'>152</a>
-<a name='L153'></a><a href='#L153'>153</a>
-<a name='L154'></a><a href='#L154'>154</a>
-<a name='L155'></a><a href='#L155'>155</a>
-<a name='L156'></a><a href='#L156'>156</a>
-<a name='L157'></a><a href='#L157'>157</a>
-<a name='L158'></a><a href='#L158'>158</a>
-<a name='L159'></a><a href='#L159'>159</a>
-<a name='L160'></a><a href='#L160'>160</a>
-<a name='L161'></a><a href='#L161'>161</a>
-<a name='L162'></a><a href='#L162'>162</a>
-<a name='L163'></a><a href='#L163'>163</a>
-<a name='L164'></a><a href='#L164'>164</a>
-<a name='L165'></a><a href='#L165'>165</a>
-<a name='L166'></a><a href='#L166'>166</a>
-<a name='L167'></a><a href='#L167'>167</a>
-<a name='L168'></a><a href='#L168'>168</a>
-<a name='L169'></a><a href='#L169'>169</a>
-<a name='L170'></a><a href='#L170'>170</a>
-<a name='L171'></a><a href='#L171'>171</a>
-<a name='L172'></a><a href='#L172'>172</a>
-<a name='L173'></a><a href='#L173'>173</a>
-<a name='L174'></a><a href='#L174'>174</a>
-<a name='L175'></a><a href='#L175'>175</a>
-<a name='L176'></a><a href='#L176'>176</a>
-<a name='L177'></a><a href='#L177'>177</a>
-<a name='L178'></a><a href='#L178'>178</a>
-<a name='L179'></a><a href='#L179'>179</a>
-<a name='L180'></a><a href='#L180'>180</a>
-<a name='L181'></a><a href='#L181'>181</a>
-<a name='L182'></a><a href='#L182'>182</a>
-<a name='L183'></a><a href='#L183'>183</a>
-<a name='L184'></a><a href='#L184'>184</a>
-<a name='L185'></a><a href='#L185'>185</a>
-<a name='L186'></a><a href='#L186'>186</a>
-<a name='L187'></a><a href='#L187'>187</a>
-<a name='L188'></a><a href='#L188'>188</a>
-<a name='L189'></a><a href='#L189'>189</a>
-<a name='L190'></a><a href='#L190'>190</a>
-<a name='L191'></a><a href='#L191'>191</a>
-<a name='L192'></a><a href='#L192'>192</a>
-<a name='L193'></a><a href='#L193'>193</a>
-<a name='L194'></a><a href='#L194'>194</a>
-<a name='L195'></a><a href='#L195'>195</a>
-<a name='L196'></a><a href='#L196'>196</a>
-<a name='L197'></a><a href='#L197'>197</a>
-<a name='L198'></a><a href='#L198'>198</a>
-<a name='L199'></a><a href='#L199'>199</a>
-<a name='L200'></a><a href='#L200'>200</a>
-<a name='L201'></a><a href='#L201'>201</a>
-<a name='L202'></a><a href='#L202'>202</a>
-<a name='L203'></a><a href='#L203'>203</a>
-<a name='L204'></a><a href='#L204'>204</a>
-<a name='L205'></a><a href='#L205'>205</a>
-<a name='L206'></a><a href='#L206'>206</a>
-<a name='L207'></a><a href='#L207'>207</a>
-<a name='L208'></a><a href='#L208'>208</a>
-<a name='L209'></a><a href='#L209'>209</a>
-<a name='L210'></a><a href='#L210'>210</a>
-<a name='L211'></a><a href='#L211'>211</a>
-<a name='L212'></a><a href='#L212'>212</a>
-<a name='L213'></a><a href='#L213'>213</a>
-<a name='L214'></a><a href='#L214'>214</a>
-<a name='L215'></a><a href='#L215'>215</a>
-<a name='L216'></a><a href='#L216'>216</a>
-<a name='L217'></a><a href='#L217'>217</a>
-<a name='L218'></a><a href='#L218'>218</a>
-<a name='L219'></a><a href='#L219'>219</a>
-<a name='L220'></a><a href='#L220'>220</a>
-<a name='L221'></a><a href='#L221'>221</a>
-<a name='L222'></a><a href='#L222'>222</a>
-<a name='L223'></a><a href='#L223'>223</a>
-<a name='L224'></a><a href='#L224'>224</a>
-<a name='L225'></a><a href='#L225'>225</a>
-<a name='L226'></a><a href='#L226'>226</a>
-<a name='L227'></a><a href='#L227'>227</a>
-<a name='L228'></a><a href='#L228'>228</a>
-<a name='L229'></a><a href='#L229'>229</a>
-<a name='L230'></a><a href='#L230'>230</a>
-<a name='L231'></a><a href='#L231'>231</a>
-<a name='L232'></a><a href='#L232'>232</a>
-<a name='L233'></a><a href='#L233'>233</a>
-<a name='L234'></a><a href='#L234'>234</a>
-<a name='L235'></a><a href='#L235'>235</a>
-<a name='L236'></a><a href='#L236'>236</a>
-<a name='L237'></a><a href='#L237'>237</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&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">34x</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-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">2x</span>
-<span class="cline-any cline-yes">2x</span>
-<span class="cline-any cline-neutral">&nbsp;</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-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-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-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">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>
-<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">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>
-<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-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-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-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-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-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-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">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-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-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>
-<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-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">import React, { useEffect, useState } from 'react';
-import type { Feed } from '../types';
-import './Settings.css';
-import { apiFetch } from '../utils';
-&nbsp;
-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;
- /* ... existing fetchFeeds ... */
- const fetchFeeds = React.useCallback(() =&gt; {
- setLoading(true);
- 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();
- })
- .then((data) =&gt; {
- setFeeds(data);
- setLoading(false);
- })
- .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;
- 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>
-&nbsp;
- setLoading(true);
- apiFetch('/api/feed/', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ url: newFeedUrl }),
- })
- .then((res) =&gt; {
- if (!res.ok) throw new Error('Failed to add feed');
- return res.json();
- })
- .then(() =&gt; {
- setNewFeedUrl('');
- fetchFeeds();
- })
- .catch((err) =&gt; {
- setError(err.message);
- setLoading(false);
- });
- };
-&nbsp;
- const handleDeleteFeed = (id: number) =&gt; {
- <span class="missing-if-branch" title="if path not taken" >I</span>if (!globalThis.confirm('Are you sure you want to delete this feed?')) <span class="cstat-no" title="statement not covered" >return;</span>
-&nbsp;
- setLoading(true);
- apiFetch(`/api/feed/${id}`, {
- method: 'DELETE',
- })
- .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 delete feed');</span>
- setFeeds(feeds.filter((f) =&gt; f._id !== id));
- setLoading(false);
- })
- .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 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;
- setLoading(true);
- const formData = new FormData();
- formData.append('file', importFile);
- formData.append('format', 'opml');
-&nbsp;
- apiFetch('/api/import', {
- method: 'POST',
- body: formData,
- })
- .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(() =&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>
-<span class="cstat-no" title="statement not covered" > setLoading(false);</span>
- });
- };
-&nbsp;
- return (
- &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;
- &lt;input
- type="url"
- value={newFeedUrl}
- onChange={(e) =&gt; setNewFeedUrl(e.target.value)}
- placeholder="https://example.com/feed.xml"
- required
- className="feed-input"
- disabled={loading}
- /&gt;
- &lt;button type="submit" disabled={loading}&gt;
- Add Feed
- &lt;/button&gt;
- &lt;/form&gt;
- &lt;/div&gt;
-&nbsp;
- &lt;div className="import-export-section"&gt;
- &lt;div className="import-section"&gt;
- &lt;h3&gt;Import Feeds (OPML)&lt;/h3&gt;
- &lt;form onSubmit={handleImport} className="import-form"&gt;
- &lt;input
- type="file"
- accept=".opml,.xml,.txt"
- 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 || loading}&gt;
- Import
- &lt;/button&gt;
- &lt;/form&gt;
- &lt;/div&gt;
-&nbsp;
- &lt;div className="export-section"&gt;
- &lt;h3&gt;Export Feeds&lt;/h3&gt;
- &lt;div className="export-buttons"&gt;
- &lt;a href="/api/export/opml" className="export-btn"&gt;OPML&lt;/a&gt;
- &lt;a href="/api/export/text" className="export-btn"&gt;Text&lt;/a&gt;
- &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; &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;
- {loading &amp;&amp; &lt;p&gt;Loading...&lt;/p&gt;}
- &lt;ul className="settings-feed-list"&gt;
- {feeds.map((feed) =&gt; (
- &lt;li key={feed._id} className="settings-feed-item"&gt;
- &lt;div className="feed-info"&gt;
- &lt;span className="feed-title"&gt;{feed.title || <span class="branch-1 cbranch-no" title="branch not covered" >'(No Title)'}&lt;</span>/span&gt;
- &lt;span className="feed-url"&gt;{feed.url}&lt;/span&gt;
- &lt;/div&gt;
- &lt;button
- onClick={() =&gt; handleDeleteFeed(feed._id)}
- className="delete-btn"
- disabled={loading}
- title="Delete Feed"
- &gt;
- Delete
- &lt;/button&gt;
- &lt;/li&gt;
- ))}
- &lt;/ul&gt;
- &lt;/div&gt;
- &lt;/div&gt;
- );
-}
-&nbsp;</pre></td></tr></table></pre>
-
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/components/index.html b/frontend/coverage/src/components/index.html
deleted file mode 100644
index fc333bb..0000000
--- a/frontend/coverage/src/components/index.html
+++ /dev/null
@@ -1,266 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src/components</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../../prettify.css" />
- <link rel="stylesheet" href="../../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../../index.html">All files</a> src/components</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">86.21% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>269/312</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">74.61% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>144/193</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">84.94% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>79/93</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">88.81% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>254/286</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line high'></div>
- <div class="pad1">
-<table class="coverage-summary">
-<thead>
-<tr>
- <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
- <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
- <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
- <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
- <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
- <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
- <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
-</tr>
-</thead>
-<tbody><tr>
- <td class="file empty" data-value="FeedItem.css"><a href="FeedItem.css.html">FeedItem.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file medium" data-value="FeedItem.tsx"><a href="FeedItem.tsx.html">FeedItem.tsx</a></td>
- <td data-value="78.12" class="pic medium">
- <div class="chart"><div class="cover-fill" style="width: 78%"></div><div class="cover-empty" style="width: 22%"></div></div>
- </td>
- <td data-value="78.12" class="pct medium">78.12%</td>
- <td data-value="32" class="abs medium">25/32</td>
- <td data-value="86.95" class="pct high">86.95%</td>
- <td data-value="23" class="abs high">20/23</td>
- <td data-value="83.33" class="pct high">83.33%</td>
- <td data-value="12" class="abs high">10/12</td>
- <td data-value="80.64" class="pct high">80.64%</td>
- <td data-value="31" class="abs high">25/31</td>
- </tr>
-
-<tr>
- <td class="file empty" data-value="FeedItems.css"><a href="FeedItems.css.html">FeedItems.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file high" data-value="FeedItems.tsx"><a href="FeedItems.tsx.html">FeedItems.tsx</a></td>
- <td data-value="89.23" class="pic high">
- <div class="chart"><div class="cover-fill" style="width: 89%"></div><div class="cover-empty" style="width: 11%"></div></div>
- </td>
- <td data-value="89.23" class="pct high">89.23%</td>
- <td data-value="130" class="abs high">116/130</td>
- <td data-value="76.19" class="pct medium">76.19%</td>
- <td data-value="84" class="abs medium">64/84</td>
- <td data-value="87.09" class="pct high">87.09%</td>
- <td data-value="31" class="abs high">27/31</td>
- <td data-value="89.07" class="pct high">89.07%</td>
- <td data-value="119" class="abs high">106/119</td>
- </tr>
-
-<tr>
- <td class="file empty" data-value="FeedList.css"><a href="FeedList.css.html">FeedList.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file high" data-value="FeedList.tsx"><a href="FeedList.tsx.html">FeedList.tsx</a></td>
- <td data-value="87.27" class="pic high">
- <div class="chart"><div class="cover-fill" style="width: 87%"></div><div class="cover-empty" style="width: 13%"></div></div>
- </td>
- <td data-value="87.27" class="pct high">87.27%</td>
- <td data-value="55" class="abs high">48/55</td>
- <td data-value="70" class="pct medium">70%</td>
- <td data-value="50" class="abs medium">35/50</td>
- <td data-value="78.94" class="pct medium">78.94%</td>
- <td data-value="19" class="abs medium">15/19</td>
- <td data-value="90" class="pct high">90%</td>
- <td data-value="50" class="abs high">45/50</td>
- </tr>
-
-<tr>
- <td class="file empty" data-value="FeedListVariants.css"><a href="FeedListVariants.css.html">FeedListVariants.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file empty" data-value="Login.css"><a href="Login.css.html">Login.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file high" data-value="Login.tsx"><a href="Login.tsx.html">Login.tsx</a></td>
- <td data-value="100" class="pic high">
- <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
- </td>
- <td data-value="100" class="pct high">100%</td>
- <td data-value="20" class="abs high">20/20</td>
- <td data-value="83.33" class="pct high">83.33%</td>
- <td data-value="6" class="abs high">5/6</td>
- <td data-value="100" class="pct high">100%</td>
- <td data-value="4" class="abs high">4/4</td>
- <td data-value="100" class="pct high">100%</td>
- <td data-value="20" class="abs high">20/20</td>
- </tr>
-
-<tr>
- <td class="file empty" data-value="Settings.css"><a href="Settings.css.html">Settings.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file high" data-value="Settings.tsx"><a href="Settings.tsx.html">Settings.tsx</a></td>
- <td data-value="80" class="pic high">
- <div class="chart"><div class="cover-fill" style="width: 80%"></div><div class="cover-empty" style="width: 20%"></div></div>
- </td>
- <td data-value="80" class="pct high">80%</td>
- <td data-value="75" class="abs high">60/75</td>
- <td data-value="66.66" class="pct medium">66.66%</td>
- <td data-value="30" class="abs medium">20/30</td>
- <td data-value="85.18" class="pct high">85.18%</td>
- <td data-value="27" class="abs high">23/27</td>
- <td data-value="87.87" class="pct high">87.87%</td>
- <td data-value="66" class="abs high">58/66</td>
- </tr>
-
-</tbody>
-</table>
-</div>
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../../sorter.js"></script>
- <script src="../../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file
diff --git a/frontend/coverage/src/index.html b/frontend/coverage/src/index.html
deleted file mode 100644
index 091ffa0..0000000
--- a/frontend/coverage/src/index.html
+++ /dev/null
@@ -1,146 +0,0 @@
-
-<!doctype html>
-<html lang="en">
-
-<head>
- <title>Code coverage report for src</title>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="../prettify.css" />
- <link rel="stylesheet" href="../base.css" />
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <style type='text/css'>
- .coverage-summary .sorter {
- background-image: url(../sort-arrow-sprite.png);
- }
- </style>
-</head>
-
-<body>
-<div class='wrapper'>
- <div class='pad1'>
- <h1><a href="../index.html">All files</a> src</h1>
- <div class='clearfix'>
-
- <div class='fl pad1y space-right2'>
- <span class="strong">70.21% </span>
- <span class="quiet">Statements</span>
- <span class='fraction'>33/47</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">65.71% </span>
- <span class="quiet">Branches</span>
- <span class='fraction'>23/35</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">60% </span>
- <span class="quiet">Functions</span>
- <span class='fraction'>9/15</span>
- </div>
-
-
- <div class='fl pad1y space-right2'>
- <span class="strong">71.11% </span>
- <span class="quiet">Lines</span>
- <span class='fraction'>32/45</span>
- </div>
-
-
- </div>
- <p class="quiet">
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
- </p>
- <template id="filterTemplate">
- <div class="quiet">
- Filter:
- <input type="search" id="fileSearch">
- </div>
- </template>
- </div>
- <div class='status-line medium'></div>
- <div class="pad1">
-<table class="coverage-summary">
-<thead>
-<tr>
- <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
- <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
- <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
- <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
- <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
- <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
- <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
- <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
-</tr>
-</thead>
-<tbody><tr>
- <td class="file empty" data-value="App.css"><a href="App.css.html">App.css</a></td>
- <td data-value="0" class="pic empty">
- <div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
- </td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- <td data-value="0" class="pct empty">0%</td>
- <td data-value="0" class="abs empty">0/0</td>
- </tr>
-
-<tr>
- <td class="file medium" data-value="App.tsx"><a href="App.tsx.html">App.tsx</a></td>
- <td data-value="65.71" class="pic medium">
- <div class="chart"><div class="cover-fill" style="width: 65%"></div><div class="cover-empty" style="width: 35%"></div></div>
- </td>
- <td data-value="65.71" class="pct medium">65.71%</td>
- <td data-value="35" class="abs medium">23/35</td>
- <td data-value="60" class="pct medium">60%</td>
- <td data-value="25" class="abs medium">15/25</td>
- <td data-value="53.84" class="pct medium">53.84%</td>
- <td data-value="13" class="abs medium">7/13</td>
- <td data-value="64.7" class="pct medium">64.7%</td>
- <td data-value="34" class="abs medium">22/34</td>
- </tr>
-
-<tr>
- <td class="file high" data-value="utils.ts"><a href="utils.ts.html">utils.ts</a></td>
- <td data-value="83.33" class="pic high">
- <div class="chart"><div class="cover-fill" style="width: 83%"></div><div class="cover-empty" style="width: 17%"></div></div>
- </td>
- <td data-value="83.33" class="pct high">83.33%</td>
- <td data-value="12" class="abs high">10/12</td>
- <td data-value="80" class="pct high">80%</td>
- <td data-value="10" class="abs high">8/10</td>
- <td data-value="100" class="pct high">100%</td>
- <td data-value="2" class="abs high">2/2</td>
- <td data-value="90.9" class="pct high">90.9%</td>
- <td data-value="11" class="abs high">10/11</td>
- </tr>
-
-</tbody>
-</table>
-</div>
- <div class='push'></div><!-- for sticky footer -->
- </div><!-- /wrapper -->
- <div class='footer quiet pad2 space-top1 center small'>
- Code coverage generated by
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
- at 2026-02-15T05:30:50.842Z
- </div>
- <script src="../prettify.js"></script>
- <script>
- window.onload = function () {
- prettyPrint();
- };
- </script>
- <script src="../sorter.js"></script>
- <script src="../block-navigation.js"></script>
- </body>
-</html>
- \ No newline at end of file