diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 47706117a..449f3338c 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -1,5 +1,4 @@
import consola from 'consola'
-import { basename } from 'pathe'
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vitepress'
import {
@@ -13,7 +12,7 @@ import {
import { generateFeed, generateImages, generateMeta } from './hooks'
import { defs, emojiRender, movePlugin } from './markdown/emoji'
import { toggleStarredPlugin } from './markdown/toggleStarred'
-import { transformer } from './transformer'
+import { transforms } from './transformer'
// @unocss-include
@@ -57,7 +56,7 @@ export default defineConfig({
UnoCSS({
configFile: '../unocss.config.ts'
}),
- transformer(),
+ transforms(),
{
name: 'custom:adjust-order',
configResolved(c) {
diff --git a/docs/.vitepress/hooks/opengraph.ts b/docs/.vitepress/hooks/opengraph.ts
index 2399ab538..74b62c505 100644
--- a/docs/.vitepress/hooks/opengraph.ts
+++ b/docs/.vitepress/hooks/opengraph.ts
@@ -6,7 +6,7 @@ import type { ContentData, SiteConfig } from 'vitepress'
import { type SatoriOptions, satoriVue } from 'x-satori/vue'
import { renderAsync } from '@resvg/resvg-js'
import consola from 'consola'
-import { headers } from '../transformer'
+import { headers } from '../transformer/constants'
const __dirname = dirname(fileURLToPath(import.meta.url))
const __fonts = resolve(__dirname, '../fonts')
@@ -71,19 +71,19 @@ async function generateImage({
const _page = getPage(url)
const title =
frontmatter.layout === 'home'
- ? (frontmatter.hero.name ?? frontmatter.title)
+ ? frontmatter.hero.name ?? frontmatter.title
: frontmatter.title
? frontmatter.title
: _page?.title
const description =
frontmatter.layout === 'home'
- ? (frontmatter.hero.tagline ?? frontmatter.description)
+ ? frontmatter.hero.tagline ?? frontmatter.description
: frontmatter.description
? frontmatter.description
: _page?.description
- consola.info(url, title, description)
+ // consola.info(url, title, description)
const options: SatoriOptions = {
width: 1200,
height: 628,
diff --git a/docs/.vitepress/transformer.ts b/docs/.vitepress/transformer.ts
index 30d99e706..8f66c514f 100644
--- a/docs/.vitepress/transformer.ts
+++ b/docs/.vitepress/transformer.ts
@@ -1,128 +1,9 @@
import { basename } from 'pathe'
import type { Plugin } from 'vitepress'
+import { replaceUnderscore, transformer } from './transformer/core'
+import { excluded, getHeader } from './transformer/constants'
-interface Header {
- [file: string]: { title: string; description: string }
-}
-
-export const headers: Header = {
- 'adblockvpnguide.md': {
- title: 'Adblocking / Privacy',
- description: "Adblocking, Privacy, VPN's, Proxies, Antivirus"
- },
- 'ai.md': {
- title: 'Artificial Intelligence',
- description: 'Chat Bots, Text Generators, Image Generators, ChatGPT Tools'
- },
- 'android-iosguide.md': {
- title: 'Android / iOS',
- description: 'Apps, Jailbreaking, Android Emulators'
- },
- 'audiopiracyguide.md': {
- title: 'Music / Podcasts / Radio',
- description: 'Stream Audio, Download Audio, Torrent Audio'
- },
- 'beginners-guide.md': {
- title: 'Beginners Guide',
- description: 'A Guide for Beginners to Piracy'
- },
- 'downloadpiracyguide.md': {
- title: 'Downloading',
- description: 'Download Sites, Software Sites, Open Directories'
- },
- 'edupiracyguide.md': {
- title: 'Educational',
- description: 'Courses, Documentaries, Learning Resources'
- },
- 'gamingpiracyguide.md': {
- title: 'Gaming / Emulation',
- description: 'Download Games, ROMs, Gaming Tools'
- },
- 'linuxguide.md': {
- title: 'Linux / MacOS',
- description: 'Apps, Software Sites, Gaming'
- },
- 'miscguide.md': {
- title: 'Miscellaneous',
- description: 'Extensions, Indexes, News, Health, Food, Fun'
- },
- 'nsfwpiracy.md': {
- title: 'NSFW',
- description: 'NSFW Indexes, Streaming, Downloading'
- },
- 'non-english.md': {
- title: 'Non-English',
- description: 'International Piracy Sites'
- },
- 'readingpiracyguide.md': {
- title: 'Books / Comics / Manga',
- description: 'Books, Comics, Magazines, Newspapers'
- },
- 'gaming-tools.md': {
- title: 'Gaming Tools',
- description: 'Gaming Optimization, Game Launchers, Multiplayer'
- },
- 'devtools.md': {
- title: 'Developer Tools',
- description: 'Git, Hosting, App Dev, Software Dev'
- },
- 'img-tools.md': {
- title: 'Image Tools',
- description: 'Image Editors, Generators, Compress'
- },
- 'audio-tools.md': {
- title: 'Audio Tools',
- description: 'Audio Players, Audio Editors, Audio Downloaders'
- },
- 'system-tools.md': {
- title: 'System Tools',
- description: 'System Tools, Hardware Tools, Windows ISOs, Customization'
- },
- 'file-tools.md': {
- title: 'File Tools',
- description: 'Download Managers, File Hosting, File Archivers'
- },
- 'video-tools.md': {
- title: 'Video Tools',
- description: 'Video Players, Video Editors, Live Streaming, Animation'
- },
- 'text-tools.md': {
- title: 'Text Tools',
- description: 'Text Editors, Pastebins, Fonts, Translators'
- },
- 'internet-tools.md': {
- title: 'Internet Tools',
- description: 'Browsers, Extensions, Search Engines'
- },
- 'social-media-tools.md': {
- title: 'Social Media Tools',
- description: 'Discord Tools, Reddit Tools, YouTube Tools'
- },
- 'storage.md': {
- title: 'Storage',
- description: 'Sections too big to fit on main pages'
- },
- 'torrentpiracyguide.md': {
- title: 'Torrenting',
- description: 'Torrent Clients, Torrent Sites, Trackers'
- },
- 'videopiracyguide.md': {
- title: 'Movies / TV / Anime',
- description: 'Stream Videos, Download Videos, Torrent Videos'
- },
- 'base64.md': {
- title: 'Base64',
- description: 'Base64 storage'
- },
- 'unsafesites.md': {
- title: 'Unsafe Sites',
- description: 'Unsafe/harmful sites to avoid.'
- }
-} as const
-
-const excluded = ['readme.md', 'single-page', 'feedback.md', 'index.md']
-
-export function transformer(): Plugin {
+export function transforms(): Plugin {
return {
name: 'custom:transform-content',
enforce: 'pre',
@@ -151,48 +32,56 @@ export function transformer(): Plugin {
}
}
-function getHeader(id: string) {
- const title =
- '
'
-
- const data = headers[id]
- let header = '---\n'
- header += `title: "${data.title}"\n`
- header += `description: ${data.description}\n`
- header += '---\n'
- header += `${title}${data.title}\n`
- header += `${description}${data.description}
\n\n`
- return header
-}
-
-export function transformGuide(text: string): string {
- const _text = text
- .replace(/\[TOC\]\n/gm, '')
- .replace(/\*\*Table of Contents\*\*\n\[TOC2\]\n/gm, '')
- .replace(/# -> \*\*\*Beginners Guide to Piracy\*\*\* <-\n/gm, '')
- .replace(/!!!note\s(.+?)\n/gm, '\n:::info\n$1\n:::\n')
- .replace(/!!!info\s(.+?)\n/gm, '\n:::info\n$1\n:::\n')
- .replace(/!!!warning\s(.+?)\n/gm, ':::warning\n$1\n:::\n')
- .replace(/>\s(.+?)\n/gm, '> $1\n\n')
- .replace(/\*\*\[\^ Back to Top\]\(#beginners-guide-to-piracy\)\*\*/gm, '')
- .replace(/!!!\s(.+?)\n/gm, ':::info\n$1\n:::\n')
- .replace(/\n\*\*\[/gm, '\n* **[')
- .replace(/>(.*)\n\n(.*)/gm, ':::details $1\n$2\n:::')
- return _text
-}
-
-function replaceUnderscore(text: string): string {
- const pattern = /\/#[\w\-]+(?:_[\w]+)*/g
- const matches = text.match(pattern) || []
- let _text = text
- for (const match of matches) {
- const replacement = match.replace(/_/g, '-')
- _text = _text.replace(match, replacement)
- }
- return _text
-}
+export const transformGuide = (text: string): string =>
+ transformer(text)
+ .transform('Beginners Guide', [
+ {
+ name: 'TOC',
+ find: /\[TOC\]\n/gm,
+ replace: ''
+ },
+ {
+ name: 'TOC2',
+ find: /\*\*Table of Contents\*\*\n\[TOC2\]\n/gm,
+ replace: ''
+ },
+ {
+ name: 'Beginners Guide',
+ find: /# -> \*\*\*Beginners Guide to Piracy\*\*\* <-\n/gm,
+ replace: ''
+ },
+ {
+ name: 'Note',
+ find: /!!!note\s(.+?)\n/gm,
+ replace: '\n:::info\n$1\n:::\n'
+ },
+ {
+ name: 'Info',
+ find: /!!!info\s(.+?)\n/gm,
+ replace: '\n:::info\n$1\n:::\n'
+ },
+ {
+ name: 'Warning',
+ find: /!!!warning\s(.+?)\n/gm,
+ replace: ':::warning\n$1\n:::\n'
+ },
+ {
+ name: 'Quote',
+ find: />\s(.+?)\n/gm,
+ replace: '> $1\n\n'
+ },
+ {
+ name: 'Back to Top',
+ find: /\*\*\[\^ Back to Top\]\(#beginners-guide-to-piracy\)\*\*/gm,
+ replace: ''
+ },
+ {
+ name: 'Back to Top',
+ find: /\*\*\[\^ Back to Top\]\(#beginners-guide-to-piracy\)\*\*/gm,
+ replace: ''
+ }
+ ])
+ .getText()
export function transform(text: string): string {
let _text = text
@@ -362,42 +251,50 @@ export function transform(text: string): string {
return _text
}
-function transformLinks(text: string): string {
- const _text = text
- // Transform Discord links to icons
- .replace(
- /\[Discord\]\(([^\)]*?)\)/gm,
- ''
- )
- // Transform GitHub links to icons
- .replace(
- /\[GitHub\]\(([^\)]*?)\)/gm,
- ''
- )
- // Fallback for GitHub
- .replace(
- /\[Github\]\(([^\)]*?)\)/gm,
- ''
- )
- // Transform GitLab links to icons
- .replace(
- /\[GitLab\]\(([^\)]*?)\)/gm,
- ''
- )
- // Fallback for GitLab
- .replace(
- /\[Gitlab\]\(([^\)]*?)\)/gm,
- ''
- )
- // Transform Telegram links to icons
- .replace(
- /\[Telegram\]\(([^\)]*?)\)/gm,
- ''
- )
- // Transform Subreddit links to icons
- .replace(
- /\[Subreddit\]\(([^\)]*?)\)/gm,
- ''
- )
- return _text
-}
+const transformLinks = (text: string): string =>
+ transformer(text)
+ .transform('Links to Icons', [
+ {
+ name: 'Discord',
+ find: /\[Discord\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'GitHub',
+ find: /\[GitHub\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'GitHub Fallback',
+ find: /\[Github\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'GitLab',
+ find: /\[GitLab\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'GitLab Fallback',
+ find: /\[Gitlab\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'Telegram',
+ find: /\[Telegram\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ },
+ {
+ name: 'Subreddit',
+ find: /\[Subreddit\]\(([^\)]*?)\)/gm,
+ replace:
+ ''
+ }
+ ])
+ .getText()
diff --git a/docs/.vitepress/transformer/constants.ts b/docs/.vitepress/transformer/constants.ts
new file mode 100644
index 000000000..24332f513
--- /dev/null
+++ b/docs/.vitepress/transformer/constants.ts
@@ -0,0 +1,136 @@
+interface Header {
+ [file: string]: { title: string; description: string }
+}
+
+export const headers: Header = {
+ 'adblockvpnguide.md': {
+ title: 'Adblocking / Privacy',
+ description: "Adblocking, Privacy, VPN's, Proxies, Antivirus"
+ },
+ 'ai.md': {
+ title: 'Artificial Intelligence',
+ description: 'Chat Bots, Text Generators, Image Generators, ChatGPT Tools'
+ },
+ 'android-iosguide.md': {
+ title: 'Android / iOS',
+ description: 'Apps, Jailbreaking, Android Emulators'
+ },
+ 'audiopiracyguide.md': {
+ title: 'Music / Podcasts / Radio',
+ description: 'Stream Audio, Download Audio, Torrent Audio'
+ },
+ 'beginners-guide.md': {
+ title: 'Beginners Guide',
+ description: 'A Guide for Beginners to Piracy'
+ },
+ 'downloadpiracyguide.md': {
+ title: 'Downloading',
+ description: 'Download Sites, Software Sites, Open Directories'
+ },
+ 'edupiracyguide.md': {
+ title: 'Educational',
+ description: 'Courses, Documentaries, Learning Resources'
+ },
+ 'gamingpiracyguide.md': {
+ title: 'Gaming / Emulation',
+ description: 'Download Games, ROMs, Gaming Tools'
+ },
+ 'linuxguide.md': {
+ title: 'Linux / MacOS',
+ description: 'Apps, Software Sites, Gaming'
+ },
+ 'miscguide.md': {
+ title: 'Miscellaneous',
+ description: 'Extensions, Indexes, News, Health, Food, Fun'
+ },
+ 'nsfwpiracy.md': {
+ title: 'NSFW',
+ description: 'NSFW Indexes, Streaming, Downloading'
+ },
+ 'non-english.md': {
+ title: 'Non-English',
+ description: 'International Piracy Sites'
+ },
+ 'readingpiracyguide.md': {
+ title: 'Books / Comics / Manga',
+ description: 'Books, Comics, Magazines, Newspapers'
+ },
+ 'gaming-tools.md': {
+ title: 'Gaming Tools',
+ description: 'Gaming Optimization, Game Launchers, Multiplayer'
+ },
+ 'devtools.md': {
+ title: 'Developer Tools',
+ description: 'Git, Hosting, App Dev, Software Dev'
+ },
+ 'img-tools.md': {
+ title: 'Image Tools',
+ description: 'Image Editors, Generators, Compress'
+ },
+ 'audio-tools.md': {
+ title: 'Audio Tools',
+ description: 'Audio Players, Audio Editors, Audio Downloaders'
+ },
+ 'system-tools.md': {
+ title: 'System Tools',
+ description: 'System Tools, Hardware Tools, Windows ISOs, Customization'
+ },
+ 'file-tools.md': {
+ title: 'File Tools',
+ description: 'Download Managers, File Hosting, File Archivers'
+ },
+ 'video-tools.md': {
+ title: 'Video Tools',
+ description: 'Video Players, Video Editors, Live Streaming, Animation'
+ },
+ 'text-tools.md': {
+ title: 'Text Tools',
+ description: 'Text Editors, Pastebins, Fonts, Translators'
+ },
+ 'internet-tools.md': {
+ title: 'Internet Tools',
+ description: 'Browsers, Extensions, Search Engines'
+ },
+ 'social-media-tools.md': {
+ title: 'Social Media Tools',
+ description: 'Discord Tools, Reddit Tools, YouTube Tools'
+ },
+ 'storage.md': {
+ title: 'Storage',
+ description: 'Sections too big to fit on main pages'
+ },
+ 'torrentpiracyguide.md': {
+ title: 'Torrenting',
+ description: 'Torrent Clients, Torrent Sites, Trackers'
+ },
+ 'videopiracyguide.md': {
+ title: 'Movies / TV / Anime',
+ description: 'Stream Videos, Download Videos, Torrent Videos'
+ },
+ 'base64.md': {
+ title: 'Base64',
+ description: 'Base64 storage'
+ },
+ 'unsafesites.md': {
+ title: 'Unsafe Sites',
+ description: 'Unsafe/harmful sites to avoid.'
+ }
+} as const
+
+export const excluded = ['readme.md', 'single-page', 'feedback.md', 'index.md']
+
+export function getHeader(id: string) {
+ const title =
+ ''
+
+ const data = headers[id]
+ let header = '---\n'
+ header += `title: "${data.title}"\n`
+ header += `description: ${data.description}\n`
+ header += '---\n'
+ header += `${title}${data.title}\n`
+ header += `${description}${data.description}
\n\n`
+ return header
+}
diff --git a/docs/.vitepress/transformer/core.ts b/docs/.vitepress/transformer/core.ts
new file mode 100644
index 000000000..c7afd8623
--- /dev/null
+++ b/docs/.vitepress/transformer/core.ts
@@ -0,0 +1,53 @@
+import consola from 'consola'
+
+type Transform = {
+ name: string
+ find: string | RegExp
+ replace: string | ((match: string) => string)
+}
+
+type TransformerFunc = (name: string, transforms: Transform[]) => Replacer
+
+interface Replacer {
+ transform: TransformerFunc
+ getText(): string
+}
+
+export const transformer = (text: string) => {
+ const handler: ProxyHandler<{ text: string }> = {
+ get(target, prop) {
+ if (prop === 'transform') {
+ return (name: string, transforms: Transform[]): Replacer => {
+ consola.debug(`Starting transform ${name} with ${transforms}`)
+
+ transforms.forEach(({ name, find, replace }) => {
+ consola.debug(`Transforming ${name} with ${find}`)
+ target.text = target.text.replace(find, replace as any)
+ })
+
+ // @ts-expect-error - Proxy is not typed
+ return proxy
+ }
+ }
+ if (prop === 'getText') {
+ return () => target.text
+ }
+ return Reflect.get(target, prop)
+ }
+ }
+
+ const target = { text }
+ const proxy = new Proxy(target, handler)
+ return proxy as unknown as Replacer
+}
+
+export function replaceUnderscore(text: string): string {
+ const pattern = /\/#[\w\-]+(?:_[\w]+)*/g
+ const matches = text.match(pattern) || []
+ let _text = text
+ for (const match of matches) {
+ const replacement = match.replace(/_/g, '-')
+ _text = _text.replace(match, replacement)
+ }
+ return _text
+}