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 description = '

' - - 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 description = '

' + + 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 +}