'
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this issue! Please select your issue type.
+ - type: markdown
+ attributes:
+ value: |
+ ### Things to note
+ * Anyone can suggest [changes or corrections](https://rentry.org/fmhyedit) to the wiki. Please read our [Contribution Guide](https://rentry.co/Contrib-Guide) before trying to add or remove anything.
+ * If you're adding a new site, please [search](https://raw.githubusercontent.com/fmhy/FMHYedit/main/single-page) (control + f) first to make sure we don't already have it.
+ * Approved changes will be applied to the [site](https://fmhy.net) and all [đ backups](https://github.com/fmhy/FMHY/wiki/Backups).
+ * You can send us stuff directly via [đŦ Discord](https://discord.gg/5W9QJKuPkD).
+ * You can also check out our [website](https://fmhy.net) and the [posts](https://fmhy.net/posts) section to know about any major updates to the wiki.
+ - type: dropdown
+ id: type
+ attributes:
+ label: Type
+ description: Type that best describes this issue.
+ options:
+ - Bad sites
+ - Grammar / Markdown
+ - Site suggestion
+ - Wiki section suggestion
+ default: 0
+ validations:
+ required: true
+ - type: textarea
+ id: context
+ attributes:
+ label: Add additional context
+ description:
+ A clear and concise description of what the issue is, as per your
+ selected issue type.
+ placeholder: https://fmhy.net is cool and should be added
+ validations:
+ required: true
diff --git a/.github/POST_TEMPLATE.md b/.github/POST_TEMPLATE.md
new file mode 100644
index 000000000..40899fe5b
--- /dev/null
+++ b/.github/POST_TEMPLATE.md
@@ -0,0 +1,53 @@
+### Post Template
+
+> [!NOTE]
+> This is a template for creating a post for the freemediaheckyeah blog, and is meant for **collaborators** only.
+
+Notes:
+
+- The title should be a short, descriptive title.
+- The date should be in the format `YYYY-MM-DD`.
+- The filename should be in the format `month-year.md`.
+- The description should be a short, descriptive description of the post.
+- Authors should be in the format `['username', ....]`
+- The ending shouldn't have a line break (`---`/`***`).
+- Links to the website should be turned into relative links, i.e. `[Text Tools](https://fmhy.net/text-tools)` -> `[Text Tools](/text-tools)`.
+
+Template:
+```
+---
+title: Monthly Updates [Month]
+description: Month 20YY updates
+date: 20YY-MM-DD
+next: false
+aside: left
+prev: false
+sidebar: false
+footer: true
+---
+
+
+
+:::info
+These update threads only contains major updates. If you're interested
+in seeing all minor changes you can follow our
+[Commits Page](https://github.com/fmhy/FMHYedit/commits/main) on GitHub or
+[Updates Channel](https://redd.it/17f8msf) in Discord.
+:::
+
+### Wiki Updates
+
+....
+
+---
+
+### Stars Added â
+
+....
+
+---
+
+### Things Removed
+
+....
+```
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000..eafce92c0
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,22 @@
+
+
+## Description
+
+
+## Context
+
+
+
+## Types of changes
+
+- [ ] Bad / Deleted sites removal
+- [ ] Grammar / Markdown fixes
+- [ ] Content addition (sites, projects, tools, etc.)
+- [ ] New Wiki section
+
+## Checklist:
+
+
+- [ ] I have read the [contribution guide](https://rentry.co/Contrib-Guide).
+- [ ] I have made sure to [search](https://feedback.tasky.workers.dev/single-page) before making any changes.
+- [ ] My code follows the code style of this project.
diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 000000000..fe1986073
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,38 @@
+# FMHYedit
+
+
+
+**The largest collection of free stuff on the internet!**
+
+## đ Wiki
+
+- Website: [fmhy.net](https://fmhy.net)
+- News & Monthly Updates: [fmhy.net/posts](https://fmhy.net/posts)
+- Backups: https://github.com/fmhy/FMHY/wiki/Backups
+
+## đ Contribute
+
+We invite you to contribute and help improve the wiki! đ
+
+Here are a few ways you can get involved:
+
+* Anyone can suggest changes or corrections to the wiki. Please read our [contribution guide](../CONTRIBUTING.md) before trying to add or remove anything.
+* If you're adding a new site, please [search](https://api.fmhy.net/single-page) (control + f) first to make sure we don't already have it.
+* Approved changes will be applied to the [site](https://fmhy.net) and all [đ backups](https://github.com/fmhy/FMHY/wiki/Backups).
+* You can send us stuff directly via [đŦ Discord](https://discord.gg/5W9QJKuPkD).
+* To help us find new sites, check out these lists: [site hunting](https://www.reddit.com/r/FREEMEDIAHECKYEAH/wiki/find-new-sites/) / [go through](https://rentry.org/oghty).
+
+***
+
+Emoji Legend:
+
+* đ - 3rd Party Indexes
+* âĒī¸ - Storage Page Links
+* â - Community Recommendations
+
+
+## đ Follow
+
+
+
+
diff --git a/.github/assets/discord.svg b/.github/assets/discord.svg
new file mode 100644
index 000000000..574a3e99d
--- /dev/null
+++ b/.github/assets/discord.svg
@@ -0,0 +1 @@
+
diff --git a/.github/assets/firefish.svg b/.github/assets/firefish.svg
new file mode 100644
index 000000000..658e08ab4
--- /dev/null
+++ b/.github/assets/firefish.svg
@@ -0,0 +1 @@
+
diff --git a/.github/assets/github.svg b/.github/assets/github.svg
new file mode 100644
index 000000000..4f6b544c5
--- /dev/null
+++ b/.github/assets/github.svg
@@ -0,0 +1 @@
+
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 000000000..5a14be831
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,7 @@
+# See https://github.com/actions/labeler
+
+docs:
+ - '**/*.md'
+
+core:
+ - '.vitepress/**'
diff --git a/.github/workflows/deploy-api.yml b/.github/workflows/deploy-api.yml
new file mode 100644
index 000000000..ad76b9d6b
--- /dev/null
+++ b/.github/workflows/deploy-api.yml
@@ -0,0 +1,45 @@
+name: Deploy API
+
+on:
+ workflow_dispatch:
+
+concurrency: ${{ github.workflow }}-${{ github.ref }}
+
+jobs:
+ ci:
+ name: Release
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [20]
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 6
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Build
+ run: pnpm api:build
+ env:
+ WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
+ NITRO_PRESET: cloudflare
+
+ - name: Publish to Cloudflare
+ uses: cloudflare/wrangler-action@v3
+ with:
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ vars: WEBHOOK_URL
+ env:
+ WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml
new file mode 100644
index 000000000..9d436e2c1
--- /dev/null
+++ b/.github/workflows/deploy-gh-pages.yml
@@ -0,0 +1,54 @@
+name: Deploy to GitHub Pages
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 1
+ - uses: pnpm/action-setup@v2
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 20
+ cache: pnpm
+ - name: Setup Pages
+ uses: actions/configure-pages@v3
+ - name: Install dependencies
+ run: pnpm install
+ - name: Build with VitePress
+ run: |
+ pnpm docs:build
+ touch docs/.vitepress/dist/.nojekyll
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v2
+ with:
+ path: docs/.vitepress/dist
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ needs: build
+ runs-on: ubuntu-latest
+ name: Deploy
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v2
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 000000000..fc0457f62
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,49 @@
+name: 'Pull Request Housekeeping'
+
+on: [pull_request_target]
+
+jobs:
+ triage:
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ - name: Label PRs
+ uses: actions/labeler@v4
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ auto-assign:
+ runs-on: ubuntu-latest
+ needs: triage
+ steps:
+ - name: Check if PR has 'core' label
+ id: check_label
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const prNumber = context.payload.pull_request.number;
+ const { data: labels } = await github.rest.issues.listLabelsOnIssue({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ });
+
+ const hasCoreLabel = labels.some(label => label.name === 'core');
+ return hasCoreLabel;
+
+ - name: Auto-assign to PR
+ if: steps.check_label.outputs.result == 'true'
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const prNumber = context.payload.pull_request.number;
+ await github.rest.issues.addAssignees({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ assignees: ['taskylizard'],
+ });
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..29a87bf7a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+**/.vitepress/dist
+**/.vitepress/cache
+node_modules
+*.log*
+.nitro
+.cache
+.output
+.env
+dist
+.eslintcache
+docs/.vitepress/.temp
diff --git a/.gitpod.yml b/.gitpod.yml
new file mode 100644
index 000000000..c6a1de11e
--- /dev/null
+++ b/.gitpod.yml
@@ -0,0 +1,7 @@
+tasks:
+ - init: pnpm install
+ command: pnpm run docs:dev
+
+ports:
+ - port: 5173
+ onOpen: open-preview
diff --git a/.mise.toml b/.mise.toml
new file mode 100644
index 000000000..a6b9ba729
--- /dev/null
+++ b/.mise.toml
@@ -0,0 +1,3 @@
+# https://github.com/vitejs/vite/issues/17291
+[tools]
+node = "21"
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 000000000..bec116745
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,3 @@
+package-manager-strict=false
+shell-emulator=true
+auto-install-peers=false
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..18f1a04b0
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,2 @@
+**/*.md
+pnpm-lock.yaml
diff --git a/.prettierrc.yaml b/.prettierrc.yaml
new file mode 100644
index 000000000..88e0a1580
--- /dev/null
+++ b/.prettierrc.yaml
@@ -0,0 +1,6 @@
+proseWrap: always
+semi: false
+singleQuote: true
+printWidth: 80
+trailingComma: none
+htmlWhitespaceSensitivity: ignore
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..3d1c11d96
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,110 @@
+# How to Edit FMHY
+
+There are three ways you can contribute to this repository:
+- [Link submissions](#submitting-a-link)
+- [Reporting a site](#reporting-a-site)
+- [Changes to the website itself](#making-changes)
+
+## Submitting a Link
+
+> [!NOTE]
+> If you haven't tested the link you'd like to submit, especially if it's a DDL site, please open an **[Issue](https://github.com/fmhy/FMHYedit/issues)** or reach out to us on **[Discord](https://discord.gg/5W9QJKuPkD)** rather than making a Pull Request.
+
+1. Before submitting a link, please **[search](https://redd.it/105xraz)** to make sure it's not already in the wiki.
+
+2. The order of priority is: **Site > Git Repository > Store Link**
+Please only use the store link if there's neither a site nor a Git repository available for the app/extension you'd like to submit.
+
+3. Always check to see if the site you'd like to submit has a Discord / Telegram server you can link with it.
+
+4. Never edit the single-page, it contains all the pages of the wiki and gets updated automatically.
+
+5. Find a suitable category for the link and then submit it by making a **[Pull Request](https://github.com/fmhy/FMHYedit/pulls)**.
+
+#### Don't Submit:
+
+**đšī¸ Emulators**
+They're already on the **[Game Tech Wiki](https://emulation.gametechwiki.com/index.php/Main_Page)**.
+
+**đģ Leeches**
+They're already on the **[File Hosting Wiki](https://filehostlist.miraheze.org/wiki/Free_Premium_Leeches)**.
+
+**đ§ Distros**
+They're already on **[DistroWatch](https://distrowatch.com/)**.
+
+**đ˛ Mining / Betting Sites**
+Don't post anything related to betting, mining, BINs, CCs, etc.
+
+**đŽ Multiplayer Game Hacks**
+Don't post any hacks/exploits that give unfair advantages in multiplayer games.
+
+## Reporting a Site
+
+> [!TIP]
+> If you want to make bigger changes to the wiki, such as debloating or restructuring a page/section, please discuss those changes with us via **[Discord](https://discord.gg/5W9QJKuPkD)** before making a **[Pull Request](https://github.com/fmhy/FMHYedit/pulls)**.
+
+You can do one of the following:
+
+- Open an **[Issue](https://github.com/fmhy/FMHYedit/issues)** or a **[Pull Request](https://github.com/fmhy/FMHYedit/pulls)** and don't forget to explain why you think the site(s) in question should be removed, unstarred, and/or changed.
+
+- Alternatively, you can reach out to us on **[Discord](https://discord.gg/5W9QJKuPkD)** if you're unsure whether the site should be reported or if you'd like to discuss your report with more people.
+
+## Making changes
+
+If you want to make changes with instant site feedback, or are simply going to work with the site, you can do so with these 3 ways:
+
+- [Using gitpod.io or GitHub Codespaces (recommended)](#using-gitpod-io-or-github-codespaces)
+- [Using the GitHub editor](#using-the-github-editor)
+- [Manually setting up a development environment](#manually-setting-up-a-development-environment)
+
+> [!TIP]
+> You can just use our [đŦ Discord](https://redd.it/17f8msf) to send us sites or any changes.
+
+### Using gitpod.io or GitHub Codespaces
+
+You can use either [gitpod.io](https://gitpod.io/) or [GitHub Codespaces](https://github.com/features/codespaces) to edit the wiki.
+
+Follow these steps:
+
+1. Fork the repository by clicking the "Fork" button in the top right corner.
+
+2. Now, to make changes, you can either use gitpod.io or GitHub Codespaces.
+
+#### Gitpod.io
+
+Login to your GitHub account and click on the "New Workspace" button. Then select your fork and you should be in your gitpod workspace.
+
+To close the workspace, click on the "Gitpod" button at the bottom left corner then type "Stop Workspace" and hit enter.
+
+#### GitHub Codespaces
+
+Click on the "Code" button on the top right corner of the page and select "Codespaces" from the dropdown menu.
+
+To close the workspace, click on the "Code" button at the top right corner then click on "Stop Codespace" and hit enter.
+
+### Using the GitHub editor
+
+1. Fork the repository by clicking the "Fork" button in the top right corner. You can open your repository in a VSCode-like environment by pressing `.` (dot) in your fork's homepage which will take you to `github.dev`.
+
+2. Find the file you want to edit. Find the "Edit" icon (of a pencil) and click on it.
+Select edit button and make your changes.
+
+
+3. Scroll down and select "Propose changes", and "Create Pull Request" on the next page, and don't forget to explain why you think the site(s) in question should be removed, unstarred, and/or changed.
+
+
+
+
+### Manually setting up a development environment
+
+1. Fork the repository by clicking the "Fork" button in the top right corner.
+
+2. Make sure you have [Node.js](https://nodejs.org/en/), [pnpm](https://pnpm.io/), [git](https://git-scm.com/), and [VSCode](https://code.visualstudio.com/) or any other editor installed.
+
+3. Clone your forked repository to your local machine.
+
+4. Open the cloned repository in your editor of choice. Find the file you want to work on, make changes.
+
+5. Add your changes with git (`git add `) and commit (`git commit -m "commit message"`), then push them (`git push`).
+
+6. Create a pull request by clicking the "New Pull Request" button in your forked repository, and don't forget to explain why you think the site(s) in question should be removed, unstarred, and/or changed.
diff --git a/api/middleware/cors.ts b/api/middleware/cors.ts
new file mode 100644
index 000000000..4e8af9dd1
--- /dev/null
+++ b/api/middleware/cors.ts
@@ -0,0 +1,11 @@
+import { corsEventHandler } from 'nitro-cors'
+
+export default corsEventHandler(
+ (_event) => {
+ /** no-op */
+ },
+ {
+ origin: '*',
+ methods: '*'
+ }
+)
diff --git a/api/routes/feedback.post.ts b/api/routes/feedback.post.ts
new file mode 100644
index 000000000..43589111d
--- /dev/null
+++ b/api/routes/feedback.post.ts
@@ -0,0 +1,45 @@
+import { fetcher } from 'itty-fetcher'
+import {
+ FeedbackSchema,
+ getFeedbackOption
+} from '../../docs/.vitepress/types/Feedback'
+
+export default defineEventHandler(async (event) => {
+ const { message, page, type } = await readValidatedBody(
+ event,
+ FeedbackSchema.parseAsync
+ )
+ const env = useRuntimeConfig(event)
+
+ // FIXME: somehow this is not working, but it worked before
+ // const path = 'feedback'
+ //
+ // const { success } = await env.MY_RATE_LIMITER.limit({ key: path })
+ // if (!success) {
+ // return new Response('429 Failure â global rate limit exceeded', {
+ // status: 429
+ // })
+ // }
+
+ let description = `${message}\n\n`
+ if (page) description += `**Page:** \`${page}\``
+
+ await fetcher()
+ .post(env.WEBHOOK_URL, {
+ username: 'Feedback',
+ avatar_url:
+ 'https://i.kym-cdn.com/entries/icons/facebook/000/043/403/cover3.jpg',
+ embeds: [
+ {
+ color: 3447003,
+ title: getFeedbackOption(type).label,
+ description
+ }
+ ]
+ })
+ .catch((error) => {
+ throw new Error(error)
+ })
+
+ return { status: 'ok' }
+})
diff --git a/api/routes/index.ts b/api/routes/index.ts
new file mode 100644
index 000000000..cb36c7c7a
--- /dev/null
+++ b/api/routes/index.ts
@@ -0,0 +1,3 @@
+export default eventHandler(() => {
+ return { nitro: 'works' }
+})
diff --git a/api/routes/single-page.ts b/api/routes/single-page.ts
new file mode 100644
index 000000000..1002f8b20
--- /dev/null
+++ b/api/routes/single-page.ts
@@ -0,0 +1,69 @@
+import { fetcher } from 'itty-fetcher'
+
+// Look inside tbe docs directory
+const GITHUB_REPO = 'https://api.github.com/repos/fmhy/FMHYEdit/contents/docs/'
+const EXCLUDE_FILES = ['README.md', 'index.md', 'feedback.md', 'posts.md']
+const EXCLUDE_DIRECTORIES = ['posts/']
+
+interface File {
+ name: string
+ path: string
+ sha: string
+ size: number
+ url: string
+ html_url: string
+ git_url: string
+ download_url: string | null
+ type: string
+ _links: {
+ self: string
+ git: string
+ html: string
+ }
+}
+
+export default defineEventHandler(async (event) => {
+ let body = '\n'
+ const f = fetcher({
+ headers: {
+ 'User-Agent': 'taskylizard'
+ }
+ })
+
+ try {
+ // Fetch the list of files in the repository
+ const files = await f.get(GITHUB_REPO)
+
+ // Filter out the excluded files and non-markdown files
+ const markdownFiles = files.filter((file: File) => {
+ const isExcludedFile = EXCLUDE_FILES.includes(file.name)
+ const isInExcludedDirectory = EXCLUDE_DIRECTORIES.some((dir) =>
+ file.path.startsWith(dir)
+ )
+ const isMarkdownFile = file.name.endsWith('.md')
+
+ return isMarkdownFile && !isExcludedFile && !isInExcludedDirectory
+ })
+
+ // console.info(markdownFiles.map((f) => f.name))
+
+ // Fetch and concatenate the contents of the markdown files
+ const contents = await Promise.all(
+ markdownFiles.map(async (file: File) => {
+ const content = await f.get(file.download_url)
+ return content
+ })
+ )
+
+ body += contents.join('\n\n')
+ } catch (error) {
+ return {
+ status: 500,
+ body: `Error fetching markdown files: ${error.message}`
+ }
+ }
+
+ // biome-ignore lint/correctness/noUndeclaredVariables:
+ appendResponseHeader(event, 'content-type', 'text/markdown;charset=utf-8')
+ return body
+})
diff --git a/biome.json b/biome.json
new file mode 100644
index 000000000..1b2f3c378
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,32 @@
+{
+ "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
+ "extends": ["@taskylizard/biome-config"],
+ "files": {
+ "ignore": ["docs/.vitepress/**/*.vue", "docs/.vitepress/vue-shim.d.ts"]
+ },
+ "formatter": {
+ "enabled": false
+ },
+ "javascript": {
+ "globals": [
+ "defineNitroConfig",
+ "eventHandler",
+ "useRuntimeConfig",
+ "readValidatedBody",
+ "defineEventHandler"
+ ]
+ },
+ "linter": {
+ "rules": {
+ "style": {
+ "useFilenamingConvention": {
+ "level": "info",
+ "options": {
+ "filenameCases": ["camelCase", "PascalCase"]
+ }
+ },
+ "noDefaultExport": "off"
+ }
+ }
+ }
+}
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
new file mode 100644
index 000000000..b14511fd7
--- /dev/null
+++ b/docs/.vitepress/config.mts
@@ -0,0 +1,131 @@
+import consola from 'consola'
+import { basename } from 'pathe'
+import UnoCSS from 'unocss/vite'
+import { defineConfig } from 'vitepress'
+import {
+ commitRef,
+ feedback,
+ meta,
+ search,
+ sidebar,
+ socialLinks
+} from './constants'
+import { generateFeed, generateImages, generateMeta } from './hooks'
+import { defs, emojiRender, movePlugin } from './markdown/emoji'
+import { toggleStarredPlugin } from './markdown/toggleStarred'
+import { transformer } from './transformer'
+
+// @unocss-include
+
+const baseUrl = process.env.GITHUB_ACTIONS ? '/FMHYedit' : '/'
+export default defineConfig({
+ title: 'FMHY',
+ description: meta.description,
+ titleTemplate: ':title âĸ freemediaheckyeah',
+ lang: 'en-US',
+ lastUpdated: false,
+ cleanUrls: true,
+ appearance: 'dark',
+ base: baseUrl,
+ srcExclude: ['README.md', 'single-page'],
+ ignoreDeadLinks: true,
+ sitemap: {
+ hostname: meta.hostname
+ },
+ head: [
+ ['meta', { name: 'theme-color', content: '#7bc5e4' }],
+ ['meta', { name: 'og:type', content: 'website' }],
+ ['meta', { name: 'og:locale', content: 'en' }],
+ ['link', { rel: 'icon', href: '/test.png' }],
+ // PWA
+ ['link', { rel: 'icon', href: '/test.png', type: 'image/svg+xml' }],
+ ['link', { rel: 'alternate icon', href: '/test.png' }],
+ ['link', { rel: 'mask-icon', href: '/test.png', color: '#7bc5e4' }],
+ // prettier-ignore
+ ["meta", { name: "keywords", content: meta.keywords.join(" ") }],
+ ['link', { rel: 'apple-touch-icon', href: '/test.png', sizes: '192x192' }]
+ ],
+ transformHead: async (context) => generateMeta(context, meta.hostname),
+ buildEnd: async (context) => {
+ generateImages(context)
+ .then(() => generateFeed(context))
+ .finally(() => consola.success('Success!'))
+ },
+ vite: {
+ optimizeDeps: { exclude: ['workbox-window'] },
+ plugins: [
+ UnoCSS({
+ configFile: '../unocss.config.ts'
+ }),
+ transformer(),
+ {
+ name: 'custom:adjust-order',
+ configResolved(c) {
+ movePlugin(
+ c.plugins as any,
+ 'vitepress',
+ 'before',
+ 'unocss:transformers:pre'
+ )
+ movePlugin(
+ c.plugins as any,
+ 'custom:transform-content',
+ 'before',
+ 'vitepress'
+ )
+ }
+ }
+ ],
+ build: {
+ // Shut the fuck up
+ chunkSizeWarningLimit: Number.POSITIVE_INFINITY
+ }
+ },
+ markdown: {
+ emoji: { defs },
+ config(md) {
+ md.use(emojiRender)
+ md.use(toggleStarredPlugin)
+ }
+ },
+ themeConfig: {
+ search,
+ footer: {
+ message: `${feedback} (rev: ${commitRef})`,
+ copyright: `Š ${new Date().getFullYear()}, nbats, taskylizard and contributors.`
+ },
+ editLink: {
+ pattern: 'https://github.com/fmhy/FMHYEdit/edit/main/docs/:path',
+ text: 'đ Edit this page'
+ },
+ outline: 'deep',
+ logo: '/fmhy.ico',
+ nav: [
+ { text: 'đ Beginners Guide', link: '/beginners-guide' },
+ { text: 'đ Glossary', link: 'https://rentry.org/The-Piracy-Glossary' },
+ { text: 'đ Guides', link: 'https://rentry.co/fmhy-guides' },
+ {
+ text: 'đž Backups',
+ link: 'https://github.com/fmhy/FMHY/wiki/Backups'
+ },
+ {
+ text: 'đĒ Ecosystem',
+ items: [
+ { text: 'đ Search', link: '/posts/search' },
+ { text: 'đ° Posts', link: '/posts' },
+ { text: 'đŦ Feedback', link: '/feedback' },
+ { text: 'đ Wallpapers', link: '/other/wallpapers' },
+ { text: 'đ snowbin', link: 'https://pastes.fmhy.net' },
+ { text: 'đ SearXNG', link: 'https://searx.fmhy.net/' },
+ { text: 'đ Whoogle', link: 'https://whoogle.fmhy.net/' },
+ {
+ text: 'đ Bookmarks',
+ link: 'https://github.com/Rust1667/make-fmhy-bookmarks'
+ }
+ ]
+ }
+ ],
+ sidebar,
+ socialLinks
+ }
+})
diff --git a/docs/.vitepress/constants.ts b/docs/.vitepress/constants.ts
new file mode 100644
index 000000000..7029c71a5
--- /dev/null
+++ b/docs/.vitepress/constants.ts
@@ -0,0 +1,229 @@
+import type { DefaultTheme } from 'vitepress'
+import { transform, transformGuide } from './transformer'
+// @unocss-include
+
+export const meta = {
+ name: 'freemediaheckyeah',
+ description: 'The largest collection of free stuff on the internet!',
+ hostname: 'https://fmhy.net',
+ keywords: ['stream', 'movies', 'gaming', 'reading', 'anime']
+}
+
+export const commitRef =
+ process.env.CF_PAGES && process.env.CF_PAGES_COMMIT_SHA
+ ? `${process.env.CF_PAGES_COMMIT_SHA.slice(0, 8)}`
+ : 'dev'
+
+export const feedback = `Made with â¤`
+
+export const search: DefaultTheme.Config['search'] = {
+ options: {
+ _render(src, env, md) {
+ let contents = src
+ // I do this as env.frontmatter is not available until I call `md.render`
+ if (contents.includes('Beginners Guide'))
+ contents = transformGuide(contents)
+ contents = transform(contents)
+ const html = md.render(contents, env)
+ return html
+ },
+ miniSearch: {
+ options: {
+ tokenize: (text) => text.split(/[\n\r #%*,=/:;?[\]{}()&]+/u), // simplified charset: removed [-_.@] and non-english chars (diacritics etc.)
+ processTerm: (term, fieldName) => {
+ // biome-ignore lint/style/noParameterAssign: h
+ term = term
+ .trim()
+ .toLowerCase()
+ .replace(/^\.+/, '')
+ .replace(/\.+$/, '')
+ const stopWords = [
+ 'frontmatter',
+ '$frontmatter.synopsis',
+ 'and',
+ 'about',
+ 'but',
+ 'now',
+ 'the',
+ 'with',
+ 'you'
+ ]
+ if (term.length < 2 || stopWords.includes(term)) return false
+
+ if (fieldName === 'text') {
+ const parts = term.split('.')
+ if (parts.length > 1) {
+ const newTerms = [term, ...parts]
+ .filter((t) => t.length >= 2)
+ .filter((t) => !stopWords.includes(t))
+ return newTerms
+ }
+ }
+ return term
+ }
+ },
+ searchOptions: {
+ combineWith: 'AND',
+ fuzzy: true,
+ // @ts-ignore
+ boostDocument: (
+ documentId,
+ term,
+ storedFields: Record
+ ) => {
+ const titles = (storedFields?.titles as string[])
+ .filter((t) => Boolean(t))
+ .map((t) => t.toLowerCase())
+ // Downrank posts
+ if (documentId.match(/\/posts/)) return -5
+ // Downrank /other
+ if (documentId.match(/\/other/)) return -5
+
+ // Uprate if term appears in titles. Add bonus for higher levels (i.e. lower index)
+ const titleIndex =
+ titles
+ .map((t, i) => (t?.includes(term) ? i : -1))
+ .find((i) => i >= 0) ?? -1
+ if (titleIndex >= 0) return 10000 - titleIndex
+
+ return 1
+ }
+ }
+ },
+ detailedView: true
+ },
+ provider: 'local'
+}
+
+export const socialLinks: DefaultTheme.SocialLink[] = [
+ { icon: 'github', link: 'https://github.com/fmhy/FMHYEdit' },
+ { icon: 'discord', link: 'https://discord.gg/Stz6y6NgNg' },
+ {
+ icon: 'reddit',
+ link: 'https://reddit.com/r/FREEMEDIAHECKYEAH'
+ }
+]
+
+export const sidebar: DefaultTheme.Sidebar | DefaultTheme.NavItemWithLink[] = [
+ {
+ text: ' Adblocking / Privacy',
+ link: '/adblockvpnguide'
+ },
+ {
+ text: ' Artificial Intelligence',
+ link: '/ai'
+ },
+ {
+ text: ' Movies / TV / Anime',
+ link: '/videopiracyguide'
+ },
+ {
+ text: ' Music / Podcasts / Radio',
+ link: '/audiopiracyguide'
+ },
+ {
+ text: ' Gaming / Emulation',
+ link: '/gamingpiracyguide'
+ },
+ {
+ text: ' Books / Comics / Manga',
+ link: '/readingpiracyguide'
+ },
+ {
+ text: ' Downloading',
+ link: '/downloadpiracyguide'
+ },
+ {
+ text: ' Torrenting',
+ link: '/torrentpiracyguide'
+ },
+ {
+ text: ' Educational',
+ link: '/edupiracyguide'
+ },
+ {
+ text: ' Android / iOS',
+ link: '/android-iosguide'
+ },
+ {
+ text: ' Linux / MacOS',
+ link: '/linuxguide'
+ },
+ {
+ text: ' Non-English',
+ link: '/non-english'
+ },
+ {
+ text: ' Miscellaneous',
+ link: '/miscguide'
+ },
+ {
+ text: ' Tools',
+ collapsed: false,
+ items: [
+ {
+ text: ' System Tools',
+ link: '/system-tools'
+ },
+ {
+ text: ' File Tools',
+ link: '/file-tools'
+ },
+ {
+ text: ' Internet Tools',
+ link: '/internet-tools'
+ },
+ {
+ text: ' Social Media Tools',
+ link: '/social-media-tools'
+ },
+ {
+ text: ' Text Tools',
+ link: '/text-tools'
+ },
+ {
+ text: ' Gaming Tools',
+ link: '/gaming-tools'
+ },
+ {
+ text: ' Image Tools',
+ link: '/img-tools'
+ },
+ {
+ text: ' Video Tools',
+ link: '/video-tools'
+ },
+ {
+ text: ' Audio Tools',
+ link: '/audiopiracyguide#audio-tools'
+ },
+ {
+ text: ' Educational Tools',
+ link: '/edupiracyguide#educational-tools'
+ },
+ {
+ text: ' Developer Tools',
+ link: '/devtools'
+ }
+ ]
+ },
+ {
+ text: ' More',
+ collapsed: true,
+ items: [
+ {
+ text: ' NSFW',
+ link: '/nsfwpiracy'
+ },
+ {
+ text: ' Unsafe Sites',
+ link: '/unsafesites'
+ },
+ {
+ text: ' Storage',
+ link: '/storage'
+ }
+ ]
+ }
+]
diff --git a/docs/.vitepress/fonts/Inter-Bold.otf b/docs/.vitepress/fonts/Inter-Bold.otf
new file mode 100644
index 0000000000000000000000000000000000000000..c74cc0c6c13ccda9d3beac6c5a7aac5176da4a7c
GIT binary patch
literal 271436
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