144 Commits

Author SHA1 Message Date
ImgBotApp
27bec76f21 [ImgBot] Optimize images
*Total -- 1,311.48kb -> 883.47kb (32.64%)

/docs/public/pwa_icon.png -- 204.78kb -> 69.50kb (66.06%)
/docs/public/xmasfmhy.png -- 574.27kb -> 382.15kb (33.45%)
/docs/public/uwu-hall.png -- 333.61kb -> 246.77kb (26.03%)
/docs/public/note.svg -- 0.52kb -> 0.41kb (20.6%)
/docs/public/hall.png -- 80.83kb -> 69.02kb (14.61%)
/docs/public/test.png -- 71.45kb -> 69.59kb (2.6%)
/docs/public/logo-uwu.svg -- 46.03kb -> 46.03kb (0%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2026-01-22 08:07:36 +00:00
nbats
7af5eb1e25 Revert "[ImgBot] Optimize images (#4618)" (#4621)
This reverts commit c792150402.
2026-01-22 00:03:44 -08:00
imgbot[bot]
c792150402 [ImgBot] Optimize images (#4618)
*Total -- 1,311.48kb -> 883.47kb (32.64%)

/docs/public/pwa_icon.png -- 204.78kb -> 69.50kb (66.06%)
/docs/public/xmasfmhy.png -- 574.27kb -> 382.15kb (33.45%)
/docs/public/uwu-hall.png -- 333.61kb -> 246.77kb (26.03%)
/docs/public/note.svg -- 0.52kb -> 0.41kb (20.6%)
/docs/public/hall.png -- 80.83kb -> 69.02kb (14.61%)
/docs/public/test.png -- 71.45kb -> 69.59kb (2.6%)
/docs/public/logo-uwu.svg -- 46.03kb -> 46.03kb (0%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2026-01-21 23:58:28 -08:00
nbats
bb984b1329 updated 11 pages 2026-01-21 23:54:12 -08:00
bread
e7af12a753 Change Tooltip Icon (#4617)
* fix: note in search preview

* tooltip icon change
2026-01-21 19:44:48 -08:00
nbats
535951fe12 updated 9 pages 2026-01-21 19:24:38 -08:00
Krolul
640c36d2ca Update beginners-guide.md (#4615) 2026-01-21 18:50:32 -08:00
nbats
180d36b70b deleted notes we don't use anymore 2026-01-21 18:46:46 -08:00
bread
0936b896af fix: note in search preview (#4616) 2026-01-21 18:28:46 -08:00
nbats
cdc50f7a8a fixed notes 2026-01-21 18:23:13 -08:00
bread
8936cc3545 tooltips (#4611)
* tooltips

* feat: Add numerous new notes, refactor the tooltip component, and update dependencies.

* notes

* fix: tooltip
2026-01-21 17:27:26 -08:00
nbats
421c9a1cab added 2 sites 2026-01-21 17:21:31 -08:00
nbats
dd405caf2f updated 8 pages 2026-01-21 17:19:21 -08:00
nbats
9b8043d948 removed site 2026-01-21 07:51:15 -08:00
nbats
00c405f2fb small update 2026-01-21 06:51:44 -08:00
nbats
570c7f1780 small update 2026-01-21 04:33:34 -08:00
nbats
ea1c0f7937 small fix 2026-01-21 04:00:36 -08:00
KHROTU
f6152be439 update link (#4609)
replace old grok rate limit with https://greasyfork.org/en/scripts/533963-grok-rate-limit-display, my version has stopped working and the original creator is now continuing to update the script
2026-01-21 03:57:20 -08:00
Abdullah Abid Ansari
6149cdc420 Update system-tools.md (#4602) 2026-01-21 03:51:00 -08:00
nbats
e5b9ccda88 updated 17 pages 2026-01-21 03:46:25 -08:00
nbats
392b1d9ece removed site 2026-01-20 05:23:00 -08:00
nbats
6615104763 updated 2 pages 2026-01-20 05:00:40 -08:00
nbats
148ace38bb Delete docs/posts/Interconnectedness.md 2026-01-20 04:35:25 -08:00
nbats
48a62e2e37 Delete docs/posts/WWCO.md 2026-01-20 04:34:25 -08:00
nbats
3b3b3fef19 Delete docs/posts/ywt.md 2026-01-20 04:33:35 -08:00
nbats
e512816041 Delete docs/posts/jsygk.md 2026-01-20 04:23:22 -08:00
nbats
f186a67049 Delete docs/posts/filecr-malware.md 2026-01-20 04:23:02 -08:00
nbats
b574771638 small fix 2026-01-20 00:42:07 -08:00
nbats
4cb3a3a12e updated 16 pages 2026-01-19 20:08:07 -08:00
nbats
f3f0e01887 Update ywt.md 2026-01-19 14:27:19 -08:00
nbats
382a56168d Update Interconnectedness.md 2026-01-19 14:27:14 -08:00
nbats
88bf229cd3 Create ywt.md 2026-01-19 14:18:16 -08:00
nbats
8824ca15d3 Create Interconnectedness.md 2026-01-19 14:15:35 -08:00
nbats
8d4fe256ce Create jsygk.md 2026-01-19 14:10:49 -08:00
nbats
97c9dd3730 small update 2026-01-18 23:36:24 -08:00
nbats
3980357204 removed site 2026-01-18 19:29:12 -08:00
nbats
c1d4257ac3 small update 2026-01-18 19:28:17 -08:00
nbats
cfeb18d2a0 added updated site 2026-01-18 18:16:49 -08:00
nbats
2f1d364b70 small update 2026-01-18 17:51:12 -08:00
nbats
b4454a496d updated 5 pages 2026-01-18 14:58:50 -08:00
nbats
393b64d481 small update 2026-01-18 11:02:27 -08:00
nbats
a0ffbc890d small update 2026-01-18 10:30:11 -08:00
nbats
4d162271cf small update 2026-01-18 09:59:03 -08:00
Michael
a0216c0381 Update linux-macos.md (#4597)
Updated descriptions and links for various Mac apps and tools, improving clarity and consistency.

Co-authored-by: nbats <44333466+nbats@users.noreply.github.com>
2026-01-18 09:09:21 -08:00
nbats
4ee816b497 updated 20 pages 2026-01-18 08:52:32 -08:00
nbats
887dcdc9c0 small update 2026-01-17 11:23:35 -08:00
nbats
fd171130a9 updated 14 pages 2026-01-17 07:59:46 -08:00
nbats
6e7a285a46 small update 2026-01-16 11:57:09 -08:00
nbats
b053290951 removed site 2026-01-16 10:25:16 -08:00
nbats
04d4449346 removed site 2026-01-16 07:47:49 -08:00
nbats
91775cc1dd updated 3 pages 2026-01-16 07:32:23 -08:00
nbats
ffb5eabd2d small update 2026-01-16 00:35:07 -08:00
nbats
bec133394e updated 16 pages 2026-01-15 22:10:10 -08:00
nbats
bf54290287 small fixes 2026-01-15 16:41:44 -08:00
nbats
33162eca11 small update 2026-01-15 00:25:40 -08:00
nbats
0096e2fbde updated 3 pages 2026-01-15 00:20:27 -08:00
nbats
ac1422c52f small update 2026-01-14 22:43:17 -08:00
nbats
9308764802 added subreddit 2026-01-14 22:28:30 -08:00
nbats
31bd66e455 updated 6 pages 2026-01-14 22:26:45 -08:00
nbats
aa95a444c5 small update 2026-01-14 16:08:52 -08:00
nbats
c0f71dfae8 updated 7 pages 2026-01-14 15:09:26 -08:00
nbats
30b4ba4ffa small fix 2026-01-14 05:20:37 -08:00
nbats
35ffe199d2 small fix 2026-01-14 05:07:27 -08:00
nbats
5091acc1f3 added site 2026-01-14 04:42:10 -08:00
nbats
4861b4bdb9 updated 15 pages 2026-01-14 04:19:04 -08:00
zero
32b11ba3c0 Update gaming-tools.md (#4584)
on line 873, changed SC to SA to better san andreas >~<
2026-01-13 07:53:08 -08:00
nbats
e099fab018 removed site 2026-01-13 07:52:17 -08:00
nbats
da772d5491 small update 2026-01-13 07:41:49 -08:00
nbats
c21b1a1686 added github 2026-01-13 07:20:51 -08:00
nbats
4746986df0 updated 11 pages 2026-01-13 07:02:13 -08:00
nbats
10014801ca small fix 2026-01-12 10:01:11 -08:00
nbats
fc9cab8d7e small update 2026-01-12 09:56:12 -08:00
nbats
03377cd68e small fix 2026-01-12 08:18:06 -08:00
nbats
eccf8472b1 updated 13 pages 2026-01-12 07:47:40 -08:00
Caleb Fissore
7e2b4c3ba5 Update educational.md (#4579)
changed scratch to a hyperlink
2026-01-11 20:45:00 -08:00
nbats
3551faed9d small fix 2026-01-11 20:00:52 -08:00
nbats
0757624cb2 updated 10 pages 2026-01-11 19:59:42 -08:00
nbats
617663d9dd updated 14 pages 2026-01-11 08:35:59 -08:00
nbats
4ec2ecb22e updated 3 pages 2026-01-10 01:37:07 -08:00
nbats
50b013d356 updated 5 pages 2026-01-09 21:30:06 -08:00
nbats
04b1829c7a small update 2026-01-09 15:33:25 -08:00
shtts
5e08bbe913 move Jujutsu from Git Hosting Services to Version Control Systems (#4569)
* remove Jujutsu from Git Hosting Services
because it is not a Git Hosting Service, it is a a version control
system.

* add Jujutsu in version control systems
2026-01-09 14:32:21 -08:00
nbats
8bb9a04331 updated 15 pages 2026-01-09 14:24:04 -08:00
Nandkishor Jadoun
4b340191ad fix: preserve TOC visibility and improve toggle consistency (#4570)
* feat: disable toggle starred to maintain consistency

* fix: prevent Toggle Starred and Indexes from hiding TOC
2026-01-09 05:42:45 -08:00
nbats
e6fb8d7520 updated 12 pages 2026-01-09 05:37:53 -08:00
nbats
ce280b9af7 Update backups link description in README 2026-01-09 05:17:24 -08:00
nbats
da9cb76361 small update 2026-01-08 13:04:39 -08:00
nbats
99acae6f45 small fix 2026-01-08 09:19:38 -08:00
nbats
89ca8d01ce updated 2 pages 2026-01-08 08:50:52 -08:00
nbats
3e2556c484 updated 3 pages 2026-01-08 07:23:57 -08:00
Nandkishor Jadoun
98ec650b29 FIx: Update internship link from 2025 to 2026 (#4567) 2026-01-08 06:58:21 -08:00
Ahmed Tawfik
1eed3819fd Fix LaTeX Tools link in educational.md - Math (#4564)
it used to redirect to LaTeX Tools in developer-tools, which no longer exists as it has been moved to text-tools. now it redirects properly to its new location in text-tools :)
2026-01-08 06:57:21 -08:00
litekin
2e126b84f0 remove r/cracksupport Guilded link (#4560)
Guilded was shut down
2026-01-08 06:57:03 -08:00
nbats
025eeacd06 updated 22 pages 2026-01-08 06:51:33 -08:00
Ashur
dc5d4abfc7 update (#4559) 2026-01-06 18:49:16 -08:00
nbats
ad15525706 wwco 2026-01-06 18:45:26 -08:00
nbats
c7ca6554ea Add discussion link in WWCO.md
Added a discussion link to the WWCO document.
2026-01-06 18:42:58 -08:00
nbats
25c48d13d6 Update index.md 2026-01-06 18:36:42 -08:00
nbats
3f0e9d04f4 wwco 2026-01-06 18:34:42 -08:00
nbats
4102c327b6 updated 5 pages 2026-01-06 18:18:36 -08:00
nbats
d6bf9dc79a updated 2 pages 2026-01-06 10:17:13 -08:00
litekin
27bc24bf0d Fix Ekvis Reddit formatting (#4556)
I didn't do the correct formatting in that pr my bad
2026-01-06 09:10:51 -08:00
nbats
a252f8ee65 added 2 discords 2026-01-06 08:38:35 -08:00
nbats
f271deb08b small update 2026-01-06 08:29:10 -08:00
Zenith Rifle
2721c780c0 Fix desync state + better contrast (#4553)
* Improve toggle contrast in monochrome mode

* Fix monochrome toggle contrast

* Dim disabled toggle in dark mode
2026-01-06 07:49:50 -08:00
nbats
dd4b15d4c0 small update 2026-01-06 07:48:34 -08:00
Wispy
d5c6b60030 reorder note taking (#4549)
Co-authored-by: wispy <wispy@gmail.com>
2026-01-06 07:29:45 -08:00
litekin
9c6335f390 Reorder Geography Quizzes and add Ekvis Discord (#4547)
* Reorder Geography Quizzes and add Ekvis Discord

* Ekvis Reddit
2026-01-06 07:29:24 -08:00
nbats
2fbe367f5e small fix 2026-01-06 07:13:46 -08:00
nbats
c143af0052 updated 16 pages 2026-01-06 07:12:00 -08:00
nbats
ad14fc0dd6 small fix 2026-01-05 03:12:49 -08:00
nbats
0ce6061497 starred site 2026-01-05 00:09:02 -08:00
nbats
6cf024a4ad updated 6 pages 2026-01-04 23:04:15 -08:00
Zenith Rifle
361e48f862 Added Toggle Indexes (#4544)
* Add monochrome theme with grayscale filter

* Add indexes toggle and disable starred

* Keep filters mutually exclusive
2026-01-04 18:43:34 -08:00
nbats
a34a97eb41 updated 7 pages 2026-01-04 18:43:21 -08:00
nbats
4a3fb8da60 updated 6 pages 2026-01-04 14:50:30 -08:00
Zenith Rifle
46b6ae53bb Add monochrome theme with grayscale filter (#4541) 2026-01-04 05:32:51 -08:00
nbats
10fa9f6d17 added annas backups 2026-01-04 04:35:42 -08:00
nbats
28d58ed18f updated AI page 2026-01-04 01:50:37 -08:00
litekin
802f418346 Add Discord link (#4533) 2026-01-04 01:27:55 -08:00
WildeBeast2521
8b53fe3833 Several changes (#4536)
1. Separated Podman as it's a Docker competitor.
2. Updated WatchTower (archived) link with active, popular fork.
2026-01-04 00:53:43 -08:00
nbats
1ce78cec8c Revert "feat: add monochrome theme support (#4537)" (#4538)
This reverts commit bfc15e8141.
2026-01-04 00:43:48 -08:00
Zenith Rifle
bfc15e8141 feat: add monochrome theme support (#4537)
* feat: add monochrome theme support

* refactor: implement dedicated monochrome mode
2026-01-04 00:22:51 -08:00
nbats
703831f6ea updated 3 pages 2026-01-04 00:22:37 -08:00
Zenith Rifle
bfda08e659 Your local exact search (#4535)
* Initial plan

* Add fuzzy/exact search toggle to VPLocalSearchBox

Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com>

* Complete fuzzy/exact search toggle implementation with screenshots

Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com>

* Add minisearch dependency and update screenshots with actual interface

Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com>

* Remove temporary comment and restore web fonts preset

Co-authored-by: eli32-vlc <84105075+eli32-vlc@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-01-03 21:39:22 -08:00
nbats
11dff3a3bd updated 6 pages 2026-01-03 21:35:39 -08:00
nbats
c7c73a89b0 updated desc 2026-01-03 05:29:55 -08:00
nbats
3987f9dfad small fix 2026-01-03 04:54:49 -08:00
nbats
8f8c904749 small fix 2026-01-03 04:37:37 -08:00
nbats
3f5ba2e81b added site backups 2026-01-03 04:08:59 -08:00
nbats
f8b6701c5f added site 2026-01-03 04:05:08 -08:00
nbats
c17c00a78b updated 16 pages 2026-01-03 03:56:05 -08:00
nbats
578fb35f0e fix 2026-01-02 05:53:24 -08:00
nbats
5cb9aa242e small update 2026-01-02 05:34:38 -08:00
nbats
f89bf55ab0 split DLPSGame sub-sites into sections they belong 2026-01-02 05:26:28 -08:00
DoThingsWithAI
56329f8bf0 update Open Bulk URL link due to 301 redirect (#4433)
Co-authored-by: shan <2302531309@qq.com>
2026-01-02 05:15:58 -08:00
fmhyhalloweenshit
908a1d8ce4 Fix theme issues (#4527)
* thr33

* super safe

* i dont like addings messages atp

* eardrummer

* trial and error again

* kill everyone

* PLEASE BRAH

* .
2026-01-02 05:07:08 -08:00
nbats
57ef8769a2 Fix typo 2026-01-02 05:03:40 -08:00
nbats
9e57d11f79 Update jan-2026.md 2026-01-02 04:59:28 -08:00
nbats
7719ec6480 Re-added the alt FMHY frontend, without over-the-top homepage this time 2026-01-02 04:55:10 -08:00
nbats
2e22f762ee updated 9 pages 2026-01-02 04:47:49 -08:00
nbats
4d333ec136 updated 16 pages 2026-01-01 22:18:22 -08:00
nbats
6fd5b90dd3 update jan-2026
Removed the section about the Alternative Frontend of FMHY, which included details about its design and syncing with the official source.
2026-01-01 21:44:06 -08:00
nbats
f18ea4564c Update backups.md 2026-01-01 21:42:54 -08:00
145 changed files with 3100 additions and 1022 deletions

View File

@@ -33,6 +33,7 @@ Here you'll find some general guidelines for those who would like to start contr
For submitting new links, follow these steps:
- Make sure it's not already in the wiki. The easiest way to do this is to check our [Single Page](https://api.fmhy.net/single-page) using `ctrl+f`.
- Don't spam a bunch of un-tested links at once. Try to only send things you genuinely feel might be worth adding.
- Reach out via the feedback system, [GitHub](https://github.com/fmhy/edit), or join our [Discord](https://github.com/fmhy/FMHY/wiki/FMHY-Discord). Note that we have to check sites ourselves, so using a issue, rather than pull request is easier.
- You can optionally include socials, tools, or any other additional info alongside the entry.

4
.github/README.md vendored
View File

@@ -8,7 +8,7 @@
- Website: [fmhy.net](https://fmhy.net)
- News & Monthly Updates: [fmhy.net/posts](https://fmhy.net/posts)
- Backups: [github.com/fmhy/FMHY/wiki/Backups](https://github.com/fmhy/FMHY/wiki/Backups)
- Backups, Markdown, JSON API: [github.com/fmhy/FMHY/wiki/Backups](https://github.com/fmhy/FMHY/wiki/Backups)
- Neither the site nor GitHub host any files
## 🗺️ Emoji Legend
@@ -33,4 +33,4 @@ Here are a few ways you can get involved:
<p>
<a href="https://github.com/fmhy/FMHY/wiki/FMHY-Discord"><img width="30px" src="./assets/discord.svg" alt="Discord"></a>&nbsp;&nbsp;<a href="https://github.com/fmhy"><img width="30px" src="./assets/github.svg" alt="GitHub"></a>
</p>
</p>

View File

@@ -20,6 +20,7 @@ import { defs, emojiRender, movePlugin } from './markdown/emoji'
import { headersPlugin } from './markdown/headers'
import { toggleStarredPlugin } from './markdown/toggleStarred'
import { transformsPlugin } from './transformer'
import { replaceNoteLink } from './utils/markdown'
// @unocss-include
@@ -98,6 +99,12 @@ export default defineConfig({
replacement: fileURLToPath(
new URL('./theme/components/ThemeDropdown.vue', import.meta.url)
)
},
{
find: /^.*VPLocalSearchBox\.vue$/,
replacement: fileURLToPath(
new URL('./theme/components/VPLocalSearchBox.vue', import.meta.url)
)
}
]
},
@@ -202,6 +209,7 @@ export default defineConfig({
md.use(emojiRender)
md.use(toggleStarredPlugin)
meta.build.api && md.use(headersPlugin)
replaceNoteLink(md)
}
},
themeConfig: {

View File

@@ -121,7 +121,7 @@ export const search: DefaultTheme.Config['search'] = {
},
searchOptions: {
combineWith: 'AND',
fuzzy: true,
fuzzy: false,
// @ts-ignore
boostDocument: (documentId, term, storedFields: Record) => {
const titles = (storedFields?.titles as string[])

View File

@@ -17,23 +17,27 @@
import type { MarkdownRenderer } from 'vitepress'
const excluded = ['Beginners Guide']
const starredMarkers = [':star:', ':glowing-star:', '⭐', '🌟']
const indexMarkers = ['🌐', ':globe_with_meridians:', ':globe-with-meridians:']
export function toggleStarredPlugin(md: MarkdownRenderer) {
md.renderer.rules.list_item_open = (tokens, index, options, env, self) => {
const contentToken = tokens[index + 2]
// Ensure the token exists
if (contentToken) {
const content = contentToken.content
if (!contentToken) return self.renderToken(tokens, index, options)
if (
!excluded.includes(env.frontmatter.title) &&
(content.includes(':star:') || content.includes(':glowing-star:'))
) {
return `<li class="starred">`
}
}
const content = contentToken.content
const isStarred =
!excluded.includes(env.frontmatter.title) &&
starredMarkers.some((marker) => content.includes(marker))
const isIndex = indexMarkers.some((marker) => content.includes(marker))
return self.renderToken(tokens, index, options)
if (!isStarred && !isIndex) return self.renderToken(tokens, index, options)
const classes = []
if (isStarred) classes.push('starred')
if (isIndex) classes.push('index')
return `<li class="${classes.join(' ')}">`
}
}

View File

@@ -0,0 +1,7 @@
#### Advanced Logic Calculators
* analytic tableaux generator: https://www.umsu.de/trees/
* natural deduction proof checker: https://proofs.openlogicproject.org/
* propositional logic calculator (finds models): https://www.inf.unibz.it/~franconi/teaching/propcalc/
* a tutorial on sequent calculus: http://logitext.mit.edu/tutorial
* modal logic playground (for constructing models): https://rkirsling.github.io/modallogic/

View File

@@ -0,0 +1,4 @@
#### Alt Twitch Player Extensions
* https://addons.mozilla.org/en-US/firefox/addon/twitch_5/
* https://chrome.google.com/webstore/detail/alternate-player-for-twit/bhplkbgoehhhddaoolmakpocnenplmhf

View File

@@ -0,0 +1,6 @@
#### Alt Warp Clients
If you can't connect, try Scanner Settings -> Endpoint -> Suggested -> Try different IP's to find one that works
* https://github.com/bepass-org/oblivion-desktop
* https://github.com/bepass-org/oblivion

View File

@@ -0,0 +1,3 @@
#### Android Spotify Note
Many modded apks are buggy as of now and may not work at all.

View File

@@ -0,0 +1,5 @@
#### APKMirror Extensions
* https://addons.mozilla.org/en-US/firefox/addon/toolbox-google-play-store/
* https://chrome.google.com/webstore/detail/toolbox-for-google-play-s/fepaalfjfchbdianlgginbmpeeacahoo
* https://addons.opera.com/en/extensions/details/toolbox-for-google-play-storetm/

View File

@@ -0,0 +1,3 @@
#### App Lock
Keep in mind this is a privacy utility meant to prevent common snooping, its not claiming to be a security tool, and will not stop forensic analysis.

View File

@@ -0,0 +1,3 @@
#### Audiobookbay Warning
Avoid Fake download links, use [Torrents / Magnets](https://i.ibb.co/8sV2061/0fa8159b11bb.png), or paste info hash into torrent client

View File

@@ -0,0 +1,3 @@
#### Aurora Note
Keep in mind that some apps that exist do not work unless you installed them from the google play store. This is usually true for things like banking apps, or some institutions app.

View File

@@ -0,0 +1,3 @@
#### Better Reasoning
For better reasoning, switch mode to "think deeper"

View File

@@ -0,0 +1,3 @@
#### Bookmarkeddit
This also extends the amount of saved posts you can view (reddit caps at 1000 by default)

View File

@@ -0,0 +1,7 @@
#### Buster Note
The client app simulates user interactions which greatly improves the success rate of buster. You can download the app through the extensions option page, or get it from the link below:
https://github.com/dessant/buster-client
The app is available for Windows, Linux, and macOS

View File

@@ -0,0 +1,3 @@
#### Buzzheavier Warning
Make sure you have an [adblocker](https://fmhy.net/adblockvpnguide#adblocking) when using Buzzheavier as there are hidden ads on download pages with malicious content. Both the download button and torrent buttons should automatically start a download in your browser, NOT redirect you to another page.

View File

@@ -0,0 +1,3 @@
#### Bypass FREEdlink
You still need to bypass Cloudflare captcha by yourself. This only bypasses timer on single downloads. You may still need to wait normal time to download another file which is enforced from server-side.

View File

@@ -0,0 +1,3 @@
#### Captcha 4PDA
Use Google Gemini to translate the captcha

View File

@@ -0,0 +1,5 @@
#### ChatGPT Limits
* GPT-5.1-medium (1 Daily)
* GPT-5.1-chat (10 per 5 hours)
* GPT-5.1- mini (Unlimited)

View File

@@ -0,0 +1,4 @@
#### Clipboard2File Addons
* https://github.com/vord1080/clipboard2file/
* https://github.com/daijro/Clipboard2File-Chrome

View File

@@ -0,0 +1,3 @@
#### Cofi Note
Useful if you're a coffee enthusiast. The methods are created by James Hoffmann, he's a world champion barista and popular YouTuber

View File

@@ -0,0 +1,3 @@
#### CrystalDiskInfo
Avoid versions labeled "Ads".

View File

@@ -0,0 +1,5 @@
#### CS.RIN Search
If your initial search doesn't work, trying searching the same term again within the "search these results" engine on the results screen.
<img width="1307" height="97" alt="image" src="https://github.com/user-attachments/assets/b2f149b9-8a9a-4250-8754-e63f50b82c59" />

View File

@@ -0,0 +1,3 @@
#### DODI Warning
Its highly recommended to stick to dodi's 1337x page or main website, as sites they linked to have fake DDL buttons, and shouldn't be used without an adblocker

View File

@@ -0,0 +1,3 @@
#### Dolby Access / Atmos Note
Many headsets come with Dolby Access for free without letting users know. You can check if you're licensed by opening Dolby Access, going to settings, and looking in the [bottom right corner](https://i.imgur.com/9vJA6CL.png). Its much better than things like iCue or similar apps.

View File

@@ -0,0 +1,3 @@
#### Driver Note
Only install the drivers you actually need. Don't install all new drivers at once, as this could lead to things breaking, especially system audio.

View File

@@ -0,0 +1,3 @@
#### Eaglercraft Note
Play on Chromium-based browsers for the best performance

View File

@@ -0,0 +1,5 @@
#### Eruda
Eruda Console for mobile browsers bookmarklet:
`javascript:(function () { var script = document.createElement('script'); script.src="//cdn.jsdelivr.net/npm/eruda"; document.body.appendChild(script); script.onload = function () { eruda.init() } })();`

View File

@@ -0,0 +1,3 @@
#### Filebin Warning
Anyone with a link to a "bin" has full access to it. They can add new files, delete existing files, etc

View File

@@ -0,0 +1,3 @@
#### Filelu Warning
According to their FAQ question "When will my files expire?", you must login to your account at least once every 180 days to prevent your account being deleted.

View File

@@ -0,0 +1,4 @@
#### FileZilla
Keep in mind the link on their frontpage is sponsored and has adware, but you can get to the non-adware version by following the link on fmhy,
or pressing download on the FileZilla website, and then clicking "additional downloads" under the big download button.

View File

@@ -0,0 +1,3 @@
#### Flicker Proxy
Note that the proxy may be slower, but it can be used in cases where the site or TMDb is blocked.

View File

@@ -0,0 +1,3 @@
#### Fluxy Repacks
Note that though it has repacks in the name, its not actually a repack site.

View File

@@ -0,0 +1,4 @@
#### Forest Extensions
* https://addons.mozilla.org/en-US/firefox/addon/forest-stay-focused-be-present/
* https://chrome.google.com/webstore/detail/forest-stay-focused-be-pr/kjacjjdnoddnpbbcjilcajfhhbdhkpgk

View File

@@ -0,0 +1,3 @@
#### Foxit Warning
The installer tries to install McAfee WebAdvisor + PhantomPDF Business. They can be skipped by clicking "decline" both times.

View File

@@ -0,0 +1,7 @@
#### FreeGOGPCGames Note
Many titles on the site are the older versions of the installers. The digital signature on the installer is signed by GOG Limited, which is the old company name before it was merged with GOG Sp. z o.o and all digital file signatures were updated to reflect this name change.
The hash does not match the gog-games database because the digital file signatures differ on the installer. Installing either version will produce identical sets of files since the game version remains unchanged.
/u/AtariRiot66

View File

@@ -0,0 +1,3 @@
#### General Tweak Warning
Its not recommended to use these unless you know what you're doing. Always research first, never just "Apply All" tweaks randomly.

View File

@@ -0,0 +1,9 @@
#### Glitchwave Note
For charts you can specify months and days using URLs like the following examples
January 2006:
`https://glitchwave.com/charts/popular/game/2006.01/excl:ratings/`
Jan-Feb 2018:
`https://glitchwave.com/charts/popular/game/2018.01-2018.02/excl:ratings/`

View File

@@ -0,0 +1,3 @@
#### Google Song Identification
Google and YouTube Music mobile apps have song identification button next to the search box.

View File

@@ -0,0 +1,3 @@
#### Google Translate Note
Google translate can serve as a web proxy. Simply paste your URL into the translate field and then click on the result and view the page in the original language. This way you can navigate any web-page via google.com. Google is almost never blocked so this trick works on most occasions.

View File

@@ -0,0 +1,3 @@
#### HDO Box Note
To use the app, HDO Box may ask you to install a third-party video player which contains ads. Check out the DNS Adblocking section on FMHY for adblocking solutions.

View File

@@ -0,0 +1,3 @@
#### Hugging Face Warning
HuggingFace uses a system called ZeroGPU to manage access to their high-end GPUs. To make sure that their GPUs don't get fully used up, there are limits on how long you can use the GPU on Spaces like this one that utilize ZeroGPU. The rate limit is 120 seconds daily for non-logged in users. You can get around the 120 second limit by changing your IP address, which can be done by using a proxy or VPN while logged out. If you sign up for a free HuggingFace account, you get a much higher 300 second rate limit, but changing your IP won't reset the limit

View File

@@ -0,0 +1,3 @@
#### Instaeclipse Note
Use ['advanced'](https://wispydocs.pages.dev/revanced-obtainium/#advanced) to build clean apks, or use antisplitm with revanced manager.

View File

@@ -0,0 +1,5 @@
#### IRC Highway Note
To request a book run: @request [author] [title] - Requests without both [author] and [title] are deleted.
To view request status and rules run: @request-list

View File

@@ -0,0 +1,3 @@
#### Jdownloader
Keep in mind the link on their frontpage is sponsored and has adware, but jdownloader2 which is linked on fmhy, does not contain any adware.

View File

@@ -0,0 +1,4 @@
#### Limit Bypass Note
- sparsebox: ios 17.0 - 18.1 beta 4 (not including 17.7.1, 17.7.2)
- live container: ios 16+

View File

@@ -0,0 +1,3 @@
#### LiteAPK + Modyolo Note
The site is safe, but they are known for mislabeling things like RockMods releases as their own, and mislabeling versions to make it look like they have newer things than they really do.

View File

@@ -0,0 +1,3 @@
#### Malware Removal Forums
Note that many of these will suggest removing pirated software, but if you got everything from trusted sources, there is no real need to do that.

View File

@@ -0,0 +1,3 @@
#### Megabasterd Note
Free proxies work but they are very hit and miss

View File

@@ -0,0 +1,13 @@
#### Mobilism Ranks
The users in red. Administrators are members assigned with the highest level of control over the entire board. Usually theyre Section Heads. Most Administrators are Section Heads but not all Section Heads are administrators.
The users in green. They moderate! Moderators are members of our staff who make everyone follows the sites rules.
The users in light green. Theyre similar to moderators but do not have the same authority. Oftentimes helpers eventually become moderators.
The people in orange. Mobilism has an Android Review Section and a Book Review Section. Users who are part of their review teams are the Reviewers.
The guys in purple. Different sections have different requirements for becoming a Major Releaser but generally it comes with making significant contributions to the release sections.
The users in blue. VIPs are either members who were rewarded with VIP status for their contributions, or donated to support Mobilism. VIPs have access to VIP sections: VIP Releases, VIP Requests, VIP Talk, receive extra WRZ$ and do not see any ads.

View File

@@ -0,0 +1,3 @@
#### Māori Note
Māori is the indigenous language of mainland New Zealand. Due to the [Native Schools Act](https://en.wikipedia.org/wiki/M%C4%81ori_language#Suppression_and_decline) in 1867, children were forbidden to speak it in the classroom, under penalty of corporal punishment, which led to a rapid decline of speakers. There are now [revitalization efforts](https://en.wikipedia.org/wiki/M%C4%81ori_language_revival) (such as Tōku Reo) attempting to promote and reinforce its use.

View File

@@ -0,0 +1,11 @@
#### movie-web
You can [enable an extension](https://pstream.org/onboarding/extension) / [2](https://github.com/sussy-code/browser-ext/releases/) that will add more sources, but it needs to connect to all sites to function. The extension is safe, and many people use it, the permissions are just needed in order for the [extension to work correctly](https://rentry.co/htagcrv4).
Note that it can be ran in a new browser or fresh browser profile if you don't want to use your main browser.
For a setup guide (including 4k) you can watch this video:
https://vimeo.com/1059834885/c3ab398d42
Docs + selfhosting guides can be found here:
https://docs.pstream.mov/

View File

@@ -0,0 +1,5 @@
#### MovieParadise Code
* In order to unlock the better host (1fichier) you need to signup code. This is important as without it the site will be rapidgator only links which are very slow. You can get a code from the link below, or the pins in our #free-stuff discord channel.
**[Click Here To Get Code](https://rentry.org/he8fhzku)**

View File

@@ -0,0 +1,3 @@
#### MVSEP Note
Register for wav and flac output, and lower queue times

View File

@@ -0,0 +1,10 @@
#### OneClick Note
Main features include:
- Download links straight to Google Drive.
- Torrent to Google Drive.
- Google Drive Download Manager (similar to pyLoad).
- Spotify Downloader.
- Jellyfin Support.
- RClone + WebUI.
- And much more.

View File

@@ -0,0 +1,3 @@
#### Openasar
The Vencord installer has an option to install OpenAsar, but you may need to click the install button twice (only once more after clicking "Accept").

View File

@@ -0,0 +1,14 @@
#### OpenRGB Beta
How to download OpenRGB beta.
Why?
Because the latest version that you can download from the website dates from July 9 2023, and since a new device is added to the software almost every day, using the beta version becomes a necessity.
Go to Gitlab OpenRgb site `https://gitlab.com/CalcProgrammer1/OpenRGB` and on the left go to Build => Pipelines and then download the appropriate version from the download button on the top right.
(Note: Before downloading it should say Passed at the top left.)
Supported devices (0.9) => `https://openrgb.org/devices_0.9.html`
(The link may become outdated after a while, go to the OpenRGB site `https://openrgb.org/index.html` and find the newer one in the menu on the top right.)
Supported devices (Latest experimental) => `https://openrgb.org/devices.html`

View File

@@ -0,0 +1,20 @@
#### Pollinations Limits
For `chat.pollinations.ai` (and the underlying API), the rate limits depend on how you're using it:
**Anonymous / Free Tier (No Login)**
- **Text/Chat**: ~1 request every **3 seconds** (per IP).
- **Images**: ~1 request every **5 seconds** (per IP).
**Logged In (Pollen System)**
- Users get a **daily free Pollen allowance** based on their tier.
- **Publishable Keys (`pk_`)**: Rate limited to prevent abuse (e.g., ~1 pollen/hour per IP).
- **Secret Keys (`sk_`)**: **No rate limits** (requests run as fast as you can pay for them with Pollen).
If you're hitting limits on the chat site:
1. Slow down slightly (wait 3-5s between messages).
2. **Log in** at [enter.pollinations.ai](https://enter.pollinations.ai) to use your daily free credits.
3. If you need massive throughput, use an API key (`sk_`) with purchased credits.
To use this site for image generation, scroll down to "Image Feed" and change it to "Try" from "Watch". Available models are flux (schnell), turbo (SDXL Turbo), and gptimage. For gptimage, allowed resolutions are 1024x1024, 1536x1024 (landscape), and 1024x1536 (portrait). Change the seed to a random number for different output. The "Write the 'Imagine' word only" button is the submit button. Pretty sure its unlimited for all models, at least through UI.

View File

@@ -0,0 +1,4 @@
#### PrintEditWe Addons
* https://addons.mozilla.org/en-US/firefox/addon/print-edit-we/
* https://chrome.google.com/webstore/detail/print-edit-we/olnblpmehglpcallpnbgmikjblmkopia

View File

@@ -0,0 +1,5 @@
#### Proton Torrenting
Torrenting on Proton VPN's free plan is only possible when using an OpenVPN configuration / [Guide](https://protonvpn.com/support/vpn-config-download). Note that they do expire, so you'll have to make new ones occasionally.
OpenVPN login credentials are located [here](https://account.protonvpn.com/account-password).

View File

@@ -0,0 +1,8 @@
#### Ranks 1337x
* ⬛ Black - Admin
* 🟩 Green - Moderator
* 🟦 Blue - VIP (Very Trusted)
* 🟨 Yellow - Uploader (Trusted)
* 🟥 Red - Trial Uploader
* ⬜ Grey - User

View File

@@ -0,0 +1,3 @@
#### Reaper Note
Asks user to buy after 60 days, but you can just close the popup and keep using for free

View File

@@ -0,0 +1,3 @@
#### RedditFilter Note
Go to Settings → Feed Filter and untoggle 'Promoted' to not see ads. Those that don't like AI suggestions can untoggle 'Recommended' as well.

View File

@@ -0,0 +1,3 @@
#### RGShows Autoplay
If you're using Firefox and you want autoplay, hit the permissions on your url search bar and allow both audio + video.

View File

@@ -0,0 +1,3 @@
#### Sanet Warning
Note that Sanet has been known to host things like KMS Matrix, so its best to avoid it for software and games

View File

@@ -0,0 +1,4 @@
#### SavePageWe
* https://addons.mozilla.org/en-US/firefox/addon/save-page-we/
* https://chrome.google.com/webstore/detail/save-page-we/dhhpefjklgkmgeafimnjhojgjamoafof

View File

@@ -0,0 +1,5 @@
#### ScrollAnywhere Addons
* https://addons.mozilla.org/en-US/firefox/addon/scroll_anywhere/
* https://chrome.google.com/webstore/detail/scrollanywhere/jehmdpemhgfgjblpkilmeoafmkhbckhi
* https://addons.opera.com/en/extensions/details/scrollanywhere/?display=en

View File

@@ -0,0 +1,3 @@
#### SD Maid
Google play version is paid. Press donate to unlock the app on F-Droid and GitHub versions.

View File

@@ -0,0 +1,3 @@
#### SH Note
Based on popular [card game](https://en.wikipedia.org/wiki/Secret_Hitler), created by cards against humanity co-founder.

View File

@@ -0,0 +1,3 @@
#### Site Favicon DL
You can also do `https://www.google.com/s2/favicons?domain=URL&sz=64` where URL is the URL of the site you want and sz is the size in pixels

View File

@@ -0,0 +1,3 @@
#### Soft98 Note
Enable `AdGuard - Ads` filterlist in uBlock to allow downloads to work. To remove all ads, you can also get the [AdGuard Extra Userscript](https://github.com/AdguardTeam/AdGuardExtra?tab=readme-ov-file#userscript) (not the extension) and enable it in your script manager. Note that you may need to disable filter `ir: PersianBlocker`.

View File

@@ -0,0 +1,9 @@
#### SoftArchive Mirrors
- https://sanet.download/
- https://softarchive.is/
- https://sanet.lc/
- https://sanet.ws/
- https://sanet.st/
- https://sanet.sb/
- https://soft.ac/

View File

@@ -0,0 +1,3 @@
#### Sora
Bypass the need for a invite code by installing Sora Mobile, and logging into OpenAI.

View File

@@ -0,0 +1,5 @@
#### Spicetify Note
Join their [Discord](https://discord.gg/VnevqPp2Rr) for version compatibility.
Note that you can use the store built in to get a full list of addons and themes.

View File

@@ -0,0 +1,3 @@
#### Sport7
Note that many sites use this player, but Sport7 is their main site.

View File

@@ -0,0 +1,3 @@
#### Steam Controller Support
Steam has built in support for most controller types, just add your games to steam, right click the game, and turn on your controller

View File

@@ -0,0 +1,3 @@
#### Steam Currency Converter Note
For instant currency conversion : Go to Firefox's extensions settings, click on the add-on, enter the permissions section and allow the sites there

View File

@@ -0,0 +1,4 @@
#### Tabiverse Extensions
* https://addons.mozilla.org/firefox/addon/tabiverse/
* https://chromewebstore.google.com/detail/hpplgjkooibhfkmmepoikcjpadcojcik

View File

@@ -0,0 +1,3 @@
#### Tautulli Note
This will sometimes get falsely flagged by defender and removed automatically, so it may need to be allowed manually.

View File

@@ -0,0 +1,3 @@
#### TeamSpeak Warning
Note that teamspeak server admins can view IPs, so only join servers you trust

View File

@@ -0,0 +1,3 @@
#### Thunderbird
To get real-time notification, press the three lines in the top left corner, select the account you want to configure, select Manage Folders, then select the folder you want from below. You can then select inbox and enable push. (Notifications must be enabled).

View File

@@ -0,0 +1,5 @@
#### TinyURL Note
To reveal the destination URL, replace "www" with "preview" in the URL like so:
https://preview.tinyurl.com/5erwtst5

View File

@@ -0,0 +1,3 @@
#### Video DownloadHelper
Note that some versions of this extension give a watermark on sites that need conversion. It seems to happen on the Windows + Firefox version.

View File

@@ -0,0 +1,3 @@
#### Vuenxx Note
If you want to download the files, you need to send the screenshot that you subscribed to the vuenxx youtube channel to the discord "teyit" channel. After a while the download channels will open.

View File

@@ -0,0 +1,3 @@
#### WeLib Note
WeLib is *not* connected to Anna's Archive, they simply mirror Anna's content onto their own site that has a different UI. It is not updated as often, and they don't share their codebase improvements publicly, so they aren't endorsed by Anna's themselves.

View File

@@ -0,0 +1,3 @@
#### WinRAR
WinRAR does not auto-update, and because it had a remote code execution vulnerability in the past, you should make sure you've manually updated **to 7.13 or later** to be safe.

View File

@@ -0,0 +1,3 @@
#### Yet Another Call Blocker Note
The app itself isn't maintained, but the repo contains the "main" phone number database. It is updated once in a couple of months. The app receives daily (incremental) updates directly from third-party services.

View File

@@ -0,0 +1,4 @@
#### YouTube Tweaks
* https://addons.mozilla.org/firefox/addon/youtube-tweaks/
* https://chrome.google.com/webstore/detail/youtube-tweaks/oeakphpfoaeggagmgphfejmfjbhjfhhh

View File

@@ -0,0 +1,3 @@
#### YTS / Yify Note
YTS / Yify has many fake ripoff sites out there, make 100% sure you're on one of the official domains before downloading.

View File

@@ -8,7 +8,7 @@ import type { Theme } from '../themes/types'
import Switch from './Switch.vue'
type ColorNames = keyof typeof colors
const selectedColor = useStorage<ColorNames>('preferred-color', 'christmas')
const selectedColor = useStorage<ColorNames>('preferred-color', 'swarm')
// Use the theme system
const { amoledEnabled, setAmoledEnabled, setTheme, state, mode, themeName } = useTheme()
@@ -211,12 +211,8 @@ watch(selectedColor, async (color) => {
if (!color) return;
const theme = generateThemeFromColor(color)
themeRegistry[`color-${color}`] = theme
// Explicitly set the theme to override any previous selection
await nextTick()
console.log('Setting theme to:', `color-${color}`)
console.log('Current themeName:', themeName ? themeName.value : undefined, 'mode:', mode ? (mode as any).value : undefined)
setTheme(`color-${color}`)
console.log('After setTheme, themeName:', themeName ? themeName.value : undefined)
})
const toggleAmoled = () => {

View File

@@ -4,6 +4,7 @@ import ColorPicker from './ColorPicker.vue'
import ThemeSelector from './ThemeSelector.vue'
import InputField from './InputField.vue'
import ToggleStarred from './ToggleStarred.vue'
import ToggleIndexes from './ToggleIndexes.vue'
</script>
<template>
@@ -26,6 +27,11 @@ import ToggleStarred from './ToggleStarred.vue'
<ToggleStarred />
</template>
</InputField>
<InputField id="toggle-indexes" label="Toggle Indexes">
<template #display>
<ToggleIndexes />
</template>
</InputField>
<div class="mt-4">
<ColorPicker />

View File

@@ -1,14 +1,26 @@
<script setup>
import { Switch } from '@headlessui/vue'
import { ref } from 'vue'
<script setup lang="ts">
import { Switch as HeadlessSwitch } from '@headlessui/vue'
const enabled = ref(false)
const props = defineProps<{
modelValue: boolean
disabled?: boolean
}>()
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void
}>()
</script>
<template>
<Switch v-model="enabled" class="switch" :class="{ enabled }">
<HeadlessSwitch
:model-value="props.modelValue"
:disabled="props.disabled"
class="switch"
:class="{ enabled: props.modelValue, disabled: props.disabled }"
@update:modelValue="emit('update:modelValue', $event)"
>
<span class="thumb" />
</Switch>
</HeadlessSwitch>
</template>
<style>
@@ -29,6 +41,23 @@ const enabled = ref(false)
.switch.enabled {
background-color: var(--vp-c-brand);
}
.switch.disabled {
opacity: 0.5;
pointer-events: none;
background-color: var(--vp-c-bg-soft, #2f2f2f);
border-color: var(--vp-c-divider, #666);
}
.switch.disabled .thumb {
background-color: #fff;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2), var(--vp-shadow-1);
}
.dark .switch.disabled {
background-color: #2f2f2f;
border-color: #7d7d7d;
}
</style>
<style scoped>
@@ -43,7 +72,7 @@ const enabled = ref(false)
width: 20px;
height: 20px;
border-radius: 50%;
box-shadow: var(--vp-shadow-1);
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.08), var(--vp-shadow-1);
}
.switch.enabled .thumb {

View File

@@ -0,0 +1,67 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import Switch from './Switch.vue'
const isDisabled = ref(false)
const isOn = ref(false)
const syncState = () => {
const root = document.documentElement
isDisabled.value = root.classList.contains('starred-only')
isOn.value = root.classList.contains('indexes-only')
}
let observer: MutationObserver | undefined
onMounted(() =>
(observer = new MutationObserver(syncState)).observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
})
)
onMounted(syncState)
onBeforeUnmount(() => observer?.disconnect())
const toggleIndexes = (value: boolean) => {
if (isDisabled.value) {
isOn.value = document.documentElement.classList.contains('indexes-only')
return
}
const root = document.documentElement
const enabling = value
const wasStarred = root.classList.contains('starred-only')
root.classList.toggle('indexes-only', enabling)
if (enabling) {
root.dataset.starredWasOn = wasStarred ? 'true' : 'false'
if (wasStarred) {
root.classList.remove('starred-only')
}
} else {
if (root.dataset.starredWasOn === 'true') {
root.classList.add('starred-only')
}
delete root.dataset.starredWasOn
}
isOn.value = enabling
}
</script>
<template>
<Switch v-model="isOn"
:disabled="isDisabled"
:class="{ disabled: isDisabled }"@update:modelValue="toggleIndexes" />
</template>
<style>
.indexes-only .vp-doc li:not(.index) {
display: none;
}
</style>

View File

@@ -1,16 +1,53 @@
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import Switch from './Switch.vue'
const toggleStarred = () =>
document.documentElement.classList.toggle('starred-only')
const isDisabled = ref(false)
const isOn = ref(false)
const syncState = () => {
const root = document.documentElement
isDisabled.value = root.classList.contains('indexes-only')
isOn.value = root.classList.contains('starred-only')
}
let observer: MutationObserver | undefined
onMounted(() =>
(observer = new MutationObserver(syncState)).observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
})
)
onMounted(syncState)
onBeforeUnmount(() => observer?.disconnect())
const toggleStarred = (value: boolean) => {
if (isDisabled.value) {
isOn.value = document.documentElement.classList.contains('starred-only')
return
}
const root = document.documentElement
root.classList.toggle('starred-only', value)
root.dataset.starredWasOn = value ? 'true' : 'false'
isOn.value = value
}
</script>
<template>
<Switch @click="toggleStarred()" />
<Switch
v-model="isOn"
:disabled="isDisabled"
:class="{ disabled: isDisabled }"
@update:modelValue="toggleStarred"
/>
</template>
<style>
.starred-only li:not(.starred) {
.starred-only .vp-doc li:not(.starred) {
display: none;
}
</style>

View File

@@ -0,0 +1,66 @@
<script setup lang="ts">
import { withBase } from 'vitepress'
import { computed } from 'vue'
const props = withDefaults(
defineProps<{ title?: string; icon?: string }>(),
{ icon: '/note.svg' }
)
const resolvedIcon = computed(() => withBase(props.icon))
</script>
<template>
<VDropdown :triggers="['click', 'touch']" :auto-hide="true" :distance="15" placement="auto">
<button
aria-label="Tooltip"
class="text-brand-1 relative inline-flex align-middle items-center justify-center leading-none p-0 select-none font-bold cursor-pointer transition-all h-[1em] w-[1.7em]"
>
<div
class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-2.5 w-[1.6em] h-[1.6em] bg-current transition-all"
:style="{
mask: `url(${resolvedIcon}) no-repeat center / contain`,
'-webkit-mask': `url(${resolvedIcon}) no-repeat center / contain`,
}"
/>
</button>
<template #popper>
<div class="border-$vp-c-divider bg-$vp-c-bg-alt b-rd-4 max-w-md max-h-md border-2 border-solid p-4 transition-all">
<h3 v-if="title" class="text-$vp-c-text-1 mb-2 text-lg font-semibold" v-text="title" />
<div class="text-$vp-c-text-1 text-sm content">
<slot />
</div>
</div>
</template>
</VDropdown>
</template>
<style>
.v-popper__popper { --uno: z-5000; }
.v-popper { display: inline-flex !important; }
.v-popper--theme-dropdown .v-popper__inner {
background: transparent !important;
box-shadow: none !important;
border: none !important;
padding: 0 !important;
}
.v-popper__popper .content ul {
list-style: disc;
padding-left: 1.25rem;
margin: 0.5rem 0;
}
.v-popper__popper .content ol {
list-style: decimal;
padding-left: 1.25rem;
margin: 0.5rem 0;
}
.v-popper__popper .content li {
margin: 0.25rem 0;
}
</style>

View File

@@ -0,0 +1,927 @@
<script lang="ts" setup>
import localSearchIndex from '@localSearchIndex'
import {
computedAsync,
debouncedWatch,
onKeyStroke,
useEventListener,
useLocalStorage,
useScrollLock,
useSessionStorage
} from '@vueuse/core'
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
import Mark from 'mark.js/src/vanilla.js'
import MiniSearch, { type SearchResult } from 'minisearch'
import { dataSymbol, inBrowser, useRouter } from 'vitepress'
import {
computed,
createApp,
markRaw,
nextTick,
onBeforeUnmount,
onMounted,
ref,
shallowRef,
watch,
watchEffect,
type Ref
} from 'vue'
import type { ModalTranslations } from 'vitepress/types/local-search'
import { pathToFile } from 'vitepress/dist/client/app/utils'
import { escapeRegExp } from 'vitepress/dist/client/shared'
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import { LRUCache } from 'vitepress/dist/client/theme-default/support/lru'
import { createSearchTranslate } from 'vitepress/dist/client/theme-default/support/translation'
import Tooltip from './Tooltip.vue'
import FloatingVue from 'floating-vue'
const emit = defineEmits<{
(e: 'close'): void
}>()
const el = shallowRef<HTMLElement>()
const resultsEl = shallowRef<HTMLElement>()
/* Search */
const searchIndexData = shallowRef(localSearchIndex)
// hmr
if (import.meta.hot) {
import.meta.hot.accept('/@localSearchIndex', (m) => {
if (m) {
searchIndexData.value = m.default
}
})
}
interface Result {
title: string
titles: string[]
text?: string
}
const vitePressData = useData()
const { activate } = useFocusTrap(el, {
immediate: true,
allowOutsideClick: true,
clickOutsideDeactivates: true,
escapeDeactivates: true
})
const { localeIndex, theme } = vitePressData
// Fuzzy search toggle state (default: false = exact search)
const isFuzzySearch = useLocalStorage('vitepress:local-search-fuzzy', false)
const searchIndex = computedAsync(async () =>
markRaw(
MiniSearch.loadJSON<Result>(
(await searchIndexData.value[localeIndex.value]?.())?.default,
{
fields: ['title', 'titles', 'text'],
storeFields: ['title', 'titles'],
searchOptions: {
fuzzy: false,
prefix: true,
boost: { title: 4, text: 2, titles: 1 },
...(theme.value.search?.provider === 'local' &&
theme.value.search.options?.miniSearch?.searchOptions)
},
...(theme.value.search?.provider === 'local' &&
theme.value.search.options?.miniSearch?.options)
}
)
)
)
const disableQueryPersistence = computed(() => {
return (
theme.value.search?.provider === 'local' &&
theme.value.search.options?.disableQueryPersistence === true
)
})
const filterText = disableQueryPersistence.value
? ref('')
: useSessionStorage('vitepress:local-search-filter', '')
const showDetailedList = useLocalStorage(
'vitepress:local-search-detailed-list',
theme.value.search?.provider === 'local' &&
theme.value.search.options?.detailedView === true
)
const disableDetailedView = computed(() => {
return (
theme.value.search?.provider === 'local' &&
(theme.value.search.options?.disableDetailedView === true ||
theme.value.search.options?.detailedView === false)
)
})
const buttonText = computed(() => {
const options = theme.value.search?.options ?? theme.value.algolia
return (
options?.locales?.[localeIndex.value]?.translations?.button?.buttonText ||
options?.translations?.button?.buttonText ||
'Search'
)
})
watchEffect(() => {
if (disableDetailedView.value) {
showDetailedList.value = false
}
})
const results: Ref<(SearchResult & Result)[]> = shallowRef([])
const enableNoResults = ref(false)
watch(filterText, () => {
enableNoResults.value = false
})
const mark = computedAsync(async () => {
if (!resultsEl.value) return
return markRaw(new Mark(resultsEl.value))
}, null)
const cache = new LRUCache<string, Map<string, string>>(16) // 16 files
debouncedWatch(
() => [searchIndex.value, filterText.value, showDetailedList.value, isFuzzySearch.value] as const,
async ([index, filterTextValue, showDetailedListValue, fuzzySearchValue], old, onCleanup) => {
if (old?.[0] !== index) {
// in case of hmr
cache.clear()
}
let canceled = false
onCleanup(() => {
canceled = true
})
if (!index) return
// Search with dynamic fuzzy option
const searchOptions = {
fuzzy: isFuzzySearch.value ? 0.2 : false
}
results.value = index
.search(filterTextValue, searchOptions)
.slice(0, 16) as (SearchResult & Result)[]
enableNoResults.value = true
// Highlighting
const mods = showDetailedListValue
? await Promise.all(results.value.map((r) => fetchExcerpt(r.id)))
: []
if (canceled) return
for (const { id, mod } of mods) {
const mapId = id.slice(0, id.indexOf('#'))
let map = cache.get(mapId)
if (map) continue
map = new Map()
cache.set(mapId, map)
const comp = mod.default ?? mod
if (comp?.render || comp?.setup) {
const app = createApp(comp)
app.use(FloatingVue)
app.component('Tooltip', Tooltip)
// Silence warnings about missing components
app.config.warnHandler = () => {}
app.provide(dataSymbol, vitePressData)
Object.defineProperties(app.config.globalProperties, {
$frontmatter: {
get() {
return vitePressData.frontmatter.value
}
},
$params: {
get() {
return vitePressData.page.value.params
}
}
})
const div = document.createElement('div')
app.mount(div)
const headings = div.querySelectorAll('h1, h2, h3, h4, h5, h6')
headings.forEach((el) => {
const href = el.querySelector('a')?.getAttribute('href')
const anchor = href?.startsWith('#') && href.slice(1)
if (!anchor) return
let html = ''
while ((el = el.nextElementSibling!) && !/^h[1-6]$/i.test(el.tagName))
html += el.outerHTML
map!.set(anchor, html)
})
app.unmount()
}
if (canceled) return
}
const terms = new Set<string>()
results.value = results.value.map((r) => {
const [id, anchor] = r.id.split('#')
const map = cache.get(id)
const text = map?.get(anchor) ?? ''
for (const term in r.match) {
terms.add(term)
}
return { ...r, text }
})
await nextTick()
if (canceled) return
await new Promise((r) => {
mark.value?.unmark({
done: () => {
mark.value?.markRegExp(formMarkRegex(terms), { done: r })
}
})
})
const excerpts = el.value?.querySelectorAll('.result .excerpt') ?? []
for (const excerpt of excerpts) {
excerpt
.querySelector('mark[data-markjs="true"]')
?.scrollIntoView({ block: 'center' })
}
// FIXME: without this whole page scrolls to the bottom
resultsEl.value?.firstElementChild?.scrollIntoView({ block: 'start' })
},
{ debounce: 200, immediate: true }
)
async function fetchExcerpt(id: string) {
const file = pathToFile(id.slice(0, id.indexOf('#')))
try {
if (!file) throw new Error(`Cannot find file for id: ${id}`)
return { id, mod: await import(/*@vite-ignore*/ file) }
} catch (e) {
console.error(e)
return { id, mod: {} }
}
}
/* Search input focus */
const searchInput = ref<HTMLInputElement>()
const disableReset = computed(() => {
return filterText.value?.length <= 0
})
function focusSearchInput(select = true) {
searchInput.value?.focus()
select && searchInput.value?.select()
}
onMounted(() => {
focusSearchInput()
})
function onSearchBarClick(event: PointerEvent) {
if (event.pointerType === 'mouse') {
focusSearchInput()
}
}
/* Search keyboard selection */
const selectedIndex = ref(-1)
const disableMouseOver = ref(true)
watch(results, (r) => {
selectedIndex.value = r.length ? 0 : -1
scrollToSelectedResult()
})
function scrollToSelectedResult() {
nextTick(() => {
const selectedEl = document.querySelector('.result.selected')
selectedEl?.scrollIntoView({ block: 'nearest' })
})
}
onKeyStroke('ArrowUp', (event) => {
event.preventDefault()
selectedIndex.value--
if (selectedIndex.value < 0) {
selectedIndex.value = results.value.length - 1
}
disableMouseOver.value = true
scrollToSelectedResult()
})
onKeyStroke('ArrowDown', (event) => {
event.preventDefault()
selectedIndex.value++
if (selectedIndex.value >= results.value.length) {
selectedIndex.value = 0
}
disableMouseOver.value = true
scrollToSelectedResult()
})
const router = useRouter()
onKeyStroke('Enter', (e) => {
if (e.isComposing) return
if (e.target instanceof HTMLButtonElement && e.target.type !== 'submit')
return
const selectedPackage = results.value[selectedIndex.value]
if (e.target instanceof HTMLInputElement && !selectedPackage) {
e.preventDefault()
return
}
if (selectedPackage) {
router.go(selectedPackage.id)
emit('close')
}
})
onKeyStroke('Escape', () => {
emit('close')
})
// Translations
const defaultTranslations: { modal: ModalTranslations } = {
modal: {
displayDetails: 'Display detailed list',
resetButtonTitle: 'Reset search',
backButtonTitle: 'Close search',
noResultsText: 'No results for',
footer: {
selectText: 'to select',
selectKeyAriaLabel: 'enter',
navigateText: 'to navigate',
navigateUpKeyAriaLabel: 'up arrow',
navigateDownKeyAriaLabel: 'down arrow',
closeText: 'to close',
closeKeyAriaLabel: 'escape'
}
}
}
const translate = createSearchTranslate(defaultTranslations)
// Back
onMounted(() => {
// Prevents going to previous site
window.history.pushState(null, '', null)
})
useEventListener('popstate', (event) => {
event.preventDefault()
emit('close')
})
/** Lock body */
const isLocked = useScrollLock(inBrowser ? document.body : null)
onMounted(() => {
nextTick(() => {
isLocked.value = true
nextTick().then(() => activate())
})
})
onBeforeUnmount(() => {
isLocked.value = false
})
function resetSearch() {
filterText.value = ''
nextTick().then(() => focusSearchInput(false))
}
function toggleFuzzySearch() {
isFuzzySearch.value = !isFuzzySearch.value
}
function formMarkRegex(terms: Set<string>) {
return new RegExp(
[...terms]
.sort((a, b) => b.length - a.length)
.map((term) => `(${escapeRegExp(term)})`)
.join('|'),
'gi'
)
}
function onMouseMove(e: MouseEvent) {
if (!disableMouseOver.value) return
const el = (e.target as HTMLElement)?.closest<HTMLAnchorElement>('.result')
const index = Number.parseInt(el?.dataset.index!)
if (index >= 0 && index !== selectedIndex.value) {
selectedIndex.value = index
}
disableMouseOver.value = false
}
</script>
<template>
<Teleport to="body">
<div
ref="el"
role="button"
:aria-owns="results?.length ? 'localsearch-list' : undefined"
aria-expanded="true"
aria-haspopup="listbox"
aria-labelledby="localsearch-label"
class="VPLocalSearchBox"
>
<div class="backdrop" @click="$emit('close')" />
<div class="shell">
<form
class="search-bar"
@pointerup="onSearchBarClick($event)"
@submit.prevent=""
>
<label
:title="buttonText"
id="localsearch-label"
for="localsearch-input"
>
<span aria-hidden="true" class="vpi-search search-icon local-search-icon" />
</label>
<div class="search-actions before">
<button
class="back-button"
:title="translate('modal.backButtonTitle')"
@click="$emit('close')"
>
<span class="vpi-arrow-left local-search-icon" />
</button>
</div>
<input
ref="searchInput"
v-model="filterText"
:aria-activedescendant="selectedIndex > -1 ? ('localsearch-item-' + selectedIndex) : undefined"
aria-autocomplete="both"
:aria-controls="results?.length ? 'localsearch-list' : undefined"
aria-labelledby="localsearch-label"
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="search-input"
id="localsearch-input"
enterkeyhint="go"
maxlength="64"
:placeholder="buttonText"
spellcheck="false"
type="search"
/>
<div class="search-actions">
<button
v-if="!disableDetailedView"
class="toggle-layout-button"
type="button"
:class="{ 'detailed-list': showDetailedList }"
:title="translate('modal.displayDetails')"
@click="
selectedIndex > -1 && (showDetailedList = !showDetailedList)
"
>
<span class="vpi-layout-list local-search-icon" />
</button>
<button
class="toggle-fuzzy-button"
type="button"
:class="{ 'fuzzy-active': isFuzzySearch }"
:title="isFuzzySearch ? 'Switch to Exact Search' : 'Switch to Fuzzy Search'"
@click="toggleFuzzySearch"
>
<span v-if="isFuzzySearch" class="fuzzy-icon">~</span>
<span v-else class="exact-icon">=</span>
</button>
<button
class="clear-button"
type="reset"
:disabled="disableReset"
:title="translate('modal.resetButtonTitle')"
@click="resetSearch"
>
<span class="vpi-delete local-search-icon" />
</button>
</div>
</form>
<ul
ref="resultsEl"
:id="results?.length ? 'localsearch-list' : undefined"
:role="results?.length ? 'listbox' : undefined"
:aria-labelledby="results?.length ? 'localsearch-label' : undefined"
class="results"
@mousemove="onMouseMove"
>
<li
v-for="(p, index) in results"
:key="p.id"
:id="'localsearch-item-' + index"
:aria-selected="selectedIndex === index ? 'true' : 'false'"
role="option"
>
<a
:href="p.id"
class="result"
:class="{
selected: selectedIndex === index
}"
:aria-label="[...p.titles, p.title].join(' > ')"
@mouseenter="!disableMouseOver && (selectedIndex = index)"
@focusin="selectedIndex = index"
@click="$emit('close')"
:data-index="index"
>
<div>
<div class="titles">
<span class="title-icon">#</span>
<span
v-for="(t, index) in p.titles"
:key="index"
class="title"
>
<span class="text" v-html="t" />
<span class="vpi-chevron-right local-search-icon" />
</span>
<span class="title main">
<span class="text" v-html="p.title" />
</span>
</div>
<div v-if="showDetailedList" class="excerpt-wrapper">
<div v-if="p.text" class="excerpt" inert>
<div class="vp-doc" v-html="p.text" />
</div>
<div class="excerpt-gradient-bottom" />
<div class="excerpt-gradient-top" />
</div>
</div>
</a>
</li>
<li
v-if="filterText && !results.length && enableNoResults"
class="no-results"
>
{{ translate('modal.noResultsText') }} "<strong>{{ filterText }}</strong
>"
</li>
</ul>
<div class="search-keyboard-shortcuts">
<span>
<kbd :aria-label="translate('modal.footer.navigateUpKeyAriaLabel')">
<span class="vpi-arrow-up navigate-icon" />
</kbd>
<kbd :aria-label="translate('modal.footer.navigateDownKeyAriaLabel')">
<span class="vpi-arrow-down navigate-icon" />
</kbd>
{{ translate('modal.footer.navigateText') }}
</span>
<span>
<kbd :aria-label="translate('modal.footer.selectKeyAriaLabel')">
<span class="vpi-corner-down-left navigate-icon" />
</kbd>
{{ translate('modal.footer.selectText') }}
</span>
<span>
<kbd :aria-label="translate('modal.footer.closeKeyAriaLabel')">esc</kbd>
{{ translate('modal.footer.closeText') }}
</span>
</div>
</div>
</div>
</Teleport>
</template>
<style scoped>
.VPLocalSearchBox {
position: fixed;
z-index: 100;
inset: 0;
display: flex;
}
.backdrop {
position: absolute;
inset: 0;
background: var(--vp-backdrop-bg-color);
transition: opacity 0.5s;
}
.shell {
position: relative;
padding: 12px;
margin: 64px auto;
display: flex;
flex-direction: column;
gap: 16px;
background: var(--vp-local-search-bg);
width: min(100vw - 60px, 900px);
height: min-content;
max-height: min(100vh - 128px, 900px);
border-radius: 6px;
}
@media (max-width: 767px) {
.shell {
margin: 0;
width: 100vw;
height: 100vh;
max-height: none;
border-radius: 0;
}
}
.search-bar {
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
display: flex;
align-items: center;
padding: 0 12px;
cursor: text;
}
@media (max-width: 767px) {
.search-bar {
padding: 0 8px;
}
}
.search-bar:focus-within {
border-color: var(--vp-c-brand-1);
}
.local-search-icon {
display: block;
font-size: 18px;
}
.navigate-icon {
display: block;
font-size: 14px;
}
.search-icon {
margin: 8px;
}
@media (max-width: 767px) {
.search-icon {
display: none;
}
}
.search-input {
padding: 6px 12px;
font-size: inherit;
width: 100%;
}
@media (max-width: 767px) {
.search-input {
padding: 6px 4px;
}
}
.search-actions {
display: flex;
gap: 4px;
}
@media (any-pointer: coarse) {
.search-actions {
gap: 8px;
}
}
@media (min-width: 769px) {
.search-actions.before {
display: none;
}
}
.search-actions button {
padding: 8px;
}
.search-actions button:not([disabled]):hover,
.toggle-layout-button.detailed-list {
color: var(--vp-c-brand-1);
}
.search-actions button.clear-button:disabled {
opacity: 0.37;
}
.toggle-fuzzy-button {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
font-size: 16px;
font-weight: bold;
border-radius: 4px;
transition: all 0.2s;
}
.toggle-fuzzy-button .fuzzy-icon,
.toggle-fuzzy-button .exact-icon {
font-size: 18px;
font-weight: bold;
line-height: 1;
}
.toggle-fuzzy-button:hover {
background: var(--vp-c-bg-soft);
}
.toggle-fuzzy-button.fuzzy-active {
color: var(--vp-c-brand-1);
background: var(--vp-c-bg-soft);
}
.search-keyboard-shortcuts {
font-size: 0.8rem;
opacity: 75%;
display: flex;
flex-wrap: wrap;
gap: 16px;
line-height: 14px;
}
.search-keyboard-shortcuts span {
display: flex;
align-items: center;
gap: 4px;
}
@media (max-width: 767px) {
.search-keyboard-shortcuts {
display: none;
}
}
.search-keyboard-shortcuts kbd {
background: rgba(128, 128, 128, 0.1);
border-radius: 4px;
padding: 3px 6px;
min-width: 24px;
display: inline-block;
text-align: center;
vertical-align: middle;
border: 1px solid rgba(128, 128, 128, 0.15);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);
}
.results {
display: flex;
flex-direction: column;
gap: 6px;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
}
.result {
display: flex;
align-items: center;
gap: 8px;
border-radius: 4px;
transition: none;
line-height: 1rem;
border: solid 2px var(--vp-local-search-result-border);
outline: none;
}
.result > div {
margin: 12px;
width: 100%;
overflow: hidden;
}
@media (max-width: 767px) {
.result > div {
margin: 8px;
}
}
.titles {
display: flex;
flex-wrap: wrap;
gap: 4px;
position: relative;
z-index: 1001;
padding: 2px 0;
}
.title {
display: flex;
align-items: center;
gap: 4px;
}
.title.main {
font-weight: 500;
}
.title-icon {
opacity: 0.5;
font-weight: 500;
color: var(--vp-c-brand-1);
}
.title svg {
opacity: 0.5;
}
.result.selected {
--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);
border-color: var(--vp-local-search-result-selected-border);
}
.excerpt-wrapper {
position: relative;
}
.excerpt {
opacity: 50%;
pointer-events: none;
max-height: 140px;
overflow: hidden;
position: relative;
margin-top: 4px;
}
.result.selected .excerpt {
opacity: 1;
}
.excerpt :deep(*) {
font-size: 0.8rem !important;
line-height: 130% !important;
}
.titles :deep(mark),
.excerpt :deep(mark) {
background-color: var(--vp-local-search-highlight-bg);
color: var(--vp-local-search-highlight-text);
border-radius: 2px;
padding: 0 2px;
}
.excerpt :deep(.vp-code-group) .tabs {
display: none;
}
.excerpt :deep(.vp-code-group) div[class*='language-'] {
border-radius: 8px !important;
}
.excerpt-gradient-bottom {
position: absolute;
bottom: -1px;
left: 0;
width: 100%;
height: 8px;
background: linear-gradient(transparent, var(--vp-local-search-result-bg));
z-index: 1000;
}
.excerpt-gradient-top {
position: absolute;
top: -1px;
left: 0;
width: 100%;
height: 8px;
background: linear-gradient(var(--vp-local-search-result-bg), transparent);
z-index: 1000;
}
.result.selected .titles,
.result.selected .title-icon {
color: var(--vp-c-brand-1) !important;
}
.no-results {
font-size: 0.9rem;
text-align: center;
padding: 12px;
}
svg {
flex: none;
}
</style>

View File

@@ -21,19 +21,22 @@ import { loadProgress } from './composables/nprogress'
import { useThemeHandler } from './themes/themeHandler'
import Layout from './Layout.vue'
import Post from './PostLayout.vue'
import './style.scss'
import 'virtual:uno.css'
import Feedback from './components/Feedback.vue'
import FloatingVue from 'floating-vue'
import 'floating-vue/dist/style.css'
import Tooltip from './components/Tooltip.vue'
export default {
extends: DefaultTheme,
Layout,
enhanceApp({ router, app }) {
app.use(FloatingVue)
app.use(Components)
app.component('Post', Post)
app.component('Feedback', Feedback)
app.component('Tooltip', Tooltip)
loadProgress(router)
// Initialize theme handler
useThemeHandler()

View File

@@ -81,6 +81,40 @@
--vp-custom-block-danger-text-deep: theme('colors.carnation.200');
}
.monochrome {
[class*='i-'],
svg,
img:not(.VPImage) {
filter: grayscale(100%);
}
.switch,
.switch * {
filter: none;
}
.switch {
background-color: #000;
border-color: #5a5a5a;
}
.switch .thumb {
background-color: #fff !important;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25), var(--vp-shadow-1);
}
.switch.enabled {
background-color: #fff;
border-color: #5a5a5a;
}
.switch.enabled .thumb {
background-color: #000 !important;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.25), var(--vp-shadow-1);
}
}
.vp-doc a {
color: var(--vp-c-brand-1);
text-decoration: underline;
@@ -138,17 +172,13 @@
*/
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
120deg,
#c4b5fd 30%,
#7bc5e4
);
--vp-home-hero-name-background: -webkit-linear-gradient(120deg,
#c4b5fd 30%,
#7bc5e4);
--vp-home-hero-image-background-image: linear-gradient(
-45deg,
#c4b5fd 50%,
#47caff 50%
);
--vp-home-hero-image-background-image: linear-gradient(-45deg,
#c4b5fd 50%,
#47caff 50%);
--vp-home-hero-image-filter: blur(44px);
}
@@ -223,6 +253,7 @@
animation: nprogress-spinner 400ms linear infinite;
}
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
@@ -253,7 +284,7 @@
}
}
#VPContent strong > a {
#VPContent strong>a {
font-weight: bold;
}

View File

@@ -14,10 +14,12 @@
* limitations under the License.
*/
import { catppuccinTheme } from './catppuccin'
import { monochromeTheme } from './monochrome'
import type { ThemeRegistry } from '../types'
export const themeRegistry: ThemeRegistry = {
catppuccin: catppuccinTheme,
monochrome: monochromeTheme,
}
export { catppuccinTheme }
export { catppuccinTheme, monochromeTheme }

Some files were not shown because too many files have changed in this diff Show More