feat: unified search panel — progressive keyword+semantic results (#80)
* feat: unify search panel — remove keyword/semantic toggle, progressive results Replace separate keyword/semantic mode toggle with a unified search that streams results progressively: keyword results appear first (<500ms), then hybrid results augment the list (~1-2s). Loading spinner shows in the input field while semantic search runs. Stale requests are discarded via generation counter for safe rapid typing. - Extract search logic into useUnifiedSearch hook (code health 9.26+) - 300ms debounce, 5s timeout on hybrid, graceful fallback on errors - 15 tests covering progressive search, spinner, stale results, failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add design wireframes for unified search panel Two frames showing the search panel states: - "keyword results loaded, semantic loading" (with spinner) - "all results loaded" (no spinner, more results including semantic) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: coverage artifacts --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">40.9% </span>
|
||||
<span class="strong">47.5% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>45/110</span>
|
||||
<span class='fraction'>57/120</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">50% </span>
|
||||
<span class="strong">40.47% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>11/22</span>
|
||||
<span class='fraction'>17/42</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">13.51% </span>
|
||||
<span class="strong">20.58% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>5/37</span>
|
||||
<span class='fraction'>7/34</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">45% </span>
|
||||
<span class="strong">57.73% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>45/100</span>
|
||||
<span class='fraction'>56/97</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -336,7 +336,50 @@
|
||||
<a name='L271'></a><a href='#L271'>271</a>
|
||||
<a name='L272'></a><a href='#L272'>272</a>
|
||||
<a name='L273'></a><a href='#L273'>273</a>
|
||||
<a name='L274'></a><a href='#L274'>274</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L274'></a><a href='#L274'>274</a>
|
||||
<a name='L275'></a><a href='#L275'>275</a>
|
||||
<a name='L276'></a><a href='#L276'>276</a>
|
||||
<a name='L277'></a><a href='#L277'>277</a>
|
||||
<a name='L278'></a><a href='#L278'>278</a>
|
||||
<a name='L279'></a><a href='#L279'>279</a>
|
||||
<a name='L280'></a><a href='#L280'>280</a>
|
||||
<a name='L281'></a><a href='#L281'>281</a>
|
||||
<a name='L282'></a><a href='#L282'>282</a>
|
||||
<a name='L283'></a><a href='#L283'>283</a>
|
||||
<a name='L284'></a><a href='#L284'>284</a>
|
||||
<a name='L285'></a><a href='#L285'>285</a>
|
||||
<a name='L286'></a><a href='#L286'>286</a>
|
||||
<a name='L287'></a><a href='#L287'>287</a>
|
||||
<a name='L288'></a><a href='#L288'>288</a>
|
||||
<a name='L289'></a><a href='#L289'>289</a>
|
||||
<a name='L290'></a><a href='#L290'>290</a>
|
||||
<a name='L291'></a><a href='#L291'>291</a>
|
||||
<a name='L292'></a><a href='#L292'>292</a>
|
||||
<a name='L293'></a><a href='#L293'>293</a>
|
||||
<a name='L294'></a><a href='#L294'>294</a>
|
||||
<a name='L295'></a><a href='#L295'>295</a>
|
||||
<a name='L296'></a><a href='#L296'>296</a>
|
||||
<a name='L297'></a><a href='#L297'>297</a>
|
||||
<a name='L298'></a><a href='#L298'>298</a>
|
||||
<a name='L299'></a><a href='#L299'>299</a>
|
||||
<a name='L300'></a><a href='#L300'>300</a>
|
||||
<a name='L301'></a><a href='#L301'>301</a>
|
||||
<a name='L302'></a><a href='#L302'>302</a>
|
||||
<a name='L303'></a><a href='#L303'>303</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -365,8 +408,14 @@
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -375,82 +424,18 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-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-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
@@ -458,26 +443,83 @@
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
@@ -485,55 +527,51 @@
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -545,6 +583,31 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -569,7 +632,25 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -584,48 +665,39 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { Sidebar } from './components/Sidebar'
|
||||
import { NoteList } from './components/NoteList'
|
||||
import { Editor } from './components/Editor'
|
||||
import { ResizeHandle } from './components/ResizeHandle'
|
||||
import { CreateNoteDialog } from './components/CreateNoteDialog'
|
||||
import { CreateTypeDialog } from './components/CreateTypeDialog'
|
||||
import { QuickOpenPalette } from './components/QuickOpenPalette'
|
||||
import { CommandPalette } from './components/CommandPalette'
|
||||
import { SearchPanel } from './components/SearchPanel'
|
||||
import { Toast } from './components/Toast'
|
||||
import { CommitDialog } from './components/CommitDialog'
|
||||
import { StatusBar } from './components/StatusBar'
|
||||
import { SettingsPanel } from './components/SettingsPanel'
|
||||
import { GitHubVaultModal } from './components/GitHubVaultModal'
|
||||
import { useVaultLoader } from './hooks/useVaultLoader'
|
||||
import { useSettings } from './hooks/useSettings'
|
||||
import { useNoteActions } from './hooks/useNoteActions'
|
||||
import { useAppKeyboard } from './hooks/useAppKeyboard'
|
||||
import { isTauri } from './mock-tauri'
|
||||
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation'
|
||||
import type { SidebarSelection, GitCommit } from './types'
|
||||
import { useEditorSave } from './hooks/useEditorSave'
|
||||
import { useCommitFlow } from './hooks/useCommitFlow'
|
||||
import { useViewMode } from './hooks/useViewMode'
|
||||
import { useEntryActions } from './hooks/useEntryActions'
|
||||
import { useAppCommands } from './hooks/useAppCommands'
|
||||
import { useDialogs } from './hooks/useDialogs'
|
||||
import { useVaultSwitcher } from './hooks/useVaultSwitcher'
|
||||
import { useGitHistory } from './hooks/useGitHistory'
|
||||
import { useUpdater } from './hooks/useUpdater'
|
||||
import { useNavigationHistory } from './hooks/useNavigationHistory'
|
||||
import { UpdateBanner } from './components/UpdateBanner'
|
||||
import { setApiKey } from './utils/ai-chat'
|
||||
import { extractOutgoingLinks } from './utils/wikilinks'
|
||||
import type { SidebarSelection } from './types'
|
||||
import './App.css'
|
||||
|
||||
// Type declaration for mock content storage
|
||||
@@ -637,186 +709,206 @@ declare global {
|
||||
|
||||
const DEFAULT_SELECTION: SidebarSelection = { kind: 'filter', filter: 'all' }
|
||||
|
||||
// In web/browser mode: only Demo v2 (no real vault access)
|
||||
// In native Tauri mode: Demo v2 + real Laputa vault
|
||||
const VAULTS = isTauri()
|
||||
? <span class="branch-0 cbranch-no" title="branch not covered" >[</span>
|
||||
{ label: 'Demo v2', path: '/Users/luca/Workspace/laputa-app/demo-vault-v2' },
|
||||
{ label: 'Laputa', path: '/Users/luca/Laputa' },
|
||||
]
|
||||
: [
|
||||
{ label: 'Demo v2', path: '/Users/luca/Workspace/laputa-app/demo-vault-v2' },
|
||||
]
|
||||
|
||||
const BUILT_IN_TYPE_NAMES = new Set([
|
||||
'Project', 'Experiment', 'Responsibility', 'Procedure',
|
||||
'Person', 'Event', 'Topic', 'Type', 'Note', 'Essay',
|
||||
'Quarter', 'Journal', 'Evergreen',
|
||||
])
|
||||
|
||||
function App() {
|
||||
const [selection, setSelection] = useState<SidebarSelection>(DEFAULT_SELECTION)
|
||||
function useLayoutPanels() {
|
||||
const [sidebarWidth, setSidebarWidth] = useState(250)
|
||||
const [noteListWidth, setNoteListWidth] = useState(300)
|
||||
const [inspectorWidth, setInspectorWidth] = useState(280)
|
||||
const [inspectorCollapsed, setInspectorCollapsed] = useState(false)
|
||||
const [gitHistory, setGitHistory] = useState<GitCommit[]>([])
|
||||
const [showCreateDialog, setShowCreateDialog] = useState(false)
|
||||
const [createNoteDefaultType, setCreateNoteDefaultType] = useState<string | undefined>()
|
||||
const [showCreateTypeDialog, setShowCreateTypeDialog] = useState(false)
|
||||
const [showQuickOpen, setShowQuickOpen] = useState(false)
|
||||
const [showCommitDialog, setShowCommitDialog] = useState(false)
|
||||
const [toastMessage, setToastMessage] = useState<string | null>(null)
|
||||
const [vaultPath, setVaultPath] = useState(VAULTS[0].path)
|
||||
const [showAIChat, setShowAIChat] = useState(false)
|
||||
const handleSidebarResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => <span class="cstat-no" title="statement not covered" >setSidebarWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(150, Math.min(400, w + delta)))</span>, [</span>])
|
||||
const handleNoteListResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => <span class="cstat-no" title="statement not covered" >setNoteListWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(200, Math.min(500, w + delta)))</span>, [</span>])
|
||||
const handleInspectorResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => <span class="cstat-no" title="statement not covered" >setInspectorWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(200, Math.min(500, w - delta)))</span>, [</span>])
|
||||
return { sidebarWidth, noteListWidth, inspectorWidth, inspectorCollapsed, setInspectorCollapsed, handleSidebarResize, handleNoteListResize, handleInspectorResize }
|
||||
}
|
||||
|
||||
const vault = useVaultLoader(vaultPath)
|
||||
const notes = useNoteActions(vault.addEntry, vault.updateContent, vault.entries, setToastMessage)
|
||||
|
||||
// Derive custom types from vault (Type entries not in built-in list)
|
||||
const customTypes = useMemo(
|
||||
() => vault.entries
|
||||
.filter((e) => e.isA === 'Type' && <span class="branch-1 cbranch-no" title="branch not covered" >!BUILT_IN_TYPE_NAMES.has(e.title))</span>
|
||||
.map(<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.title)</span>
|
||||
.sort(),
|
||||
[vault.entries],
|
||||
)
|
||||
|
||||
// Reset UI state when vault changes
|
||||
const handleSwitchVault = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setVaultPath(path)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelection(DEFAULT_SELECTION)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setGitHistory([])</span>
|
||||
<span class="cstat-no" title="statement not covered" > notes.closeAllTabs()</span>
|
||||
}, [notes])
|
||||
|
||||
// Load git history when active tab changes
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!notes.activeTabPath) {
|
||||
setGitHistory([])
|
||||
return
|
||||
/** Wraps useEditorSave to also keep outgoingLinks in sync on save and on content change. */
|
||||
function useEditorSaveWithLinks(config: {
|
||||
updateContent: (path: string, content: string) => void
|
||||
updateEntry: (path: string, patch: Partial<import('./types').VaultEntry>) => void
|
||||
setTabs: Parameters<typeof useEditorSave>[0]['setTabs']
|
||||
setToastMessage: (msg: string | null) => void
|
||||
onAfterSave: () => void
|
||||
}) {
|
||||
const { updateContent, updateEntry } = config
|
||||
const saveContent = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string, content: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > updateContent(path, content)</span>
|
||||
<span class="cstat-no" title="statement not covered" > updateEntry(path, { outgoingLinks: extractOutgoingLinks(content) })</span>
|
||||
}, [updateContent, updateEntry])
|
||||
const editor = useEditorSave({ updateVaultContent: saveContent, setTabs: config.setTabs, setToastMessage: config.setToastMessage, onAfterSave: config.onAfterSave })
|
||||
const { handleContentChange: rawOnChange } = editor
|
||||
const prevLinksKeyRef = useRef('')
|
||||
const handleContentChange = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string, content: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > rawOnChange(path, content)</span>
|
||||
const <span class="cstat-no" title="statement not covered" >links = extractOutgoingLinks(content)</span>
|
||||
const key = <span class="cstat-no" title="statement not covered" >links.join('\0')</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (key !== prevLinksKeyRef.current) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > prevLinksKeyRef.current = key</span>
|
||||
<span class="cstat-no" title="statement not covered" > updateEntry(path, { outgoingLinks: links })</span>
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > vault.loadGitHistory(notes.activeTabPath).then(setGitHistory)</span>
|
||||
}, [notes.activeTabPath, vault.loadGitHistory])
|
||||
}, [rawOnChange, updateEntry])
|
||||
return { ...editor, handleContentChange }
|
||||
}
|
||||
|
||||
const openCreateDialog = useCallback(<span class="fstat-no" title="function not covered" >(t</span>ype?: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setCreateNoteDefaultType(type)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setShowCreateDialog(true)</span>
|
||||
}, [])
|
||||
function App() {
|
||||
const [selection, setSelection] = useState<SidebarSelection>(DEFAULT_SELECTION)
|
||||
const layout = useLayoutPanels()
|
||||
const [toastMessage, setToastMessage] = useState<string | null>(null)
|
||||
const dialogs = useDialogs()
|
||||
|
||||
const openCreateTypeDialog = useCallback(<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setShowCreateTypeDialog(true)</span>
|
||||
}, [])
|
||||
// onSwitch closure captures `notes` declared below — safe because it's only
|
||||
// called on user interaction, never during render (refs inside the hook
|
||||
// guarantee the latest closure is always used).
|
||||
const vaultSwitcher = useVaultSwitcher({
|
||||
onSwitch: <span class="fstat-no" title="function not covered" >() => {</span> <span class="cstat-no" title="statement not covered" >setSelection(DEFAULT_SELECTION); <span class="cstat-no" title="statement not covered" >n</span>otes.closeAllTabs() }</span>,
|
||||
onToast: <span class="fstat-no" title="function not covered" >(m</span>sg) => <span class="cstat-no" title="statement not covered" >setToastMessage(msg),</span>
|
||||
})
|
||||
|
||||
const vault = useVaultLoader(vaultSwitcher.vaultPath)
|
||||
const { settings, saveSettings } = useSettings()
|
||||
|
||||
useEffect(() => { setApiKey(settings.anthropic_key ?? '') }, [settings.anthropic_key])
|
||||
|
||||
const notes = useNoteActions({ addEntry: vault.addEntry, removeEntry: vault.removeEntry, updateContent: vault.updateContent, entries: vault.entries, setToastMessage, updateEntry: vault.updateEntry })
|
||||
|
||||
const navHistory = useNavigationHistory()
|
||||
|
||||
// Push to navigation history whenever the active tab changes (user-initiated)
|
||||
const navFromHistoryRef = useRef(false)
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (notes.activeTabPath && <span class="branch-1 cbranch-no" title="branch not covered" >!navFromHistoryRef.current) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > navHistory.push(notes.activeTabPath)</span>
|
||||
}
|
||||
navFromHistoryRef.current = false
|
||||
}, [notes.activeTabPath]) // eslint-disable-line react-hooks/exhaustive-deps -- navHistory.push is stable
|
||||
|
||||
const isTabOpen = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string) => <span class="cstat-no" title="statement not covered" >notes.tabs.some(<span class="fstat-no" title="function not covered" >t => <span class="cstat-no" title="statement not covered" >t</span>.entry.path === path)</span>, [</span>notes.tabs])
|
||||
|
||||
const handleGoBack = useCallback(<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
const target = <span class="cstat-no" title="statement not covered" >navHistory.goBack(isTabOpen)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (target) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > navFromHistoryRef.current = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleSwitchTab(target)</span>
|
||||
}
|
||||
}, [navHistory, isTabOpen, notes])
|
||||
|
||||
const handleGoForward = useCallback(<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
const target = <span class="cstat-no" title="statement not covered" >navHistory.goForward(isTabOpen)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (target) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > navFromHistoryRef.current = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleSwitchTab(target)</span>
|
||||
}
|
||||
}, [navHistory, isTabOpen, notes])
|
||||
|
||||
// Mouse button 3/4 (back/forward) and macOS trackpad two-finger swipe
|
||||
useEffect(() => {
|
||||
const handleMouseBack = <span class="fstat-no" title="function not covered" >(e</span>: MouseEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (e.button === 3) { <span class="cstat-no" title="statement not covered" >e.preventDefault(); <span class="cstat-no" title="statement not covered" >h</span>andleGoBack() }</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (e.button === 4) { <span class="cstat-no" title="statement not covered" >e.preventDefault(); <span class="cstat-no" title="statement not covered" >h</span>andleGoForward() }</span></span>
|
||||
}
|
||||
window.addEventListener('mouseup', handleMouseBack)
|
||||
|
||||
// Trackpad swipe: accumulate horizontal wheel delta and trigger on threshold
|
||||
let accumulatedDeltaX = 0
|
||||
let resetTimer: ReturnType<typeof setTimeout> | null = null
|
||||
const SWIPE_THRESHOLD = 120
|
||||
|
||||
const handleWheel = <span class="fstat-no" title="function not covered" >(e</span>: WheelEvent) => {
|
||||
// Only handle horizontal-dominant gestures (trackpad swipe)
|
||||
<span class="cstat-no" title="statement not covered" > if (Math.abs(e.deltaX) <= Math.abs(e.deltaY)) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (e.ctrlKey || e.metaKey) <span class="cstat-no" title="statement not covered" >return // ignore pinch-zoom</span></span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > accumulatedDeltaX += e.deltaX</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (resetTimer) <span class="cstat-no" title="statement not covered" >clearTimeout(resetTimer)</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > resetTimer = setTimeout(<span class="fstat-no" title="function not covered" >() => {</span> <span class="cstat-no" title="statement not covered" >accumulatedDeltaX = 0 }</span>, 300)</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (accumulatedDeltaX > SWIPE_THRESHOLD) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > accumulatedDeltaX = 0</span>
|
||||
<span class="cstat-no" title="statement not covered" > handleGoForward()</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (accumulatedDeltaX < -SWIPE_THRESHOLD) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > accumulatedDeltaX = 0</span>
|
||||
<span class="cstat-no" title="statement not covered" > handleGoBack()</span>
|
||||
}
|
||||
}
|
||||
window.addEventListener('wheel', handleWheel, { passive: true })
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('mouseup', handleMouseBack)
|
||||
window.removeEventListener('wheel', handleWheel)
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (resetTimer) <span class="cstat-no" title="statement not covered" >clearTimeout(resetTimer)</span>
|
||||
}
|
||||
}, [handleGoBack, handleGoForward])
|
||||
|
||||
const { handleSave, handleContentChange, savePendingForPath, savePending } = useEditorSaveWithLinks({
|
||||
updateContent: vault.updateContent, updateEntry: vault.updateEntry,
|
||||
setTabs: notes.setTabs, setToastMessage, onAfterSave: vault.loadModifiedFiles,
|
||||
})
|
||||
|
||||
const commitFlow = useCommitFlow({ savePending, loadModifiedFiles: vault.loadModifiedFiles, commitAndPush: vault.commitAndPush, setToastMessage })
|
||||
|
||||
const entryActions = useEntryActions({
|
||||
entries: vault.entries, updateEntry: vault.updateEntry,
|
||||
handleUpdateFrontmatter: notes.handleUpdateFrontmatter,
|
||||
handleDeleteProperty: notes.handleDeleteProperty, setToastMessage,
|
||||
})
|
||||
|
||||
const gitHistory = useGitHistory(notes.activeTabPath, vault.loadGitHistory)
|
||||
|
||||
const handleCreateType = useCallback(<span class="fstat-no" title="function not covered" >(n</span>ame: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleCreateType(name)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage(`Type "${name}" created`)</span>
|
||||
}, [notes, setToastMessage])
|
||||
}, [notes])
|
||||
|
||||
const handleCustomizeType = useCallback(<span class="fstat-no" title="function not covered" >(t</span>ypeName: string, icon: string, color: string) => {
|
||||
const typeEntry = <span class="cstat-no" title="statement not covered" >vault.entries.find(<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.isA === 'Type' && e.title === typeName)</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!typeEntry) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
// Update icon and color in frontmatter (two separate calls)
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleUpdateFrontmatter(typeEntry.path, 'icon', icon)</span>
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleUpdateFrontmatter(typeEntry.path, 'color', color)</span>
|
||||
// Also update the entry in-memory for instant UI feedback
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(typeEntry.path, { icon, color })</span>
|
||||
}, [vault, notes])
|
||||
const handleRenameTab = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string, newTitle: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > await savePendingForPath(path)</span>
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleRenameNote(path, newTitle, vaultSwitcher.vaultPath, vault.replaceEntry).then(vault.loadModifiedFiles)</span>
|
||||
}, [notes, vaultSwitcher.vaultPath, vault, savePendingForPath])
|
||||
|
||||
const handleTrashNote = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string) => {
|
||||
const <span class="cstat-no" title="statement not covered" >now = new Date().toISOString().slice(0, 10)</span>
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleUpdateFrontmatter(path, 'trashed', true)</span>
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleUpdateFrontmatter(path, 'trashed_at', now)</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(path, { trashed: true, trashedAt: Date.now() / 1000 })</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage('Note moved to trash')</span>
|
||||
}, [notes, vault, setToastMessage])
|
||||
const { setViewMode, sidebarVisible, noteListVisible } = useViewMode()
|
||||
|
||||
const handleRestoreNote = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleUpdateFrontmatter(path, 'trashed', false)</span>
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleDeleteProperty(path, 'trashed_at')</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(path, { trashed: false, trashedAt: null })</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage('Note restored from trash')</span>
|
||||
}, [notes, vault, setToastMessage])
|
||||
|
||||
const handleArchiveNote = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleUpdateFrontmatter(path, 'archived', true)</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(path, { archived: true })</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage('Note archived')</span>
|
||||
}, [notes, vault, setToastMessage])
|
||||
|
||||
const handleUnarchiveNote = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > await notes.handleUpdateFrontmatter(path, 'archived', false)</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(path, { archived: false })</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage('Note unarchived')</span>
|
||||
}, [notes, vault, setToastMessage])
|
||||
|
||||
const handleReorderSections = useCallback(<span class="fstat-no" title="function not covered" >(o</span>rderedTypes: { typeName: string; order: number }[]) => {
|
||||
<span class="cstat-no" title="statement not covered" > for (const { typeName, order } of orderedTypes) {</span>
|
||||
const typeEntry = <span class="cstat-no" title="statement not covered" >vault.entries.find(<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.isA === 'Type' && e.title === typeName)</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!typeEntry) <span class="cstat-no" title="statement not covered" >continue</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > notes.handleUpdateFrontmatter(typeEntry.path, 'order', order)</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.updateEntry(typeEntry.path, { order })</span>
|
||||
}
|
||||
}, [vault, notes])
|
||||
|
||||
useAppKeyboard({
|
||||
onQuickOpen: <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowQuickOpen(true),</span>
|
||||
onCreateNote: openCreateDialog,
|
||||
onSave: () => setToastMessage('Saved'),
|
||||
onTrashNote: handleTrashNote,
|
||||
onArchiveNote: handleArchiveNote,
|
||||
activeTabPathRef: notes.activeTabPathRef,
|
||||
handleCloseTabRef: notes.handleCloseTabRef,
|
||||
})
|
||||
|
||||
useKeyboardNavigation({
|
||||
tabs: notes.tabs,
|
||||
activeTabPath: notes.activeTabPath,
|
||||
entries: vault.entries,
|
||||
selection,
|
||||
allContent: vault.allContent,
|
||||
onSwitchTab: notes.handleSwitchTab,
|
||||
onReplaceActiveTab: notes.handleReplaceActiveTab,
|
||||
const commands = useAppCommands({
|
||||
activeTabPath: notes.activeTabPath, activeTabPathRef: notes.activeTabPathRef,
|
||||
handleCloseTabRef: notes.handleCloseTabRef, tabs: notes.tabs,
|
||||
entries: vault.entries, allContent: vault.allContent,
|
||||
modifiedCount: vault.modifiedFiles.length, selection,
|
||||
onQuickOpen: dialogs.openQuickOpen, onCommandPalette: dialogs.openCommandPalette,
|
||||
onSearch: dialogs.openSearch,
|
||||
onCreateNote: notes.handleCreateNoteImmediate, onSave: handleSave,
|
||||
onOpenSettings: dialogs.openSettings,
|
||||
onTrashNote: entryActions.handleTrashNote, onArchiveNote: entryActions.handleArchiveNote,
|
||||
onUnarchiveNote: entryActions.handleUnarchiveNote,
|
||||
onCommitPush: commitFlow.openCommitDialog, onSetViewMode: setViewMode,
|
||||
onToggleInspector: <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >l</span>ayout.setInspectorCollapsed(<span class="fstat-no" title="function not covered" >c => <span class="cstat-no" title="statement not covered" >!</span>c)</span>,</span>
|
||||
onSelect: setSelection, onCloseTab: notes.handleCloseTab,
|
||||
onSwitchTab: notes.handleSwitchTab, onReplaceActiveTab: notes.handleReplaceActiveTab,
|
||||
onSelectNote: notes.handleSelectNote,
|
||||
onGoBack: handleGoBack, onGoForward: handleGoForward,
|
||||
canGoBack: navHistory.canGoBack, canGoForward: navHistory.canGoForward,
|
||||
})
|
||||
|
||||
const handleSidebarResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => {
|
||||
<span class="cstat-no" title="statement not covered" > setSidebarWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(150, Math.min(400, w + delta)))</span></span>
|
||||
}, [])
|
||||
|
||||
const handleNoteListResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => {
|
||||
<span class="cstat-no" title="statement not covered" > setNoteListWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(200, Math.min(500, w + delta)))</span></span>
|
||||
}, [])
|
||||
|
||||
const handleInspectorResize = useCallback(<span class="fstat-no" title="function not covered" >(d</span>elta: number) => {
|
||||
<span class="cstat-no" title="statement not covered" > setInspectorWidth(<span class="fstat-no" title="function not covered" >(w</span>) => <span class="cstat-no" title="statement not covered" >Math.max(200, Math.min(500, w - delta)))</span></span>
|
||||
}, [])
|
||||
|
||||
const handleCommitPush = useCallback(<span class="fstat-no" title="function not covered" >async (m</span>essage: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setShowCommitDialog(false)</span>
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
const result = <span class="cstat-no" title="statement not covered" >await vault.commitAndPush(message)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage(result)</span>
|
||||
<span class="cstat-no" title="statement not covered" > vault.loadModifiedFiles()</span>
|
||||
} catch (err) {
|
||||
<span class="cstat-no" title="statement not covered" > console.error('Commit failed:', err)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setToastMessage(`Commit failed: ${err}`)</span>
|
||||
}
|
||||
}, [vault])
|
||||
const { status: updateStatus, actions: updateActions } = useUpdater()
|
||||
|
||||
const activeTab = notes.tabs.find(<span class="fstat-no" title="function not covered" >(t</span>) => <span class="cstat-no" title="statement not covered" >t.entry.path === notes.activeTabPath)</span> ?? null
|
||||
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<UpdateBanner status={updateStatus} actions={updateActions} />
|
||||
<div className="app">
|
||||
<div className="app__sidebar" style={{ width: sidebarWidth }}>
|
||||
<Sidebar entries={vault.entries} selection={selection} onSelect={setSelection} onSelectNote={notes.handleSelectNote} onCreateType={openCreateDialog} onCreateNewType={openCreateTypeDialog} onCustomizeType={handleCustomizeType} onReorderSections={handleReorderSections} modifiedCount={vault.modifiedFiles.length} onCommitPush={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowCommitDialog(true)} /</span>>
|
||||
</div>
|
||||
<ResizeHandle onResize={handleSidebarResize} />
|
||||
<div className="app__note-list" style={{ width: noteListWidth }}>
|
||||
<NoteList entries={vault.entries} selection={selection} selectedNote={activeTab?.entry ?? null} allContent={vault.allContent} modifiedFiles={vault.modifiedFiles} onSelectNote={notes.handleSelectNote} onCreateNote={openCreateDialog} />
|
||||
</div>
|
||||
<ResizeHandle onResize={handleNoteListResize} />
|
||||
{sidebarVisible && (
|
||||
<>
|
||||
<div className="app__sidebar" style={{ width: layout.sidebarWidth }}>
|
||||
<Sidebar entries={vault.entries} selection={selection} onSelect={setSelection} onSelectNote={notes.handleSelectNote} onCreateType={notes.handleCreateNoteImmediate} onCreateNewType={dialogs.openCreateType} onCustomizeType={entryActions.handleCustomizeType} onReorderSections={entryActions.handleReorderSections} modifiedCount={vault.modifiedFiles.length} onCommitPush={commitFlow.openCommitDialog} />
|
||||
</div>
|
||||
<ResizeHandle onResize={layout.handleSidebarResize} />
|
||||
</>
|
||||
)}
|
||||
{noteListVisible && (
|
||||
<>
|
||||
<div className="app__note-list" style={{ width: layout.noteListWidth }}>
|
||||
<NoteList entries={vault.entries} selection={selection} selectedNote={activeTab?.entry ?? null} allContent={vault.allContent} modifiedFiles={vault.modifiedFiles} getNoteStatus={vault.getNoteStatus} onSelectNote={notes.handleSelectNote} onReplaceActiveTab={notes.handleReplaceActiveTab} onCreateNote={notes.handleCreateNoteImmediate} />
|
||||
</div>
|
||||
<ResizeHandle onResize={layout.handleNoteListResize} />
|
||||
</>
|
||||
)}
|
||||
<div className="app__editor">
|
||||
<Editor
|
||||
tabs={notes.tabs}
|
||||
@@ -828,12 +920,12 @@ function App() {
|
||||
onNavigateWikilink={notes.handleNavigateWikilink}
|
||||
onLoadDiff={vault.loadDiff}
|
||||
onLoadDiffAtCommit={vault.loadDiffAtCommit}
|
||||
isModified={vault.isFileModified}
|
||||
onCreateNote={openCreateDialog}
|
||||
inspectorCollapsed={inspectorCollapsed}
|
||||
onToggleInspector={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etInspectorCollapsed(<span class="fstat-no" title="function not covered" >(c</span>) => <span class="cstat-no" title="statement not covered" >!c)</span>}</span>
|
||||
inspectorWidth={inspectorWidth}
|
||||
onInspectorResize={handleInspectorResize}
|
||||
getNoteStatus={vault.getNoteStatus}
|
||||
onCreateNote={notes.handleCreateNoteImmediate}
|
||||
inspectorCollapsed={layout.inspectorCollapsed}
|
||||
onToggleInspector={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >l</span>ayout.setInspectorCollapsed(<span class="fstat-no" title="function not covered" >(c</span>) => <span class="cstat-no" title="statement not covered" >!c)</span>}</span>
|
||||
inspectorWidth={layout.inspectorWidth}
|
||||
onInspectorResize={layout.handleInspectorResize}
|
||||
inspectorEntry={activeTab?.entry ?? null}
|
||||
inspectorContent={activeTab?.content ?? null}
|
||||
allContent={vault.allContent}
|
||||
@@ -841,41 +933,36 @@ function App() {
|
||||
onUpdateFrontmatter={notes.handleUpdateFrontmatter}
|
||||
onDeleteProperty={notes.handleDeleteProperty}
|
||||
onAddProperty={notes.handleAddProperty}
|
||||
showAIChat={showAIChat}
|
||||
onToggleAIChat={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowAIChat(<span class="fstat-no" title="function not covered" >c => <span class="cstat-no" title="statement not covered" >!</span>c)</span>}</span>
|
||||
vaultPath={vaultPath}
|
||||
onTrashNote={handleTrashNote}
|
||||
onRestoreNote={handleRestoreNote}
|
||||
onArchiveNote={handleArchiveNote}
|
||||
onUnarchiveNote={handleUnarchiveNote}
|
||||
showAIChat={dialogs.showAIChat}
|
||||
onToggleAIChat={dialogs.toggleAIChat}
|
||||
vaultPath={vaultSwitcher.vaultPath}
|
||||
onTrashNote={entryActions.handleTrashNote}
|
||||
onRestoreNote={entryActions.handleRestoreNote}
|
||||
onArchiveNote={entryActions.handleArchiveNote}
|
||||
onUnarchiveNote={entryActions.handleUnarchiveNote}
|
||||
onRenameTab={handleRenameTab}
|
||||
onContentChange={handleContentChange}
|
||||
canGoBack={navHistory.canGoBack}
|
||||
canGoForward={navHistory.canGoForward}
|
||||
onGoBack={handleGoBack}
|
||||
onGoForward={handleGoForward}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<StatusBar noteCount={vault.entries.length} vaultPath={vaultPath} vaults={VAULTS} onSwitchVault={handleSwitchVault} />
|
||||
<StatusBar noteCount={vault.entries.length} modifiedCount={vault.modifiedFiles.length} vaultPath={vaultSwitcher.vaultPath} vaults={vaultSwitcher.allVaults} onSwitchVault={vaultSwitcher.switchVault} onOpenSettings={dialogs.openSettings} onOpenLocalFolder={vaultSwitcher.handleOpenLocalFolder} onConnectGitHub={dialogs.openGitHubVault} onClickPending={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSelection({ kind: 'filter', filter: 'changes' })} h</span>asGitHub={!!settings.github_token} />
|
||||
<Toast message={toastMessage} onDismiss={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etToastMessage(null)} /</span>>
|
||||
<QuickOpenPalette
|
||||
open={showQuickOpen}
|
||||
entries={vault.entries}
|
||||
onSelect={notes.handleSelectNote}
|
||||
onClose={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowQuickOpen(false)}</span>
|
||||
/>
|
||||
<CreateNoteDialog
|
||||
open={showCreateDialog}
|
||||
onClose={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowCreateDialog(false)}</span>
|
||||
onCreate={notes.handleCreateNote}
|
||||
defaultType={createNoteDefaultType}
|
||||
customTypes={customTypes}
|
||||
/>
|
||||
<CreateTypeDialog
|
||||
open={showCreateTypeDialog}
|
||||
onClose={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowCreateTypeDialog(false)}</span>
|
||||
onCreate={handleCreateType}
|
||||
/>
|
||||
<CommitDialog
|
||||
open={showCommitDialog}
|
||||
modifiedCount={vault.modifiedFiles.length}
|
||||
onCommit={handleCommitPush}
|
||||
onClose={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowCommitDialog(false)}</span>
|
||||
<QuickOpenPalette open={dialogs.showQuickOpen} entries={vault.entries} onSelect={notes.handleSelectNote} onClose={dialogs.closeQuickOpen} />
|
||||
<CommandPalette open={dialogs.showCommandPalette} commands={commands} onClose={dialogs.closeCommandPalette} />
|
||||
<SearchPanel open={dialogs.showSearch} vaultPath={vaultSwitcher.vaultPath} entries={vault.entries} onSelectNote={notes.handleSelectNote} onClose={dialogs.closeSearch} />
|
||||
<CreateTypeDialog open={dialogs.showCreateTypeDialog} onClose={dialogs.closeCreateType} onCreate={handleCreateType} />
|
||||
<CommitDialog open={commitFlow.showCommitDialog} modifiedCount={vault.modifiedFiles.length} onCommit={commitFlow.handleCommitPush} onClose={commitFlow.closeCommitDialog} />
|
||||
<SettingsPanel open={dialogs.showSettings} settings={settings} onSave={saveSettings} onClose={dialogs.closeSettings} />
|
||||
<GitHubVaultModal
|
||||
open={dialogs.showGitHubVault}
|
||||
githubToken={settings.github_token}
|
||||
onClose={dialogs.closeGitHubVault}
|
||||
onVaultCloned={vaultSwitcher.handleVaultCloned}
|
||||
onOpenSettings={<span class="fstat-no" title="function not covered" >() => {</span> <span class="cstat-no" title="statement not covered" >dialogs.closeGitHubVault(); <span class="cstat-no" title="statement not covered" >d</span>ialogs.openSettings() }</span>}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -889,7 +976,7 @@ export default App
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,9 +30,9 @@
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">69.23% </span>
|
||||
<span class="strong">71.42% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>18/26</span>
|
||||
<span class='fraction'>20/28</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -240,7 +240,13 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -280,7 +286,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -387,7 +393,13 @@
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -418,7 +430,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { memo } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import type { VaultEntry, NoteStatus } from '../types'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
MagnifyingGlass,
|
||||
@@ -436,7 +448,7 @@ import {
|
||||
interface BreadcrumbBarProps {
|
||||
entry: VaultEntry
|
||||
wordCount: number
|
||||
isModified: boolean
|
||||
noteStatus: NoteStatus
|
||||
showDiffToggle: boolean
|
||||
diffMode: boolean
|
||||
diffLoading: boolean
|
||||
@@ -456,7 +468,7 @@ const DISABLED_ICON_STYLE = { opacity: 0.4, cursor: 'not-allowed' } as const
|
||||
function BreadcrumbActions({ entry, showDiffToggle, diffMode, diffLoading, onToggleDiff,
|
||||
showAIChat, onToggleAIChat, inspectorCollapsed, onToggleInspector,
|
||||
onTrash, onRestore, onArchive, onUnarchive,
|
||||
}: Omit<BreadcrumbBarProps, 'wordCount' | 'isModified'>) {
|
||||
}: Omit<BreadcrumbBarProps, 'wordCount' | 'noteStatus'>) {
|
||||
return (
|
||||
<div className="flex items-center" style={{ gap: 12 }}>
|
||||
<button
|
||||
@@ -562,7 +574,7 @@ function BreadcrumbActions({ entry, showDiffToggle, diffMode, diffLoading, onTog
|
||||
}
|
||||
|
||||
export const BreadcrumbBar = memo(function BreadcrumbBar({
|
||||
entry, wordCount, isModified, ...actionProps
|
||||
entry, wordCount, noteStatus, ...actionProps
|
||||
}: BreadcrumbBarProps) {
|
||||
return (
|
||||
<div
|
||||
@@ -581,7 +593,13 @@ export const BreadcrumbBar = memo(function BreadcrumbBar({
|
||||
<span className="font-medium text-foreground">{entry.title}</span>
|
||||
<span className="text-muted-foreground" style={{ margin: '0 4px' }}>&middot;</span>
|
||||
<span className="text-muted-foreground">{wordCount.toLocaleString()} words</span>
|
||||
{isModified && (
|
||||
{noteStatus === 'new' && (
|
||||
<>
|
||||
<span className="text-muted-foreground" style={{ margin: '0 4px' }}>&middot;</span>
|
||||
<span className="font-semibold" style={{ color: 'var(--accent-green)' }}>N</span>
|
||||
</>
|
||||
)}
|
||||
{noteStatus === 'modified' && (
|
||||
<>
|
||||
<span className="text-muted-foreground" style={{ margin: '0 4px' }}>&middot;</span>
|
||||
<span className="font-semibold" style={{ color: 'var(--accent-yellow)' }}>M</span>
|
||||
@@ -601,7 +619,7 @@ export const BreadcrumbBar = memo(function BreadcrumbBar({
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">31.81% </span>
|
||||
<span class="strong">95.45% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>7/22</span>
|
||||
<span class='fraction'>21/22</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">13.33% </span>
|
||||
<span class="strong">73.33% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>2/15</span>
|
||||
<span class='fraction'>11/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">28.57% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>2/7</span>
|
||||
<span class='fraction'>7/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">36.84% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>7/19</span>
|
||||
<span class='fraction'>19/19</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -149,33 +149,33 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-yes">20x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">53x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -190,7 +190,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -226,35 +226,35 @@ export function CommitDialog({ open, modifiedCount, onCommit, onClose }: CommitD
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (open) {
|
||||
<span class="cstat-no" title="statement not covered" > setMessage('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >i</span>nputRef.current?.focus(), 5</span>0)</span>
|
||||
if (open) {
|
||||
setMessage('') // eslint-disable-line react-hooks/set-state-in-effect -- reset on dialog open
|
||||
setTimeout(() => inputRef.current?.focus(), 50)
|
||||
}
|
||||
}, [open])
|
||||
|
||||
const handleSubmit = <span class="fstat-no" title="function not covered" >() => {</span>
|
||||
const trimmed = <span class="cstat-no" title="statement not covered" >message.trim()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!trimmed) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > onCommit(trimmed)</span>
|
||||
const handleSubmit = () => {
|
||||
const trimmed = message.trim()
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!trimmed) <span class="cstat-no" title="statement not covered" >return</span>
|
||||
onCommit(trimmed)
|
||||
}
|
||||
|
||||
const handleKeyDown = <span class="fstat-no" title="function not covered" >(e</span>: React.KeyboardEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > handleSubmit()</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'Escape') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onClose()</span>
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' && (e.metaKey || <span class="branch-2 cbranch-no" title="branch not covered" >e.ctrlKey)) {</span>
|
||||
e.preventDefault()
|
||||
handleSubmit()
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 'Escape') {
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={<span class="fstat-no" title="function not covered" >(i</span>sOpen) => { <span class="cstat-no" title="statement not covered" >if (!isOpen) <span class="cstat-no" title="statement not covered" >onClose() }</span></span>}>
|
||||
<Dialog open={open} onOpenChange={(isOpen) => { <span class="missing-if-branch" title="else path not taken" >E</span>if (!isOpen) onClose() }}>
|
||||
<DialogContent showCloseButton={false} className="sm:max-w-[420px]">
|
||||
<DialogHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<DialogTitle>Commit & Push</DialogTitle>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{modifiedCount} file{modifiedCount !== 1 ? 's' : <span class="branch-1 cbranch-no" title="branch not covered" >''} </span>changed
|
||||
{modifiedCount} file{modifiedCount !== 1 ? 's' : ''} changed
|
||||
</Badge>
|
||||
</div>
|
||||
</DialogHeader>
|
||||
@@ -263,7 +263,7 @@ export function CommitDialog({ open, modifiedCount, onCommit, onClose }: CommitD
|
||||
className="w-full resize-y rounded-lg border border-input bg-[var(--bg-input)] px-3 py-2.5 text-[13px] text-foreground placeholder:text-muted-foreground outline-none transition-colors focus:border-ring"
|
||||
placeholder="Commit message..."
|
||||
value={message}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setMessage(e.target.value)}</span>
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
rows={3}
|
||||
/>
|
||||
@@ -289,7 +289,7 @@ export function CommitDialog({ open, modifiedCount, onCommit, onClose }: CommitD
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">36% </span>
|
||||
<span class="strong">92% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>9/25</span>
|
||||
<span class='fraction'>23/25</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">35.29% </span>
|
||||
<span class="strong">88.23% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>6/17</span>
|
||||
<span class='fraction'>15/17</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">30% </span>
|
||||
<span class="strong">90% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>3/10</span>
|
||||
<span class='fraction'>9/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">40.9% </span>
|
||||
<span class="strong">95.23% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>9/22</span>
|
||||
<span class='fraction'>20/21</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -211,27 +211,27 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">25x</span>
|
||||
<span class="cline-any cline-yes">25x</span>
|
||||
<span class="cline-any cline-yes">25x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">25x</span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">25x</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">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">25x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -246,7 +246,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -255,7 +255,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">176x</span>
|
||||
<span class="cline-any cline-yes">200x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -264,13 +264,13 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -281,7 +281,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -335,19 +335,19 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customT
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (open) {
|
||||
<span class="cstat-no" title="statement not covered" > setTitle('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setType(defaultType ?? 'Note')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >i</span>nputRef.current?.focus(), 5</span>0)</span>
|
||||
if (open) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- reset on dialog open
|
||||
setTitle(''); setType(defaultType ?? 'Note')
|
||||
setTimeout(() => inputRef.current?.focus(), 50)
|
||||
}
|
||||
}, [open, defaultType])
|
||||
|
||||
const handleSubmit = <span class="fstat-no" title="function not covered" >(e</span>: React.FormEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
const trimmed = <span class="cstat-no" title="statement not covered" >title.trim()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!trimmed) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > onCreate(trimmed, type)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onClose()</span>
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
const trimmed = title.trim()
|
||||
if (!trimmed) return
|
||||
onCreate(trimmed, type)
|
||||
onClose()
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -365,7 +365,7 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customT
|
||||
ref={inputRef}
|
||||
placeholder="Enter note title..."
|
||||
value={title}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setTitle(e.target.value)}</span>
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
@@ -383,13 +383,13 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customT
|
||||
"rounded-full text-xs",
|
||||
type === t && "bg-primary text-primary-foreground"
|
||||
)}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etType(t)}</span>
|
||||
onClick={() => setType(t)}
|
||||
>
|
||||
{t}
|
||||
</Button>
|
||||
))}
|
||||
{customTypes.map(<span class="fstat-no" title="function not covered" >(t</span>) => (
|
||||
<span class="cstat-no" title="statement not covered" > <Button</span>
|
||||
{customTypes.map((t) => (
|
||||
<Button
|
||||
key={t}
|
||||
type="button"
|
||||
variant={type === t ? 'default' : 'outline'}
|
||||
@@ -400,7 +400,7 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customT
|
||||
? "bg-[var(--accent-blue)] text-white"
|
||||
: "border-[var(--accent-blue)] text-[var(--accent-blue)]"
|
||||
)}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etType(t)}</span>
|
||||
onClick={() => setType(t)}
|
||||
>
|
||||
{t}
|
||||
</Button>
|
||||
@@ -427,7 +427,7 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customT
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -139,17 +139,17 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">38x</span>
|
||||
<span class="cline-any cline-yes">38x</span>
|
||||
<span class="cline-any cline-yes">51x</span>
|
||||
<span class="cline-any cline-yes">51x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">38x</span>
|
||||
<span class="cline-any cline-yes">15x</span>
|
||||
<span class="cline-any cline-yes">51x</span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">38x</span>
|
||||
<span class="cline-any cline-yes">51x</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>
|
||||
@@ -157,7 +157,7 @@
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">38x</span>
|
||||
<span class="cline-any cline-yes">51x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -208,7 +208,7 @@ export function CreateTypeDialog({ open, onClose, onCreate }: CreateTypeDialogPr
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setName('')
|
||||
setName('') // eslint-disable-line react-hooks/set-state-in-effect -- reset on dialog open
|
||||
setTimeout(() => inputRef.current?.focus(), 50)
|
||||
}
|
||||
}, [open])
|
||||
@@ -262,7 +262,7 @@ export function CreateTypeDialog({ open, onClose, onCreate }: CreateTypeDialogPr
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/14</span>
|
||||
<span class='fraction'>16/16</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">93.75% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/21</span>
|
||||
<span class='fraction'>15/16</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
<span class='fraction'>5/5</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/14</span>
|
||||
<span class='fraction'>11/11</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -105,41 +105,24 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L43'></a><a href='#L43'>43</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">43x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -148,53 +131,61 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { cn } from '@/lib/utils'
|
||||
|
||||
interface DiffViewProps {
|
||||
diff: string
|
||||
}
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >DiffView({</span> diff }: DiffViewProps) {
|
||||
<span class="cstat-no" title="statement not covered" > if (!diff) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
const DIFF_HEADER_PREFIXES = ['diff', 'index', '---', '+++', 'new file']
|
||||
|
||||
function classifyDiffLine(line: string): string {
|
||||
if (line.startsWith('+') && !line.startsWith('+++')) return 'bg-[rgba(76,175,80,0.12)] text-[#4caf50]'
|
||||
if (line.startsWith('-') && !line.startsWith('---')) return 'bg-[rgba(244,67,54,0.12)] text-[#f44336]'
|
||||
if (line.startsWith('@@')) return 'bg-[rgba(33,150,243,0.08)] text-primary italic'
|
||||
if (DIFF_HEADER_PREFIXES.some((p) => line.startsWith(p))) return 'bg-muted text-muted-foreground font-semibold'
|
||||
return 'text-secondary-foreground'
|
||||
}
|
||||
|
||||
function DiffLine({ line, lineNumber }: { line: string; lineNumber: number }) {
|
||||
return (
|
||||
<div className={cn("flex min-h-[22px] px-4", classifyDiffLine(line))}>
|
||||
<span className="w-10 shrink-0 text-right pr-3 text-muted-foreground select-none">{lineNumber}</span>
|
||||
<span className="flex-1 whitespace-pre-wrap break-all px-2">{line || <span class="branch-1 cbranch-no" title="branch not covered" >'\u00A0'}<</span>/span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function DiffView({ diff }: DiffViewProps) {
|
||||
if (!diff) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
|
||||
No changes to display
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const lines = <span class="cstat-no" title="statement not covered" >diff.split('\n')</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
return (
|
||||
<div className="font-mono text-[13px] leading-relaxed py-3">
|
||||
{lines.map(<span class="fstat-no" title="function not covered" >(l</span>ine, i) => {
|
||||
let lineClass = <span class="cstat-no" title="statement not covered" >'text-secondary-foreground'</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (line.startsWith('+') && !line.startsWith('+++')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > lineClass = 'bg-[rgba(76,175,80,0.12)] text-[#4caf50]'</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (line.startsWith('-') && !line.startsWith('---')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > lineClass = 'bg-[rgba(244,67,54,0.12)] text-[#f44336]'</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (line.startsWith('@@')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > lineClass = 'bg-[rgba(33,150,243,0.08)] text-primary italic'</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (line.startsWith('diff') || line.startsWith('index') || line.startsWith('---') || line.startsWith('+++') || line.startsWith('new file')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > lineClass = 'bg-muted text-muted-foreground font-semibold'</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div key={i} className={cn("flex min-h-[22px] px-4", lineClass)}>
|
||||
<span className="w-10 shrink-0 text-right pr-3 text-muted-foreground select-none">
|
||||
{i + 1}
|
||||
</span>
|
||||
<span className="flex-1 whitespace-pre-wrap break-all px-2">
|
||||
{line || '\u00A0'}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{diff.split('\n').map((line, i) => (
|
||||
<DiffLine key={i} line={line} lineNumber={i + 1} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -205,7 +196,7 @@ export function <span class="fstat-no" title="function not covered" >DiffView({<
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">24.59% </span>
|
||||
<span class="strong">97.72% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>15/61</span>
|
||||
<span class='fraction'>86/88</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">16.66% </span>
|
||||
<span class="strong">82.5% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>5/30</span>
|
||||
<span class='fraction'>33/40</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">15% </span>
|
||||
<span class="strong">92.85% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>3/20</span>
|
||||
<span class='fraction'>26/28</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">26.31% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>15/57</span>
|
||||
<span class='fraction'>82/82</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -244,7 +244,91 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<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>
|
||||
<a name='L253'></a><a href='#L253'>253</a>
|
||||
<a name='L254'></a><a href='#L254'>254</a>
|
||||
<a name='L255'></a><a href='#L255'>255</a>
|
||||
<a name='L256'></a><a href='#L256'>256</a>
|
||||
<a name='L257'></a><a href='#L257'>257</a>
|
||||
<a name='L258'></a><a href='#L258'>258</a>
|
||||
<a name='L259'></a><a href='#L259'>259</a>
|
||||
<a name='L260'></a><a href='#L260'>260</a>
|
||||
<a name='L261'></a><a href='#L261'>261</a>
|
||||
<a name='L262'></a><a href='#L262'>262</a>
|
||||
<a name='L263'></a><a href='#L263'>263</a>
|
||||
<a name='L264'></a><a href='#L264'>264</a>
|
||||
<a name='L265'></a><a href='#L265'>265</a>
|
||||
<a name='L266'></a><a href='#L266'>266</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -259,43 +343,56 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">46x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">46x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">46x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">46x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -304,92 +401,64 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">42x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">45x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">45x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">45x</span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">33x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -403,29 +472,212 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState } from 'react'
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">93x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useCallback, useRef } from 'react'
|
||||
import { normalizeUrl, openExternalUrl } from '../utils/url'
|
||||
|
||||
export function UrlValue({
|
||||
value,
|
||||
onSave,
|
||||
onCancel,
|
||||
isEditing,
|
||||
onStartEdit,
|
||||
}: {
|
||||
value: string
|
||||
onSave: (newValue: string) => void
|
||||
onCancel: () => void
|
||||
isEditing: boolean
|
||||
onStartEdit: () => void
|
||||
}) {
|
||||
const [editValue, setEditValue] = useState(value)
|
||||
const openingRef = useRef(false)
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
onSave(editValue)
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 'Escape') {
|
||||
setEditValue(value)
|
||||
onCancel()
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpen = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (openingRef.current) <span class="cstat-no" title="statement not covered" >return</span>
|
||||
openingRef.current = true
|
||||
const normalized = normalizeUrl(value)
|
||||
try {
|
||||
new URL(normalized)
|
||||
openExternalUrl(normalized).catch(<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
// opener failed — ignore silently
|
||||
})
|
||||
} catch {
|
||||
// malformed URL — do nothing
|
||||
} finally {
|
||||
setTimeout(<span class="fstat-no" title="function not covered" >() => {</span> <span class="cstat-no" title="statement not covered" >openingRef.current = false }</span>, 500)
|
||||
}
|
||||
}, [value])
|
||||
|
||||
const handleEditClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
onStartEdit()
|
||||
}, [onStartEdit])
|
||||
|
||||
if (isEditing) {
|
||||
return (
|
||||
<input
|
||||
className="w-full rounded border border-ring bg-muted px-2 py-1 text-[12px] text-foreground outline-none focus:border-primary"
|
||||
type="text"
|
||||
value={editValue}
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={() => onSave(editValue)}
|
||||
autoFocus
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="group/url inline-flex min-w-0 items-center gap-1">
|
||||
<span
|
||||
className="min-w-0 cursor-pointer truncate rounded px-1 py-0.5 text-right text-[12px] text-secondary-foreground transition-colors hover:text-primary hover:underline"
|
||||
onClick={handleOpen}
|
||||
title={value}
|
||||
data-testid="url-link"
|
||||
>
|
||||
{value || <span class="branch-1 cbranch-no" title="branch not covered" >'\u2014'}</span>
|
||||
</span>
|
||||
<button
|
||||
className="shrink-0 border-none bg-transparent p-0 text-[12px] leading-none text-muted-foreground opacity-0 transition-all hover:text-foreground group-hover/url:opacity-100"
|
||||
onClick={handleEditClick}
|
||||
title="Edit URL"
|
||||
data-testid="url-edit-btn"
|
||||
>
|
||||
&#9998;
|
||||
</button>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export function EditableValue({
|
||||
value,
|
||||
@@ -442,24 +694,24 @@ export function EditableValue({
|
||||
}) {
|
||||
const [editValue, setEditValue] = useState(value)
|
||||
|
||||
const handleKeyDown = <span class="fstat-no" title="function not covered" >(e</span>: React.KeyboardEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (e.key === 'Enter') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSave(editValue)</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'Escape') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setEditValue(value)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onCancel()</span>
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
onSave(editValue)
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 'Escape') {
|
||||
setEditValue(value)
|
||||
onCancel()
|
||||
}
|
||||
}
|
||||
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (isEditing) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
if (isEditing) {
|
||||
return (
|
||||
<input
|
||||
className="w-full rounded border border-ring bg-muted px-2 py-1 text-[13px] text-foreground outline-none focus:border-primary"
|
||||
className="w-full rounded border border-ring bg-muted px-2 py-1 text-[12px] text-foreground outline-none focus:border-primary"
|
||||
type="text"
|
||||
value={editValue}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setEditValue(e.target.value)}</span>
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >o</span>nSave(editValue)}</span>
|
||||
onBlur={() => onSave(editValue)}
|
||||
autoFocus
|
||||
/>
|
||||
)
|
||||
@@ -467,11 +719,11 @@ export function EditableValue({
|
||||
|
||||
return (
|
||||
<span
|
||||
className="min-w-0 cursor-pointer truncate rounded px-1 py-0.5 text-right text-secondary-foreground transition-colors hover:bg-muted"
|
||||
className="min-w-0 cursor-pointer truncate rounded px-1 py-0.5 text-right text-[12px] text-secondary-foreground transition-colors hover:bg-muted"
|
||||
onClick={onStartEdit}
|
||||
title={value || <span class="branch-1 cbranch-no" title="branch not covered" >'Click to edit'}</span>
|
||||
title={value || 'Click to edit'}
|
||||
>
|
||||
{value || <span class="branch-1 cbranch-no" title="branch not covered" >'\u2014'}</span>
|
||||
{value || '\u2014'}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -490,48 +742,48 @@ export function TagPillList({
|
||||
const [isAddingNew, setIsAddingNew] = useState(false)
|
||||
const [newValue, setNewValue] = useState('')
|
||||
|
||||
const handleStartEdit = <span class="fstat-no" title="function not covered" >(i</span>ndex: number) => {
|
||||
<span class="cstat-no" title="statement not covered" > setEditingIndex(index)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setEditValue(items[index])</span>
|
||||
const handleStartEdit = (index: number) => {
|
||||
setEditingIndex(index)
|
||||
setEditValue(items[index])
|
||||
}
|
||||
|
||||
const handleSaveEdit = <span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (editingIndex !== null) {</span>
|
||||
const newItems = <span class="cstat-no" title="statement not covered" >[...items]</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (editValue.trim()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > newItems[editingIndex] = editValue.trim()</span>
|
||||
const handleSaveEdit = () => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (editingIndex !== null) {
|
||||
const newItems = [...items]
|
||||
if (editValue.trim()) {
|
||||
newItems[editingIndex] = editValue.trim()
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > newItems.splice(editingIndex, 1)</span>
|
||||
newItems.splice(editingIndex, 1)
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > onSave(newItems)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setEditingIndex(null)</span>
|
||||
onSave(newItems)
|
||||
setEditingIndex(null)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeleteItem = <span class="fstat-no" title="function not covered" >(i</span>ndex: number) => {
|
||||
const newItems = <span class="cstat-no" title="statement not covered" >items.filter(<span class="fstat-no" title="function not covered" >(_</span>, i) => <span class="cstat-no" title="statement not covered" >i !== index)</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > onSave(newItems)</span>
|
||||
const handleDeleteItem = (index: number) => {
|
||||
const newItems = items.filter((_, i) => i !== index)
|
||||
onSave(newItems)
|
||||
}
|
||||
|
||||
const handleAddNew = <span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (newValue.trim()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSave([...items, newValue.trim()])</span>
|
||||
<span class="cstat-no" title="statement not covered" > setNewValue('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsAddingNew(false)</span>
|
||||
const handleAddNew = () => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (newValue.trim()) {
|
||||
onSave([...items, newValue.trim()])
|
||||
setNewValue('')
|
||||
setIsAddingNew(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyDown = <span class="fstat-no" title="function not covered" >(e</span>: React.KeyboardEvent, action: 'edit' | 'add') => {
|
||||
<span class="cstat-no" title="statement not covered" > if (e.key === 'Enter') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (action === 'edit') <span class="cstat-no" title="statement not covered" >handleSaveEdit()</span></span>
|
||||
else <span class="cstat-no" title="statement not covered" >handleAddNew()</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'Escape') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (action === 'edit') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setEditingIndex(null)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setEditValue('')</span>
|
||||
const handleKeyDown = (e: React.KeyboardEvent, action: 'edit' | 'add') => {
|
||||
if (e.key === 'Enter') {
|
||||
if (action === 'edit') handleSaveEdit()
|
||||
else handleAddNew()
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>} else if (e.key === 'Escape') {
|
||||
if (action === 'edit') {
|
||||
setEditingIndex(null)
|
||||
setEditValue('')
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > setIsAddingNew(false)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setNewValue('')</span>
|
||||
setIsAddingNew(false)
|
||||
setNewValue('')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -540,14 +792,14 @@ export function TagPillList({
|
||||
<div className="flex flex-wrap items-center gap-1">
|
||||
{items.map((item, idx) =>
|
||||
editingIndex === idx ? (
|
||||
<span class="branch-0 cbranch-no" title="branch not covered" > <input</span>
|
||||
<input
|
||||
key={idx}
|
||||
className="rounded-full border border-ring bg-muted px-2 py-0.5 text-[11px] text-foreground outline-none focus:border-primary"
|
||||
style={{ width: Math.max(60, editValue.length * 7 + 16) }}
|
||||
type="text"
|
||||
value={editValue}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setEditValue(e.target.value)}</span>
|
||||
onKeyDown={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >handleKeyDown(e, 'edit')}</span>
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, 'edit')}
|
||||
onBlur={handleSaveEdit}
|
||||
autoFocus
|
||||
/>
|
||||
@@ -561,16 +813,16 @@ export function TagPillList({
|
||||
fontSize: 11,
|
||||
fontWeight: 500,
|
||||
}}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >h</span>andleStartEdit(idx)}</span>
|
||||
onClick={() => handleStartEdit(idx)}
|
||||
title="Click to edit"
|
||||
>
|
||||
{item}
|
||||
<button
|
||||
className="ml-0.5 inline-flex h-3.5 w-3.5 items-center justify-center rounded-full border-none bg-transparent p-0 text-[10px] leading-none opacity-0 transition-all hover:bg-[var(--accent-red-light)] hover:text-[var(--accent-red)] group-hover/pill:opacity-100"
|
||||
style={{ color: 'var(--accent-blue)' }}
|
||||
onClick={<span class="fstat-no" title="function not covered" >(e</span>) => {
|
||||
<span class="cstat-no" title="statement not covered" > e.stopPropagation()</span>
|
||||
<span class="cstat-no" title="statement not covered" > handleDeleteItem(idx)</span>
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleDeleteItem(idx)
|
||||
}}
|
||||
title="Remove"
|
||||
>
|
||||
@@ -580,16 +832,16 @@ export function TagPillList({
|
||||
)
|
||||
)}
|
||||
{isAddingNew ? (
|
||||
<span class="branch-0 cbranch-no" title="branch not covered" > <input</span>
|
||||
<input
|
||||
className="rounded-full border border-ring bg-muted px-2 py-0.5 text-[11px] text-foreground outline-none focus:border-primary"
|
||||
style={{ width: Math.max(60, newValue.length * 7 + 16) }}
|
||||
type="text"
|
||||
value={newValue}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setNewValue(e.target.value)}</span>
|
||||
onKeyDown={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >handleKeyDown(e, 'add')}</span>
|
||||
onBlur={<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (newValue.trim()) <span class="cstat-no" title="statement not covered" >handleAddNew()</span></span>
|
||||
else { <span class="cstat-no" title="statement not covered" >setIsAddingNew(false); <span class="cstat-no" title="statement not covered" >s</span>etNewValue('') }</span>
|
||||
onChange={(e) => setNewValue(e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, 'add')}
|
||||
onBlur={() => {
|
||||
if (newValue.trim()) handleAddNew()
|
||||
else { setIsAddingNew(false); setNewValue('') }
|
||||
}}
|
||||
placeholder={`${label}...`}
|
||||
autoFocus
|
||||
@@ -597,7 +849,7 @@ export function TagPillList({
|
||||
) : (
|
||||
<button
|
||||
className="inline-flex h-5 w-5 items-center justify-center rounded-full border border-dashed border-[var(--accent-blue)] bg-transparent p-0 text-[12px] leading-none text-[var(--accent-blue)] transition-colors hover:bg-[var(--accent-blue-light)]"
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etIsAddingNew(true)}</span>
|
||||
onClick={() => setIsAddingNew(true)}
|
||||
title={`Add ${label.toLowerCase()}`}
|
||||
>
|
||||
+
|
||||
@@ -613,7 +865,7 @@ export function TagPillList({
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">27.02% </span>
|
||||
<span class="strong">97.14% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>20/74</span>
|
||||
<span class='fraction'>34/35</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">17.07% </span>
|
||||
<span class="strong">91.66% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>7/41</span>
|
||||
<span class='fraction'>11/12</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">31.81% </span>
|
||||
<span class="strong">90.9% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>7/22</span>
|
||||
<span class='fraction'>10/11</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">25.39% </span>
|
||||
<span class="strong">96.77% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>16/63</span>
|
||||
<span class='fraction'>30/31</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -144,71 +144,7 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L82'></a><a href='#L82'>82</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -221,102 +157,65 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-yes">47x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">15x</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-yes">3x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">43x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -326,37 +225,10 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useRef, useEffect, useMemo } from 'react'
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useRef, useEffect } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { NoteSearchList } from './NoteSearchList'
|
||||
import { useNoteSearch } from '../hooks/useNoteSearch'
|
||||
|
||||
interface QuickOpenPaletteProps {
|
||||
open: boolean
|
||||
@@ -365,97 +237,50 @@ interface QuickOpenPaletteProps {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
/** Simple fuzzy match: all query chars appear in order in the target */
|
||||
function <span class="fstat-no" title="function not covered" >fuzzyMatch(q</span>uery: string, target: string): { match: boolean; score: number } {
|
||||
const q = <span class="cstat-no" title="statement not covered" >query.toLowerCase()</span>
|
||||
const t = <span class="cstat-no" title="statement not covered" >target.toLowerCase()</span>
|
||||
let qi = <span class="cstat-no" title="statement not covered" >0</span>
|
||||
let score = <span class="cstat-no" title="statement not covered" >0</span>
|
||||
let lastMatchIndex = <span class="cstat-no" title="statement not covered" >-1</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > for (let ti = <span class="cstat-no" title="statement not covered" >0; t</span>i < t.length && qi < q.length; ti++) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (t[ti] === q[qi]) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (ti === lastMatchIndex + 1) <span class="cstat-no" title="statement not covered" >score += 2</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (ti === 0 || t[ti - 1] === ' ' || t[ti - 1] === '-') <span class="cstat-no" title="statement not covered" >score += 3</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > score += 1</span>
|
||||
<span class="cstat-no" title="statement not covered" > lastMatchIndex = ti</span>
|
||||
<span class="cstat-no" title="statement not covered" > qi++</span>
|
||||
}
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return { match: qi === q.length, score }</span>
|
||||
}
|
||||
|
||||
export function QuickOpenPalette({ open, entries, onSelect, onClose }: QuickOpenPaletteProps) {
|
||||
const [query, setQuery] = useState('')
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
const listRef = useRef<HTMLDivElement>(null)
|
||||
const { results, selectedIndex, setSelectedIndex, handleKeyDown } = useNoteSearch(entries, query)
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (open) {
|
||||
<span class="cstat-no" title="statement not covered" > setQuery('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelectedIndex(0)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >i</span>nputRef.current?.focus(), 5</span>0)</span>
|
||||
if (open) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- reset on dialog open
|
||||
setQuery('')
|
||||
setSelectedIndex(0)
|
||||
setTimeout(() => inputRef.current?.focus(), 50)
|
||||
}
|
||||
}, [open])
|
||||
|
||||
const results = useMemo(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!query.trim()) {
|
||||
return [...entries].sort((a, b) => (b.modifiedAt ?? <span class="branch-1 cbranch-no" title="branch not covered" >0) - (a</span>.modifiedAt ?? <span class="branch-1 cbranch-no" title="branch not covered" >0))</span>.slice(0, 20)
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > return entries</span>
|
||||
.map(<span class="fstat-no" title="function not covered" >(e</span>ntry) => (<span class="cstat-no" title="statement not covered" >{ entry, ...fuzzyMatch(query, entry.title) }))</span>
|
||||
.filter(<span class="fstat-no" title="function not covered" >(r</span>) => <span class="cstat-no" title="statement not covered" >r.match)</span>
|
||||
.sort(<span class="fstat-no" title="function not covered" >(a</span>, b) => <span class="cstat-no" title="statement not covered" >b.score - a.score)</span>
|
||||
.slice(0, 20)
|
||||
.map(<span class="fstat-no" title="function not covered" >(r</span>) => <span class="cstat-no" title="statement not covered" >r.entry)</span>
|
||||
}, [entries, query])
|
||||
}, [open, setSelectedIndex])
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedIndex(0)
|
||||
}, [query])
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!listRef.current) return
|
||||
const selected = <span class="cstat-no" title="statement not covered" >listRef.current.children[selectedIndex] as HTMLElement | undefined</span>
|
||||
<span class="cstat-no" title="statement not covered" > selected?.scrollIntoView({ block: 'nearest' })</span>
|
||||
}, [selectedIndex])
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!open) return
|
||||
const handleKey = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(e</span>: KeyboardEvent) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (e.key === 'Escape') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > onClose()</span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'ArrowDown') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelectedIndex(<span class="fstat-no" title="function not covered" >(i</span>) => <span class="cstat-no" title="statement not covered" >Math.min(i + 1, results.length - 1))</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'ArrowUp') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelectedIndex(<span class="fstat-no" title="function not covered" >(i</span>) => <span class="cstat-no" title="statement not covered" >Math.max(i - 1, 0))</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > } else if (e.key === 'Enter') {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (results[selectedIndex]) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSelect(results[selectedIndex])</span>
|
||||
<span class="cstat-no" title="statement not covered" > onClose()</span>
|
||||
if (!open) return
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
handleKeyDown(e)
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault()
|
||||
onClose()
|
||||
} else if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
const selected = results[selectedIndex]
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (selected) {
|
||||
onSelect(selected.entry)
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > window.addEventListener('keydown', handleKey)</span>
|
||||
<span class="cstat-no" title="statement not covered" > return <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >w</span>indow.removeEventListener('keydown', handleKey)</span></span>
|
||||
}, [open, results, selectedIndex, onSelect, onClose])
|
||||
window.addEventListener('keydown', handler)
|
||||
return () => window.removeEventListener('keydown', handler)
|
||||
}, [open, results, selectedIndex, onSelect, onClose, handleKeyDown])
|
||||
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!open) return null
|
||||
if (!open) return null
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-[1000] flex justify-center bg-[var(--shadow-dialog)] pt-[15vh]"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div
|
||||
className="flex w-[500px] max-w-[90vw] max-h-[400px] flex-col self-start overflow-hidden rounded-xl border border-[var(--border-dialog)] bg-popover shadow-[0_8px_32px_var(--shadow-dialog)]"
|
||||
onClick={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.stopPropagation()}</span>
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<input
|
||||
ref={inputRef}
|
||||
@@ -463,37 +288,20 @@ export function QuickOpenPalette({ open, entries, onSelect, onClose }: QuickOpen
|
||||
type="text"
|
||||
placeholder="Search notes..."
|
||||
value={query}
|
||||
onChange={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >setQuery(e.target.value)}</span>
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
/>
|
||||
<NoteSearchList
|
||||
items={results}
|
||||
selectedIndex={selectedIndex}
|
||||
getItemKey={(item) => item.entry.path}
|
||||
onItemClick={(item) => {
|
||||
onSelect(item.entry)
|
||||
onClose()
|
||||
}}
|
||||
onItemHover={<span class="fstat-no" title="function not covered" >(i</span>) => <span class="cstat-no" title="statement not covered" >setSelectedIndex(i)}</span>
|
||||
emptyMessage="No matching notes"
|
||||
className="flex-1 overflow-y-auto"
|
||||
/>
|
||||
<div className="flex-1 overflow-y-auto py-1" ref={listRef}>
|
||||
{results.length === 0 ? (
|
||||
<div className="px-4 py-4 text-center text-[13px] text-muted-foreground">
|
||||
No matching notes
|
||||
</div>
|
||||
) : (
|
||||
results.map(<span class="fstat-no" title="function not covered" >(e</span>ntry, i) => (
|
||||
<span class="cstat-no" title="statement not covered" > <div</span>
|
||||
key={entry.path}
|
||||
className={cn(
|
||||
"flex cursor-pointer items-center justify-between px-4 py-2 transition-colors",
|
||||
i === selectedIndex ? "bg-accent" : "hover:bg-secondary"
|
||||
)}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSelect(entry)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onClose()</span>
|
||||
}}
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etSelectedIndex(i)}</span>
|
||||
>
|
||||
<span className="text-sm text-foreground">{entry.title}</span>
|
||||
{entry.isA && (
|
||||
<Badge variant="secondary" className="text-[11px]">
|
||||
{entry.isA}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -505,7 +313,7 @@ export function QuickOpenPalette({ open, entries, onSelect, onClose }: QuickOpen
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">35.71% </span>
|
||||
<span class="strong">97.61% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>15/42</span>
|
||||
<span class='fraction'>41/42</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">7.14% </span>
|
||||
<span class="strong">78.57% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>1/14</span>
|
||||
<span class='fraction'>11/14</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">42.85% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>3/7</span>
|
||||
<span class='fraction'>7/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">37.5% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>15/40</span>
|
||||
<span class='fraction'>40/40</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -144,67 +144,67 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-yes">107x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -224,47 +224,47 @@ export function ResizeHandle({ onResize }: ResizeHandleProps) {
|
||||
const rafId = useRef(0)
|
||||
|
||||
const handleMouseDown = useCallback(
|
||||
<span class="fstat-no" title="function not covered" > (e</span>: React.MouseEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > isDragging.current = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > lastX.current = e.clientX</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingDelta.current = 0</span>
|
||||
<span class="cstat-no" title="statement not covered" > document.body.style.cursor = 'col-resize'</span>
|
||||
<span class="cstat-no" title="statement not covered" > document.body.style.userSelect = 'none'</span>
|
||||
(e: React.MouseEvent) => {
|
||||
e.preventDefault()
|
||||
isDragging.current = true
|
||||
lastX.current = e.clientX
|
||||
pendingDelta.current = 0
|
||||
document.body.style.cursor = 'col-resize'
|
||||
document.body.style.userSelect = 'none'
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = <span class="fstat-no" title="function not covered" >(e</span>: MouseEvent) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (!isDragging.current) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingDelta.current += e.clientX - lastX.current</span>
|
||||
<span class="cstat-no" title="statement not covered" > lastX.current = e.clientX</span>
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
if (!isDragging.current) return
|
||||
pendingDelta.current += e.clientX - lastX.current
|
||||
lastX.current = e.clientX
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (!rafId.current) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > rafId.current = requestAnimationFrame(<span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (pendingDelta.current !== 0) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onResize(pendingDelta.current)</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingDelta.current = 0</span>
|
||||
if (!rafId.current) {
|
||||
rafId.current = requestAnimationFrame(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (pendingDelta.current !== 0) {
|
||||
onResize(pendingDelta.current)
|
||||
pendingDelta.current = 0
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > rafId.current = 0</span>
|
||||
rafId.current = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleMouseUp = <span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (isDragging.current) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > isDragging.current = false</span>
|
||||
<span class="cstat-no" title="statement not covered" > document.body.style.cursor = ''</span>
|
||||
<span class="cstat-no" title="statement not covered" > document.body.style.userSelect = ''</span>
|
||||
const handleMouseUp = () => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (isDragging.current) {
|
||||
isDragging.current = false
|
||||
document.body.style.cursor = ''
|
||||
document.body.style.userSelect = ''
|
||||
// Flush any pending delta
|
||||
<span class="cstat-no" title="statement not covered" > if (rafId.current) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > cancelAnimationFrame(rafId.current)</span>
|
||||
<span class="cstat-no" title="statement not covered" > rafId.current = 0</span>
|
||||
if (rafId.current) {
|
||||
cancelAnimationFrame(rafId.current)
|
||||
rafId.current = 0
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > if (pendingDelta.current !== 0) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onResize(pendingDelta.current)</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingDelta.current = 0</span>
|
||||
if (pendingDelta.current !== 0) {
|
||||
onResize(pendingDelta.current)
|
||||
pendingDelta.current = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,7 +292,7 @@ export function ResizeHandle({ onResize }: ResizeHandleProps) {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">34.78% </span>
|
||||
<span class="strong">65% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>8/23</span>
|
||||
<span class='fraction'>26/40</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">18.18% </span>
|
||||
<span class="strong">80.64% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>4/22</span>
|
||||
<span class='fraction'>25/31</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">27.27% </span>
|
||||
<span class="strong">52.17% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>3/11</span>
|
||||
<span class='fraction'>12/23</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">35.29% </span>
|
||||
<span class="strong">62.06% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>6/17</span>
|
||||
<span class='fraction'>18/29</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -214,15 +214,7 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L152'></a><a href='#L152'>152</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -238,29 +230,103 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">65x</span>
|
||||
<span class="cline-any cline-yes">65x</span>
|
||||
<span class="cline-any cline-yes">66x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">65x</span>
|
||||
<span class="cline-any cline-yes">40x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">65x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">52x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -275,59 +341,6 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -343,37 +356,8 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -382,7 +366,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useRef, useEffect } from 'react'
|
||||
import { Package, GitBranch, RefreshCw, Sparkles, FileText, Bell, Settings, FolderOpen, Check } from 'lucide-react'
|
||||
import { Package, GitBranch, RefreshCw, Sparkles, FileText, Bell, Settings, FolderOpen, Check, Github, CircleDot } from 'lucide-react'
|
||||
|
||||
export interface VaultOption {
|
||||
label: string
|
||||
@@ -391,148 +375,140 @@ export interface VaultOption {
|
||||
|
||||
interface StatusBarProps {
|
||||
noteCount: number
|
||||
modifiedCount?: number
|
||||
vaultPath: string
|
||||
vaults: VaultOption[]
|
||||
onSwitchVault: (path: string) => void
|
||||
onOpenSettings?: () => void
|
||||
onOpenLocalFolder?: () => void
|
||||
onConnectGitHub?: () => void
|
||||
onClickPending?: () => void
|
||||
hasGitHub?: boolean
|
||||
}
|
||||
|
||||
export function StatusBar({ noteCount, vaultPath, vaults, onSwitchVault }: StatusBarProps) {
|
||||
const [showVaultMenu, setShowVaultMenu] = useState(false)
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
function VaultMenuItem({ vault, isActive, onSelect }: { vault: VaultOption; isActive: boolean; onSelect: () => void }) {
|
||||
return (
|
||||
<div
|
||||
role="button" onClick={onSelect}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: 6, padding: '4px 8px', borderRadius: 4, cursor: 'pointer',
|
||||
background: isActive ? 'var(--hover)' : 'transparent',
|
||||
color: isActive ? 'var(--foreground)' : 'var(--muted-foreground)', fontSize: 12,
|
||||
}}
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >(e</span>) => { <span class="cstat-no" title="statement not covered" >if (!isActive) <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)' }</span></span>}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >(e</span>) => { <span class="cstat-no" title="statement not covered" >if (!isActive) <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent' }</span></span>}
|
||||
>
|
||||
{isActive ? <Check size={12} /> : <span style={{ width: 12 }} />}
|
||||
{vault.label}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function VaultMenu({ vaults, vaultPath, onSwitchVault, onOpenLocalFolder, onConnectGitHub, hasGitHub }: { vaults: VaultOption[]; vaultPath: string; onSwitchVault: (path: string) => void; onOpenLocalFolder?: () => void; onConnectGitHub?: () => void; hasGitHub?: boolean }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
const activeVault = vaults.find((v) => v.path === vaultPath)
|
||||
|
||||
useEffect(() => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!showVaultMenu) return
|
||||
const handleClick = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(e</span>: MouseEvent) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (menuRef.current && !menuRef.current.contains(e.target as Node)) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setShowVaultMenu(false)</span>
|
||||
}
|
||||
if (!open) return
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (menuRef.current && !menuRef.current.contains(e.target as Node)) setOpen(false)
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > document.addEventListener('mousedown', handleClick)</span>
|
||||
<span class="cstat-no" title="statement not covered" > return <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >d</span>ocument.removeEventListener('mousedown', handleClick)</span></span>
|
||||
}, [showVaultMenu])
|
||||
document.addEventListener('mousedown', handleClick)
|
||||
return () => document.removeEventListener('mousedown', handleClick)
|
||||
}, [open])
|
||||
|
||||
return (
|
||||
<footer
|
||||
style={{
|
||||
height: 30,
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
background: 'var(--sidebar)',
|
||||
borderTop: '1px solid var(--border)',
|
||||
padding: '0 8px',
|
||||
fontSize: 11,
|
||||
color: 'var(--muted-foreground)',
|
||||
}}
|
||||
>
|
||||
{/* Left section */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<div ref={menuRef} style={{ position: 'relative' }}>
|
||||
<span
|
||||
role="button"
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >s</span>etShowVaultMenu(<span class="fstat-no" title="function not covered" >(v</span>) => <span class="cstat-no" title="statement not covered" >!v)</span>}</span>
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
cursor: 'pointer',
|
||||
padding: '2px 4px',
|
||||
borderRadius: 3,
|
||||
background: showVaultMenu ? <span class="branch-0 cbranch-no" title="branch not covered" >'var(--hover)' : '</span>transparent',
|
||||
}}
|
||||
title="Switch vault"
|
||||
>
|
||||
<FolderOpen size={13} />
|
||||
{activeVault?.label ?? <span class="branch-1 cbranch-no" title="branch not covered" >'Vault'}</span>
|
||||
</span>
|
||||
{showVaultMenu && (
|
||||
<span class="branch-1 cbranch-no" title="branch not covered" > <div</span>
|
||||
<div ref={menuRef} style={{ position: 'relative' }}>
|
||||
<span role="button" onClick={() => setOpen((v) => !v)} style={{ display: 'flex', alignItems: 'center', gap: 4, cursor: 'pointer', padding: '2px 4px', borderRadius: 3, background: open ? 'var(--hover)' : 'transparent' }} title="Switch vault">
|
||||
<FolderOpen size={13} />
|
||||
{activeVault?.label ?? 'Vault'}
|
||||
</span>
|
||||
{open && (
|
||||
<div style={{ position: 'absolute', bottom: '100%', left: 0, marginBottom: 4, background: 'var(--sidebar)', border: '1px solid var(--border)', borderRadius: 6, padding: 4, minWidth: 200, boxShadow: '0 4px 12px rgba(0,0,0,0.3)', zIndex: 1000 }}>
|
||||
{vaults.map((v) => <VaultMenuItem key={v.path} vault={v} isActive={v.path === vaultPath} onSelect={() => { onSwitchVault(v.path); setOpen(false) }} />)}
|
||||
<div style={{ height: 1, background: 'var(--border)', margin: '4px 0' }} />
|
||||
{onOpenLocalFolder && (
|
||||
<div
|
||||
role="button"
|
||||
onClick={() => { onOpenLocalFolder(); setOpen(false) }}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '100%',
|
||||
left: 0,
|
||||
marginBottom: 4,
|
||||
background: 'var(--sidebar)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 6,
|
||||
padding: 4,
|
||||
minWidth: 160,
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
|
||||
zIndex: 1000,
|
||||
display: 'flex', alignItems: 'center', gap: 6, padding: '4px 8px', borderRadius: 4,
|
||||
cursor: 'pointer', background: 'transparent',
|
||||
color: 'var(--muted-foreground)', fontSize: 12,
|
||||
}}
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)' }</span>}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent' }</span>}
|
||||
data-testid="vault-menu-open-local"
|
||||
>
|
||||
{vaults.map(<span class="fstat-no" title="function not covered" >(v</span>) => (
|
||||
<span class="cstat-no" title="statement not covered" > <div</span>
|
||||
key={v.path}
|
||||
role="button"
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSwitchVault(v.path)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setShowVaultMenu(false)</span>
|
||||
}}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
padding: '4px 8px',
|
||||
borderRadius: 4,
|
||||
cursor: 'pointer',
|
||||
background: v.path === vaultPath ? 'var(--hover)' : 'transparent',
|
||||
color: v.path === vaultPath ? 'var(--foreground)' : 'var(--muted-foreground)',
|
||||
fontSize: 12,
|
||||
}}
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >(e</span>) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (v.path !== vaultPath) <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)'</span></span>
|
||||
}}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >(e</span>) => {
|
||||
<span class="cstat-no" title="statement not covered" > if (v.path !== vaultPath) <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent'</span></span>
|
||||
}}
|
||||
>
|
||||
{v.path === vaultPath ? <Check size={12} /> : <span style={{ width: 12 }} />}
|
||||
{v.label}
|
||||
</div>
|
||||
))}
|
||||
<FolderOpen size={12} />
|
||||
Open local folder
|
||||
</div>
|
||||
)}
|
||||
{onConnectGitHub && (
|
||||
<div
|
||||
role="button"
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => {</span> <span class="cstat-no" title="statement not covered" >onConnectGitHub(); <span class="cstat-no" title="statement not covered" >s</span>etOpen(false) }</span>}
|
||||
style={{
|
||||
display: 'flex', alignItems: 'center', gap: 6, padding: '4px 8px', borderRadius: 4,
|
||||
cursor: 'pointer', background: 'transparent',
|
||||
color: hasGitHub ? <span class="branch-0 cbranch-no" title="branch not covered" >'var(--muted-foreground)' : '</span>var(--accent-blue)', fontSize: 12,
|
||||
}}
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)' }</span>}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent' }</span>}
|
||||
data-testid="vault-menu-connect-github"
|
||||
>
|
||||
<Github size={12} />
|
||||
Connect GitHub repo
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span style={{ color: 'var(--border)' }}>|</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<Package size={13} />
|
||||
v0.4.2
|
||||
</span>
|
||||
<span style={{ color: 'var(--border)' }}>|</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<GitBranch size={13} />
|
||||
main
|
||||
</span>
|
||||
<span style={{ color: 'var(--border)' }}>|</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<RefreshCw size={13} style={{ color: 'var(--accent-green)' }} />
|
||||
Synced 2m ago
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
{/* Right section */}
|
||||
const ICON_STYLE = { display: 'flex', alignItems: 'center', gap: 4 } as const
|
||||
const DISABLED_STYLE = { display: 'flex', alignItems: 'center', opacity: 0.4, cursor: 'not-allowed' } as const
|
||||
const SEP_STYLE = { color: 'var(--border)' } as const
|
||||
|
||||
export function StatusBar({ noteCount, modifiedCount = 0, vaultPath, vaults, onSwitchVault, onOpenSettings, onOpenLocalFolder, onConnectGitHub, onClickPending, hasGitHub }: StatusBarProps) {
|
||||
return (
|
||||
<footer style={{ height: 30, flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'var(--sidebar)', borderTop: '1px solid var(--border)', padding: '0 8px', fontSize: 11, color: 'var(--muted-foreground)' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<Sparkles size={13} style={{ color: 'var(--accent-purple)' }} />
|
||||
Claude Sonnet 4
|
||||
</span>
|
||||
<span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||||
<FileText size={13} />
|
||||
{noteCount.toLocaleString()} notes
|
||||
</span>
|
||||
<VaultMenu vaults={vaults} vaultPath={vaultPath} onSwitchVault={onSwitchVault} onOpenLocalFolder={onOpenLocalFolder} onConnectGitHub={onConnectGitHub} hasGitHub={hasGitHub} />
|
||||
<span style={SEP_STYLE}>|</span>
|
||||
<span style={ICON_STYLE}><Package size={13} />v0.4.2</span>
|
||||
<span style={SEP_STYLE}>|</span>
|
||||
<span style={ICON_STYLE}><GitBranch size={13} />main</span>
|
||||
<span style={SEP_STYLE}>|</span>
|
||||
<span style={ICON_STYLE}><RefreshCw size={13} style={{ color: 'var(--accent-green)' }} />Synced 2m ago</span>
|
||||
{modifiedCount > 0 && (
|
||||
<>
|
||||
<span style={SEP_STYLE}>|</span>
|
||||
<span
|
||||
role="button"
|
||||
onClick={onClickPending}
|
||||
style={{ ...ICON_STYLE, cursor: 'pointer', padding: '2px 4px', borderRadius: 3, background: 'transparent' }}
|
||||
title="View pending changes"
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)' }</span>}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent' }</span>}
|
||||
data-testid="status-modified-count"
|
||||
><CircleDot size={13} style={{ color: 'var(--accent-orange)' }} />{modifiedCount} pending</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<span style={ICON_STYLE}><Sparkles size={13} style={{ color: 'var(--accent-purple)' }} />Claude Sonnet 4</span>
|
||||
<span style={ICON_STYLE}><FileText size={13} />{noteCount.toLocaleString()} notes</span>
|
||||
<span style={DISABLED_STYLE} title="Coming soon"><Bell size={14} /></span>
|
||||
<span
|
||||
style={{ display: 'flex', alignItems: 'center', opacity: 0.4, cursor: 'not-allowed' }}
|
||||
title="Coming soon"
|
||||
>
|
||||
<Bell size={14} />
|
||||
</span>
|
||||
<span
|
||||
style={{ display: 'flex', alignItems: 'center', opacity: 0.4, cursor: 'not-allowed' }}
|
||||
title="Coming soon"
|
||||
role="button"
|
||||
onClick={onOpenSettings}
|
||||
style={{ display: 'flex', alignItems: 'center', cursor: 'pointer', padding: '2px 4px', borderRadius: 3, background: 'transparent' }}
|
||||
title="Settings (⌘,)"
|
||||
onMouseEnter={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'var(--hover)' }</span>}
|
||||
onMouseLeave={<span class="fstat-no" title="function not covered" >e => {</span> <span class="cstat-no" title="statement not covered" >e.currentTarget.style.background = 'transparent' }</span>}
|
||||
>
|
||||
<Settings size={14} />
|
||||
</span>
|
||||
@@ -547,7 +523,7 @@ export function StatusBar({ noteCount, vaultPath, vaults, onSwitchVault }: Statu
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -100,13 +100,13 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -154,7 +154,7 @@ export function Toast({ message, onDismiss }: ToastProps) {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">21.05% </span>
|
||||
<span class="strong">95.83% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>4/19</span>
|
||||
<span class='fraction'>23/24</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">22.22% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>2/9</span>
|
||||
<span class='fraction'>10/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">18.18% </span>
|
||||
<span class="strong">92.3% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>2/11</span>
|
||||
<span class='fraction'>12/13</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">21.05% </span>
|
||||
<span class="strong">95.23% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>4/19</span>
|
||||
<span class='fraction'>20/21</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -186,29 +186,16 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L124'></a><a href='#L124'>124</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">572x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -221,100 +208,46 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">105x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">96x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -324,7 +257,6 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -333,7 +265,30 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2867x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -353,64 +308,17 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, type ComponentType } from 'react'
|
||||
import {
|
||||
FileText, Wrench, Flask, Target, ArrowsClockwise, Users, CalendarBlank,
|
||||
Tag, StackSimple, BookOpen, CookingPot, Heart, Star, House, Lightbulb,
|
||||
Briefcase, Gear, Cube, Leaf, MusicNote, Camera, Airplane, GameController,
|
||||
PaintBrush, ShoppingCart, GraduationCap, Trophy, ChatCircle, Notebook,
|
||||
MapPin, Code, Barbell, PawPrint, Pill, Knife,
|
||||
type IconProps,
|
||||
} from '@phosphor-icons/react'
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useMemo } from 'react'
|
||||
import { MagnifyingGlass } from '@phosphor-icons/react'
|
||||
import { ICON_OPTIONS, type IconEntry } from '../utils/iconRegistry'
|
||||
import { ACCENT_COLORS } from '../utils/typeColors'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
/** Curated Phosphor icons (normal weight) for type customization */
|
||||
export const ICON_OPTIONS: { name: string; Icon: ComponentType<IconProps> }[] = [
|
||||
{ name: 'file-text', Icon: FileText },
|
||||
{ name: 'wrench', Icon: Wrench },
|
||||
{ name: 'flask', Icon: Flask },
|
||||
{ name: 'target', Icon: Target },
|
||||
{ name: 'arrows-clockwise', Icon: ArrowsClockwise },
|
||||
{ name: 'users', Icon: Users },
|
||||
{ name: 'calendar-blank', Icon: CalendarBlank },
|
||||
{ name: 'tag', Icon: Tag },
|
||||
{ name: 'stack-simple', Icon: StackSimple },
|
||||
{ name: 'book-open', Icon: BookOpen },
|
||||
{ name: 'cooking-pot', Icon: CookingPot },
|
||||
{ name: 'heart', Icon: Heart },
|
||||
{ name: 'star', Icon: Star },
|
||||
{ name: 'house', Icon: House },
|
||||
{ name: 'lightbulb', Icon: Lightbulb },
|
||||
{ name: 'briefcase', Icon: Briefcase },
|
||||
{ name: 'gear', Icon: Gear },
|
||||
{ name: 'cube', Icon: Cube },
|
||||
{ name: 'leaf', Icon: Leaf },
|
||||
{ name: 'music-note', Icon: MusicNote },
|
||||
{ name: 'camera', Icon: Camera },
|
||||
{ name: 'airplane', Icon: Airplane },
|
||||
{ name: 'game-controller', Icon: GameController },
|
||||
{ name: 'paint-brush', Icon: PaintBrush },
|
||||
{ name: 'shopping-cart', Icon: ShoppingCart },
|
||||
{ name: 'graduation-cap', Icon: GraduationCap },
|
||||
{ name: 'trophy', Icon: Trophy },
|
||||
{ name: 'chat-circle', Icon: ChatCircle },
|
||||
{ name: 'notebook', Icon: Notebook },
|
||||
{ name: 'map-pin', Icon: MapPin },
|
||||
{ name: 'code', Icon: Code },
|
||||
{ name: 'barbell', Icon: Barbell },
|
||||
{ name: 'paw-print', Icon: PawPrint },
|
||||
{ name: 'pill', Icon: Pill },
|
||||
{ name: 'knife', Icon: Knife },
|
||||
]
|
||||
|
||||
const ICON_MAP: Record<string, ComponentType<IconProps>> = Object.fromEntries(
|
||||
ICON_OPTIONS.map((o) => [o.name, o.Icon]),
|
||||
)
|
||||
|
||||
/** Resolves a Phosphor icon name to its component, with fallback to FileText */
|
||||
export function resolveIcon(name: string | null): ComponentType<IconProps> {
|
||||
return (name && <span class="branch-1 cbranch-no" title="branch not covered" >ICON_MAP[name]) || F</span>ileText
|
||||
function filterIcons(icons: IconEntry[], query: string): IconEntry[] {
|
||||
if (!query) return icons
|
||||
const lower = query.toLowerCase()
|
||||
return icons.filter((o) => o.name.includes(lower))
|
||||
}
|
||||
|
||||
interface TypeCustomizePopoverProps {
|
||||
@@ -421,45 +329,48 @@ interface TypeCustomizePopoverProps {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >TypeCustomizePopover({</span>
|
||||
export function TypeCustomizePopover({
|
||||
currentIcon,
|
||||
currentColor,
|
||||
onChangeIcon,
|
||||
onChangeColor,
|
||||
onClose,
|
||||
}: TypeCustomizePopoverProps) {
|
||||
const [selectedColor, setSelectedColor<span class="cstat-no" title="statement not covered" >] = useState(currentColor)</span>
|
||||
const [selectedIcon, setSelectedIcon<span class="cstat-no" title="statement not covered" >] = useState(currentIcon)</span>
|
||||
const [selectedColor, setSelectedColor] = useState(currentColor)
|
||||
const [selectedIcon, setSelectedIcon] = useState(currentIcon)
|
||||
const [search, setSearch] = useState('')
|
||||
|
||||
const handleColorClick = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(k</span>ey: string) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelectedColor(key)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onChangeColor(key)</span>
|
||||
const filteredIcons = useMemo(() => filterIcons(ICON_OPTIONS, search), [search])
|
||||
|
||||
const handleColorClick = (key: string) => {
|
||||
setSelectedColor(key)
|
||||
onChangeColor(key)
|
||||
}
|
||||
|
||||
const handleIconClick = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(n</span>ame: string) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > setSelectedIcon(name)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onChangeIcon(name)</span>
|
||||
const handleIconClick = (name: string) => {
|
||||
setSelectedIcon(name)
|
||||
onChangeIcon(name)
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
return (
|
||||
<div
|
||||
className="bg-popover text-popover-foreground z-50 rounded-lg border shadow-md"
|
||||
style={{ width: 264, padding: 12 }}
|
||||
onClick={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.stopPropagation()}</span>
|
||||
style={{ width: 280, padding: 12 }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onContextMenu={<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.stopPropagation()}</span>
|
||||
>
|
||||
{/* Color section */}
|
||||
<div className="font-mono-overline mb-2 text-muted-foreground">COLOR</div>
|
||||
<div className="flex gap-2 mb-3">
|
||||
{ACCENT_COLORS.map(<span class="fstat-no" title="function not covered" >(c</span>) => (
|
||||
<span class="cstat-no" title="statement not covered" > <button</span>
|
||||
<div className="flex gap-2 mb-3 flex-wrap">
|
||||
{ACCENT_COLORS.map((c) => (
|
||||
<button
|
||||
key={c.key}
|
||||
className={cn(
|
||||
"flex items-center justify-center rounded-full border-2 cursor-pointer transition-all",
|
||||
selectedColor === c.key ? "border-foreground scale-110" : "border-transparent hover:scale-105",
|
||||
)}
|
||||
style={{ width: 28, height: 28, backgroundColor: c.css, border: selectedColor === c.key ? '2px solid var(--foreground)' : '2px solid transparent' }}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >h</span>andleColorClick(c.key)}</span>
|
||||
style={{ width: 24, height: 24, backgroundColor: c.css, border: selectedColor === c.key ? '2px solid var(--foreground)' : '2px solid transparent' }}
|
||||
onClick={() => handleColorClick(c.key)}
|
||||
title={c.label}
|
||||
/>
|
||||
))}
|
||||
@@ -467,23 +378,46 @@ export function <span class="fstat-no" title="function not covered" >TypeCustomi
|
||||
|
||||
{/* Icon section */}
|
||||
<div className="font-mono-overline mb-2 text-muted-foreground">ICON</div>
|
||||
<div className="flex flex-wrap gap-1" style={{ maxHeight: 200, overflowY: 'auto' }}>
|
||||
{ICON_OPTIONS.map(<span class="fstat-no" title="function not covered" >({</span> name, Icon }) => (
|
||||
<span class="cstat-no" title="statement not covered" > <button</span>
|
||||
key={name}
|
||||
className={cn(
|
||||
"flex items-center justify-center rounded cursor-pointer transition-colors",
|
||||
selectedIcon === name
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-muted-foreground hover:bg-accent hover:text-foreground",
|
||||
)}
|
||||
style={{ width: 30, height: 30 }}
|
||||
onClick={<span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >h</span>andleIconClick(name)}</span>
|
||||
title={name}
|
||||
>
|
||||
<Icon size={16} />
|
||||
</button>
|
||||
))}
|
||||
|
||||
{/* Search input */}
|
||||
<div className="relative mb-2">
|
||||
<MagnifyingGlass
|
||||
size={14}
|
||||
className="absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
placeholder="Search icons…"
|
||||
className="w-full rounded border border-border bg-background pl-7 pr-2 py-1 text-[12px] text-foreground placeholder:text-muted-foreground outline-none focus:border-primary"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Icon grid */}
|
||||
<div className="flex flex-wrap gap-1 overflow-y-auto" style={{ maxHeight: 240 }}>
|
||||
{filteredIcons.length === 0 ? (
|
||||
<div className="w-full py-6 text-center text-[12px] text-muted-foreground">
|
||||
No icons found
|
||||
</div>
|
||||
) : (
|
||||
filteredIcons.map(({ name, Icon }) => (
|
||||
<button
|
||||
key={name}
|
||||
className={cn(
|
||||
"flex items-center justify-center rounded cursor-pointer transition-colors",
|
||||
selectedIcon === name
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-muted-foreground hover:bg-accent hover:text-foreground",
|
||||
)}
|
||||
style={{ width: 30, height: 30 }}
|
||||
onClick={() => handleIconClick(name)}
|
||||
title={name}
|
||||
>
|
||||
<Icon size={16} />
|
||||
</button>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Done button */}
|
||||
@@ -505,7 +439,7 @@ export function <span class="fstat-no" title="function not covered" >TypeCustomi
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">54.44% </span>
|
||||
<span class="strong">80.93% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>710/1304</span>
|
||||
<span class='fraction'>1482/1831</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">50.75% </span>
|
||||
<span class="strong">73.93% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>540/1064</span>
|
||||
<span class='fraction'>990/1339</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">50.11% </span>
|
||||
<span class="strong">80.36% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>210/419</span>
|
||||
<span class='fraction'>491/611</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">57.02% </span>
|
||||
<span class="strong">82.93% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>629/1103</span>
|
||||
<span class='fraction'>1249/1506</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line medium'></div>
|
||||
<div class='status-line high'></div>
|
||||
<div class="pad1">
|
||||
<table class="coverage-summary">
|
||||
<thead>
|
||||
@@ -79,29 +79,14 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file low" data-value="AIChatPanel.tsx"><a href="AIChatPanel.tsx.html">AIChatPanel.tsx</a></td>
|
||||
<td data-value="1.17" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 1%"></div><div class="cover-empty" style="width: 99%"></div></div>
|
||||
</td>
|
||||
<td data-value="1.17" class="pct low">1.17%</td>
|
||||
<td data-value="85" class="abs low">1/85</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="49" class="abs low">0/49</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="55" class="abs low">0/55</td>
|
||||
<td data-value="1.47" class="pct low">1.47%</td>
|
||||
<td data-value="68" class="abs low">1/68</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="BreadcrumbBar.tsx"><a href="BreadcrumbBar.tsx.html">BreadcrumbBar.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="4" class="abs high">4/4</td>
|
||||
<td data-value="69.23" class="pct medium">69.23%</td>
|
||||
<td data-value="26" class="abs medium">18/26</td>
|
||||
<td data-value="71.42" class="pct medium">71.42%</td>
|
||||
<td data-value="28" class="abs medium">20/28</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="2" class="abs high">2/2</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
@@ -109,33 +94,48 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="CommitDialog.tsx"><a href="CommitDialog.tsx.html">CommitDialog.tsx</a></td>
|
||||
<td data-value="31.81" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 31%"></div><div class="cover-empty" style="width: 69%"></div></div>
|
||||
<td class="file high" data-value="CommandPalette.tsx"><a href="CommandPalette.tsx.html">CommandPalette.tsx</a></td>
|
||||
<td data-value="96.73" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 96%"></div><div class="cover-empty" style="width: 4%"></div></div>
|
||||
</td>
|
||||
<td data-value="31.81" class="pct low">31.81%</td>
|
||||
<td data-value="22" class="abs low">7/22</td>
|
||||
<td data-value="13.33" class="pct low">13.33%</td>
|
||||
<td data-value="15" class="abs low">2/15</td>
|
||||
<td data-value="28.57" class="pct low">28.57%</td>
|
||||
<td data-value="7" class="abs low">2/7</td>
|
||||
<td data-value="36.84" class="pct low">36.84%</td>
|
||||
<td data-value="19" class="abs low">7/19</td>
|
||||
<td data-value="96.73" class="pct high">96.73%</td>
|
||||
<td data-value="92" class="abs high">89/92</td>
|
||||
<td data-value="88.88" class="pct high">88.88%</td>
|
||||
<td data-value="36" class="abs high">32/36</td>
|
||||
<td data-value="93.54" class="pct high">93.54%</td>
|
||||
<td data-value="31" class="abs high">29/31</td>
|
||||
<td data-value="97.14" class="pct high">97.14%</td>
|
||||
<td data-value="70" class="abs high">68/70</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="CreateNoteDialog.tsx"><a href="CreateNoteDialog.tsx.html">CreateNoteDialog.tsx</a></td>
|
||||
<td data-value="36" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 36%"></div><div class="cover-empty" style="width: 64%"></div></div>
|
||||
<td class="file high" data-value="CommitDialog.tsx"><a href="CommitDialog.tsx.html">CommitDialog.tsx</a></td>
|
||||
<td data-value="95.45" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||
</td>
|
||||
<td data-value="36" class="pct low">36%</td>
|
||||
<td data-value="25" class="abs low">9/25</td>
|
||||
<td data-value="35.29" class="pct low">35.29%</td>
|
||||
<td data-value="17" class="abs low">6/17</td>
|
||||
<td data-value="30" class="pct low">30%</td>
|
||||
<td data-value="10" class="abs low">3/10</td>
|
||||
<td data-value="40.9" class="pct low">40.9%</td>
|
||||
<td data-value="22" class="abs low">9/22</td>
|
||||
<td data-value="95.45" class="pct high">95.45%</td>
|
||||
<td data-value="22" class="abs high">21/22</td>
|
||||
<td data-value="73.33" class="pct medium">73.33%</td>
|
||||
<td data-value="15" class="abs medium">11/15</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="7" class="abs high">7/7</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="19" class="abs high">19/19</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="CreateNoteDialog.tsx"><a href="CreateNoteDialog.tsx.html">CreateNoteDialog.tsx</a></td>
|
||||
<td data-value="92" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 92%"></div><div class="cover-empty" style="width: 8%"></div></div>
|
||||
</td>
|
||||
<td data-value="92" class="pct high">92%</td>
|
||||
<td data-value="25" class="abs high">23/25</td>
|
||||
<td data-value="88.23" class="pct high">88.23%</td>
|
||||
<td data-value="17" class="abs high">15/17</td>
|
||||
<td data-value="90" class="pct high">90%</td>
|
||||
<td data-value="10" class="abs high">9/10</td>
|
||||
<td data-value="95.23" class="pct high">95.23%</td>
|
||||
<td data-value="21" class="abs high">20/21</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -154,168 +154,303 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="DiffView.tsx"><a href="DiffView.tsx.html">DiffView.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
|
||||
<td class="file high" data-value="DiffView.tsx"><a href="DiffView.tsx.html">DiffView.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="0" class="pct low">0%</td>
|
||||
<td data-value="14" class="abs low">0/14</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="21" class="abs low">0/21</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="14" class="abs low">0/14</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="16" class="abs high">16/16</td>
|
||||
<td data-value="93.75" class="pct high">93.75%</td>
|
||||
<td data-value="16" class="abs high">15/16</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="11" class="abs high">11/11</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="DynamicPropertiesPanel.tsx"><a href="DynamicPropertiesPanel.tsx.html">DynamicPropertiesPanel.tsx</a></td>
|
||||
<td data-value="41.96" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 41%"></div><div class="cover-empty" style="width: 59%"></div></div>
|
||||
<td class="file high" data-value="DynamicPropertiesPanel.tsx"><a href="DynamicPropertiesPanel.tsx.html">DynamicPropertiesPanel.tsx</a></td>
|
||||
<td data-value="87.78" 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="41.96" class="pct low">41.96%</td>
|
||||
<td data-value="112" class="abs low">47/112</td>
|
||||
<td data-value="40.24" class="pct low">40.24%</td>
|
||||
<td data-value="82" class="abs low">33/82</td>
|
||||
<td data-value="27.77" class="pct low">27.77%</td>
|
||||
<td data-value="36" class="abs low">10/36</td>
|
||||
<td data-value="47.19" class="pct low">47.19%</td>
|
||||
<td data-value="89" class="abs low">42/89</td>
|
||||
<td data-value="87.78" class="pct high">87.78%</td>
|
||||
<td data-value="131" class="abs high">115/131</td>
|
||||
<td data-value="80.73" class="pct high">80.73%</td>
|
||||
<td data-value="109" class="abs high">88/109</td>
|
||||
<td data-value="90.38" class="pct high">90.38%</td>
|
||||
<td data-value="52" class="abs high">47/52</td>
|
||||
<td data-value="93.68" class="pct high">93.68%</td>
|
||||
<td data-value="95" class="abs high">89/95</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="EditableValue.tsx"><a href="EditableValue.tsx.html">EditableValue.tsx</a></td>
|
||||
<td data-value="24.59" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 24%"></div><div class="cover-empty" style="width: 76%"></div></div>
|
||||
<td class="file high" data-value="EditableValue.tsx"><a href="EditableValue.tsx.html">EditableValue.tsx</a></td>
|
||||
<td data-value="97.72" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
|
||||
</td>
|
||||
<td data-value="24.59" class="pct low">24.59%</td>
|
||||
<td data-value="61" class="abs low">15/61</td>
|
||||
<td data-value="16.66" class="pct low">16.66%</td>
|
||||
<td data-value="30" class="abs low">5/30</td>
|
||||
<td data-value="15" class="pct low">15%</td>
|
||||
<td data-value="20" class="abs low">3/20</td>
|
||||
<td data-value="26.31" class="pct low">26.31%</td>
|
||||
<td data-value="57" class="abs low">15/57</td>
|
||||
<td data-value="97.72" class="pct high">97.72%</td>
|
||||
<td data-value="88" class="abs high">86/88</td>
|
||||
<td data-value="82.5" class="pct high">82.5%</td>
|
||||
<td data-value="40" class="abs high">33/40</td>
|
||||
<td data-value="92.85" class="pct high">92.85%</td>
|
||||
<td data-value="28" class="abs high">26/28</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="82" class="abs high">82/82</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="Editor.tsx"><a href="Editor.tsx.html">Editor.tsx</a></td>
|
||||
<td data-value="50.52" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 50%"></div><div class="cover-empty" style="width: 50%"></div></div>
|
||||
<td data-value="61.81" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 61%"></div><div class="cover-empty" style="width: 39%"></div></div>
|
||||
</td>
|
||||
<td data-value="50.52" class="pct medium">50.52%</td>
|
||||
<td data-value="192" class="abs medium">97/192</td>
|
||||
<td data-value="48.33" class="pct low">48.33%</td>
|
||||
<td data-value="120" class="abs low">58/120</td>
|
||||
<td data-value="47.36" class="pct low">47.36%</td>
|
||||
<td data-value="38" class="abs low">18/38</td>
|
||||
<td data-value="53.84" class="pct medium">53.84%</td>
|
||||
<td data-value="169" class="abs medium">91/169</td>
|
||||
<td data-value="61.81" class="pct medium">61.81%</td>
|
||||
<td data-value="220" class="abs medium">136/220</td>
|
||||
<td data-value="55.83" class="pct medium">55.83%</td>
|
||||
<td data-value="120" class="abs medium">67/120</td>
|
||||
<td data-value="62.5" class="pct medium">62.5%</td>
|
||||
<td data-value="48" class="abs medium">30/48</td>
|
||||
<td data-value="63.73" class="pct medium">63.73%</td>
|
||||
<td data-value="193" class="abs medium">123/193</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="Inspector.tsx"><a href="Inspector.tsx.html">Inspector.tsx</a></td>
|
||||
<td data-value="64.28" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 64%"></div><div class="cover-empty" style="width: 36%"></div></div>
|
||||
<td class="file medium" data-value="GitHubVaultModal.tsx"><a href="GitHubVaultModal.tsx.html">GitHubVaultModal.tsx</a></td>
|
||||
<td data-value="70" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 70%"></div><div class="cover-empty" style="width: 30%"></div></div>
|
||||
</td>
|
||||
<td data-value="64.28" class="pct medium">64.28%</td>
|
||||
<td data-value="140" class="abs medium">90/140</td>
|
||||
<td data-value="52.17" class="pct medium">52.17%</td>
|
||||
<td data-value="161" class="abs medium">84/161</td>
|
||||
<td data-value="72.09" class="pct medium">72.09%</td>
|
||||
<td data-value="43" class="abs medium">31/43</td>
|
||||
<td data-value="76.19" class="pct medium">76.19%</td>
|
||||
<td data-value="105" class="abs medium">80/105</td>
|
||||
<td data-value="70" class="pct medium">70%</td>
|
||||
<td data-value="100" class="abs medium">70/100</td>
|
||||
<td data-value="53.84" class="pct medium">53.84%</td>
|
||||
<td data-value="78" class="abs medium">42/78</td>
|
||||
<td data-value="62.96" class="pct medium">62.96%</td>
|
||||
<td data-value="27" class="abs medium">17/27</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="92" class="abs medium">69/92</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="Inspector.tsx"><a href="Inspector.tsx.html">Inspector.tsx</a></td>
|
||||
<td data-value="88" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
|
||||
</td>
|
||||
<td data-value="88" class="pct high">88%</td>
|
||||
<td data-value="50" class="abs high">44/50</td>
|
||||
<td data-value="59.25" class="pct medium">59.25%</td>
|
||||
<td data-value="54" class="abs medium">32/54</td>
|
||||
<td data-value="78.57" class="pct medium">78.57%</td>
|
||||
<td data-value="14" class="abs medium">11/14</td>
|
||||
<td data-value="92.3" class="pct high">92.3%</td>
|
||||
<td data-value="39" class="abs high">36/39</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="InspectorPanels.tsx"><a href="InspectorPanels.tsx.html">InspectorPanels.tsx</a></td>
|
||||
<td data-value="85.41" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 85%"></div><div class="cover-empty" style="width: 15%"></div></div>
|
||||
</td>
|
||||
<td data-value="85.41" class="pct high">85.41%</td>
|
||||
<td data-value="192" class="abs high">164/192</td>
|
||||
<td data-value="80.5" class="pct high">80.5%</td>
|
||||
<td data-value="159" class="abs high">128/159</td>
|
||||
<td data-value="86.36" class="pct high">86.36%</td>
|
||||
<td data-value="66" class="abs high">57/66</td>
|
||||
<td data-value="91.03" class="pct high">91.03%</td>
|
||||
<td data-value="145" class="abs high">132/145</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="NoteAutocomplete.tsx"><a href="NoteAutocomplete.tsx.html">NoteAutocomplete.tsx</a></td>
|
||||
<td data-value="75" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 75%"></div><div class="cover-empty" style="width: 25%"></div></div>
|
||||
</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="72" class="abs medium">54/72</td>
|
||||
<td data-value="74.5" class="pct medium">74.5%</td>
|
||||
<td data-value="51" class="abs medium">38/51</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="20" class="abs medium">15/20</td>
|
||||
<td data-value="74.6" class="pct medium">74.6%</td>
|
||||
<td data-value="63" class="abs medium">47/63</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="NoteItem.tsx"><a href="NoteItem.tsx.html">NoteItem.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="19" class="abs high">19/19</td>
|
||||
<td data-value="94.73" class="pct high">94.73%</td>
|
||||
<td data-value="38" class="abs high">36/38</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="6" class="abs high">6/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="17" class="abs high">17/17</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="NoteList.tsx"><a href="NoteList.tsx.html">NoteList.tsx</a></td>
|
||||
<td data-value="85.71" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 85%"></div><div class="cover-empty" style="width: 15%"></div></div>
|
||||
<td data-value="93.6" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 93%"></div><div class="cover-empty" style="width: 7%"></div></div>
|
||||
</td>
|
||||
<td data-value="85.71" class="pct high">85.71%</td>
|
||||
<td data-value="245" class="abs high">210/245</td>
|
||||
<td data-value="76.49" class="pct medium">76.49%</td>
|
||||
<td data-value="251" class="abs medium">192/251</td>
|
||||
<td data-value="85.52" class="pct high">85.52%</td>
|
||||
<td data-value="76" class="abs high">65/76</td>
|
||||
<td data-value="87.5" class="pct high">87.5%</td>
|
||||
<td data-value="208" class="abs high">182/208</td>
|
||||
<td data-value="93.6" class="pct high">93.6%</td>
|
||||
<td data-value="125" class="abs high">117/125</td>
|
||||
<td data-value="83.78" class="pct high">83.78%</td>
|
||||
<td data-value="111" class="abs high">93/111</td>
|
||||
<td data-value="93.47" class="pct high">93.47%</td>
|
||||
<td data-value="46" class="abs high">43/46</td>
|
||||
<td data-value="97.8" class="pct high">97.8%</td>
|
||||
<td data-value="91" class="abs high">89/91</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="QuickOpenPalette.tsx"><a href="QuickOpenPalette.tsx.html">QuickOpenPalette.tsx</a></td>
|
||||
<td data-value="27.02" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 27%"></div><div class="cover-empty" style="width: 73%"></div></div>
|
||||
<td class="file high" data-value="NoteSearchList.tsx"><a href="NoteSearchList.tsx.html">NoteSearchList.tsx</a></td>
|
||||
<td data-value="91.66" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 91%"></div><div class="cover-empty" style="width: 9%"></div></div>
|
||||
</td>
|
||||
<td data-value="27.02" class="pct low">27.02%</td>
|
||||
<td data-value="74" class="abs low">20/74</td>
|
||||
<td data-value="17.07" class="pct low">17.07%</td>
|
||||
<td data-value="41" class="abs low">7/41</td>
|
||||
<td data-value="31.81" class="pct low">31.81%</td>
|
||||
<td data-value="22" class="abs low">7/22</td>
|
||||
<td data-value="25.39" class="pct low">25.39%</td>
|
||||
<td data-value="63" class="abs low">16/63</td>
|
||||
<td data-value="91.66" class="pct high">91.66%</td>
|
||||
<td data-value="12" class="abs high">11/12</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="11" class="abs high">10/11</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="11" class="abs high">11/11</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="ResizeHandle.tsx"><a href="ResizeHandle.tsx.html">ResizeHandle.tsx</a></td>
|
||||
<td data-value="35.71" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 35%"></div><div class="cover-empty" style="width: 65%"></div></div>
|
||||
<td class="file high" data-value="QuickOpenPalette.tsx"><a href="QuickOpenPalette.tsx.html">QuickOpenPalette.tsx</a></td>
|
||||
<td data-value="97.14" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
|
||||
</td>
|
||||
<td data-value="35.71" class="pct low">35.71%</td>
|
||||
<td data-value="42" class="abs low">15/42</td>
|
||||
<td data-value="7.14" class="pct low">7.14%</td>
|
||||
<td data-value="14" class="abs low">1/14</td>
|
||||
<td data-value="42.85" class="pct low">42.85%</td>
|
||||
<td data-value="7" class="abs low">3/7</td>
|
||||
<td data-value="37.5" class="pct low">37.5%</td>
|
||||
<td data-value="40" class="abs low">15/40</td>
|
||||
<td data-value="97.14" class="pct high">97.14%</td>
|
||||
<td data-value="35" class="abs high">34/35</td>
|
||||
<td data-value="91.66" class="pct high">91.66%</td>
|
||||
<td data-value="12" class="abs high">11/12</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="11" class="abs high">10/11</td>
|
||||
<td data-value="96.77" class="pct high">96.77%</td>
|
||||
<td data-value="31" class="abs high">30/31</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="ResizeHandle.tsx"><a href="ResizeHandle.tsx.html">ResizeHandle.tsx</a></td>
|
||||
<td data-value="97.61" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
|
||||
</td>
|
||||
<td data-value="97.61" class="pct high">97.61%</td>
|
||||
<td data-value="42" class="abs high">41/42</td>
|
||||
<td data-value="78.57" class="pct medium">78.57%</td>
|
||||
<td data-value="14" class="abs medium">11/14</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="7" class="abs high">7/7</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="40" class="abs high">40/40</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="SearchPanel.tsx"><a href="SearchPanel.tsx.html">SearchPanel.tsx</a></td>
|
||||
<td data-value="88.88" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
|
||||
</td>
|
||||
<td data-value="88.88" class="pct high">88.88%</td>
|
||||
<td data-value="54" class="abs high">48/54</td>
|
||||
<td data-value="86.95" class="pct high">86.95%</td>
|
||||
<td data-value="46" class="abs high">40/46</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="88.37" class="pct high">88.37%</td>
|
||||
<td data-value="43" class="abs high">38/43</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="SettingsPanel.tsx"><a href="SettingsPanel.tsx.html">SettingsPanel.tsx</a></td>
|
||||
<td data-value="69.42" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 69%"></div><div class="cover-empty" style="width: 31%"></div></div>
|
||||
</td>
|
||||
<td data-value="69.42" class="pct medium">69.42%</td>
|
||||
<td data-value="121" class="abs medium">84/121</td>
|
||||
<td data-value="68.29" class="pct medium">68.29%</td>
|
||||
<td data-value="82" class="abs medium">56/82</td>
|
||||
<td data-value="72.97" class="pct medium">72.97%</td>
|
||||
<td data-value="37" class="abs medium">27/37</td>
|
||||
<td data-value="69.09" class="pct medium">69.09%</td>
|
||||
<td data-value="110" class="abs medium">76/110</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="Sidebar.tsx"><a href="Sidebar.tsx.html">Sidebar.tsx</a></td>
|
||||
<td data-value="66.07" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 66%"></div><div class="cover-empty" style="width: 34%"></div></div>
|
||||
<td data-value="68.79" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 68%"></div><div class="cover-empty" style="width: 32%"></div></div>
|
||||
</td>
|
||||
<td data-value="66.07" class="pct medium">66.07%</td>
|
||||
<td data-value="168" class="abs medium">111/168</td>
|
||||
<td data-value="55.92" class="pct medium">55.92%</td>
|
||||
<td data-value="152" class="abs medium">85/152</td>
|
||||
<td data-value="72.41" class="pct medium">72.41%</td>
|
||||
<td data-value="58" class="abs medium">42/58</td>
|
||||
<td data-value="65.69" class="pct medium">65.69%</td>
|
||||
<td data-value="137" class="abs medium">90/137</td>
|
||||
<td data-value="68.79" class="pct medium">68.79%</td>
|
||||
<td data-value="141" class="abs medium">97/141</td>
|
||||
<td data-value="52.43" class="pct medium">52.43%</td>
|
||||
<td data-value="82" class="abs medium">43/82</td>
|
||||
<td data-value="70.37" class="pct medium">70.37%</td>
|
||||
<td data-value="54" class="abs medium">38/54</td>
|
||||
<td data-value="70.75" class="pct medium">70.75%</td>
|
||||
<td data-value="106" class="abs medium">75/106</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="StatusBar.tsx"><a href="StatusBar.tsx.html">StatusBar.tsx</a></td>
|
||||
<td data-value="34.78" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 34%"></div><div class="cover-empty" style="width: 66%"></div></div>
|
||||
<td class="file high" data-value="SidebarParts.tsx"><a href="SidebarParts.tsx.html">SidebarParts.tsx</a></td>
|
||||
<td data-value="90" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 90%"></div><div class="cover-empty" style="width: 10%"></div></div>
|
||||
</td>
|
||||
<td data-value="34.78" class="pct low">34.78%</td>
|
||||
<td data-value="23" class="abs low">8/23</td>
|
||||
<td data-value="18.18" class="pct low">18.18%</td>
|
||||
<td data-value="22" class="abs low">4/22</td>
|
||||
<td data-value="27.27" class="pct low">27.27%</td>
|
||||
<td data-value="11" class="abs low">3/11</td>
|
||||
<td data-value="35.29" class="pct low">35.29%</td>
|
||||
<td data-value="17" class="abs low">6/17</td>
|
||||
<td data-value="90" class="pct high">90%</td>
|
||||
<td data-value="40" class="abs high">36/40</td>
|
||||
<td data-value="82.69" class="pct high">82.69%</td>
|
||||
<td data-value="52" class="abs high">43/52</td>
|
||||
<td data-value="95" class="pct high">95%</td>
|
||||
<td data-value="20" class="abs high">19/20</td>
|
||||
<td data-value="87.5" class="pct high">87.5%</td>
|
||||
<td data-value="32" class="abs high">28/32</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="TabBar.tsx"><a href="TabBar.tsx.html">TabBar.tsx</a></td>
|
||||
<td data-value="92.15" class="pic high">
|
||||
<td class="file high" data-value="SortDropdown.tsx"><a href="SortDropdown.tsx.html">SortDropdown.tsx</a></td>
|
||||
<td data-value="92.3" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 92%"></div><div class="cover-empty" style="width: 8%"></div></div>
|
||||
</td>
|
||||
<td data-value="92.15" class="pct high">92.15%</td>
|
||||
<td data-value="51" class="abs high">47/51</td>
|
||||
<td data-value="79.54" class="pct medium">79.54%</td>
|
||||
<td data-value="44" class="abs medium">35/44</td>
|
||||
<td data-value="91.66" class="pct high">91.66%</td>
|
||||
<td data-value="12" class="abs high">11/12</td>
|
||||
<td data-value="92.15" class="pct high">92.15%</td>
|
||||
<td data-value="51" class="abs high">47/51</td>
|
||||
<td data-value="92.3" class="pct high">92.3%</td>
|
||||
<td data-value="26" class="abs high">24/26</td>
|
||||
<td data-value="78.57" class="pct medium">78.57%</td>
|
||||
<td data-value="28" class="abs medium">22/28</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="11" class="abs high">10/11</td>
|
||||
<td data-value="94.73" class="pct high">94.73%</td>
|
||||
<td data-value="19" class="abs high">18/19</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="StatusBar.tsx"><a href="StatusBar.tsx.html">StatusBar.tsx</a></td>
|
||||
<td data-value="65" 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" class="pct medium">65%</td>
|
||||
<td data-value="40" class="abs medium">26/40</td>
|
||||
<td data-value="80.64" class="pct high">80.64%</td>
|
||||
<td data-value="31" class="abs high">25/31</td>
|
||||
<td data-value="52.17" class="pct medium">52.17%</td>
|
||||
<td data-value="23" class="abs medium">12/23</td>
|
||||
<td data-value="62.06" class="pct medium">62.06%</td>
|
||||
<td data-value="29" class="abs medium">18/29</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="TabBar.tsx"><a href="TabBar.tsx.html">TabBar.tsx</a></td>
|
||||
<td data-value="67.92" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 67%"></div><div class="cover-empty" style="width: 33%"></div></div>
|
||||
</td>
|
||||
<td data-value="67.92" class="pct medium">67.92%</td>
|
||||
<td data-value="106" class="abs medium">72/106</td>
|
||||
<td data-value="68" class="pct medium">68%</td>
|
||||
<td data-value="75" class="abs medium">51/75</td>
|
||||
<td data-value="63.88" class="pct medium">63.88%</td>
|
||||
<td data-value="36" class="abs medium">23/36</td>
|
||||
<td data-value="70.52" class="pct medium">70.52%</td>
|
||||
<td data-value="95" class="abs medium">67/95</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -334,18 +469,48 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="TypeCustomizePopover.tsx"><a href="TypeCustomizePopover.tsx.html">TypeCustomizePopover.tsx</a></td>
|
||||
<td data-value="21.05" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 21%"></div><div class="cover-empty" style="width: 79%"></div></div>
|
||||
<td class="file high" data-value="TypeCustomizePopover.tsx"><a href="TypeCustomizePopover.tsx.html">TypeCustomizePopover.tsx</a></td>
|
||||
<td data-value="95.83" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||
</td>
|
||||
<td data-value="21.05" class="pct low">21.05%</td>
|
||||
<td data-value="19" class="abs low">4/19</td>
|
||||
<td data-value="22.22" class="pct low">22.22%</td>
|
||||
<td data-value="9" class="abs low">2/9</td>
|
||||
<td data-value="18.18" class="pct low">18.18%</td>
|
||||
<td data-value="11" class="abs low">2/11</td>
|
||||
<td data-value="21.05" class="pct low">21.05%</td>
|
||||
<td data-value="19" class="abs low">4/19</td>
|
||||
<td data-value="95.83" class="pct high">95.83%</td>
|
||||
<td data-value="24" class="abs high">23/24</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="10" class="abs high">10/10</td>
|
||||
<td data-value="92.3" class="pct high">92.3%</td>
|
||||
<td data-value="13" class="abs high">12/13</td>
|
||||
<td data-value="95.23" class="pct high">95.23%</td>
|
||||
<td data-value="21" class="abs high">20/21</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="UpdateBanner.tsx"><a href="UpdateBanner.tsx.html">UpdateBanner.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="3" class="abs high">3/3</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="10" class="abs high">10/10</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="2" class="abs high">2/2</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="WikilinkSuggestionMenu.tsx"><a href="WikilinkSuggestionMenu.tsx.html">WikilinkSuggestionMenu.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="3" class="abs low">0/3</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
@@ -356,7 +521,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">33.33% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>1/3</span>
|
||||
<span class='fraction'>3/3</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">75% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/4</span>
|
||||
<span class='fraction'>3/4</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/1</span>
|
||||
<span class='fraction'>1/1</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">33.33% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>1/3</span>
|
||||
<span class='fraction'>3/3</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -111,13 +111,14 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L49'></a><a href='#L49'>49</a>
|
||||
<a name='L50'></a><a href='#L50'>50</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -146,9 +147,10 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">102x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">102x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -187,16 +189,16 @@ const badgeVariants = cva(
|
||||
}
|
||||
)
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Badge({</span>
|
||||
function Badge({
|
||||
className,
|
||||
variant = <span class="branch-0 cbranch-no" title="branch not covered" >"default",</span>
|
||||
asChild = <span class="branch-0 cbranch-no" title="branch not covered" >false,</span>
|
||||
variant = "default",
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"span"> &
|
||||
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
||||
const Comp = <span class="cstat-no" title="statement not covered" >asChild ? Slot.Root : "span"</span>
|
||||
const Comp = asChild ? <span class="branch-0 cbranch-no" title="branch not covered" >Slot.Root : "</span>span"
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
return (
|
||||
<Comp
|
||||
data-slot="badge"
|
||||
data-variant={variant}
|
||||
@@ -206,6 +208,7 @@ function <span class="fstat-no" title="function not covered" >Badge({</span>
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components -- shadcn/ui pattern
|
||||
export { Badge, badgeVariants }
|
||||
</pre></td></tr></table></pre>
|
||||
|
||||
@@ -214,7 +217,7 @@ export { Badge, badgeVariants }
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -127,13 +127,14 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L65'></a><a href='#L65'>65</a>
|
||||
<a name='L66'></a><a href='#L66'>66</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -177,9 +178,10 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">284x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">284x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -254,6 +256,7 @@ function Button({
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components -- shadcn/ui pattern
|
||||
export { Button, buttonVariants }
|
||||
</pre></td></tr></table></pre>
|
||||
|
||||
@@ -262,7 +265,7 @@ export { Button, buttonVariants }
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,361 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/card.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/ui</a> card.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">100% </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/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/7</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Card({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card"
|
||||
className={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardHeader({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardTitle({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-title"
|
||||
className={cn("leading-none font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardDescription({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardAction({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardContent({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn("px-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >CardFooter({</span> className, ...props }: React.ComponentProps<"div">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
}
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">70% </span>
|
||||
<span class="strong">80% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>7/10</span>
|
||||
<span class='fraction'>8/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">66.66% </span>
|
||||
<span class="strong">83.33% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>4/6</span>
|
||||
<span class='fraction'>5/6</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">70% </span>
|
||||
<span class="strong">80% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>7/10</span>
|
||||
<span class='fraction'>8/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">70% </span>
|
||||
<span class="strong">80% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>7/10</span>
|
||||
<span class='fraction'>8/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line medium'></div>
|
||||
<div class='status-line high'></div>
|
||||
<pre><table class="coverage">
|
||||
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||
<a name='L2'></a><a href='#L2'>2</a>
|
||||
@@ -229,7 +229,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">78x</span>
|
||||
<span class="cline-any cline-yes">190x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -241,7 +241,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">78x</span>
|
||||
<span class="cline-any cline-yes">190x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -254,7 +254,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-yes">108x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -274,7 +274,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">78x</span>
|
||||
<span class="cline-any cline-yes">190x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -301,7 +301,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-yes">71x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -318,7 +318,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-yes">67x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -341,7 +341,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">11x</span>
|
||||
<span class="cline-any cline-yes">71x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -354,7 +354,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">29x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -443,7 +443,7 @@ function DialogContent({
|
||||
>
|
||||
{children}
|
||||
{showCloseButton && (
|
||||
<span class="branch-1 cbranch-no" title="branch not covered" > <DialogPrimitive.Close</span>
|
||||
<DialogPrimitive.Close
|
||||
data-slot="dialog-close"
|
||||
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||
>
|
||||
@@ -506,11 +506,11 @@ function DialogTitle({
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DialogDescription({</span>
|
||||
function DialogDescription({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
return (
|
||||
<DialogPrimitive.Description
|
||||
data-slot="dialog-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
@@ -538,7 +538,7 @@ export {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,856 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/dropdown-menu.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/ui</a> dropdown-menu.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/15</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>
|
||||
<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>
|
||||
<a name='L253'></a><a href='#L253'>253</a>
|
||||
<a name='L254'></a><a href='#L254'>254</a>
|
||||
<a name='L255'></a><a href='#L255'>255</a>
|
||||
<a name='L256'></a><a href='#L256'>256</a>
|
||||
<a name='L257'></a><a href='#L257'>257</a>
|
||||
<a name='L258'></a><a href='#L258'>258</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenu({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuPortal({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuTrigger({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Trigger
|
||||
data-slot="dropdown-menu-trigger"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuContent({</span>
|
||||
className,
|
||||
sideOffset = <span class="branch-0 cbranch-no" title="branch not covered" >4,</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Portal>
|
||||
<DropdownMenuPrimitive.Content
|
||||
data-slot="dropdown-menu-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuGroup({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuItem({</span>
|
||||
className,
|
||||
inset,
|
||||
variant = <span class="branch-0 cbranch-no" title="branch not covered" >"default",</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean
|
||||
variant?: "default" | "destructive"
|
||||
}) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Item
|
||||
data-slot="dropdown-menu-item"
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuCheckboxItem({</span>
|
||||
className,
|
||||
children,
|
||||
checked,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
data-slot="dropdown-menu-checkbox-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuRadioGroup({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.RadioGroup
|
||||
data-slot="dropdown-menu-radio-group"
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuRadioItem({</span>
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
data-slot="dropdown-menu-radio-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<CircleIcon className="size-2 fill-current" />
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuLabel({</span>
|
||||
className,
|
||||
inset,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean
|
||||
}) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Label
|
||||
data-slot="dropdown-menu-label"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuSeparator({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.Separator
|
||||
data-slot="dropdown-menu-separator"
|
||||
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuShortcut({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"span">) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<span
|
||||
data-slot="dropdown-menu-shortcut"
|
||||
className={cn(
|
||||
"text-muted-foreground ml-auto text-xs tracking-widest",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuSub({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuSubTrigger({</span>
|
||||
className,
|
||||
inset,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean
|
||||
}) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
data-slot="dropdown-menu-sub-trigger"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRightIcon className="ml-auto size-4" />
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >DropdownMenuSubContent({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
data-slot="dropdown-menu-sub-content"
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuSubContent,
|
||||
}
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">19.67% </span>
|
||||
<span class="strong">88.23% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>12/61</span>
|
||||
<span class='fraction'>15/17</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">22.85% </span>
|
||||
<span class="strong">80% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>8/35</span>
|
||||
<span class='fraction'>12/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">16.07% </span>
|
||||
<span class="strong">84.61% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>9/56</span>
|
||||
<span class='fraction'>11/13</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">19.67% </span>
|
||||
<span class="strong">88.23% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>12/61</span>
|
||||
<span class='fraction'>15/17</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></div>
|
||||
<div class='status-line high'></div>
|
||||
<div class="pad1">
|
||||
<table class="coverage-summary">
|
||||
<thead>
|
||||
@@ -79,18 +79,18 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file low" data-value="badge.tsx"><a href="badge.tsx.html">badge.tsx</a></td>
|
||||
<td data-value="33.33" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 33%"></div><div class="cover-empty" style="width: 67%"></div></div>
|
||||
<td class="file high" data-value="badge.tsx"><a href="badge.tsx.html">badge.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="33.33" class="pct low">33.33%</td>
|
||||
<td data-value="3" class="abs low">1/3</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="1" class="abs low">0/1</td>
|
||||
<td data-value="33.33" class="pct low">33.33%</td>
|
||||
<td data-value="3" class="abs low">1/3</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="4" class="abs medium">3/4</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -109,48 +109,18 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="card.tsx"><a href="card.tsx.html">card.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
|
||||
<td class="file high" data-value="dialog.tsx"><a href="dialog.tsx.html">dialog.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="0" class="pct low">0%</td>
|
||||
<td data-value="7" class="abs low">0/7</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="0" class="abs high">0/0</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="7" class="abs low">0/7</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="7" class="abs low">0/7</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="dialog.tsx"><a href="dialog.tsx.html">dialog.tsx</a></td>
|
||||
<td data-value="70" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 70%"></div><div class="cover-empty" style="width: 30%"></div></div>
|
||||
</td>
|
||||
<td data-value="70" class="pct medium">70%</td>
|
||||
<td data-value="10" class="abs medium">7/10</td>
|
||||
<td data-value="66.66" class="pct medium">66.66%</td>
|
||||
<td data-value="6" class="abs medium">4/6</td>
|
||||
<td data-value="70" class="pct medium">70%</td>
|
||||
<td data-value="10" class="abs medium">7/10</td>
|
||||
<td data-value="70" class="pct medium">70%</td>
|
||||
<td data-value="10" class="abs medium">7/10</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="dropdown-menu.tsx"><a href="dropdown-menu.tsx.html">dropdown-menu.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="15" class="abs low">0/15</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="15" class="abs low">0/15</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="15" class="abs low">0/15</td>
|
||||
<td data-value="80" class="pct high">80%</td>
|
||||
<td data-value="10" class="abs high">8/10</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="80" class="pct high">80%</td>
|
||||
<td data-value="10" class="abs high">8/10</td>
|
||||
<td data-value="80" class="pct high">80%</td>
|
||||
<td data-value="10" class="abs high">8/10</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -168,81 +138,6 @@
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="scroll-area.tsx"><a href="scroll-area.tsx.html">scroll-area.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="5" class="abs low">0/5</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="select.tsx"><a href="select.tsx.html">select.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="10" class="abs low">0/10</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="7" class="abs low">0/7</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="10" class="abs low">0/10</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="10" class="abs low">0/10</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="separator.tsx"><a href="separator.tsx.html">separator.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="1" class="abs low">0/1</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="1" class="abs low">0/1</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="1" class="abs low">0/1</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="tabs.tsx"><a href="tabs.tsx.html">tabs.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="5" class="abs low">0/5</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="5" class="abs low">0/5</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="tooltip.tsx"><a href="tooltip.tsx.html">tooltip.tsx</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<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 low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="2" class="abs low">0/2</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="4" class="abs low">0/4</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -251,7 +146,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">84x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -133,7 +133,7 @@ export { Input }
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/scroll-area.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/ui</a> scroll-area.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/5</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/2</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import * as React from "react"
|
||||
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >ScrollArea({</span>
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<ScrollAreaPrimitive.Root
|
||||
data-slot="scroll-area"
|
||||
className={cn("relative", className)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport
|
||||
data-slot="scroll-area-viewport"
|
||||
className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
||||
>
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
<ScrollBar />
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >ScrollBar({</span>
|
||||
className,
|
||||
orientation = <span class="branch-0 cbranch-no" title="branch not covered" >"vertical",</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||
data-slot="scroll-area-scrollbar"
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"flex touch-none p-px transition-colors select-none",
|
||||
orientation === "vertical" &&
|
||||
"h-full w-2.5 border-l border-l-transparent",
|
||||
orientation === "horizontal" &&
|
||||
"h-2.5 flex-col border-t border-t-transparent",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.ScrollAreaThumb
|
||||
data-slot="scroll-area-thumb"
|
||||
className="bg-border relative flex-1 rounded-full"
|
||||
/>
|
||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
)
|
||||
}
|
||||
|
||||
export { ScrollArea, ScrollBar }
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -1,649 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/select.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/ui</a> select.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/10</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import * as React from "react"
|
||||
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
||||
import { Select as SelectPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Select({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <SelectPrimitive.Root data-slot="select" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectGroup({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <SelectPrimitive.Group data-slot="select-group" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectValue({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <SelectPrimitive.Value data-slot="select-value" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectTrigger({</span>
|
||||
className,
|
||||
size = <span class="branch-0 cbranch-no" title="branch not covered" >"default",</span>
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
||||
size?: "sm" | "default"
|
||||
}) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.Trigger
|
||||
data-slot="select-trigger"
|
||||
data-size={size}
|
||||
className={cn(
|
||||
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<ChevronDownIcon className="size-4 opacity-50" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectContent({</span>
|
||||
className,
|
||||
children,
|
||||
position = <span class="branch-0 cbranch-no" title="branch not covered" >"item-aligned",</span>
|
||||
align = <span class="branch-0 cbranch-no" title="branch not covered" >"center",</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.Portal>
|
||||
<SelectPrimitive.Content
|
||||
data-slot="select-content"
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
||||
position === "popper" &&
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||
className
|
||||
)}
|
||||
position={position}
|
||||
align={align}
|
||||
{...props}
|
||||
>
|
||||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
"p-1",
|
||||
position === "popper" &&
|
||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Viewport>
|
||||
<SelectScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectLabel({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.Label
|
||||
data-slot="select-label"
|
||||
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectItem({</span>
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.Item
|
||||
data-slot="select-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span
|
||||
data-slot="select-item-indicator"
|
||||
className="absolute right-2 flex size-3.5 items-center justify-center"
|
||||
>
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<CheckIcon className="size-4" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||
</SelectPrimitive.Item>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectSeparator({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.Separator
|
||||
data-slot="select-separator"
|
||||
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectScrollUpButton({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.ScrollUpButton
|
||||
data-slot="select-scroll-up-button"
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronUpIcon className="size-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >SelectScrollDownButton({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SelectPrimitive.ScrollDownButton
|
||||
data-slot="select-scroll-down-button"
|
||||
className={cn(
|
||||
"flex cursor-default items-center justify-center py-1",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronDownIcon className="size-4" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectScrollDownButton,
|
||||
SelectScrollUpButton,
|
||||
SelectSeparator,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
}
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/separator.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/ui</a> separator.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/1</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/1</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/1</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Separator as SeparatorPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Separator({</span>
|
||||
className,
|
||||
orientation = <span class="branch-0 cbranch-no" title="branch not covered" >"horizontal",</span>
|
||||
decorative = <span class="branch-0 cbranch-no" title="branch not covered" >true,</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<SeparatorPrimitive.Root
|
||||
data-slot="separator"
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Separator }
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/tabs.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/ui</a> tabs.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/5</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/4</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/5</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { Tabs as TabsPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Tabs({</span>
|
||||
className,
|
||||
orientation = <span class="branch-0 cbranch-no" title="branch not covered" >"horizontal",</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TabsPrimitive.Root
|
||||
data-slot="tabs"
|
||||
data-orientation={orientation}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >tabsListVariants = cva(</span>
|
||||
"rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-muted",
|
||||
line: "gap-1 bg-transparent",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TabsList({</span>
|
||||
className,
|
||||
variant = <span class="branch-0 cbranch-no" title="branch not covered" >"default",</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.List> &
|
||||
VariantProps<typeof tabsListVariants>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TabsPrimitive.List
|
||||
data-slot="tabs-list"
|
||||
data-variant={variant}
|
||||
className={cn(tabsListVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TabsTrigger({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TabsPrimitive.Trigger
|
||||
data-slot="tabs-trigger"
|
||||
className={cn(
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
|
||||
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
|
||||
"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TabsContent({</span>
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TabsPrimitive.Content
|
||||
data-slot="tabs-content"
|
||||
className={cn("flex-1 outline-none", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/components/ui/tooltip.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/ui</a> tooltip.tsx</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/4</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/2</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/4</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/4</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Tooltip as TooltipPrimitive } from "radix-ui"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TooltipProvider({</span>
|
||||
delayDuration = <span class="branch-0 cbranch-no" title="branch not covered" >0,</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TooltipPrimitive.Provider
|
||||
data-slot="tooltip-provider"
|
||||
delayDuration={delayDuration}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >Tooltip({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <TooltipPrimitive.Root data-slot="tooltip" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TooltipTrigger({</span>
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
||||
<span class="cstat-no" title="statement not covered" > return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} /></span>
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >TooltipContent({</span>
|
||||
className,
|
||||
sideOffset = <span class="branch-0 cbranch-no" title="branch not covered" >0,</span>
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
||||
<span class="cstat-no" title="statement not covered" > return (</span>
|
||||
<TooltipPrimitive.Portal>
|
||||
<TooltipPrimitive.Content
|
||||
data-slot="tooltip-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
||||
</TooltipPrimitive.Content>
|
||||
</TooltipPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">27.51% </span>
|
||||
<span class="strong">85.11% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>153/556</span>
|
||||
<span class='fraction'>915/1075</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">16.45% </span>
|
||||
<span class="strong">78.01% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>38/231</span>
|
||||
<span class='fraction'>323/414</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">26.01% </span>
|
||||
<span class="strong">77.91% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>32/123</span>
|
||||
<span class='fraction'>254/326</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">29.77% </span>
|
||||
<span class="strong">87.99% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>145/487</span>
|
||||
<span class='fraction'>762/866</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></div>
|
||||
<div class='status-line high'></div>
|
||||
<div class="pad1">
|
||||
<table class="coverage-summary">
|
||||
<thead>
|
||||
@@ -79,78 +79,243 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file low" data-value="useAIChat.ts"><a href="useAIChat.ts.html">useAIChat.ts</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
|
||||
<td class="file high" data-value="mockFrontmatterHelpers.ts"><a href="mockFrontmatterHelpers.ts.html">mockFrontmatterHelpers.ts</a></td>
|
||||
<td data-value="98.03" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 98%"></div><div class="cover-empty" style="width: 2%"></div></div>
|
||||
</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="74" class="abs low">0/74</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="30" class="abs low">0/30</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="15" class="abs low">0/15</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="61" class="abs low">0/61</td>
|
||||
<td data-value="98.03" class="pct high">98.03%</td>
|
||||
<td data-value="51" class="abs high">50/51</td>
|
||||
<td data-value="96.87" class="pct high">96.87%</td>
|
||||
<td data-value="32" class="abs high">31/32</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="9" class="abs high">9/9</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="42" class="abs high">42/42</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="useAppKeyboard.ts"><a href="useAppKeyboard.ts.html">useAppKeyboard.ts</a></td>
|
||||
<td class="file high" data-value="useAppCommands.ts"><a href="useAppCommands.ts.html">useAppCommands.ts</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="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="0" class="abs high">0/0</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useAppKeyboard.ts"><a href="useAppKeyboard.ts.html">useAppKeyboard.ts</a></td>
|
||||
<td data-value="95.45" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||
</td>
|
||||
<td data-value="95.45" class="pct high">95.45%</td>
|
||||
<td data-value="44" class="abs high">42/44</td>
|
||||
<td data-value="96.55" class="pct high">96.55%</td>
|
||||
<td data-value="29" class="abs high">28/29</td>
|
||||
<td data-value="84.61" class="pct high">84.61%</td>
|
||||
<td data-value="13" class="abs high">11/13</td>
|
||||
<td data-value="94.44" class="pct high">94.44%</td>
|
||||
<td data-value="36" class="abs high">34/36</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="useCommandRegistry.ts"><a href="useCommandRegistry.ts.html">useCommandRegistry.ts</a></td>
|
||||
<td data-value="46.42" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 46%"></div><div class="cover-empty" style="width: 54%"></div></div>
|
||||
</td>
|
||||
<td data-value="46.42" class="pct low">46.42%</td>
|
||||
<td data-value="28" class="abs low">13/28</td>
|
||||
<td data-value="42.85" class="pct low">42.85%</td>
|
||||
<td data-value="14" class="abs low">6/14</td>
|
||||
<td data-value="36.84" class="pct low">36.84%</td>
|
||||
<td data-value="19" class="abs low">7/19</td>
|
||||
<td data-value="50" class="pct medium">50%</td>
|
||||
<td data-value="24" class="abs medium">12/24</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useCommitFlow.ts"><a href="useCommitFlow.ts.html">useCommitFlow.ts</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="17" class="abs high">17/17</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="0" class="abs high">0/0</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="16" class="abs high">16/16</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="useDialogs.ts"><a href="useDialogs.ts.html">useDialogs.ts</a></td>
|
||||
<td data-value="60" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 60%"></div><div class="cover-empty" style="width: 40%"></div></div>
|
||||
</td>
|
||||
<td data-value="60" class="pct medium">60%</td>
|
||||
<td data-value="35" class="abs medium">21/35</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="0" class="abs high">0/0</td>
|
||||
<td data-value="6.66" class="pct low">6.66%</td>
|
||||
<td data-value="15" class="abs low">1/15</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="21" class="abs high">21/21</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useEditorSave.ts"><a href="useEditorSave.ts.html">useEditorSave.ts</a></td>
|
||||
<td data-value="96.77" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 96%"></div><div class="cover-empty" style="width: 4%"></div></div>
|
||||
</td>
|
||||
<td data-value="96.77" class="pct high">96.77%</td>
|
||||
<td data-value="31" class="abs high">30/31</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="11" class="abs high">10/11</td>
|
||||
<td data-value="90" class="pct high">90%</td>
|
||||
<td data-value="10" class="abs high">9/10</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="27" class="abs high">27/27</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useEntryActions.ts"><a href="useEntryActions.ts.html">useEntryActions.ts</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="36" class="abs high">36/36</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="6" class="abs high">6/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="9" class="abs high">9/9</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="33" class="abs high">33/33</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useGitHistory.ts"><a href="useGitHistory.ts.html">useGitHistory.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="6" class="abs high">5/6</td>
|
||||
<td data-value="50" class="pct medium">50%</td>
|
||||
<td data-value="4" class="abs medium">2/4</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="2" class="abs high">2/2</td>
|
||||
<td data-value="80" class="pct high">80%</td>
|
||||
<td data-value="5" class="abs high">4/5</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useImageDrop.ts"><a href="useImageDrop.ts.html">useImageDrop.ts</a></td>
|
||||
<td data-value="95.74" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 95%"></div><div class="cover-empty" style="width: 5%"></div></div>
|
||||
</td>
|
||||
<td data-value="95.74" class="pct high">95.74%</td>
|
||||
<td data-value="47" class="abs high">45/47</td>
|
||||
<td data-value="87.5" class="pct high">87.5%</td>
|
||||
<td data-value="16" class="abs high">14/16</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="11" class="abs high">10/11</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="39" class="abs high">39/39</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useKeyboardNavigation.ts"><a href="useKeyboardNavigation.ts.html">useKeyboardNavigation.ts</a></td>
|
||||
<td data-value="94.82" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 94%"></div><div class="cover-empty" style="width: 6%"></div></div>
|
||||
</td>
|
||||
<td data-value="94.82" class="pct high">94.82%</td>
|
||||
<td data-value="58" class="abs high">55/58</td>
|
||||
<td data-value="85.36" class="pct high">85.36%</td>
|
||||
<td data-value="41" class="abs high">35/41</td>
|
||||
<td data-value="93.33" class="pct high">93.33%</td>
|
||||
<td data-value="15" class="abs high">14/15</td>
|
||||
<td data-value="95.74" class="pct high">95.74%</td>
|
||||
<td data-value="47" class="abs high">45/47</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="useMenuEvents.ts"><a href="useMenuEvents.ts.html">useMenuEvents.ts</a></td>
|
||||
<td data-value="75" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 75%"></div><div class="cover-empty" style="width: 25%"></div></div>
|
||||
</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="20" class="abs medium">15/20</td>
|
||||
<td data-value="37.5" class="pct low">37.5%</td>
|
||||
<td data-value="8" class="abs low">3/8</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="8" class="abs medium">6/8</td>
|
||||
<td data-value="80" class="pct high">80%</td>
|
||||
<td data-value="15" class="abs high">12/15</td>
|
||||
<td data-value="40" class="abs medium">30/40</td>
|
||||
<td data-value="86.66" class="pct high">86.66%</td>
|
||||
<td data-value="15" class="abs high">13/15</td>
|
||||
<td data-value="33.33" class="pct low">33.33%</td>
|
||||
<td data-value="12" class="abs low">4/12</td>
|
||||
<td data-value="73.07" class="pct medium">73.07%</td>
|
||||
<td data-value="26" class="abs medium">19/26</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="useKeyboardNavigation.ts"><a href="useKeyboardNavigation.ts.html">useKeyboardNavigation.ts</a></td>
|
||||
<td data-value="51.85" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 51%"></div><div class="cover-empty" style="width: 49%"></div></div>
|
||||
<td class="file high" data-value="useNavigationHistory.ts"><a href="useNavigationHistory.ts.html">useNavigationHistory.ts</a></td>
|
||||
<td data-value="97.56" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 97%"></div><div class="cover-empty" style="width: 3%"></div></div>
|
||||
</td>
|
||||
<td data-value="51.85" class="pct medium">51.85%</td>
|
||||
<td data-value="54" class="abs medium">28/54</td>
|
||||
<td data-value="26.31" class="pct low">26.31%</td>
|
||||
<td data-value="38" class="abs low">10/38</td>
|
||||
<td data-value="54.54" class="pct medium">54.54%</td>
|
||||
<td data-value="11" class="abs medium">6/11</td>
|
||||
<td data-value="56.25" class="pct medium">56.25%</td>
|
||||
<td data-value="48" class="abs medium">27/48</td>
|
||||
<td data-value="97.56" class="pct high">97.56%</td>
|
||||
<td data-value="41" class="abs high">40/41</td>
|
||||
<td data-value="77.27" class="pct medium">77.27%</td>
|
||||
<td data-value="22" class="abs medium">17/22</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="9" class="abs high">9/9</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="35" class="abs high">35/35</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="useMcpBridge.ts"><a href="useMcpBridge.ts.html">useMcpBridge.ts</a></td>
|
||||
<td data-value="0" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
|
||||
<td class="file medium" data-value="useNoteActions.ts"><a href="useNoteActions.ts.html">useNoteActions.ts</a></td>
|
||||
<td data-value="76.12" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 76%"></div><div class="cover-empty" style="width: 24%"></div></div>
|
||||
</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="48" class="abs low">0/48</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="11" class="abs low">0/11</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="14" class="abs low">0/14</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="47" class="abs low">0/47</td>
|
||||
<td data-value="76.12" class="pct medium">76.12%</td>
|
||||
<td data-value="155" class="abs medium">118/155</td>
|
||||
<td data-value="68.75" class="pct medium">68.75%</td>
|
||||
<td data-value="64" class="abs medium">44/64</td>
|
||||
<td data-value="70" class="pct medium">70%</td>
|
||||
<td data-value="50" class="abs medium">35/50</td>
|
||||
<td data-value="78.29" class="pct medium">78.29%</td>
|
||||
<td data-value="129" class="abs medium">101/129</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="useNoteActions.ts"><a href="useNoteActions.ts.html">useNoteActions.ts</a></td>
|
||||
<td data-value="13.87" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 13%"></div><div class="cover-empty" style="width: 87%"></div></div>
|
||||
<td class="file high" data-value="useNoteSearch.ts"><a href="useNoteSearch.ts.html">useNoteSearch.ts</a></td>
|
||||
<td data-value="96.15" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 96%"></div><div class="cover-empty" style="width: 4%"></div></div>
|
||||
</td>
|
||||
<td data-value="13.87" class="pct low">13.87%</td>
|
||||
<td data-value="245" class="abs low">34/245</td>
|
||||
<td data-value="1.88" class="pct low">1.88%</td>
|
||||
<td data-value="106" class="abs low">2/106</td>
|
||||
<td data-value="8.88" class="pct low">8.88%</td>
|
||||
<td data-value="45" class="abs low">4/45</td>
|
||||
<td data-value="15.23" class="pct low">15.23%</td>
|
||||
<td data-value="210" class="abs low">32/210</td>
|
||||
<td data-value="96.15" class="pct high">96.15%</td>
|
||||
<td data-value="26" class="abs high">25/26</td>
|
||||
<td data-value="89.47" class="pct high">89.47%</td>
|
||||
<td data-value="19" class="abs high">17/19</td>
|
||||
<td data-value="91.66" class="pct high">91.66%</td>
|
||||
<td data-value="12" class="abs high">11/12</td>
|
||||
<td data-value="95.83" class="pct high">95.83%</td>
|
||||
<td data-value="24" class="abs high">23/24</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useSaveNote.ts"><a href="useSaveNote.ts.html">useSaveNote.ts</a></td>
|
||||
<td data-value="88.88" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
|
||||
</td>
|
||||
<td data-value="88.88" class="pct high">88.88%</td>
|
||||
<td data-value="9" class="abs high">8/9</td>
|
||||
<td data-value="50" class="pct medium">50%</td>
|
||||
<td data-value="4" class="abs medium">2/4</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
<td data-value="88.88" class="pct high">88.88%</td>
|
||||
<td data-value="9" class="abs high">8/9</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -168,6 +333,36 @@
|
||||
<td data-value="20" class="abs high">20/20</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useSettings.ts"><a href="useSettings.ts.html">useSettings.ts</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="18" class="abs high">18/18</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="4" class="abs medium">3/4</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="18" class="abs high">18/18</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useTabManagement.ts"><a href="useTabManagement.ts.html">useTabManagement.ts</a></td>
|
||||
<td data-value="84.21" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 84%"></div><div class="cover-empty" style="width: 16%"></div></div>
|
||||
</td>
|
||||
<td data-value="84.21" class="pct high">84.21%</td>
|
||||
<td data-value="114" class="abs high">96/114</td>
|
||||
<td data-value="64.28" class="pct medium">64.28%</td>
|
||||
<td data-value="28" class="abs medium">18/28</td>
|
||||
<td data-value="90.24" class="pct high">90.24%</td>
|
||||
<td data-value="41" class="abs high">37/41</td>
|
||||
<td data-value="84.81" class="pct high">84.81%</td>
|
||||
<td data-value="79" class="abs high">67/79</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useTheme.ts"><a href="useTheme.ts.html">useTheme.ts</a></td>
|
||||
<td data-value="95.45" class="pic high">
|
||||
@@ -184,18 +379,78 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="useVaultLoader.ts"><a href="useVaultLoader.ts.html">useVaultLoader.ts</a></td>
|
||||
<td data-value="47.22" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 47%"></div><div class="cover-empty" style="width: 53%"></div></div>
|
||||
<td class="file high" data-value="useUnifiedSearch.ts"><a href="useUnifiedSearch.ts.html">useUnifiedSearch.ts</a></td>
|
||||
<td data-value="85.33" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 85%"></div><div class="cover-empty" style="width: 15%"></div></div>
|
||||
</td>
|
||||
<td data-value="47.22" class="pct low">47.22%</td>
|
||||
<td data-value="72" class="abs low">34/72</td>
|
||||
<td data-value="18.75" class="pct low">18.75%</td>
|
||||
<td data-value="16" class="abs low">3/16</td>
|
||||
<td data-value="26.31" class="pct low">26.31%</td>
|
||||
<td data-value="19" class="abs low">5/19</td>
|
||||
<td data-value="51.51" class="pct medium">51.51%</td>
|
||||
<td data-value="66" class="abs medium">34/66</td>
|
||||
<td data-value="85.33" class="pct high">85.33%</td>
|
||||
<td data-value="75" class="abs high">64/75</td>
|
||||
<td data-value="60" class="pct medium">60%</td>
|
||||
<td data-value="20" class="abs medium">12/20</td>
|
||||
<td data-value="93.75" class="pct high">93.75%</td>
|
||||
<td data-value="16" class="abs high">15/16</td>
|
||||
<td data-value="88.33" class="pct high">88.33%</td>
|
||||
<td data-value="60" class="abs high">53/60</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useUpdater.ts"><a href="useUpdater.ts.html">useUpdater.ts</a></td>
|
||||
<td data-value="85.41" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 85%"></div><div class="cover-empty" style="width: 15%"></div></div>
|
||||
</td>
|
||||
<td data-value="85.41" class="pct high">85.41%</td>
|
||||
<td data-value="48" class="abs high">41/48</td>
|
||||
<td data-value="81.81" class="pct high">81.81%</td>
|
||||
<td data-value="22" class="abs high">18/22</td>
|
||||
<td data-value="90" class="pct high">90%</td>
|
||||
<td data-value="10" class="abs high">9/10</td>
|
||||
<td data-value="86.04" class="pct high">86.04%</td>
|
||||
<td data-value="43" class="abs high">37/43</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useVaultLoader.ts"><a href="useVaultLoader.ts.html">useVaultLoader.ts</a></td>
|
||||
<td data-value="84.15" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 84%"></div><div class="cover-empty" style="width: 16%"></div></div>
|
||||
</td>
|
||||
<td data-value="84.15" class="pct high">84.15%</td>
|
||||
<td data-value="101" class="abs high">85/101</td>
|
||||
<td data-value="73.07" class="pct medium">73.07%</td>
|
||||
<td data-value="26" class="abs medium">19/26</td>
|
||||
<td data-value="86.48" class="pct high">86.48%</td>
|
||||
<td data-value="37" class="abs high">32/37</td>
|
||||
<td data-value="85.5" class="pct high">85.5%</td>
|
||||
<td data-value="69" class="abs high">59/69</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="useVaultSwitcher.ts"><a href="useVaultSwitcher.ts.html">useVaultSwitcher.ts</a></td>
|
||||
<td data-value="45.45" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 45%"></div><div class="cover-empty" style="width: 55%"></div></div>
|
||||
</td>
|
||||
<td data-value="45.45" class="pct low">45.45%</td>
|
||||
<td data-value="33" class="abs low">15/33</td>
|
||||
<td data-value="12.5" class="pct low">12.5%</td>
|
||||
<td data-value="8" class="abs low">1/8</td>
|
||||
<td data-value="33.33" class="pct low">33.33%</td>
|
||||
<td data-value="9" class="abs low">3/9</td>
|
||||
<td data-value="44.44" class="pct low">44.44%</td>
|
||||
<td data-value="27" class="abs low">12/27</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="useViewMode.ts"><a href="useViewMode.ts.html">useViewMode.ts</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="14" class="abs high">14/14</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="7" class="abs high">7/7</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="12" class="abs high">12/12</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
@@ -206,7 +461,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/hooks/useAIChat.ts</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/hooks</a> useAIChat.ts</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/74</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/30</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/61</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||
* Custom hook encapsulating AI chat state and message handling.
|
||||
*/
|
||||
import { useState, useCallback, useRef } from 'react'
|
||||
import type { VaultEntry } from '../types'
|
||||
import {
|
||||
type ChatMessage, nextMessageId, getApiKey,
|
||||
buildSystemPrompt, streamChat,
|
||||
} from '../utils/ai-chat'
|
||||
import { countWords } from '../utils/wikilinks'
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >generateMockResponse(m</span>essage: string, entry: VaultEntry | null, content: string): string {
|
||||
const title = <span class="cstat-no" title="statement not covered" >entry?.title ?? 'Untitled'</span>
|
||||
const <span class="cstat-no" title="statement not covered" >words = countWords(content)</span>
|
||||
const lower = <span class="cstat-no" title="statement not covered" >message.toLowerCase()</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (lower.includes('summarize')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return `This note is about **${title}**. It contains ${words} words covering the main concepts documented in your vault.`</span>
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > if (lower.includes('expand')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return `Here are some ways to expand this note:\n\n1. Add more detail to the introduction\n2. Include related examples\n3. Connect it to your quarterly goals\n4. Add a summary section at the end`</span>
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > if (lower.includes('grammar')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return `I reviewed the document for grammar issues. The writing looks clean overall — no major errors found.`</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return `Based on **${title}**, I can help with analysis, summarization, or expansion. What would you like to focus on?`</span>
|
||||
}
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >useAIChat(</span>
|
||||
entry: VaultEntry | null,
|
||||
allContent: Record<string, string>,
|
||||
contextNotes: VaultEntry[],
|
||||
model: string,
|
||||
) {
|
||||
const [messages, setMessages<span class="cstat-no" title="statement not covered" >] = useState<ChatMessage[]>([])</span>
|
||||
const [isStreaming, setIsStreaming<span class="cstat-no" title="statement not covered" >] = useState(false)</span>
|
||||
const [streamingContent, setStreamingContent<span class="cstat-no" title="statement not covered" >] = useState('')</span>
|
||||
const <span class="cstat-no" title="statement not covered" >abortRef = useRef(false)</span>
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >sendMessage = useCallback(<span class="fstat-no" title="function not covered" >(t</span>ext: string) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!text.trim() || isStreaming) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
|
||||
const userMsg: ChatMessage = <span class="cstat-no" title="statement not covered" >{ role: 'user', content: text.trim(), id: nextMessageId() }</span>
|
||||
<span class="cstat-no" title="statement not covered" > setMessages(<span class="fstat-no" title="function not covered" >prev => <span class="cstat-no" title="statement not covered" >[</span>...prev, userMsg])</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsStreaming(true)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setStreamingContent('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > abortRef.current = false</span>
|
||||
|
||||
const allMessages = <span class="cstat-no" title="statement not covered" >[...messages, userMsg].map(<span class="fstat-no" title="function not covered" >m => (<span class="cstat-no" title="statement not covered" >{</span> role: m.role, content: m.content }))</span></span>
|
||||
const hasApiKey = <span class="cstat-no" title="statement not covered" >!!getApiKey()</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (!hasApiKey) {</span>
|
||||
const content = <span class="cstat-no" title="statement not covered" >entry ? (allContent[entry.path] ?? '') : ''</span>
|
||||
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (abortRef.current) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
const response = <span class="cstat-no" title="statement not covered" >generateMockResponse(text, entry, content)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setMessages(<span class="fstat-no" title="function not covered" >prev => <span class="cstat-no" title="statement not covered" >[</span>...prev, { role: 'assistant', content: response, id: nextMessageId() }])</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsStreaming(false)</span>
|
||||
}, 800)
|
||||
<span class="cstat-no" title="statement not covered" > return</span>
|
||||
}
|
||||
|
||||
const { prompt: systemPrompt <span class="cstat-no" title="statement not covered" >} = buildSystemPrompt(contextNotes, allContent, model)</span>
|
||||
let accumulated = <span class="cstat-no" title="statement not covered" >''</span>
|
||||
|
||||
const onChunk = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(c</span>hunk: string) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (abortRef.current) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > accumulated += chunk</span>
|
||||
<span class="cstat-no" title="statement not covered" > setStreamingContent(accumulated)</span>
|
||||
}
|
||||
|
||||
const onDone = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (abortRef.current) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setMessages(<span class="fstat-no" title="function not covered" >prev => <span class="cstat-no" title="statement not covered" >[</span>...prev, { role: 'assistant', content: accumulated, id: nextMessageId() }])</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setStreamingContent('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsStreaming(false)</span>
|
||||
}
|
||||
|
||||
const onError = <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >(e</span>rror: string) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (abortRef.current) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setMessages(<span class="fstat-no" title="function not covered" >prev => <span class="cstat-no" title="statement not covered" >[</span>...prev, { role: 'assistant', content: `Error: ${error}`, id: nextMessageId() }])</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setStreamingContent('')</span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsStreaming(false)</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > streamChat(allMessages, systemPrompt, model, onChunk, onDone, onError)</span>
|
||||
}, [isStreaming, entry, allContent, contextNotes, model, messages])
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >clearConversation = useCallback(<span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > abortRef.current = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > setMessages([])</span>
|
||||
<span class="cstat-no" title="statement not covered" > setIsStreaming(false)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setStreamingContent('')</span>
|
||||
}, [])
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >retryMessage = useCallback(<span class="fstat-no" title="function not covered" >(m</span>sgIndex: number) => {</span>
|
||||
const userMsgIndex = <span class="cstat-no" title="statement not covered" >msgIndex - 1</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (userMsgIndex < 0) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
const userMsg = <span class="cstat-no" title="statement not covered" >messages[userMsgIndex]</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (userMsg.role !== 'user') <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > setMessages(<span class="fstat-no" title="function not covered" >prev => <span class="cstat-no" title="statement not covered" >p</span>rev.slice(0, msgIndex))</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > sendMessage(userMsg.content)</span>
|
||||
}, [messages, sendMessage])
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return { messages, isStreaming, streamingContent, sendMessage, clearConversation, retryMessage }</span>
|
||||
}
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">75% </span>
|
||||
<span class="strong">95.45% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>15/20</span>
|
||||
<span class='fraction'>42/44</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">37.5% </span>
|
||||
<span class="strong">96.55% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>3/8</span>
|
||||
<span class='fraction'>28/29</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">75% </span>
|
||||
<span class="strong">84.61% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>6/8</span>
|
||||
<span class='fraction'>11/13</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">80% </span>
|
||||
<span class="strong">94.44% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>12/15</span>
|
||||
<span class='fraction'>34/36</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line medium'></div>
|
||||
<div class='status-line high'></div>
|
||||
<pre><table class="coverage">
|
||||
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||
<a name='L2'></a><a href='#L2'>2</a>
|
||||
@@ -110,7 +110,57 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -128,81 +178,181 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">88x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">15x</span>
|
||||
<span class="cline-any cline-yes">15x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">49x</span>
|
||||
<span class="cline-any cline-yes">196x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">49x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">49x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">19x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">49x</span>
|
||||
<span class="cline-any cline-yes">49x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</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-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useEffect, useMemo } from 'react'
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useEffect } from 'react'
|
||||
import type { ViewMode } from './useViewMode'
|
||||
|
||||
interface KeyboardActions {
|
||||
onQuickOpen: () => void
|
||||
onCommandPalette: () => void
|
||||
onSearch: () => void
|
||||
onCreateNote: () => void
|
||||
onSave: () => void
|
||||
onOpenSettings: () => void
|
||||
onTrashNote: (path: string) => void
|
||||
onArchiveNote: (path: string) => void
|
||||
onSetViewMode: (mode: ViewMode) => void
|
||||
onGoBack?: () => void
|
||||
onGoForward?: () => void
|
||||
activeTabPathRef: React.MutableRefObject<string | null>
|
||||
handleCloseTabRef: React.MutableRefObject<(path: string) => void>
|
||||
}
|
||||
|
||||
type ShortcutHandler = () => void
|
||||
|
||||
const TEXT_EDITING_KEYS = new Set(['Backspace', 'Delete'])
|
||||
|
||||
function isTextInputFocused(): boolean {
|
||||
const tag = document.activeElement?.tagName
|
||||
return tag === 'INPUT' || tag === 'TEXTAREA'
|
||||
}
|
||||
|
||||
const VIEW_MODE_KEYS: Record<string, ViewMode> = {
|
||||
'1': 'editor-only',
|
||||
'2': 'editor-list',
|
||||
'3': 'all',
|
||||
}
|
||||
|
||||
function isCmdOnly(e: KeyboardEvent): boolean {
|
||||
return (e.metaKey || e.ctrlKey) && !e.altKey
|
||||
}
|
||||
|
||||
function handleViewModeKey(e: KeyboardEvent, onSetViewMode: (m: ViewMode) => void): boolean {
|
||||
if (!isCmdOnly(e)) return false
|
||||
const mode = VIEW_MODE_KEYS[e.key]
|
||||
if (!mode) return false
|
||||
e.preventDefault()
|
||||
onSetViewMode(mode)
|
||||
return true
|
||||
}
|
||||
|
||||
function handleCmdKey(e: KeyboardEvent, keyMap: Record<string, ShortcutHandler>): boolean {
|
||||
const mod = e.metaKey || e.ctrlKey
|
||||
if (!mod) return false
|
||||
const handler = keyMap[e.key]
|
||||
if (!handler) return false
|
||||
if (TEXT_EDITING_KEYS.has(e.key) && isTextInputFocused()) return false
|
||||
e.preventDefault()
|
||||
handler()
|
||||
return true
|
||||
}
|
||||
|
||||
export function useAppKeyboard({
|
||||
onQuickOpen, onCreateNote, onSave, onTrashNote, onArchiveNote,
|
||||
activeTabPathRef, handleCloseTabRef,
|
||||
onQuickOpen, onCommandPalette, onSearch, onCreateNote, onSave, onOpenSettings, onTrashNote, onArchiveNote,
|
||||
onSetViewMode, onGoBack, onGoForward, activeTabPathRef, handleCloseTabRef,
|
||||
}: KeyboardActions) {
|
||||
const withActiveTab = (fn: (path: string) => void): ShortcutHandler => <span class="fstat-no" title="function not covered" >() => {</span>
|
||||
const path = <span class="cstat-no" title="statement not covered" >activeTabPathRef.current</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (path) <span class="cstat-no" title="statement not covered" >fn(path)</span></span>
|
||||
}
|
||||
|
||||
const keyMap = useMemo((): Record<string, ShortcutHandler> => ({
|
||||
p: onQuickOpen,
|
||||
n: onCreateNote,
|
||||
s: onSave,
|
||||
e: withActiveTab(onArchiveNote),
|
||||
w: withActiveTab(<span class="fstat-no" title="function not covered" >(p</span>ath) => <span class="cstat-no" title="statement not covered" >handleCloseTabRef.current(path))</span>,
|
||||
Backspace: withActiveTab(onTrashNote),
|
||||
Delete: withActiveTab(onTrashNote),
|
||||
}), [onQuickOpen, onCreateNote, onSave, onTrashNote, onArchiveNote, activeTabPathRef, handleCloseTabRef])
|
||||
|
||||
useEffect(() => {
|
||||
const withActiveTab = (fn: (path: string) => void): ShortcutHandler => () => {
|
||||
const path = activeTabPathRef.current
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (path) fn(path)
|
||||
}
|
||||
|
||||
const cmdKeyMap: Record<string, ShortcutHandler> = {
|
||||
k: onCommandPalette,
|
||||
p: onQuickOpen,
|
||||
n: onCreateNote,
|
||||
s: onSave,
|
||||
',': onOpenSettings,
|
||||
e: withActiveTab(onArchiveNote),
|
||||
w: withActiveTab((path) => handleCloseTabRef.current(path)),
|
||||
Backspace: withActiveTab(onTrashNote),
|
||||
Delete: withActiveTab(onTrashNote),
|
||||
'[': <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >o</span>nGoBack?.(),</span>
|
||||
']': <span class="fstat-no" title="function not covered" >() => <span class="cstat-no" title="statement not covered" >o</span>nGoForward?.(),</span>
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const mod = e.metaKey || <span class="branch-1 cbranch-no" title="branch not covered" >e.ctrlKey</span>
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!mod) <span class="cstat-no" title="statement not covered" >return</span>
|
||||
const handler = keyMap[e.key]
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (handler) {
|
||||
// Cmd+Shift+F: full-text search (distinct from Cmd+F browser find)
|
||||
if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key === 'f') {
|
||||
e.preventDefault()
|
||||
handler()
|
||||
onSearch()
|
||||
return
|
||||
}
|
||||
if (!handleViewModeKey(e, onSetViewMode)) {
|
||||
handleCmdKey(e, cmdKeyMap)
|
||||
}
|
||||
}
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [keyMap])
|
||||
}, [onQuickOpen, onCommandPalette, onSearch, onCreateNote, onSave, onOpenSettings, onTrashNote, onArchiveNote, activeTabPathRef, handleCloseTabRef, onSetViewMode, onGoBack, onGoForward])
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
|
||||
@@ -211,7 +361,7 @@ export function useAppKeyboard({
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">51.85% </span>
|
||||
<span class="strong">94.82% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>28/54</span>
|
||||
<span class='fraction'>55/58</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">26.31% </span>
|
||||
<span class="strong">85.36% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>10/38</span>
|
||||
<span class='fraction'>35/41</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">54.54% </span>
|
||||
<span class="strong">93.33% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>6/11</span>
|
||||
<span class='fraction'>14/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">56.25% </span>
|
||||
<span class="strong">95.74% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>27/48</span>
|
||||
<span class='fraction'>45/47</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line medium'></div>
|
||||
<div class='status-line high'></div>
|
||||
<pre><table class="coverage">
|
||||
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||
<a name='L2'></a><a href='#L2'>2</a>
|
||||
@@ -186,10 +186,7 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L124'></a><a href='#L124'>124</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -215,11 +212,11 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -228,13 +225,13 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -244,80 +241,77 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">21x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">264x</span>
|
||||
<span class="cline-any cline-yes">264x</span>
|
||||
<span class="cline-any cline-yes">264x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">19x</span>
|
||||
<span class="cline-any cline-yes">19x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">19x</span>
|
||||
<span class="cline-any cline-yes">19x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useEffect, useMemo, useRef } from 'react'
|
||||
import { isTauri } from '../mock-tauri'
|
||||
import { filterEntries, sortByModified, buildRelationshipGroups } from '../components/NoteList'
|
||||
import { filterEntries, sortByModified, buildRelationshipGroups } from '../utils/noteListHelpers'
|
||||
import type { VaultEntry, SidebarSelection } from '../types'
|
||||
|
||||
interface Tab {
|
||||
@@ -348,98 +342,95 @@ function computeVisibleNotes(
|
||||
return [...filterEntries(entries, selection)].sort(sortByModified)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >navigateTab(</span>
|
||||
function navigateTab(
|
||||
tabsRef: React.RefObject<Tab[]>,
|
||||
activeTabPathRef: React.RefObject<string | null>,
|
||||
onSwitchTab: React.RefObject<(path: string) => void>,
|
||||
direction: 1 | -1,
|
||||
) {
|
||||
const currentTabs = <span class="cstat-no" title="statement not covered" >tabsRef.current!</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (currentTabs.length === 0) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
const currentTabs = tabsRef.current!
|
||||
if (currentTabs.length === 0) return
|
||||
|
||||
const currentPath = <span class="cstat-no" title="statement not covered" >activeTabPathRef.current</span>
|
||||
const currentIndex = <span class="cstat-no" title="statement not covered" >currentTabs.findIndex(<span class="fstat-no" title="function not covered" >(t</span>) => <span class="cstat-no" title="statement not covered" >t.entry.path === currentPath)</span></span>
|
||||
const <span class="cstat-no" title="statement not covered" >nextIndex = (currentIndex + direction + currentTabs.length) % currentTabs.length</span>
|
||||
<span class="cstat-no" title="statement not covered" > onSwitchTab.current!(currentTabs[nextIndex].entry.path)</span>
|
||||
const currentPath = activeTabPathRef.current
|
||||
const currentIndex = currentTabs.findIndex((t) => t.entry.path === currentPath)
|
||||
const nextIndex = (currentIndex + direction + currentTabs.length) % currentTabs.length
|
||||
onSwitchTab.current!(currentTabs[nextIndex].entry.path)
|
||||
}
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >navigateNote(</span>
|
||||
function navigateNote(
|
||||
visibleNotesRef: React.RefObject<VaultEntry[]>,
|
||||
activeTabPathRef: React.RefObject<string | null>,
|
||||
onReplace: React.RefObject<(entry: VaultEntry) => void>,
|
||||
onSelect: React.RefObject<(entry: VaultEntry) => void>,
|
||||
direction: 1 | -1,
|
||||
) {
|
||||
const notes = <span class="cstat-no" title="statement not covered" >visibleNotesRef.current!</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (notes.length === 0) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
const notes = visibleNotesRef.current!
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (notes.length === 0) <span class="cstat-no" title="statement not covered" >return</span>
|
||||
|
||||
const currentPath = <span class="cstat-no" title="statement not covered" >activeTabPathRef.current</span>
|
||||
const currentIndex = <span class="cstat-no" title="statement not covered" >notes.findIndex(<span class="fstat-no" title="function not covered" >(n</span>) => <span class="cstat-no" title="statement not covered" >n.path === currentPath)</span></span>
|
||||
const currentPath = activeTabPathRef.current
|
||||
const currentIndex = notes.findIndex((n) => n.path === currentPath)
|
||||
|
||||
const nextIndex = <span class="cstat-no" title="statement not covered" >currentIndex === -1</span>
|
||||
? (direction === 1 ? 0 : notes.length - 1)
|
||||
const nextIndex = currentIndex === -1
|
||||
? (direction === 1 ? 0 : <span class="branch-1 cbranch-no" title="branch not covered" >notes.length - 1)</span>
|
||||
: (currentIndex + direction + notes.length) % notes.length
|
||||
|
||||
const nextNote = <span class="cstat-no" title="statement not covered" >notes[nextIndex]</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (currentPath) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onReplace.current!(nextNote)</span>
|
||||
const nextNote = notes[nextIndex]
|
||||
if (currentPath) {
|
||||
onReplace.current!(nextNote)
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > onSelect.current!(nextNote)</span>
|
||||
onSelect.current!(nextNote)
|
||||
}
|
||||
}
|
||||
|
||||
type ShortcutKind = 'tab' | 'note' | null
|
||||
|
||||
function classifyShortcut(e: KeyboardEvent, inTauri: boolean): ShortcutKind {
|
||||
const mod = e.metaKey || e.ctrlKey
|
||||
if (!mod) return null
|
||||
const isTabShortcut = inTauri ? (<span class="branch-0 cbranch-no" title="branch not covered" >e.altKey && !e.shiftKey) : (e</span>.shiftKey && !e.altKey)
|
||||
if (isTabShortcut && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) return 'tab'
|
||||
if (e.altKey && !e.shiftKey && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) return 'note'
|
||||
return null
|
||||
}
|
||||
|
||||
function arrowDirection(key: string): 1 | -1 {
|
||||
return (key === 'ArrowRight' || key === 'ArrowDown') ? 1 : -1
|
||||
}
|
||||
|
||||
function useLatestRef<T>(value: T): React.RefObject<T> {
|
||||
const ref = useRef(value)
|
||||
useEffect(() => { ref.current = value })
|
||||
return ref
|
||||
}
|
||||
|
||||
export function useKeyboardNavigation({
|
||||
tabs,
|
||||
activeTabPath,
|
||||
entries,
|
||||
selection,
|
||||
allContent,
|
||||
onSwitchTab,
|
||||
onReplaceActiveTab,
|
||||
onSelectNote,
|
||||
tabs, activeTabPath, entries, selection, allContent,
|
||||
onSwitchTab, onReplaceActiveTab, onSelectNote,
|
||||
}: KeyboardNavigationOptions) {
|
||||
const visibleNotes = useMemo(
|
||||
() => computeVisibleNotes(entries, selection, allContent),
|
||||
[entries, selection, allContent],
|
||||
)
|
||||
|
||||
const tabsRef = useRef(tabs)
|
||||
tabsRef.current = tabs
|
||||
const activeTabPathRef = useRef(activeTabPath)
|
||||
activeTabPathRef.current = activeTabPath
|
||||
const visibleNotesRef = useRef(visibleNotes)
|
||||
visibleNotesRef.current = visibleNotes
|
||||
const onSwitchTabRef = useRef(onSwitchTab)
|
||||
onSwitchTabRef.current = onSwitchTab
|
||||
const onReplaceRef = useRef(onReplaceActiveTab)
|
||||
onReplaceRef.current = onReplaceActiveTab
|
||||
const onSelectNoteRef = useRef(onSelectNote)
|
||||
onSelectNoteRef.current = onSelectNote
|
||||
const tabsRef = useLatestRef(tabs)
|
||||
const activeTabPathRef = useLatestRef(activeTabPath)
|
||||
const visibleNotesRef = useLatestRef(visibleNotes)
|
||||
const onSwitchTabRef = useLatestRef(onSwitchTab)
|
||||
const onReplaceRef = useLatestRef(onReplaceActiveTab)
|
||||
const onSelectNoteRef = useLatestRef(onSelectNote)
|
||||
|
||||
useEffect(() => {
|
||||
const isRunningInTauri = isTauri()
|
||||
|
||||
const inTauri = isTauri()
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const mod = e.metaKey || <span class="branch-1 cbranch-no" title="branch not covered" >e.ctrlKey</span>
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!mod) <span class="cstat-no" title="statement not covered" >return</span>
|
||||
|
||||
const isTabShortcut = isRunningInTauri
|
||||
? <span class="branch-0 cbranch-no" title="branch not covered" >e.altKey && !e.shiftKey</span>
|
||||
: e.shiftKey && <span class="branch-1 cbranch-no" title="branch not covered" >!e.altKey</span>
|
||||
const isNoteShortcut = e.altKey && <span class="branch-1 cbranch-no" title="branch not covered" >!e.shiftKey</span>
|
||||
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (isTabShortcut && (<span class="branch-1 cbranch-no" title="branch not covered" >e.key === 'ArrowLeft' || <span class="branch-2 cbranch-no" title="branch not covered" >e</span>.key === 'ArrowRight')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > navigateTab(tabsRef, activeTabPathRef, onSwitchTabRef, e.key === 'ArrowRight' ? 1 : -1)</span>
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>} else if (isNoteShortcut && (<span class="branch-1 cbranch-no" title="branch not covered" >e.key === 'ArrowUp' || <span class="branch-2 cbranch-no" title="branch not covered" >e</span>.key === 'ArrowDown')) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > e.preventDefault()</span>
|
||||
<span class="cstat-no" title="statement not covered" > navigateNote(visibleNotesRef, activeTabPathRef, onReplaceRef, onSelectNoteRef, e.key === 'ArrowDown' ? 1 : -1)</span>
|
||||
}
|
||||
const kind = classifyShortcut(e, inTauri)
|
||||
if (!kind) return
|
||||
e.preventDefault()
|
||||
if (kind === 'tab') navigateTab(tabsRef, activeTabPathRef, onSwitchTabRef, arrowDirection(e.key))
|
||||
else navigateNote(visibleNotesRef, activeTabPathRef, onReplaceRef, onSelectNoteRef, arrowDirection(e.key))
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [])
|
||||
}, [tabsRef, activeTabPathRef, visibleNotesRef, onSwitchTabRef, onReplaceRef, onSelectNoteRef])
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
|
||||
@@ -448,7 +439,7 @@ export function useKeyboardNavigation({
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/hooks/useMcpBridge.ts</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/hooks</a> useMcpBridge.ts</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>0/48</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/11</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/14</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>0/47</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||
* Hook for communicating with the Laputa MCP WebSocket bridge.
|
||||
*
|
||||
* Provides typed tool invocations for vault operations:
|
||||
* - readNote, createNote, searchNotes, appendToNote
|
||||
*
|
||||
* Connection is lazy — only opens when first tool is called.
|
||||
*/
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
|
||||
const DEFAULT_WS_URL = <span class="cstat-no" title="statement not covered" >'ws://localhost:9710'</span>
|
||||
|
||||
interface PendingRequest {
|
||||
resolve: (value: any) => void
|
||||
reject: (reason: any) => void
|
||||
}
|
||||
|
||||
interface SearchResult {
|
||||
path: string
|
||||
title: string
|
||||
snippet: string
|
||||
}
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >useMcpBridge(w</span>sUrl = <span class="branch-0 cbranch-no" title="branch not covered" >DEFAULT_WS_URL) {</span>
|
||||
const <span class="cstat-no" title="statement not covered" >wsRef = useRef<WebSocket | null>(null)</span>
|
||||
const <span class="cstat-no" title="statement not covered" >pendingRef = useRef<Map<string, PendingRequest>>(new Map())</span>
|
||||
const <span class="cstat-no" title="statement not covered" >idCounterRef = useRef(0)</span>
|
||||
const [connected, setConnected<span class="cstat-no" title="statement not covered" >] = useState(false)</span>
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >ensureConnection = useCallback(<span class="fstat-no" title="function not covered" >(): Promise<WebSocket> => {</span></span>
|
||||
const ws = <span class="cstat-no" title="statement not covered" >wsRef.current</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (ws && ws.readyState === WebSocket.OPEN) <span class="cstat-no" title="statement not covered" >return Promise.resolve(ws)</span></span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return new Promise(<span class="fstat-no" title="function not covered" >(r</span>esolve, reject) => {</span>
|
||||
const newWs = <span class="cstat-no" title="statement not covered" >new WebSocket(wsUrl)</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > newWs.onopen = <span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > wsRef.current = newWs</span>
|
||||
<span class="cstat-no" title="statement not covered" > setConnected(true)</span>
|
||||
<span class="cstat-no" title="statement not covered" > resolve(newWs)</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > newWs.onmessage = <span class="fstat-no" title="function not covered" >(e</span>vent) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
const msg = <span class="cstat-no" title="statement not covered" >JSON.parse(event.data)</span>
|
||||
const pending = <span class="cstat-no" title="statement not covered" >pendingRef.current.get(msg.id)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (pending) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingRef.current.delete(msg.id)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (msg.error) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > pending.reject(new Error(msg.error))</span>
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > pending.resolve(msg.result)</span>
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore malformed messages
|
||||
}
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > newWs.onclose = <span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > wsRef.current = null</span>
|
||||
<span class="cstat-no" title="statement not covered" > setConnected(false)</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > newWs.onerror = <span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > reject(new Error('WebSocket connection failed'))</span>
|
||||
}
|
||||
})
|
||||
}, [wsUrl])
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >callTool = useCallback(<span class="fstat-no" title="function not covered" >async <T>(t</span>ool: string, args: Record<string, any>): Promise<T> => {</span>
|
||||
const ws = <span class="cstat-no" title="statement not covered" >await ensureConnection()</span>
|
||||
const id = <span class="cstat-no" title="statement not covered" >`mcp-${++idCounterRef.current}`</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return new Promise(<span class="fstat-no" title="function not covered" >(r</span>esolve, reject) => {</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingRef.current.set(id, { resolve, reject })</span>
|
||||
<span class="cstat-no" title="statement not covered" > ws.send(JSON.stringify({ id, tool, args }))</span>
|
||||
|
||||
// Timeout after 30 seconds
|
||||
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >() => {</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > if (pendingRef.current.has(id)) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > pendingRef.current.delete(id)</span>
|
||||
<span class="cstat-no" title="statement not covered" > reject(new Error('MCP tool call timed out'))</span>
|
||||
}
|
||||
}, 30_000)
|
||||
})
|
||||
}, [ensureConnection])
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >readNote = useCallback(</span>
|
||||
<span class="fstat-no" title="function not covered" > (p</span>ath: string) => <span class="cstat-no" title="statement not covered" >callTool<{ content: string }>('read_note', { path }),</span>
|
||||
[callTool],
|
||||
)
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >createNote = useCallback(</span>
|
||||
<span class="fstat-no" title="function not covered" > (p</span>ath: string, title: string, isA?: string) =>
|
||||
<span class="cstat-no" title="statement not covered" > callTool<string>('create_note', { path, title, is_a: isA }),</span>
|
||||
[callTool],
|
||||
)
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >searchNotes = useCallback(</span>
|
||||
<span class="fstat-no" title="function not covered" > (q</span>uery: string, limit?: number) =>
|
||||
<span class="cstat-no" title="statement not covered" > callTool<SearchResult[]>('search_notes', { query, limit }),</span>
|
||||
[callTool],
|
||||
)
|
||||
|
||||
const <span class="cstat-no" title="statement not covered" >appendToNote = useCallback(</span>
|
||||
<span class="fstat-no" title="function not covered" > (p</span>ath: string, text: string) =>
|
||||
<span class="cstat-no" title="statement not covered" > callTool<{ ok: boolean }>('append_to_note', { path, text }),</span>
|
||||
[callTool],
|
||||
)
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > return { connected, readNote, createNote, searchNotes, appendToNote, callTool }</span>
|
||||
}
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,16 +112,16 @@
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">37x</span>
|
||||
<span class="cline-any cline-yes">37x</span>
|
||||
<span class="cline-any cline-yes">37x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">44x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">35x</span>
|
||||
<span class="cline-any cline-yes">42x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -129,9 +129,9 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">74x</span>
|
||||
<span class="cline-any cline-yes">87x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">74x</span>
|
||||
<span class="cline-any cline-yes">87x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
@@ -144,12 +144,12 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">74x</span>
|
||||
<span class="cline-any cline-yes">592x</span>
|
||||
<span class="cline-any cline-yes">87x</span>
|
||||
<span class="cline-any cline-yes">624x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">74x</span>
|
||||
<span class="cline-any cline-yes">87x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useState, useCallback } from 'react'
|
||||
|
||||
@@ -202,7 +202,7 @@ export function useSectionVisibility() {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -124,46 +124,46 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">168x</span>
|
||||
<span class="cline-any cline-yes">462x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">168x</span>
|
||||
<span class="cline-any cline-yes">936x</span>
|
||||
<span class="cline-any cline-yes">462x</span>
|
||||
<span class="cline-any cline-yes">2574x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">936x</span>
|
||||
<span class="cline-any cline-yes">936x</span>
|
||||
<span class="cline-any cline-yes">2574x</span>
|
||||
<span class="cline-any cline-yes">2574x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">928x</span>
|
||||
<span class="cline-any cline-yes">160x</span>
|
||||
<span class="cline-any cline-yes">768x</span>
|
||||
<span class="cline-any cline-yes">2552x</span>
|
||||
<span class="cline-any cline-yes">440x</span>
|
||||
<span class="cline-any cline-yes">2112x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">456x</span>
|
||||
<span class="cline-any cline-yes">1254x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">456x</span>
|
||||
<span class="cline-any cline-yes">456x</span>
|
||||
<span class="cline-any cline-yes">1254x</span>
|
||||
<span class="cline-any cline-yes">1254x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">312x</span>
|
||||
<span class="cline-any cline-yes">858x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">168x</span>
|
||||
<span class="cline-any cline-yes">462x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">936x</span>
|
||||
<span class="cline-any cline-yes">2574x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">768x</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">2112x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useMemo } from 'react'
|
||||
import themeConfig from '../theme.json'
|
||||
@@ -223,7 +223,7 @@ export function useEditorTheme() {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">47.22% </span>
|
||||
<span class="strong">84.15% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>34/72</span>
|
||||
<span class='fraction'>85/101</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">18.75% </span>
|
||||
<span class="strong">73.07% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>3/16</span>
|
||||
<span class='fraction'>19/26</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">26.31% </span>
|
||||
<span class="strong">86.48% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>5/19</span>
|
||||
<span class='fraction'>32/37</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">51.51% </span>
|
||||
<span class="strong">85.5% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>34/66</span>
|
||||
<span class='fraction'>59/69</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></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>
|
||||
@@ -190,125 +190,30 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L128'></a><a href='#L128'>128</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">66x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
@@ -316,22 +221,97 @@
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">40x</span>
|
||||
<span class="cline-any cline-yes">36x</span>
|
||||
<span class="cline-any cline-yes">36x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">32x</span>
|
||||
<span class="cline-any cline-yes">32x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">22x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">4x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">33x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -340,138 +320,128 @@
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { useCallback, useEffect, useState } from 'react'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { isTauri, mockInvoke } from '../mock-tauri'
|
||||
import type { VaultEntry, GitCommit, ModifiedFile } from '../types'
|
||||
import type { VaultEntry, GitCommit, ModifiedFile, NoteStatus } from '../types'
|
||||
|
||||
function tauriCall<T>(command: string, tauriArgs: Record<string, unknown>, mockArgs?: Record<string, unknown>): Promise<T> {
|
||||
return isTauri(<span class="branch-0 cbranch-no" title="branch not covered" >) ? invoke<T>(command, tauriArgs) : m</span>ockInvoke<T>(command, mockArgs ?? tauriArgs)
|
||||
}
|
||||
|
||||
async function loadVaultData(vaultPath: string) {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!isTauri()) console.info('[mock] Using mock Tauri data for browser testing')
|
||||
const entries = await tauriCall<VaultEntry[]>('list_vault', { path: vaultPath })
|
||||
console.log(`Vault scan complete: ${entries.length} entries found`)
|
||||
const allContent = isTauri() ? <span class="branch-0 cbranch-no" title="branch not covered" >{} : a</span>wait mockInvoke<Record<string, string>>('get_all_content', { path: vaultPath })
|
||||
return { entries, allContent }
|
||||
}
|
||||
|
||||
async function commitWithPush(vaultPath: string, message: string): Promise<string> {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (!isTauri()) {
|
||||
await mockInvoke<string>('git_commit', { message })
|
||||
await mockInvoke<string>('git_push', {})
|
||||
return 'Committed and pushed'
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > await invoke<string>('git_commit', { vaultPath, message })</span>
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
<span class="cstat-no" title="statement not covered" > await invoke<string>('git_push', { vaultPath })</span>
|
||||
<span class="cstat-no" title="statement not covered" > return 'Committed and pushed'</span>
|
||||
} catch {
|
||||
<span class="cstat-no" title="statement not covered" > return 'Committed (push failed)'</span>
|
||||
}
|
||||
}
|
||||
|
||||
function useNewNoteTracker() {
|
||||
const [newPaths, setNewPaths] = useState<Set<string>>(new Set())
|
||||
|
||||
const trackNew = useCallback((path: string) => {
|
||||
setNewPaths((prev) => new Set(prev).add(path))
|
||||
}, [])
|
||||
|
||||
const clear = useCallback(() => setNewPaths(new Set()), [])
|
||||
|
||||
return { newPaths, trackNew, clear }
|
||||
}
|
||||
|
||||
export function resolveNoteStatus(path: string, newPaths: Set<string>, modifiedFiles: ModifiedFile[]): NoteStatus {
|
||||
if (newPaths.has(path)) return 'new'
|
||||
const gitEntry = modifiedFiles.find((f) => f.path === path)
|
||||
if (!gitEntry) return 'clean'
|
||||
if (gitEntry.status === 'untracked' || gitEntry.status === 'added') return 'new'
|
||||
if (gitEntry.status === 'modified') return 'modified'
|
||||
return 'clean'
|
||||
}
|
||||
|
||||
export function useVaultLoader(vaultPath: string) {
|
||||
const [entries, setEntries] = useState<VaultEntry[]>([])
|
||||
const [allContent, setAllContent] = useState<Record<string, string>>({})
|
||||
const [modifiedFiles, setModifiedFiles] = useState<ModifiedFile[]>([])
|
||||
const tracker = useNewNoteTracker()
|
||||
|
||||
useEffect(() => {
|
||||
setEntries([])
|
||||
setAllContent({})
|
||||
setModifiedFiles([])
|
||||
|
||||
const loadVault = async () => {
|
||||
try {
|
||||
let result: VaultEntry[]
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (isTauri()) {
|
||||
<span class="cstat-no" title="statement not covered" > result = await invoke<VaultEntry[]>('list_vault', { path: vaultPath })</span>
|
||||
} else {
|
||||
console.info('[mock] Using mock Tauri data for browser testing')
|
||||
result = await mockInvoke<VaultEntry[]>('list_vault', { path: vaultPath })
|
||||
}
|
||||
console.log(`Vault scan complete: ${result.length} entries found`)
|
||||
setEntries(result)
|
||||
|
||||
let content: Record<string, string>
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (isTauri()) {
|
||||
<span class="cstat-no" title="statement not covered" > content = {}</span>
|
||||
} else {
|
||||
content = await mockInvoke<Record<string, string>>('get_all_content', { path: vaultPath })
|
||||
}
|
||||
setAllContent(content)
|
||||
} catch (err) {
|
||||
<span class="cstat-no" title="statement not covered" > console.warn('Vault scan failed:', err)</span>
|
||||
}
|
||||
}
|
||||
loadVault()
|
||||
}, [vaultPath])
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- clear stale data then load new vault
|
||||
setEntries([]); setAllContent({}); setModifiedFiles([]); tracker.clear()
|
||||
loadVaultData(vaultPath)
|
||||
.then(({ entries: e, allContent: c }) => { setEntries(e); setAllContent(c) })
|
||||
.catch(<span class="fstat-no" title="function not covered" >(e</span>rr) => <span class="cstat-no" title="statement not covered" >console.warn('Vault scan failed:', err))</span>
|
||||
}, [vaultPath]) // eslint-disable-line react-hooks/exhaustive-deps -- tracker.clear is stable
|
||||
|
||||
const loadModifiedFiles = useCallback(async () => {
|
||||
try {
|
||||
let files: ModifiedFile[]
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (isTauri()) {
|
||||
<span class="cstat-no" title="statement not covered" > files = await invoke<ModifiedFile[]>('get_modified_files', { vaultPath })</span>
|
||||
} else {
|
||||
files = await mockInvoke<ModifiedFile[]>('get_modified_files', {})
|
||||
}
|
||||
setModifiedFiles(files)
|
||||
setModifiedFiles(await tauriCall<ModifiedFile[]>('get_modified_files', { vaultPath }, {}))
|
||||
} catch (err) {
|
||||
<span class="cstat-no" title="statement not covered" > console.warn('Failed to load modified files:', err)</span>
|
||||
<span class="cstat-no" title="statement not covered" > setModifiedFiles([])</span>
|
||||
}
|
||||
}, [vaultPath])
|
||||
|
||||
useEffect(() => {
|
||||
loadModifiedFiles()
|
||||
}, [loadModifiedFiles])
|
||||
useEffect(() => { loadModifiedFiles() }, [loadModifiedFiles]) // eslint-disable-line react-hooks/set-state-in-effect -- trigger initial load
|
||||
|
||||
const addEntry = useCallback(<span class="fstat-no" title="function not covered" >(e</span>ntry: VaultEntry, content: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setEntries(<span class="fstat-no" title="function not covered" >(p</span>rev) => <span class="cstat-no" title="statement not covered" >[entry, ...prev])</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setAllContent(<span class="fstat-no" title="function not covered" >(p</span>rev) => (<span class="cstat-no" title="statement not covered" >{ ...prev, [entry.path]: content }))</span></span>
|
||||
const addEntry = useCallback((entry: VaultEntry, content: string) => {
|
||||
setEntries((prev) => {
|
||||
if (prev.some(e => e.path === entry.path)) return prev
|
||||
return [entry, ...prev]
|
||||
})
|
||||
setAllContent((prev) => ({ ...prev, [entry.path]: content }))
|
||||
tracker.trackNew(entry.path)
|
||||
}, [tracker])
|
||||
|
||||
const updateContent = useCallback((path: string, content: string) =>
|
||||
setAllContent((prev) => ({ ...prev, [path]: content })), [])
|
||||
|
||||
const updateEntry = useCallback((path: string, patch: Partial<VaultEntry>) =>
|
||||
setEntries((prev) => prev.map((e) => e.path === path ? { ...e, ...patch } : <span class="branch-1 cbranch-no" title="branch not covered" >e)</span>), [])
|
||||
|
||||
const removeEntry = useCallback((path: string) => {
|
||||
setEntries((prev) => prev.filter((e) => e.path !== path))
|
||||
setAllContent((prev) => { const next = { ...prev }; delete next[path]; return next })
|
||||
}, [])
|
||||
|
||||
const updateContent = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string, content: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setAllContent(<span class="fstat-no" title="function not covered" >(p</span>rev) => (<span class="cstat-no" title="statement not covered" >{ ...prev, [path]: content }))</span></span>
|
||||
const replaceEntry = useCallback(<span class="fstat-no" title="function not covered" >(o</span>ldPath: string, patch: Partial<VaultEntry> & { path: string }, newContent: string) => {
|
||||
<span class="cstat-no" title="statement not covered" > setEntries(<span class="fstat-no" title="function not covered" >(p</span>rev) => <span class="cstat-no" title="statement not covered" >prev.map(<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.path === oldPath ? { ...e, ...patch } : e)</span>)</span></span>
|
||||
<span class="cstat-no" title="statement not covered" > setAllContent(<span class="fstat-no" title="function not covered" >(p</span>rev) => { const next = <span class="cstat-no" title="statement not covered" >{ ...prev }; <span class="cstat-no" title="statement not covered" >d</span>elete next[oldPath]; <span class="cstat-no" title="statement not covered" >n</span>ext[patch.path] = newContent; <span class="cstat-no" title="statement not covered" >r</span>eturn next }</span>)</span>
|
||||
}, [])
|
||||
|
||||
const updateEntry = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string, patch: Partial<VaultEntry>) => {
|
||||
<span class="cstat-no" title="statement not covered" > setEntries(<span class="fstat-no" title="function not covered" >(p</span>rev) => <span class="cstat-no" title="statement not covered" >prev.map(<span class="fstat-no" title="function not covered" >(e</span>) => <span class="cstat-no" title="statement not covered" >e.path === path ? { ...e, ...patch } : e)</span>)</span></span>
|
||||
}, [])
|
||||
|
||||
const loadGitHistory = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string): Promise<GitCommit[]> => {
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (isTauri()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return await invoke<GitCommit[]>('get_file_history', { vaultPath, path })</span>
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > return await mockInvoke<GitCommit[]>('get_file_history', { path })</span>
|
||||
}
|
||||
} catch (err) {
|
||||
<span class="cstat-no" title="statement not covered" > console.warn('Failed to load git history:', err)</span>
|
||||
<span class="cstat-no" title="statement not covered" > return []</span>
|
||||
}
|
||||
const loadGitHistory = useCallback(async (path: string): Promise<GitCommit[]> => {
|
||||
try { return await tauriCall<GitCommit[]>('get_file_history', { vaultPath, path }, { path }) }
|
||||
catch (err) { console.warn('Failed to load git history:', err); return [] }
|
||||
}, [vaultPath])
|
||||
|
||||
const loadDiffAtCommit = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string, commitHash: string): Promise<string> => {
|
||||
<span class="cstat-no" title="statement not covered" > if (isTauri()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return invoke<string>('get_file_diff_at_commit', { vaultPath, path, commitHash })</span>
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > return mockInvoke<string>('get_file_diff_at_commit', { path, commitHash })</span>
|
||||
}
|
||||
}, [vaultPath])
|
||||
const loadDiffAtCommit = useCallback((path: string, commitHash: string): Promise<string> =>
|
||||
tauriCall<string>('get_file_diff_at_commit', { vaultPath, path, commitHash }, { path, commitHash }), [vaultPath])
|
||||
|
||||
const loadDiff = useCallback(<span class="fstat-no" title="function not covered" >async (p</span>ath: string): Promise<string> => {
|
||||
<span class="cstat-no" title="statement not covered" > if (isTauri()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return invoke<string>('get_file_diff', { vaultPath, path })</span>
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > return mockInvoke<string>('get_file_diff', { path })</span>
|
||||
}
|
||||
}, [vaultPath])
|
||||
const loadDiff = useCallback((path: string): Promise<string> =>
|
||||
tauriCall<string>('get_file_diff', { vaultPath, path }, { path }), [vaultPath])
|
||||
|
||||
const isFileModified = useCallback(<span class="fstat-no" title="function not covered" >(p</span>ath: string): boolean => {
|
||||
<span class="cstat-no" title="statement not covered" > return modifiedFiles.some(<span class="fstat-no" title="function not covered" >(f</span>) => <span class="cstat-no" title="statement not covered" >f.path === path)</span></span>
|
||||
}, [modifiedFiles])
|
||||
const getNoteStatus = useCallback((path: string): NoteStatus =>
|
||||
resolveNoteStatus(path, tracker.newPaths, modifiedFiles), [tracker.newPaths, modifiedFiles])
|
||||
|
||||
const commitAndPush = useCallback(<span class="fstat-no" title="function not covered" >async (m</span>essage: string): Promise<string> => {
|
||||
<span class="cstat-no" title="statement not covered" > if (isTauri()) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > await invoke<string>('git_commit', { vaultPath, message })</span>
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
<span class="cstat-no" title="statement not covered" > await invoke<string>('git_push', { vaultPath })</span>
|
||||
<span class="cstat-no" title="statement not covered" > return 'Committed and pushed'</span>
|
||||
} catch {
|
||||
<span class="cstat-no" title="statement not covered" > return 'Committed (push failed)'</span>
|
||||
}
|
||||
} else {
|
||||
<span class="cstat-no" title="statement not covered" > await mockInvoke<string>('git_commit', { message })</span>
|
||||
<span class="cstat-no" title="statement not covered" > await mockInvoke<string>('git_push', {})</span>
|
||||
<span class="cstat-no" title="statement not covered" > return 'Committed and pushed'</span>
|
||||
}
|
||||
}, [vaultPath])
|
||||
const commitAndPush = useCallback((message: string): Promise<string> =>
|
||||
commitWithPush(vaultPath, message), [vaultPath])
|
||||
|
||||
return {
|
||||
entries,
|
||||
allContent,
|
||||
modifiedFiles,
|
||||
addEntry,
|
||||
updateEntry,
|
||||
updateContent,
|
||||
loadModifiedFiles,
|
||||
loadGitHistory,
|
||||
loadDiff,
|
||||
loadDiffAtCommit,
|
||||
isFileModified,
|
||||
commitAndPush,
|
||||
entries, allContent, modifiedFiles,
|
||||
addEntry, updateEntry, removeEntry, replaceEntry, updateContent,
|
||||
loadModifiedFiles, loadGitHistory, loadDiff, loadDiffAtCommit,
|
||||
getNoteStatus, commitAndPush,
|
||||
}
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
@@ -481,7 +451,7 @@ export function useVaultLoader(vaultPath: string) {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">40.9% </span>
|
||||
<span class="strong">47.5% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>45/110</span>
|
||||
<span class='fraction'>57/120</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">50% </span>
|
||||
<span class="strong">40.47% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>11/22</span>
|
||||
<span class='fraction'>17/42</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">13.51% </span>
|
||||
<span class="strong">20.58% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>5/37</span>
|
||||
<span class='fraction'>7/34</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">45% </span>
|
||||
<span class="strong">57.73% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>45/100</span>
|
||||
<span class='fraction'>56/97</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -80,32 +80,17 @@
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file low" data-value="App.tsx"><a href="App.tsx.html">App.tsx</a></td>
|
||||
<td data-value="40.9" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 40%"></div><div class="cover-empty" style="width: 60%"></div></div>
|
||||
<td data-value="47.5" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 47%"></div><div class="cover-empty" style="width: 53%"></div></div>
|
||||
</td>
|
||||
<td data-value="40.9" class="pct low">40.9%</td>
|
||||
<td data-value="110" class="abs low">45/110</td>
|
||||
<td data-value="50" class="pct medium">50%</td>
|
||||
<td data-value="22" class="abs medium">11/22</td>
|
||||
<td data-value="13.51" class="pct low">13.51%</td>
|
||||
<td data-value="37" class="abs low">5/37</td>
|
||||
<td data-value="45" class="pct low">45%</td>
|
||||
<td data-value="100" class="abs low">45/100</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file empty" data-value="types.ts"><a href="types.ts.html">types.ts</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>
|
||||
<td data-value="47.5" class="pct low">47.5%</td>
|
||||
<td data-value="120" class="abs low">57/120</td>
|
||||
<td data-value="40.47" class="pct low">40.47%</td>
|
||||
<td data-value="42" class="abs low">17/42</td>
|
||||
<td data-value="20.58" class="pct low">20.58%</td>
|
||||
<td data-value="34" class="abs low">7/34</td>
|
||||
<td data-value="57.73" class="pct medium">57.73%</td>
|
||||
<td data-value="97" class="abs medium">56/97</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
@@ -116,7 +101,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1714x</span>
|
||||
<span class="cline-any cline-yes">30814x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import { clsx, type ClassValue } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
@@ -88,7 +88,7 @@ export function cn(...inputs: ClassValue[]) {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/types.ts</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> types.ts</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">export interface VaultEntry {
|
||||
path: string
|
||||
filename: string
|
||||
title: string
|
||||
isA: string | null
|
||||
aliases: string[]
|
||||
belongsTo: string[]
|
||||
relatedTo: string[]
|
||||
status: string | null
|
||||
owner: string | null
|
||||
cadence: string | null
|
||||
archived: boolean
|
||||
trashed: boolean
|
||||
trashedAt: number | null
|
||||
modifiedAt: number | null
|
||||
createdAt: number | null
|
||||
fileSize: number
|
||||
snippet: string
|
||||
/** Generic relationship fields: any frontmatter key whose value contains wikilinks. */
|
||||
relationships: Record<string, string[]>
|
||||
/** Phosphor icon name (kebab-case) for Type entries, e.g. "cooking-pot" */
|
||||
icon: string | null
|
||||
/** Accent color key for Type entries: "red" | "purple" | "blue" | "green" | "yellow" | "orange" */
|
||||
color: string | null
|
||||
/** Display order for Type entries in sidebar (lower = higher). null = use default order. */
|
||||
order: number | null
|
||||
}
|
||||
|
||||
export interface GitCommit {
|
||||
hash: string
|
||||
shortHash: string
|
||||
message: string
|
||||
author: string
|
||||
date: number // unix timestamp
|
||||
}
|
||||
|
||||
export interface ModifiedFile {
|
||||
path: string
|
||||
relativePath: string
|
||||
status: 'modified' | 'added' | 'deleted' | 'untracked' | 'renamed'
|
||||
}
|
||||
|
||||
export type SidebarSelection =
|
||||
| { kind: 'filter'; filter: 'all' | 'favorites' | 'archived' | 'trash' }
|
||||
| { kind: 'sectionGroup'; type: string }
|
||||
| { kind: 'entity'; entry: VaultEntry }
|
||||
| { kind: 'topic'; entry: VaultEntry }
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -1,655 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Code coverage report for src/utils/ai-chat.ts</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/utils</a> ai-chat.ts</h1>
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">5.26% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>4/76</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>0/43</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">0% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>0/10</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">5.63% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>4/71</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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||
* AI Chat utilities — Anthropic API client, token estimation, context building.
|
||||
*/
|
||||
|
||||
import type { VaultEntry } from '../types'
|
||||
|
||||
// --- localStorage key for API key ---
|
||||
const API_KEY_STORAGE_KEY = 'laputa:anthropic-api-key'
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >getApiKey(): string {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return localStorage.getItem(API_KEY_STORAGE_KEY) ?? ''</span>
|
||||
}
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >setApiKey(k</span>ey: string): void {
|
||||
<span class="cstat-no" title="statement not covered" > localStorage.setItem(API_KEY_STORAGE_KEY, key)</span>
|
||||
}
|
||||
|
||||
// --- Token estimation ---
|
||||
|
||||
/** Rough token estimate: ~4 chars per token for English text. */
|
||||
export function <span class="fstat-no" title="function not covered" >estimateTokens(t</span>ext: string | number): number {
|
||||
const len = <span class="cstat-no" title="statement not covered" >typeof text === 'number' ? text : text.length</span>
|
||||
<span class="cstat-no" title="statement not covered" > return Math.ceil(len / 4)</span>
|
||||
}
|
||||
|
||||
const DEFAULT_CONTEXT_LIMIT = 180_000
|
||||
|
||||
export function <span class="fstat-no" title="function not covered" >getContextLimit(_</span>model: string): number {
|
||||
<span class="cstat-no" title="statement not covered" > return DEFAULT_CONTEXT_LIMIT</span>
|
||||
}
|
||||
|
||||
// --- Context building ---
|
||||
|
||||
/** Build system prompt from selected context notes. */
|
||||
export function <span class="fstat-no" title="function not covered" >buildSystemPrompt(</span>
|
||||
notes: VaultEntry[],
|
||||
allContent: Record<string, string>,
|
||||
model: string,
|
||||
): { prompt: string; totalTokens: number; truncated: boolean } {
|
||||
<span class="cstat-no" title="statement not covered" > if (notes.length === 0) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return { prompt: '', totalTokens: 0, truncated: false }</span>
|
||||
}
|
||||
|
||||
const contextBudget = <span class="cstat-no" title="statement not covered" >Math.floor(getContextLimit(model) * 0.6)</span>
|
||||
const preamble = <span class="cstat-no" title="statement not covered" >[</span>
|
||||
'You are a helpful AI assistant integrated into Laputa, a personal knowledge management app.',
|
||||
'The user has selected the following notes as context. Use them to answer questions accurately.',
|
||||
'',
|
||||
].join('\n')
|
||||
|
||||
const parts: string[] = <span class="cstat-no" title="statement not covered" >[preamble]</span>
|
||||
let totalChars = <span class="cstat-no" title="statement not covered" >preamble.length</span>
|
||||
let truncated = <span class="cstat-no" title="statement not covered" >false</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > for (const note of notes) {</span>
|
||||
const content = <span class="cstat-no" title="statement not covered" >allContent[note.path] ?? ''</span>
|
||||
const header = <span class="cstat-no" title="statement not covered" >`--- Note: ${note.title} (${note.isA ?? 'Note'}) ---`</span>
|
||||
const noteText = <span class="cstat-no" title="statement not covered" >`${header}\n${content}\n`</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (estimateTokens(totalChars + noteText.length) > contextBudget) {</span>
|
||||
const <span class="cstat-no" title="statement not covered" >remaining = (contextBudget - estimateTokens(totalChars)) * 4</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (remaining > 200) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > parts.push(`${header}\n${content.slice(0, remaining)}\n[... truncated ...]`)</span>
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > truncated = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > break</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > parts.push(noteText)</span>
|
||||
<span class="cstat-no" title="statement not covered" > totalChars += noteText.length</span>
|
||||
}
|
||||
|
||||
const prompt = <span class="cstat-no" title="statement not covered" >parts.join('\n')</span>
|
||||
<span class="cstat-no" title="statement not covered" > return { prompt, totalTokens: estimateTokens(prompt), truncated }</span>
|
||||
}
|
||||
|
||||
// --- API types ---
|
||||
|
||||
export interface ChatMessage {
|
||||
role: 'user' | 'assistant'
|
||||
content: string
|
||||
id: string
|
||||
}
|
||||
|
||||
let msgIdCounter = 0
|
||||
export function <span class="fstat-no" title="function not covered" >nextMessageId(): string {</span>
|
||||
<span class="cstat-no" title="statement not covered" > return `msg-${++msgIdCounter}-${Date.now()}`</span>
|
||||
}
|
||||
|
||||
// --- SSE parsing ---
|
||||
|
||||
function <span class="fstat-no" title="function not covered" >parseSseEvent(l</span>ine: string, onChunk: (text: string) => void): boolean {
|
||||
<span class="cstat-no" title="statement not covered" > if (!line.startsWith('data: ')) <span class="cstat-no" title="statement not covered" >return false</span></span>
|
||||
const data = <span class="cstat-no" title="statement not covered" >line.slice(6)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (data === '[DONE]') <span class="cstat-no" title="statement not covered" >return true</span></span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
const event = <span class="cstat-no" title="statement not covered" >JSON.parse(data)</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (event.type === 'content_block_delta' && event.delta?.text) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onChunk(event.delta.text)</span>
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > if (event.type === 'message_stop') <span class="cstat-no" title="statement not covered" >return true</span></span>
|
||||
} catch {
|
||||
// skip malformed events
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > return false</span>
|
||||
}
|
||||
|
||||
async function <span class="fstat-no" title="function not covered" >readSseStream(</span>
|
||||
reader: ReadableStreamDefaultReader<Uint8Array>,
|
||||
onChunk: (text: string) => void,
|
||||
): Promise<void> {
|
||||
const decoder = <span class="cstat-no" title="statement not covered" >new TextDecoder()</span>
|
||||
let buffer = <span class="cstat-no" title="statement not covered" >''</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > while (true) {</span>
|
||||
const { value, done } = <span class="cstat-no" title="statement not covered" >await reader.read()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (done) <span class="cstat-no" title="statement not covered" >break</span></span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > buffer += decoder.decode(value, { stream: true })</span>
|
||||
const lines = <span class="cstat-no" title="statement not covered" >buffer.split('\n')</span>
|
||||
<span class="cstat-no" title="statement not covered" > buffer = lines.pop() ?? ''</span>
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > for (const line of lines) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (parseSseEvent(line, onChunk)) <span class="cstat-no" title="statement not covered" >return</span></span>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function <span class="fstat-no" title="function not covered" >parseApiError(r</span>esponse: Response): Promise<string> {
|
||||
const errText = <span class="cstat-no" title="statement not covered" >await response.text()</span>
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
const errJson = <span class="cstat-no" title="statement not covered" >JSON.parse(errText)</span>
|
||||
<span class="cstat-no" title="statement not covered" > return errJson.error?.message || errJson.error || `API error (${response.status})`</span>
|
||||
} catch {
|
||||
<span class="cstat-no" title="statement not covered" > return `API error (${response.status})`</span>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Streaming API call ---
|
||||
|
||||
export async function <span class="fstat-no" title="function not covered" >streamChat(</span>
|
||||
messages: { role: 'user' | 'assistant'; content: string }[],
|
||||
systemPrompt: string,
|
||||
model: string,
|
||||
onChunk: (text: string) => void,
|
||||
onDone: () => void,
|
||||
onError: (error: string) => void,
|
||||
): Promise<void> {
|
||||
const apiKey = <span class="cstat-no" title="statement not covered" >getApiKey()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!apiKey) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onError('No API key configured. Click the key icon to set your Anthropic API key.')</span>
|
||||
<span class="cstat-no" title="statement not covered" > return</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > try {</span>
|
||||
const response = <span class="cstat-no" title="statement not covered" >await fetch('/api/ai/chat', {</span>
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
apiKey, model, messages,
|
||||
system: systemPrompt || undefined,
|
||||
maxTokens: 4096,
|
||||
}),
|
||||
})
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > if (!response.ok) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onError(await parseApiError(response))</span>
|
||||
<span class="cstat-no" title="statement not covered" > return</span>
|
||||
}
|
||||
|
||||
const reader = <span class="cstat-no" title="statement not covered" >response.body?.getReader()</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (!reader) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > onError('No response body')</span>
|
||||
<span class="cstat-no" title="statement not covered" > return</span>
|
||||
}
|
||||
|
||||
<span class="cstat-no" title="statement not covered" > await readSseStream(reader, onChunk)</span>
|
||||
<span class="cstat-no" title="statement not covered" > onDone()</span>
|
||||
} catch (err: any) {
|
||||
<span class="cstat-no" title="statement not covered" > onError(err.message || 'Network error')</span>
|
||||
}
|
||||
}
|
||||
|
||||
// --- Model options ---
|
||||
export const MODEL_OPTIONS = [
|
||||
{ value: 'claude-3-5-haiku-20241022', label: 'Haiku 3.5' },
|
||||
{ value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' },
|
||||
{ value: 'claude-opus-4-20250514', label: 'Opus 4' },
|
||||
] as const
|
||||
</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-22T09:10:55.587Z
|
||||
</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>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">88.37% </span>
|
||||
<span class="strong">93.33% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>38/43</span>
|
||||
<span class='fraction'>42/45</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">81.08% </span>
|
||||
<span class="strong">90.9% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>30/37</span>
|
||||
<span class='fraction'>30/33</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>2/2</span>
|
||||
<span class='fraction'>7/7</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">90% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>36/40</span>
|
||||
<span class='fraction'>35/35</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -131,81 +131,73 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<a name='L69'></a><a href='#L69'>69</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">207x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">26x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">54x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">146x</span>
|
||||
<span class="cline-any cline-yes">146x</span>
|
||||
<span class="cline-any cline-yes">28x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">54x</span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">117x</span>
|
||||
<span class="cline-any cline-yes">117x</span>
|
||||
<span class="cline-any cline-yes">117x</span>
|
||||
<span class="cline-any cline-yes">117x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">41x</span>
|
||||
<span class="cline-any cline-yes">28x</span>
|
||||
<span class="cline-any cline-yes">28x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-yes">207x</span>
|
||||
<span class="cline-any cline-yes">207x</span>
|
||||
<span class="cline-any cline-yes">36x</span>
|
||||
<span class="cline-any cline-yes">36x</span>
|
||||
<span class="cline-any cline-yes">36x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-yes">18x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">118x</span>
|
||||
<span class="cline-any cline-yes">28x</span>
|
||||
<span class="cline-any cline-yes">171x</span>
|
||||
<span class="cline-any cline-yes">135x</span>
|
||||
<span class="cline-any cline-yes">117x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">90x</span>
|
||||
<span class="cline-any cline-yes">42x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">76x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">76x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">76x</span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">76x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">14x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import type { FrontmatterValue } from '../components/Inspector'
|
||||
|
||||
@@ -213,70 +205,66 @@ export interface ParsedFrontmatter {
|
||||
[key: string]: FrontmatterValue
|
||||
}
|
||||
|
||||
function unquote(s: string): string {
|
||||
return s.replace(/^["']|["']$/g, '')
|
||||
}
|
||||
|
||||
function collapseList(items: string[]): FrontmatterValue {
|
||||
return items.length === 1 ? items[0] : items
|
||||
}
|
||||
|
||||
function isBlockScalar(value: string): boolean {
|
||||
return value === '' || value === '|' || value === '>'
|
||||
}
|
||||
|
||||
function parseInlineArray(value: string): FrontmatterValue {
|
||||
const items = value.slice(1, -1).split(',').map(s => unquote(s.trim()))
|
||||
return collapseList(items)
|
||||
}
|
||||
|
||||
function parseScalar(value: string): FrontmatterValue {
|
||||
const clean = unquote(value)
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (clean.toLowerCase() === 'true') <span class="cstat-no" title="statement not covered" >return true</span>
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (clean.toLowerCase() === 'false') <span class="cstat-no" title="statement not covered" >return false</span>
|
||||
return clean
|
||||
}
|
||||
|
||||
/** Parse YAML frontmatter from content */
|
||||
export function parseFrontmatter(content: string | null): ParsedFrontmatter {
|
||||
if (!content) return {}
|
||||
|
||||
const match = content.match(/^---\n([\s\S]*?)\n---/)
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!match) <span class="cstat-no" title="statement not covered" >return {}</span>
|
||||
if (!match) return {}
|
||||
|
||||
const yaml = match[1]
|
||||
const result: ParsedFrontmatter = {}
|
||||
|
||||
let currentKey: string | null = null
|
||||
let currentList: string[] = []
|
||||
let inList = false
|
||||
|
||||
const lines = yaml.split('\n')
|
||||
|
||||
for (const line of lines) {
|
||||
const listMatch = line.match(/^ - (.*)$/)
|
||||
for (const line of match[1].split('\n')) {
|
||||
const listMatch = line.match(/^ {2}- (.*)$/)
|
||||
if (listMatch && currentKey) {
|
||||
inList = true
|
||||
currentList.push(listMatch[1].replace(/^["']|["']$/g, ''))
|
||||
currentList.push(unquote(listMatch[1]))
|
||||
continue
|
||||
}
|
||||
|
||||
if (inList && currentKey) {
|
||||
result[currentKey] = currentList.length === 1 ? currentList[0] : <span class="branch-1 cbranch-no" title="branch not covered" >currentList</span>
|
||||
result[currentKey] = collapseList(currentList)
|
||||
currentList = []
|
||||
inList = false
|
||||
}
|
||||
|
||||
const kvMatch = line.match(/^["']?([^"':]+)["']?\s*:\s*(.*)$/)
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (kvMatch) {
|
||||
currentKey = kvMatch[1].trim()
|
||||
const value = kvMatch[2].trim()
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!kvMatch) <span class="cstat-no" title="statement not covered" >continue</span>
|
||||
currentKey = kvMatch[1].trim()
|
||||
const value = kvMatch[2].trim()
|
||||
|
||||
if (value === '' || value === '|' || value === '>') {
|
||||
continue
|
||||
}
|
||||
|
||||
if (value.startsWith('[') && value.endsWith(']')) {
|
||||
const items = value.slice(1, -1).split(',').map(s => s.trim().replace(/^["']|["']$/g, ''))
|
||||
result[currentKey] = items.length === 1 ? <span class="branch-0 cbranch-no" title="branch not covered" >items[0] : i</span>tems
|
||||
continue
|
||||
}
|
||||
|
||||
const unquoted = value.replace(/^["']|["']$/g, '')
|
||||
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (unquoted.toLowerCase() === 'true') {
|
||||
<span class="cstat-no" title="statement not covered" > result[currentKey] = true</span>
|
||||
<span class="cstat-no" title="statement not covered" > continue</span>
|
||||
}
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (unquoted.toLowerCase() === 'false') {
|
||||
<span class="cstat-no" title="statement not covered" > result[currentKey] = false</span>
|
||||
<span class="cstat-no" title="statement not covered" > continue</span>
|
||||
}
|
||||
|
||||
result[currentKey] = unquoted
|
||||
}
|
||||
}
|
||||
|
||||
if (inList && currentKey) {
|
||||
result[currentKey] = currentList.length === 1 ? currentList[0] : <span class="branch-1 cbranch-no" title="branch not covered" >currentList</span>
|
||||
if (isBlockScalar(value)) continue
|
||||
if (value.startsWith('[') && value.endsWith(']')) { result[currentKey] = parseInlineArray(value); continue }
|
||||
result[currentKey] = parseScalar(value)
|
||||
}
|
||||
|
||||
if (inList && currentKey) result[currentKey] = collapseList(currentList)
|
||||
return result
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
@@ -286,7 +274,7 @@ export function parseFrontmatter(content: string | null): ParsedFrontmatter {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">46.85% </span>
|
||||
<span class="strong">91.69% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>82/175</span>
|
||||
<span class='fraction'>320/349</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">45.37% </span>
|
||||
<span class="strong">85.93% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>54/119</span>
|
||||
<span class='fraction'>226/263</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">52.17% </span>
|
||||
<span class="strong">96.51% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>12/23</span>
|
||||
<span class='fraction'>83/86</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">49.37% </span>
|
||||
<span class="strong">92.6% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>79/160</span>
|
||||
<span class='fraction'>263/284</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line low'></div>
|
||||
<div class='status-line high'></div>
|
||||
<div class="pad1">
|
||||
<table class="coverage-summary">
|
||||
<thead>
|
||||
@@ -79,44 +79,89 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td class="file low" data-value="ai-chat.ts"><a href="ai-chat.ts.html">ai-chat.ts</a></td>
|
||||
<td data-value="5.26" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 5%"></div><div class="cover-empty" style="width: 95%"></div></div>
|
||||
<td class="file high" data-value="frontmatter.ts"><a href="frontmatter.ts.html">frontmatter.ts</a></td>
|
||||
<td data-value="93.33" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 93%"></div><div class="cover-empty" style="width: 7%"></div></div>
|
||||
</td>
|
||||
<td data-value="5.26" class="pct low">5.26%</td>
|
||||
<td data-value="76" class="abs low">4/76</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="43" class="abs low">0/43</td>
|
||||
<td data-value="0" class="pct low">0%</td>
|
||||
<td data-value="10" class="abs low">0/10</td>
|
||||
<td data-value="5.63" class="pct low">5.63%</td>
|
||||
<td data-value="71" class="abs low">4/71</td>
|
||||
<td data-value="93.33" class="pct high">93.33%</td>
|
||||
<td data-value="45" class="abs high">42/45</td>
|
||||
<td data-value="90.9" class="pct high">90.9%</td>
|
||||
<td data-value="33" class="abs high">30/33</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="7" class="abs high">7/7</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="35" class="abs high">35/35</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="frontmatter.ts"><a href="frontmatter.ts.html">frontmatter.ts</a></td>
|
||||
<td data-value="88.37" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 88%"></div><div class="cover-empty" style="width: 12%"></div></div>
|
||||
<td class="file high" data-value="fuzzyMatch.ts"><a href="fuzzyMatch.ts.html">fuzzyMatch.ts</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="88.37" class="pct high">88.37%</td>
|
||||
<td data-value="43" class="abs high">38/43</td>
|
||||
<td data-value="81.08" class="pct high">81.08%</td>
|
||||
<td data-value="37" class="abs high">30/37</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="16" class="abs high">16/16</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="11" class="abs high">11/11</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="13" class="abs high">13/13</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="iconRegistry.ts"><a href="iconRegistry.ts.html">iconRegistry.ts</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="4" class="abs high">4/4</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="2" class="abs high">2/2</td>
|
||||
<td data-value="90" class="pct high">90%</td>
|
||||
<td data-value="40" class="abs high">36/40</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="4" class="abs high">4/4</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="noteListHelpers.ts"><a href="noteListHelpers.ts.html">noteListHelpers.ts</a></td>
|
||||
<td data-value="86.23" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 86%"></div><div class="cover-empty" style="width: 14%"></div></div>
|
||||
</td>
|
||||
<td data-value="86.23" class="pct high">86.23%</td>
|
||||
<td data-value="138" class="abs high">119/138</td>
|
||||
<td data-value="77.87" class="pct medium">77.87%</td>
|
||||
<td data-value="113" class="abs medium">88/113</td>
|
||||
<td data-value="95.12" class="pct high">95.12%</td>
|
||||
<td data-value="41" class="abs high">39/41</td>
|
||||
<td data-value="86.79" class="pct high">86.79%</td>
|
||||
<td data-value="106" class="abs high">92/106</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="personMentionSuggestions.ts"><a href="personMentionSuggestions.ts.html">personMentionSuggestions.ts</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="6" class="abs high">6/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="2" class="abs high">2/2</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="typeColors.ts"><a href="typeColors.ts.html">typeColors.ts</a></td>
|
||||
<td data-value="86.66" class="pic high">
|
||||
<div class="chart"><div class="cover-fill" style="width: 86%"></div><div class="cover-empty" style="width: 14%"></div></div>
|
||||
<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="86.66" class="pct high">86.66%</td>
|
||||
<td data-value="15" class="abs high">13/15</td>
|
||||
<td data-value="71.42" class="pct medium">71.42%</td>
|
||||
<td data-value="14" class="abs medium">10/14</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="15" class="abs high">15/15</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="14" class="abs high">14/14</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>
|
||||
@@ -124,18 +169,93 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file medium" data-value="wikilinks.ts"><a href="wikilinks.ts.html">wikilinks.ts</a></td>
|
||||
<td data-value="65.85" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 65%"></div><div class="cover-empty" style="width: 35%"></div></div>
|
||||
<td class="file medium" data-value="url.ts"><a href="url.ts.html">url.ts</a></td>
|
||||
<td data-value="66.66" class="pic medium">
|
||||
<div class="chart"><div class="cover-fill" style="width: 66%"></div><div class="cover-empty" style="width: 34%"></div></div>
|
||||
</td>
|
||||
<td data-value="65.85" class="pct medium">65.85%</td>
|
||||
<td data-value="41" class="abs medium">27/41</td>
|
||||
<td data-value="56" class="pct medium">56%</td>
|
||||
<td data-value="25" class="abs medium">14/25</td>
|
||||
<td data-value="85.71" class="pct high">85.71%</td>
|
||||
<td data-value="7" class="abs high">6/7</td>
|
||||
<td data-value="72.22" class="pct medium">72.22%</td>
|
||||
<td data-value="36" class="abs medium">26/36</td>
|
||||
<td data-value="66.66" class="pct medium">66.66%</td>
|
||||
<td data-value="12" class="abs medium">8/12</td>
|
||||
<td data-value="75" class="pct medium">75%</td>
|
||||
<td data-value="8" class="abs medium">6/8</td>
|
||||
<td data-value="66.66" class="pct medium">66.66%</td>
|
||||
<td data-value="3" class="abs medium">2/3</td>
|
||||
<td data-value="60" class="pct medium">60%</td>
|
||||
<td data-value="10" class="abs medium">6/10</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file low" data-value="vault-dialog.ts"><a href="vault-dialog.ts.html">vault-dialog.ts</a></td>
|
||||
<td data-value="40" class="pic low">
|
||||
<div class="chart"><div class="cover-fill" style="width: 40%"></div><div class="cover-empty" style="width: 60%"></div></div>
|
||||
</td>
|
||||
<td data-value="40" class="pct low">40%</td>
|
||||
<td data-value="5" class="abs low">2/5</td>
|
||||
<td data-value="50" class="pct medium">50%</td>
|
||||
<td data-value="6" class="abs medium">3/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="1" class="abs high">1/1</td>
|
||||
<td data-value="40" class="pct low">40%</td>
|
||||
<td data-value="5" class="abs low">2/5</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="wikilink.ts"><a href="wikilink.ts.html">wikilink.ts</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="10" class="abs high">10/10</td>
|
||||
<td data-value="83.33" class="pct high">83.33%</td>
|
||||
<td data-value="6" class="abs high">5/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="3" class="abs high">3/3</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="8" class="abs high">8/8</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="wikilinkColors.ts"><a href="wikilinkColors.ts.html">wikilinkColors.ts</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="15" class="abs high">15/15</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="13" class="abs high">13/13</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="5" class="abs high">5/5</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="11" class="abs high">11/11</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="wikilinkSuggestions.ts"><a href="wikilinkSuggestions.ts.html">wikilinkSuggestions.ts</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="22" class="abs high">22/22</td>
|
||||
<td data-value="86.66" class="pct high">86.66%</td>
|
||||
<td data-value="15" class="abs high">13/15</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="6" class="abs high">6/6</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="19" class="abs high">19/19</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="file high" data-value="wikilinks.ts"><a href="wikilinks.ts.html">wikilinks.ts</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="61" class="abs high">61/61</td>
|
||||
<td data-value="97.22" class="pct high">97.22%</td>
|
||||
<td data-value="36" class="abs high">35/36</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="11" class="abs high">11/11</td>
|
||||
<td data-value="100" class="pct high">100%</td>
|
||||
<td data-value="55" class="abs high">55/55</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
@@ -146,7 +266,7 @@
|
||||
<div class='footer quiet pad2 space-top1 center small'>
|
||||
Code coverage generated by
|
||||
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
||||
at 2026-02-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">86.66% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>13/15</span>
|
||||
<span class='fraction'>15/15</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">71.42% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>10/14</span>
|
||||
<span class='fraction'>14/14</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -121,12 +121,14 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -137,7 +139,7 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -148,11 +150,11 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
@@ -161,23 +163,25 @@
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">13x</span>
|
||||
<span class="cline-any cline-yes">104x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">832x</span>
|
||||
<span class="cline-any cline-yes">832x</span>
|
||||
<span class="cline-any cline-yes">13224x</span>
|
||||
<span class="cline-any cline-yes">13206x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">758x</span>
|
||||
<span class="cline-any cline-yes">758x</span>
|
||||
<span class="cline-any cline-yes">12965x</span>
|
||||
<span class="cline-any cline-yes">12962x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">/**
|
||||
* Maps note types to their accent color CSS variables.
|
||||
@@ -206,8 +210,8 @@ const TYPE_LIGHT_COLOR_MAP: Record<string, string> = {
|
||||
Type: 'var(--accent-blue-light)',
|
||||
}
|
||||
|
||||
const DEFAULT_COLOR = 'var(--accent-blue)'
|
||||
const DEFAULT_LIGHT_COLOR = 'var(--accent-blue-light)'
|
||||
const DEFAULT_COLOR = 'var(--muted-foreground)'
|
||||
const DEFAULT_LIGHT_COLOR = 'var(--muted)'
|
||||
|
||||
/** Color key → CSS variable mapping for the design system accent palette */
|
||||
export const ACCENT_COLORS: { key: string; label: string; css: string; cssLight: string }[] = [
|
||||
@@ -217,6 +221,8 @@ export const ACCENT_COLORS: { key: string; label: string; css: string; cssLight:
|
||||
{ key: 'green', label: 'Green', css: 'var(--accent-green)', cssLight: 'var(--accent-green-light)' },
|
||||
{ key: 'blue', label: 'Blue', css: 'var(--accent-blue)', cssLight: 'var(--accent-blue-light)' },
|
||||
{ key: 'purple', label: 'Purple', css: 'var(--accent-purple)', cssLight: 'var(--accent-purple-light)' },
|
||||
{ key: 'teal', label: 'Teal', css: 'var(--accent-teal)', cssLight: 'var(--accent-teal-light)' },
|
||||
{ key: 'pink', label: 'Pink', css: 'var(--accent-pink)', cssLight: 'var(--accent-pink-light)' },
|
||||
]
|
||||
|
||||
const COLOR_KEY_TO_CSS: Record<string, string> = Object.fromEntries(
|
||||
@@ -228,13 +234,13 @@ const COLOR_KEY_TO_CSS_LIGHT: Record<string, string> = Object.fromEntries(
|
||||
|
||||
/** Returns the CSS variable for the accent color of a given note type, with optional custom override */
|
||||
export function getTypeColor(isA: string | null, customColorKey?: string | null): string {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (customColorKey && <span class="branch-1 cbranch-no" title="branch not covered" >COLOR_KEY_TO_CSS[customColorKey]) <span class="cstat-no" title="statement not covered" >r</span>eturn COLOR_KEY_TO_CSS[customColorKey]</span>
|
||||
if (customColorKey && COLOR_KEY_TO_CSS[customColorKey]) return COLOR_KEY_TO_CSS[customColorKey]
|
||||
return (isA && TYPE_COLOR_MAP[isA]) ?? DEFAULT_COLOR
|
||||
}
|
||||
|
||||
/** Returns the CSS variable for the light/background variant of a given note type's color */
|
||||
export function getTypeLightColor(isA: string | null, customColorKey?: string | null): string {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (customColorKey && <span class="branch-1 cbranch-no" title="branch not covered" >COLOR_KEY_TO_CSS_LIGHT[customColorKey]) <span class="cstat-no" title="statement not covered" >r</span>eturn COLOR_KEY_TO_CSS_LIGHT[customColorKey]</span>
|
||||
if (customColorKey && COLOR_KEY_TO_CSS_LIGHT[customColorKey]) return COLOR_KEY_TO_CSS_LIGHT[customColorKey]
|
||||
return (isA && TYPE_LIGHT_COLOR_MAP[isA]) ?? DEFAULT_LIGHT_COLOR
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
@@ -244,7 +250,7 @@ export function getTypeLightColor(isA: string | null, customColorKey?: string |
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
@@ -23,30 +23,30 @@
|
||||
<div class='clearfix'>
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">65.85% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Statements</span>
|
||||
<span class='fraction'>27/41</span>
|
||||
<span class='fraction'>61/61</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">56% </span>
|
||||
<span class="strong">97.22% </span>
|
||||
<span class="quiet">Branches</span>
|
||||
<span class='fraction'>14/25</span>
|
||||
<span class='fraction'>35/36</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">85.71% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Functions</span>
|
||||
<span class='fraction'>6/7</span>
|
||||
<span class='fraction'>11/11</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class='fl pad1y space-right2'>
|
||||
<span class="strong">72.22% </span>
|
||||
<span class="strong">100% </span>
|
||||
<span class="quiet">Lines</span>
|
||||
<span class='fraction'>26/36</span>
|
||||
<span class='fraction'>55/55</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class='status-line medium'></div>
|
||||
<div class='status-line high'></div>
|
||||
<pre><table class="coverage">
|
||||
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
||||
<a name='L2'></a><a href='#L2'>2</a>
|
||||
@@ -131,74 +131,198 @@
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">27x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">39x</span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">15x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">17x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">30x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-yes">2x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">3x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-yes">9x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-yes">12x</span>
|
||||
<span class="cline-any cline-yes">5x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">7x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">6x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-no"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">1x</span>
|
||||
<span class="cline-any cline-yes">154x</span>
|
||||
<span class="cline-any cline-yes">92x</span>
|
||||
<span class="cline-any cline-yes">92x</span>
|
||||
<span class="cline-any cline-yes">88x</span>
|
||||
<span class="cline-any cline-yes">88x</span>
|
||||
<span class="cline-any cline-yes">88x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-yes">16x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-yes">10x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">8x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-yes">127x</span>
|
||||
<span class="cline-any cline-yes">127x</span>
|
||||
<span class="cline-any cline-yes">127x</span>
|
||||
<span class="cline-any cline-yes">127x</span>
|
||||
<span class="cline-any cline-yes">127x</span>
|
||||
<span class="cline-any cline-yes">57x</span>
|
||||
<span class="cline-any cline-neutral"> </span>
|
||||
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">// Wikilink placeholder tokens for markdown round-trip
|
||||
const WL_START = '\u2039WIKILINK:'
|
||||
const WL_END = '\u203A'
|
||||
@@ -206,46 +330,90 @@ const WL_RE = new RegExp(`${WL_START.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}
|
||||
|
||||
/** Pre-process markdown: replace [[target]] with placeholder tokens */
|
||||
export function preProcessWikilinks(md: string): string {
|
||||
return md.replace(/\[\[([^\]]+)\]\]/g, <span class="fstat-no" title="function not covered" >(_</span>m, target) => <span class="cstat-no" title="statement not covered" >`${WL_START}${target}${WL_END}`)</span>
|
||||
return md.replace(/\[\[([^\]]+)\]\]/g, (_m, target) => `${WL_START}${target}${WL_END}`)
|
||||
}
|
||||
|
||||
/** Walk blocks and replace placeholder text with wikilink inline content */
|
||||
export function injectWikilinks(blocks: any[]): any[] {
|
||||
return blocks.map(block => {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (block.content && Array.isArray(block.content)) {
|
||||
block.content = expandWikilinksInContent(block.content)
|
||||
// Minimal shape of a BlockNote block for wikilink processing
|
||||
interface BlockLike {
|
||||
content?: InlineItem[]
|
||||
children?: BlockLike[]
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
interface InlineItem {
|
||||
type: string
|
||||
text?: string
|
||||
props?: Record<string, string>
|
||||
content?: unknown
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
type ContentTransform = (content: InlineItem[]) => InlineItem[]
|
||||
|
||||
/** Walk blocks recursively, applying a transform to each block's inline content */
|
||||
function walkBlocks(blocks: unknown[], transform: ContentTransform, clone = false): unknown[] {
|
||||
return (blocks as BlockLike[]).map(block => {
|
||||
const b = clone ? { ...block } : block
|
||||
if (b.content && Array.isArray(b.content)) {
|
||||
b.content = transform(b.content)
|
||||
}
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (block.children && Array.isArray(block.children)) {
|
||||
block.children = injectWikilinks(block.children)
|
||||
if (b.children && Array.isArray(b.children)) {
|
||||
b.children = walkBlocks(b.children, transform, clone) as BlockLike[]
|
||||
}
|
||||
return block
|
||||
return b
|
||||
})
|
||||
}
|
||||
|
||||
function expandWikilinksInContent(content: any[]): any[] {
|
||||
const result: any[] = []
|
||||
/** Walk blocks and replace placeholder text with wikilink inline content */
|
||||
export function injectWikilinks(blocks: unknown[]): unknown[] {
|
||||
return walkBlocks(blocks, expandWikilinksInContent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-clone blocks and convert wikilink inline content back to [[target]] text.
|
||||
* This is the reverse of injectWikilinks — used before blocksToMarkdownLossy
|
||||
* so that wikilinks survive the markdown round-trip.
|
||||
*/
|
||||
export function restoreWikilinksInBlocks(blocks: unknown[]): unknown[] {
|
||||
return walkBlocks(blocks, collapseWikilinksInContent, true)
|
||||
}
|
||||
|
||||
function expandWikilinksInContent(content: InlineItem[]): InlineItem[] {
|
||||
const result: InlineItem[] = []
|
||||
for (const item of content) {
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (item.type !== 'text' || typeof item.text !== 'string' || !item.text.includes(WL_START)) {
|
||||
if (item.type !== 'text' || typeof item.text !== 'string' || !item.text.includes(WL_START)) {
|
||||
result.push(item)
|
||||
continue
|
||||
}
|
||||
const text = <span class="cstat-no" title="statement not covered" >item.text as string</span>
|
||||
let lastIndex = <span class="cstat-no" title="statement not covered" >0</span>
|
||||
<span class="cstat-no" title="statement not covered" > WL_RE.lastIndex = 0</span>
|
||||
const text = item.text as string
|
||||
let lastIndex = 0
|
||||
WL_RE.lastIndex = 0
|
||||
let match
|
||||
<span class="cstat-no" title="statement not covered" > while ((match = WL_RE.exec(text)) !== null) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > if (match.index > lastIndex) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > result.push({ ...item, text: text.slice(lastIndex, match.index) })</span>
|
||||
while ((match = WL_RE.exec(text)) !== null) {
|
||||
if (match.index > lastIndex) {
|
||||
result.push({ ...item, text: text.slice(lastIndex, match.index) })
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > result.push({</span>
|
||||
result.push({
|
||||
type: 'wikilink',
|
||||
props: { target: match[1] },
|
||||
content: undefined,
|
||||
})
|
||||
<span class="cstat-no" title="statement not covered" > lastIndex = match.index + match[0].length</span>
|
||||
lastIndex = match.index + match[0].length
|
||||
}
|
||||
<span class="cstat-no" title="statement not covered" > if (lastIndex < text.length) {</span>
|
||||
<span class="cstat-no" title="statement not covered" > result.push({ ...item, text: text.slice(lastIndex) })</span>
|
||||
if (lastIndex < text.length) {
|
||||
result.push({ ...item, text: text.slice(lastIndex) })
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function collapseWikilinksInContent(content: InlineItem[]): InlineItem[] {
|
||||
const result: InlineItem[] = []
|
||||
for (const item of content) {
|
||||
if (item.type === 'wikilink' && item.props?.target) {
|
||||
result.push({ type: 'text', text: `[[${item.props.target}]]` })
|
||||
} else {
|
||||
result.push(item)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -253,18 +421,36 @@ function expandWikilinksInContent(content: any[]): any[] {
|
||||
|
||||
/** Strip YAML frontmatter from markdown, returning [frontmatter, body] */
|
||||
export function splitFrontmatter(content: string): [string, string] {
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!content.startsWith('---')) <span class="cstat-no" title="statement not covered" >return ['', content]</span>
|
||||
if (!content.startsWith('---')) return ['', content]
|
||||
const end = content.indexOf('\n---', 3)
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (end === -1) <span class="cstat-no" title="statement not covered" >return ['', content]</span>
|
||||
if (end === -1) return ['', content]
|
||||
let to = end + 4
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (content[to] === '\n') to++
|
||||
if (content[to] === '\n') to++
|
||||
return [content.slice(0, to), content.slice(to)]
|
||||
}
|
||||
|
||||
/** Extract all outgoing wikilink targets from content.
|
||||
* Finds [[target]] and [[target|display]] patterns, returning just the target part.
|
||||
* Returns a sorted, deduplicated array. */
|
||||
export function extractOutgoingLinks(content: string): string[] {
|
||||
const links: string[] = []
|
||||
const re = /\[\[([^\]]+)\]\]/g
|
||||
let match
|
||||
while ((match = re.exec(content)) !== null) {
|
||||
const inner = match[1]
|
||||
const pipeIdx = inner.indexOf('|')
|
||||
const target = pipeIdx !== -1 ? inner.slice(0, pipeIdx) : inner
|
||||
<span class="missing-if-branch" title="else path not taken" >E</span>if (target) links.push(target)
|
||||
}
|
||||
return [...new Set(links)].sort()
|
||||
}
|
||||
|
||||
export function countWords(content: string): number {
|
||||
const [, body] = splitFrontmatter(content)
|
||||
const text = body.replace(/[#*_\[\]`>~\-|]/g, '').trim()
|
||||
<span class="missing-if-branch" title="if path not taken" >I</span>if (!text) <span class="cstat-no" title="statement not covered" >return 0</span>
|
||||
const withoutTitle = body.replace(/^\s*# [^\n]+\n?/, '')
|
||||
const withoutWikilinks = withoutTitle.replace(/\[\[[^\]]*\]\]/g, '')
|
||||
const text = withoutWikilinks.replace(/[#*_[\]`>~\-|]/g, '').trim()
|
||||
if (!text) return 0
|
||||
return text.split(/\s+/).filter(Boolean).length
|
||||
}
|
||||
</pre></td></tr></table></pre>
|
||||
@@ -274,7 +460,7 @@ export function countWords(content: string): number {
|
||||
<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-22T09:10:55.587Z
|
||||
at 2026-02-25T20:19:25.575Z
|
||||
</div>
|
||||
<script src="../../prettify.js"></script>
|
||||
<script>
|
||||
|
||||
Reference in New Issue
Block a user