From 8ec3ab370c20f4b1bcceb3bf2d1379f7e7d4be9f Mon Sep 17 00:00:00 2001 From: fynks <75840152+fynks@users.noreply.github.com> Date: Mon, 29 Sep 2025 09:29:27 +0500 Subject: [PATCH] porting to vitepress --- .gitignore | 5 +- docs/.vitepress/config.mjs | 172 ++++++++++++++++ Adult-hosts.md => docs/Adult-hosts.md | 6 + {dist => docs}/_redirects | 0 docs/hosts.md | 6 + docs/index.md | 117 +++++++++++ docs/policies.md | 6 + docs/pricing.md | 62 ++++++ {dist => docs/public}/favicon.ico | Bin {dist => docs/public}/favicon.svg | 0 .../public}/images/android-chrome-192x192.png | Bin .../public}/images/android-chrome-512x512.png | Bin .../public}/images/apple-touch-icon.png | Bin .../public}/images/favicon-16x16.png | Bin .../public}/images/favicon-32x32.png | Bin dist/image.png => docs/public/images/og.png | Bin {dist => docs/public}/robots.txt | 0 .../rzd7n8dtydkn3rusq48azrfacbx5zapr.txt | 0 {dist => docs/public}/site.webmanifest | 0 {dist => docs/public}/sitemap.xml | 0 docs/tools.md | 6 + package.json | 40 ++-- scripts/build-docs.sh | 147 ++++++++++++++ scripts/json-optimizer.sh | 191 ------------------ scripts/replace-assets.js | 158 --------------- workbox-config.js | 143 ------------- 26 files changed, 548 insertions(+), 511 deletions(-) create mode 100644 docs/.vitepress/config.mjs rename Adult-hosts.md => docs/Adult-hosts.md (92%) rename {dist => docs}/_redirects (100%) create mode 100644 docs/hosts.md create mode 100644 docs/index.md create mode 100644 docs/policies.md create mode 100644 docs/pricing.md rename {dist => docs/public}/favicon.ico (100%) rename {dist => docs/public}/favicon.svg (100%) rename {dist => docs/public}/images/android-chrome-192x192.png (100%) rename {dist => docs/public}/images/android-chrome-512x512.png (100%) rename {dist => docs/public}/images/apple-touch-icon.png (100%) rename {dist => docs/public}/images/favicon-16x16.png (100%) rename {dist => docs/public}/images/favicon-32x32.png (100%) rename dist/image.png => docs/public/images/og.png (100%) rename {dist => docs/public}/robots.txt (100%) rename {dist => docs/public}/rzd7n8dtydkn3rusq48azrfacbx5zapr.txt (100%) rename {dist => docs/public}/site.webmanifest (100%) rename {dist => docs/public}/sitemap.xml (100%) create mode 100644 docs/tools.md create mode 100755 scripts/build-docs.sh delete mode 100755 scripts/json-optimizer.sh delete mode 100644 scripts/replace-assets.js delete mode 100644 workbox-config.js diff --git a/.gitignore b/.gitignore index 24581a5..8ec8825 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ -/node_modules -pnpm-lock.yaml \ No newline at end of file +docs/.vitepress/dist +docs/.vitepress/cache +node_modules \ No newline at end of file diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs new file mode 100644 index 0000000..b626406 --- /dev/null +++ b/docs/.vitepress/config.mjs @@ -0,0 +1,172 @@ +import { defineConfig } from 'vitepress' + +export default defineConfig({ + lang: 'en-US', + title: 'Debrid Services Comparison', + description: 'Community-maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools.', + ignoreDeadLinks: true, + cleanUrls: true, + lastUpdated: true, + + markdown: { + lineNumbers: true + }, + + head: [ + ['link', { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }], + ['link', { rel: 'shortcut icon', href: '/favicon.ico' }], + ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/images/apple-touch-icon.png' }], + ['meta', { name: 'theme-color', content: '#ffffff', media: '(prefers-color-scheme: light)' }], + ['meta', { name: 'theme-color', content: '#0b0b0c', media: '(prefers-color-scheme: dark)' }], + ['meta', { name: 'viewport', content: 'width=device-width, initial-scale=1.0, viewport-fit=cover' }], + ['meta', { name: 'author', content: 'Fynks' }], + ['meta', { name: 'robots', content: 'index, follow, max-image-preview:large, max-snippet:-1' }], + ['meta', { property: 'og:title', content: 'Debrid Services Comparison' }], + ['meta', { property: 'og:description', content: 'Community-maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools.' }], + ['meta', { property: 'og:type', content: 'website' }], + ['meta', { property: 'og:image', content: '/images/og.png' }], + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], + ['meta', { name: 'twitter:title', content: 'Debrid Services Comparison' }], + ['meta', { name: 'twitter:description', content: 'Community-maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools.' }], + ['meta', { name: 'twitter:image', content: '/images/og.png' }] + ], + + themeConfig: { + logo: { + light: 'favicon.svg', + dark: 'favicon.svg', + alt: 'Debrid Services Comparison Logo' + }, + + search: { + provider: 'local', + options: { + detailedView: true + } + }, + + nav: [ + { text: 'Home', link: '/' }, + { text: 'Pricing', link: '/pricing' }, + { text: 'Hosts', link: '/hosts' }, + { text: 'Adult Hosts', link: '/Adult-hosts' }, + { text: 'Policies', link: '/policies' }, + { text: 'Tools', link: '/tools' }, + { + text: 'More', + items: [ + { text: 'Interactive Comparison', link: 'https://debridcompare.pages.dev' }, + { text: 'GitHub', link: 'https://github.com/fynks/debrid-services-comparison' } + ] + } + ], + + sidebar: { + '/': [ + { + text: 'Getting Started', + items: [ + { text: 'What are Debrid Services?', link: '/#what-are-debrid-services' }, + { text: 'Support This Project', link: '/#support-this-project' }, + { text: 'Interactive Comparison', link: 'https://debridcompare.pages.dev' } + ] + }, + { + text: 'Service Comparison', + items: [ + { text: 'Pricing Comparison', link: '/pricing' }, + { text: 'Available Hosts', link: '/hosts' }, + { text: 'Adult Hosts', link: '/Adult-hosts' }, + { text: 'Policies & Legal', link: '/policies' } + ] + }, + { + text: 'Tools & Resources', + items: [ + { text: 'Tools & Community', link: '/tools' }, + { text: 'Speed Testing', link: '/tools#speed-test' } + ] + }, + { + text: 'Community', + collapsed: true, + items: [ + { text: 'Contributing', link: 'https://github.com/fynks/debrid-services-comparison/blob/main/CONTRIBUTING.md' }, + { text: 'Report Issues', link: 'https://github.com/fynks/debrid-services-comparison/issues' } + ] + } + ], + + '/pricing': [ + { + text: 'Pricing Information', + items: [ + { text: 'Overview', link: '/pricing' }, + { text: 'Detailed Pricing Analysis', link: '/pricing#detailed-pricing-and-value-analysis' }, + { text: 'Official Pricing Pages', link: '/pricing#up-to-date-pricing' } + ] + } + ], + + '/hosts': [ + { + text: 'File Hosting Services', + items: [ + { text: 'Complete Host List', link: '/hosts' }, + { text: 'Interactive Comparison', link: 'https://debridcompare.pages.dev' } + ] + } + ], + + '/Adult-hosts': [ + { + text: 'Adult Content Hosts', + items: [ + { text: 'Supported Hosts', link: '/Adult-hosts' } + ] + } + ], + + '/policies': [ + { + text: 'Service Policies', + items: [ + { text: 'Policies & Legal', link: '/policies' } + ] + } + ], + + '/tools': [ + { + text: 'Tools & Community', + items: [ + { text: 'Recommended Tools', link: '/tools#recommended-tools' }, + { text: 'Communities', link: '/tools#communities' }, + { text: 'Speed Testing', link: '/tools#speed-test' } + ] + } + ] + }, + + footer: { + message: 'Made with ❤️ by Fynks', + copyright: 'Copyright © 2025 Debrid Services Comparison' + }, + + outline: { + level: [2, 3], + label: 'On this page' + }, + + lastUpdated: { + text: 'Updated at', + formatOptions: { + dateStyle: 'short', + timeStyle: 'medium' + } + }, + socialLinks: [ + { icon: 'github', link: 'https://github.com/fynks/debrid-services-comparison' } + ] + } +}) diff --git a/Adult-hosts.md b/docs/Adult-hosts.md similarity index 92% rename from Adult-hosts.md rename to docs/Adult-hosts.md index a5cef1d..76b9299 100644 --- a/Adult-hosts.md +++ b/docs/Adult-hosts.md @@ -1,3 +1,9 @@ +--- +layout: home +title: Adult Hosts +titleTemplate: Debrid Compare +description: "Detailed adult hoster support comparison for leading debrid/multi-hoster services." +--- ### Adult Hosts diff --git a/dist/_redirects b/docs/_redirects similarity index 100% rename from dist/_redirects rename to docs/_redirects diff --git a/docs/hosts.md b/docs/hosts.md new file mode 100644 index 0000000..9637ea7 --- /dev/null +++ b/docs/hosts.md @@ -0,0 +1,6 @@ +--- +layout: home +title: Hosts +titleTemplate: Debrid Compare +description: "Comprehensive hoster support comparison for leading debrid/multi-hoster services including file and torrent hosters." +--- diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..d94ff9f --- /dev/null +++ b/docs/index.md @@ -0,0 +1,117 @@ +--- +layout: home +title: Best Debrid Compare +description: "Community‑maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools etc." +head: + - - meta + - name: robots + content: "index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" + - - meta + - property: og:type + content: "website" + - - meta + - property: og:url + content: "https://debridcompare.pages.dev" + - - meta + - property: og:image + content: "https://debridcompare.pages.dev/images/og.png" + - - meta + - property: og:title + content: "Debrid Compare" + - - meta + - property: og:description + content: "Community‑maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools etc." + - - meta + - property: og:image:secure_url + content: "https://debridcompare.pages.dev/images/og.png" + - - meta + - property: og:image:alt + content: "Debrid Compare" + - - meta + - property: og:image:width + content: "1200" + - - meta + - property: og:image:height + content: "630" + - - meta + - property: og:image:type + content: "image/png" + - - meta + - property: og:site_name + content: "Debrid Compare" + - - meta + - property: og:locale + content: "en_US" + - - meta + - property: og:updated_time + content: "2025-09-19T00:00:00Z" + - - link + - rel: canonical + href: "https://debridcompare.pages.dev" + - - link + - rel: alternate + hreflang: "en" + href: "https://debridcompare.pages.dev" +hero: + name: "Debrid Compare" + tagline: "Community‑maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools etc." + image: + src: /images/logo_dark.svg + alt: Debrid Compare Logo + actions: + - theme: brand + text: 🚀 Supported Hosts + link: /hosts + size: large + - theme: alt + text: 📚 Pricing + link: /pricing + - theme: alt + text: ⭐ GitHub + link: https://github.com/fynks/debrid-services-comparison + target: _blank +features: + - icon: ⚡ + title: Performance & Gaming + details: "Supercharge your device with performance optimization, gaming enhancements, CPU/GPU tuning, and intelligent automation." + link: /android-root-apps/#performance-tweaks-and-optimizations + + - icon: 🌐 + title: Network & Connectivity Control + details: "Master network management with firewall tools, DNS control, Wi-Fi optimization, and advanced connectivity features." + link: /android-root-apps/#network-and-connectivity + + - icon: 🛠️ + title: Root Management & Hiding + details: "Manage root access, hide root from banking apps, ensure integrity checks pass, and maintain system security." + link: /android-root-apps/#root-management + +--- + +
+ +### Support This Project + +> ✨ This guide is **free, open-source, and community-run**. If it helped: starring, reporting corrections, or using a referral link helps sustain maintenance (at no extra cost to you). + +| Service | Referral | Direct Signup | +| :------ | :------- | :------------ | +| AllDebrid | [Referral](https://alldebrid.com/?uid=3wvya&lang=en) | [Signup](https://alldebrid.com/register/) | +| Real-Debrid | [Referral](https://real-debrid.com/?id=10990901) | [Signup](https://real-debrid.com/) | +| TorBox | – | [Signup](https://torbox.app/login) | +| Premiumize | – | [Signup](https://www.premiumize.me/register) | +| LinkSnappy | [Referral](https://linksnappy.com/?ref=774668) | [Signup](https://linksnappy.com/home#Register) | +| Debrid-Link | [Referral](https://debrid-link.com/id/7B3BO) | [Signup](https://debrid-link.com/webapp/register) | +| Mega-Debrid | – | [Signup](https://www.mega-debrid.eu/index.php?page=freeregister) | +| Deepbrid | [Referral](https://www.deepbrid.com/aff/go/upward1971) | [Signup](https://www.deepbrid.com/signup) | +| Offcloud | [Referral](https://offcloud.com/?=c44b1fa5) | [Signup](https://offcloud.com/register) | +| High-Way | – | [Signup](https://high-way.me/login/login) | + +> [!NOTE] +> No financial ties to services. Referrals offset hosting & data validation costs only. + +
+ +[(↑ Back to Top)](#table-of-contents) + +
diff --git a/docs/policies.md b/docs/policies.md new file mode 100644 index 0000000..0368aea --- /dev/null +++ b/docs/policies.md @@ -0,0 +1,6 @@ +--- +layout: home +title: Policies +titleTemplate: Debrid Compare +description: "Refund, privacy, and usage policies for leading debrid/multi-hoster services." +--- \ No newline at end of file diff --git a/docs/pricing.md b/docs/pricing.md new file mode 100644 index 0000000..f5d6b5a --- /dev/null +++ b/docs/pricing.md @@ -0,0 +1,62 @@ +--- +layout: home +title: Pricing +titleTemplate: Debrid Compare +description: "Comprehensive pricing comparison of leading debrid/multi-hoster services including plans, costs, and value analysis." +--- + +
+ +## Pricing Comparison + +### Detailed Pricing and Value Analysis + +| **Plan Duration** | **AllDebrid** | **Premiumize** | **Real-Debrid** | **TorBox** | **Debrid-Link** | **LinkSnappy** | **Mega-Debrid** | **Deepbrid** | **High-Way** | **Offcloud** | +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | +| **Free / Trial** | 7-day trial¹ | ❌ | ❌ | Free tier² | ❌ | ❌ | ❌ | Limited hosts only | Limited Hosts⁶ | ❌ | +| **7 Days** | ❌ | ❌ | ❌ | ❌ | ❌ | $4.99 | ❌ | ❌ | ❌ | ❌ | +| **15 Days** | €2.99 (one-time)⁴ | ❌ | €3.00 | ❌ | €3.00 | ❌ | ❌ | €4.50 | ❌ | ❌ | +| **30 Days** | €2.99 (recurring)³<br>€3.99 (one-time)⁴ | $11.99 | €4.00 | From $3.00/month⁵ | €4.00 | $12.99 | €4.00 | €4.99 | From €5.99 | $9.99 | +| **90 Days** | €8.99 (one-time)⁴ | $29.99 | €9.00 | ❌ | €9.00 | $29.99 | €9.00 | €12.99 | From €15.99 | $29.97 | +| **180 Days** | €15.99 (one-time)⁴ | ❌ | €16.00 | ❌ | €16.00 | $54.99 | €16.00 | €19.99 | From €29.99 | ❌ | +| **300 Days** | €24.99 (one-time)⁴ | ❌ | ❌ | ❌ | €25.00 | ❌ | ❌ | ❌ | ❌ | ❌ | +| **365 Days / 1 Year** | ❌ | $79.99 | ❌ | ❌ | ❌ | ❌ | ❌ | €32.99 | ❌ | $69.99 | + +> [!NOTE] Pricing Notes +> - **¹ AllDebrid Free Trial**: 7-day trial requires phone verification. +> - **² TorBox Free Tier**: Limited speed and features; no torrenting. +> - **³ AllDebrid Recurring**: Auto-renews monthly at €2.99 +> - **⁴ AllDebrid / Debrid-Link One-Time**: Non-recurring payment. Often better value than recurring. +> - **⁵ TorBox Tiers**: Multiple plans starting at $3.00/month. Higher tiers unlock more features. +> - **⁶ High-Way**: Limited Hoster, FreeMB through activity in the forum + +### Up-to-date Pricing + +> [!IMPORTANT] +> *Always verify prices on official sites as they change frequently.* + +
👉 Click to expand + +| **Service** | **Official Pricing Page** | +| :---------- | :------------------------------------------------------------------------- | +| AllDebrid | [alldebrid.com/offer](https://alldebrid.com/offer/) | +| Real-Debrid | [real-debrid.com/premium](https://real-debrid.com/premium) | +| TorBox | [torbox.app/pricing](https://torbox.app/pricing) | +| Premiumize | [premiumize.me/premium](https://www.premiumize.me/premium) | +| LinkSnappy | [linksnappy.com/myaccount/extend](https://linksnappy.com/myaccount/extend) | +| Debrid-Link | [debrid-link.com/premium](https://debrid-link.com/premium) | +| Mega-Debrid | [mega-debrid.eu/offres](https://www.mega-debrid.eu/index.php?page=offres) | +| Deepbrid | [deepbrid.com/signup](https://www.deepbrid.com/signup) | +| High-Way | [high-way.me/pages/tariffs](https://high-way.me/pages/tariffs) | +| Offcloud | [https://offcloud.com/#pricing](https://offcloud.com/#pricing) | + +

+ +![Last Updated](https://img.shields.io/badge/Last%20Updated-September%2019%2C%202025-blue?style=for-the-badge) + +
+
+ +[(↑ Back to Top)](#table-of-contents) + +
diff --git a/dist/favicon.ico b/docs/public/favicon.ico similarity index 100% rename from dist/favicon.ico rename to docs/public/favicon.ico diff --git a/dist/favicon.svg b/docs/public/favicon.svg similarity index 100% rename from dist/favicon.svg rename to docs/public/favicon.svg diff --git a/dist/images/android-chrome-192x192.png b/docs/public/images/android-chrome-192x192.png similarity index 100% rename from dist/images/android-chrome-192x192.png rename to docs/public/images/android-chrome-192x192.png diff --git a/dist/images/android-chrome-512x512.png b/docs/public/images/android-chrome-512x512.png similarity index 100% rename from dist/images/android-chrome-512x512.png rename to docs/public/images/android-chrome-512x512.png diff --git a/dist/images/apple-touch-icon.png b/docs/public/images/apple-touch-icon.png similarity index 100% rename from dist/images/apple-touch-icon.png rename to docs/public/images/apple-touch-icon.png diff --git a/dist/images/favicon-16x16.png b/docs/public/images/favicon-16x16.png similarity index 100% rename from dist/images/favicon-16x16.png rename to docs/public/images/favicon-16x16.png diff --git a/dist/images/favicon-32x32.png b/docs/public/images/favicon-32x32.png similarity index 100% rename from dist/images/favicon-32x32.png rename to docs/public/images/favicon-32x32.png diff --git a/dist/image.png b/docs/public/images/og.png similarity index 100% rename from dist/image.png rename to docs/public/images/og.png diff --git a/dist/robots.txt b/docs/public/robots.txt similarity index 100% rename from dist/robots.txt rename to docs/public/robots.txt diff --git a/dist/rzd7n8dtydkn3rusq48azrfacbx5zapr.txt b/docs/public/rzd7n8dtydkn3rusq48azrfacbx5zapr.txt similarity index 100% rename from dist/rzd7n8dtydkn3rusq48azrfacbx5zapr.txt rename to docs/public/rzd7n8dtydkn3rusq48azrfacbx5zapr.txt diff --git a/dist/site.webmanifest b/docs/public/site.webmanifest similarity index 100% rename from dist/site.webmanifest rename to docs/public/site.webmanifest diff --git a/dist/sitemap.xml b/docs/public/sitemap.xml similarity index 100% rename from dist/sitemap.xml rename to docs/public/sitemap.xml diff --git a/docs/tools.md b/docs/tools.md new file mode 100644 index 0000000..b8bc1de --- /dev/null +++ b/docs/tools.md @@ -0,0 +1,6 @@ +--- +layout: home +title: Tools +titleTemplate: Debrid Compare +description: "Tools and integrations for leading debrid/multi-hoster services including browser extensions, download managers, and media center plugins." +--- \ No newline at end of file diff --git a/package.json b/package.json index 74c9b37..2e89b8b 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,30 @@ { - "name": "@fynks/debrid-service-comparison", - "version": "2.0.1", - "description": "A concise comparison of pricing and supported hosts for popular debrid services including AllDebrid, Real-Debrid, LinkSnappy, Premiumize, Debrid-Link, TorBox, and Mega-Debrid.", - "main": "index.js", - "homepage": "", + "name": "debrid-services-comparison", + "version": "1.1.0", + "description": "Community‑maintained, up-to-date comparison of leading debrid / multi-hoster services for pricing, host coverage, policies & tools etc.", + "private": true, + "homepage": "https://awesome-android-root.org", "repository": { "type": "git", - "url": "" + "url": "https://github.com/fynks/debrid-services-comparison.git" + }, + "bugs": { + "url": "https://github.com/fynks/debrid-services-comparison/issues" }, "scripts": { - "minify:css": "cleancss -o dist/css/styles-min.css dist/css/styles.css", - "minify:js": "terser dist/js/app.js -o dist/js/app-min.js --compress --mangle", - "optimize-json": "chmod +x scripts/json-optimizer.sh && scripts/json-optimizer.sh dist/json/file-hosts.json dist/json/file-hosts-optimized.json && scripts/json-optimizer.sh dist/json/adult-hosts.json dist/json/adult-hosts-optimized.json", - "build": "npm run minify:css && npm run minify:js && npm run optimize-json && workbox generateSW workbox-config.js", - "postbuild": "node scripts/replace-assets.js" + "docs:dev": "vitepress dev docs", + "docs:build": "scripts/build-docs.sh && vitepress build docs", + "docs:preview": "vitepress preview docs" }, - "author": "fynks", - "dependencies": { - "clean-css-cli": "^5.6.3", - "terser": "^5.44.0", - "workbox-cli": "^7.3.0" - } + "devDependencies": { + "vitepress": "^1.6.4", + "terser": "^5.44.0" + }, + "keywords": [ + ], + "author": { + "name": "debrid-services-comparison", + "url": "https://debridcompare.pages.dev" + }, + "license": "MIT" } \ No newline at end of file diff --git a/scripts/build-docs.sh b/scripts/build-docs.sh new file mode 100755 index 0000000..9c18a1a --- /dev/null +++ b/scripts/build-docs.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +# Exit on any error and treat unset variables as errors +set -euo pipefail + +# Colors for output +readonly GREEN='\033[0;32m' +readonly NC='\033[0m' # No Color +readonly RED='\033[0;31m' +readonly BLUE='\033[0;34m' +readonly YELLOW='\033[1;33m' + +# Script info +readonly SCRIPT_NAME="$(basename "$0")" +readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Error handling function with line number +handle_error() { + local line_number="${2:-unknown}" + echo -e "${RED}Error on line ${line_number}: $1${NC}" >&2 + exit 1 +} + +# Trap errors and show line number +trap 'handle_error "Script failed" ${LINENO}' ERR + +# Logging functions +log_info() { + echo -e "${GREEN}✓ $1${NC}" +} + +log_warn() { + echo -e "${YELLOW}⚠ $1${NC}" +} + +log_error() { + echo -e "${RED}✗ $1${NC}" >&2 +} + +echo -e "${GREEN}Starting build-docs process...${NC}" + +# 1. Check required files and directories +[ ! -d "docs" ] && handle_error "'docs' directory not found." +[ ! -f "README.md" ] && handle_error "'README.md' not found." + +# 2. Function to extract div content with specific class from README.md +extract_div_content() { + local class_name="$1" + local start_line end_line + + # Find the start line of the div with the specified class + start_line=$(grep -n "]*class=\"${class_name}\"" README.md | head -1 | cut -d: -f1) + + if [ -z "$start_line" ]; then + log_warn "No div with class '${class_name}' found in README.md" + return 1 + fi + + # Find the corresponding closing after the start line + end_line=$(tail -n +$((start_line + 1)) README.md | grep -n "" | head -1 | cut -d: -f1) + + if [ -z "$end_line" ]; then + log_warn "No closing found for class '${class_name}'" + return 1 + fi + + # Calculate the actual end line number + end_line=$((start_line + end_line)) + + # Extract the content between start and end lines + sed -n "${start_line},${end_line}p" README.md +} + +# 3. Function to copy div content to docs file +copy_div_to_docs() { + local class_name="$1" + local target_file="$2" + local content + + content=$(extract_div_content "$class_name") + + if [ $? -eq 0 ] && [ -n "$content" ]; then + if [ -f "$target_file" ]; then + # Append to existing file with separator + { + cat "$target_file" + echo "" + echo "$content" + } > "${target_file}.tmp" && mv "${target_file}.tmp" "$target_file" || handle_error "Failed appending content to $target_file" + log_info "Appended '$class_name' div content to $target_file" + else + # Create new file with content + echo "$content" > "$target_file" || handle_error "Failed creating $target_file" + log_info "Created $target_file with '$class_name' div content" + fi + + # Adjust relative links for docs directory structure + adjust_links_for_docs "$target_file" + else + log_warn "Failed to extract content for class '$class_name'" + fi +} + +# 4. Function to adjust links for docs directory structure +adjust_links_for_docs() { + local file="$1" + + # Adjust relative links (skip absolute URLs) + sed -i '/http[s]*:\/\/\//! s|\.\/docs/|\.\/|g' "$file" || handle_error "Failed adjusting links in $file" + + # Adjust image paths + sed -i 's|docs/public/images/|public/images/|g' "$file" || handle_error "Failed adjusting image paths in $file" + sed -i 's|\./dist/|public/images/|g' "$file" || handle_error "Failed adjusting dist image paths in $file" + + log_info "Adjusted links and image paths in $file" +} + +# 5. Copy div sections to respective docs files +copy_div_to_docs "support" "docs/index.md" +copy_div_to_docs "pricing" "docs/pricing.md" +copy_div_to_docs "hosts" "docs/hosts.md" +copy_div_to_docs "policies" "docs/policies.md" +copy_div_to_docs "tools" "docs/tools.md" + +# 6. Append speedtest content to the bottom of tools.md +speedtest_content=$(extract_div_content "speedtest") +if [ $? -eq 0 ] && [ -n "$speedtest_content" ]; then + { + cat "docs/tools.md" + echo "" + echo "---" + echo "" + echo "$speedtest_content" + } > "docs/tools.md.tmp" && mv "docs/tools.md.tmp" "docs/tools.md" || handle_error "Failed appending speedtest content to docs/tools.md" + log_info "Appended speedtest content to bottom of docs/tools.md" + adjust_links_for_docs "docs/tools.md" +else + log_warn "Failed to extract speedtest content" +fi + +# 7. Remove standalone speedtest.md file if it exists +if [ -f "docs/speedtest.md" ]; then + rm "docs/speedtest.md" || handle_error "Failed removing docs/speedtest.md" + log_info "Removed standalone docs/speedtest.md file" +fi + +echo -e "${GREEN}Documentation build process completed successfully.${NC}" diff --git a/scripts/json-optimizer.sh b/scripts/json-optimizer.sh deleted file mode 100755 index ab25304..0000000 --- a/scripts/json-optimizer.sh +++ /dev/null @@ -1,191 +0,0 @@ -#!/bin/bash - -# JSON Optimizer Script - Converts host data to indexed format -# Usage: ./scripts/json-optimizer.sh file-hosts.json -# ./scripts/json-optimizer.sh adult-hosts.json -# ./scripts/json-optimizer.sh pricing.json - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_status() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Default values -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -DEFAULT_INPUT_DIR="." -DEFAULT_OUTPUT_DIR="." - -# Check if at least one argument is provided -if [ $# -eq 0 ]; then - print_error "No input file specified" - echo "Usage: $0 [output-file.json]" - echo "Examples:" - echo " $0 file-hosts.json" - echo " $0 ./json/adult-hosts.json" - echo " $0 pricing.json pricing-optimized.json" - exit 1 -fi - -# Get input file -INPUT_FILE="$1" - -# Generate output filename if not provided -if [ $# -eq 2 ]; then - OUTPUT_FILE="$2" -else - # Extract filename without path and extension - FILENAME=$(basename "$INPUT_FILE") - NAME="${FILENAME%.*}" - EXT="${FILENAME##*.}" - OUTPUT_FILE="${NAME}-optimized.${EXT}" -fi - -# Check if input file exists -if [ ! -f "$INPUT_FILE" ]; then - print_error "Input file '$INPUT_FILE' not found" - exit 1 -fi - -# Create output directory if it doesn't exist -OUTPUT_DIR=$(dirname "$OUTPUT_FILE") -if [ ! -d "$OUTPUT_DIR" ] && [ "$OUTPUT_DIR" != "." ]; then - print_status "Creating output directory: $OUTPUT_DIR" - mkdir -p "$OUTPUT_DIR" -fi - -print_status "Processing: $INPUT_FILE" -print_status "Output will be saved to: $OUTPUT_FILE" - -# Python script to handle the conversion -python3 -c " -import json -import sys -import os -from collections import defaultdict - -def convert_to_indexed_format(input_file, output_file): - try: - # Read the input JSON - print('Reading input file...') - with open(input_file, 'r') as f: - data = json.load(f) - - host_count = len(data) - print(f'Loaded {host_count:,} hosts') - - # Handle empty data - if not data: - print('Warning: Input file is empty') - output_data = {'services': [], 'supported': {}} - with open(output_file, 'w') as f: - json.dump(output_data, f, separators=(',', ':')) - return True - - # Extract all services (keys from entries) - all_services = set() - for host_data in data.values(): - all_services.update(host_data.keys()) - - services = sorted(list(all_services)) - service_count = len(services) - print(f'Found {service_count} services: {\", \".join(services[:5])}{\"...\" if service_count > 5 else \"\"}') - - # Create service to index mapping - service_to_index = {service: idx for idx, service in enumerate(services)} - - # Convert data to indexed format - print('Converting data to indexed format...') - supported = {} - total_support_instances = 0 - - for host, host_data in data.items(): - # Get indices of services with 'yes' values (case insensitive) - supported_indices = [ - service_to_index[service] - for service, value in host_data.items() - if str(value).lower() == 'yes' - ] - supported[host] = sorted(supported_indices) - total_support_instances += len(supported_indices) - - # Create output structure - output_data = { - 'services': services, - 'supported': supported - } - - # Write optimized JSON (compact format) - print('Writing optimized JSON...') - with open(output_file, 'w') as f: - json.dump(output_data, f, separators=(',', ':')) - - # Get file sizes for comparison - original_size = os.path.getsize(input_file) - new_size = os.path.getsize(output_file) - reduction = ((original_size - new_size) / original_size) * 100 if original_size > 0 else 0 - - print('✅ Conversion successful!') - print(f'📁 Original size: {original_size:,} bytes') - print(f'📁 New size: {new_size:,} bytes') - print(f'📉 Size reduction: {reduction:.1f}%') - print(f'💾 Output saved to: {output_file}') - - # Show statistics - avg_support_per_host = total_support_instances / host_count if host_count > 0 else 0 - - print('📈 Statistics:') - print(f' - Hosts: {host_count:,}') - print(f' - Services: {service_count:,}') - print(f' - Total support instances: {total_support_instances:,}') - print(f' - Average support per host: {avg_support_per_host:.1f}') - - return True - - except json.JSONDecodeError as e: - print(f'❌ JSON parsing error: {str(e)}') - return False - except Exception as e: - print(f'❌ Error during conversion: {str(e)}') - return False - -# Run the conversion -success = convert_to_indexed_format('$INPUT_FILE', '$OUTPUT_FILE') - -if not success: - sys.exit(1) -" || { - print_error "Python conversion failed. Please ensure Python 3 is installed." - exit 1 -} - -print_success "Conversion completed successfully!" - -# Optional: Show file size comparison in bash as well -if command -v stat >/dev/null 2>&1; then - ORIGINAL_SIZE=$(stat -f%z "$INPUT_FILE" 2>/dev/null || stat -c%s "$INPUT_FILE" 2>/dev/null) - NEW_SIZE=$(stat -f%z "$OUTPUT_FILE" 2>/dev/null || stat -c%s "$OUTPUT_FILE" 2>/dev/null) - - if [ $? -eq 0 ] && [ $ORIGINAL_SIZE -gt 0 ]; then - REDUCTION_PERCENTAGE=$(( (ORIGINAL_SIZE - NEW_SIZE) * 100 / ORIGINAL_SIZE )) - print_status "Final size reduction: ${REDUCTION_PERCENTAGE}%" - fi -fi \ No newline at end of file diff --git a/scripts/replace-assets.js b/scripts/replace-assets.js deleted file mode 100644 index 0185bd9..0000000 --- a/scripts/replace-assets.js +++ /dev/null @@ -1,158 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -// Improved script with better error handling and focused head tag processing -function replaceAssets() { - const file = path.resolve(__dirname, '..', 'dist', 'index.html'); - - // Check if dist/index.html exists - if (!fs.existsSync(file)) { - console.error('Error: dist/index.html not found'); - process.exit(1); - } - - try { - let html = fs.readFileSync(file, 'utf8'); - console.log('Original HTML loaded successfully'); - - // Extract the head section - const headMatch = html.match(/(]*>)([\s\S]*?)(<\/head>)/i); - if (!headMatch) { - console.error('Error: Could not find tag in HTML'); - process.exit(1); - } - - const [fullHeadTag, headStart, headContent, headEnd] = headMatch; - console.log('Head section found, processing assets...'); - - let updatedHeadContent = headContent; - let cssReplaced = 0; - let jsReplaced = 0; - - // Compute simple query hash for cache-busting if files exist - const cssMinPath = path.resolve(__dirname, '..', 'dist', 'css', 'styles-min.css'); - const jsMinPath = path.resolve(__dirname, '..', 'dist', 'js', 'app-min.js'); - const safeHash = (p) => { - try { - const buf = fs.readFileSync(p); - let hash = 0; - for (let i = 0; i < buf.length; i += Math.ceil(buf.length / 128) || 1) { - hash = (hash * 31 + buf[i]) >>> 0; - } - return hash.toString(36); - } catch { - return null; - } - }; - const cssHash = safeHash(cssMinPath); - const jsHash = safeHash(jsMinPath); - const cssTarget = cssHash ? `href="./css/styles-min.css?v=${cssHash}"` : 'href="./css/styles-min.css"'; - const jsTarget = jsHash ? `src="js/app-min.js?v=${jsHash}"` : 'src="js/app-min.js"'; - - // Replace CSS links in head - more flexible patterns - const cssPatterns = [ - /href=["']\.\/css\/styles\.css["']/g, - /href=["']css\/styles\.css["']/g, - /href=["'][^"']*\/styles\.css["']/g - ]; - - cssPatterns.forEach(pattern => { - const matches = updatedHeadContent.match(pattern); - if (matches) { - updatedHeadContent = updatedHeadContent.replace(pattern, cssTarget); - cssReplaced += matches.length; - } - }); - - // Ensure existing preload to styles-min.css carries the same version hash - if (cssHash) { - const preloadMinCssPattern = /href=["']\/?css\/styles-min\.css["']/g; - if (preloadMinCssPattern.test(updatedHeadContent)) { - updatedHeadContent = updatedHeadContent.replace(preloadMinCssPattern, `href="/css/styles-min.css?v=${cssHash}"`); - } - } - - // Replace JS script src in head - more flexible patterns - const jsPatterns = [ - /src=["']\.\/js\/app\.js["']/g, - /src=["']js\/app\.js["']/g, - /src=["'][^"']*\/app\.js["']/g - ]; - - jsPatterns.forEach(pattern => { - const matches = updatedHeadContent.match(pattern); - if (matches) { - updatedHeadContent = updatedHeadContent.replace(pattern, jsTarget); - jsReplaced += matches.length; - } - }); - - // Also check for script tags at the end of body (common pattern) - const bodyMatch = html.match(/(]*>)([\s\S]*?)(<\/body>)/i); - if (bodyMatch) { - const [fullBodyTag, bodyStart, bodyContent, bodyEnd] = bodyMatch; - let updatedBodyContent = bodyContent; - - jsPatterns.forEach(pattern => { - const matches = updatedBodyContent.match(pattern); - if (matches) { - updatedBodyContent = updatedBodyContent.replace(pattern, jsTarget); - jsReplaced += matches.length; - } - }); - - // Reconstruct the body if changes were made - if (updatedBodyContent !== bodyContent) { - html = html.replace(fullBodyTag, bodyStart + updatedBodyContent + bodyEnd); - } - } - - // Reconstruct the HTML with updated head - const updatedHeadTag = headStart + updatedHeadContent + headEnd; - html = html.replace(fullHeadTag, updatedHeadTag); - - // Log results - console.log(`CSS replacements made: ${cssReplaced}`); - console.log(`JS replacements made: ${jsReplaced}`); - - if (cssReplaced === 0 && jsReplaced === 0) { - console.warn('Warning: No asset links were found to replace'); - console.log('Checking for existing patterns in head section:'); - - // Debug: show what's actually in the head - const linkTags = headContent.match(/]*>/gi) || []; - const scriptTags = headContent.match(/]*>/gi) || []; - - console.log('Found link tags:', linkTags); - console.log('Found script tags:', scriptTags); - } else { - console.log('Asset links replaced successfully'); - } - - // Write the updated HTML back - fs.writeFileSync(file, html, 'utf8'); - console.log('Updated dist/index.html saved'); - - // Verify the minified files exist - const cssFile = path.resolve(__dirname, '..', 'dist', 'css', 'styles-min.css'); - const jsFile = path.resolve(__dirname, '..', 'dist', 'js', 'app-min.js'); - - if (!fs.existsSync(cssFile)) { - console.warn('Warning: styles-min.css not found - CSS minification may have failed'); - } else { - console.log('✓ styles-min.css exists'); - } - - if (!fs.existsSync(jsFile)) { - console.warn('Warning: app-min.js not found - JS minification may have failed'); - } else { - console.log('✓ app-min.js exists'); - } - - } catch (error) { - console.error('Error processing HTML file:', error.message); - process.exit(1); - } -} - -replaceAssets(); \ No newline at end of file diff --git a/workbox-config.js b/workbox-config.js deleted file mode 100644 index 323b41f..0000000 --- a/workbox-config.js +++ /dev/null @@ -1,143 +0,0 @@ -module.exports = { - // Base directory - still needed for SW generation - globDirectory: "dist/", - // Explicitly disable precaching for lean SW install - globPatterns: [], - - // Enhanced runtime caching strategies - runtimeCaching: [ - // 1. Navigation routes (for SPAs) - Network first with offline fallback - { - urlPattern: ({ request }) => request.mode === 'navigate', - handler: 'NetworkFirst', - options: { - cacheName: 'navigation-cache', - networkTimeoutSeconds: 3, // Fallback to cache after 3s - expiration: { - maxEntries: 50, - maxAgeSeconds: 24 * 60 * 60 // 24 hours - }, - cacheableResponse: { - statuses: [0, 200] // Cache successful responses - } - } - }, - - // 2. HTML pages - Network first for fresh content - { - urlPattern: /\.html$/i, - handler: 'NetworkFirst', - options: { - cacheName: 'html-cache', - networkTimeoutSeconds: 2, - expiration: { - maxEntries: 50, - maxAgeSeconds: 12 * 60 * 60 // 12 hours - } - } - }, - - // 3. JS/CSS - StaleWhileRevalidate with versioning awareness - { - urlPattern: /\.(?:js|css)$/i, - handler: 'StaleWhileRevalidate', - options: { - cacheName: 'static-resources', - expiration: { - maxEntries: 60, - maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days - purgeOnQuotaError: true // Auto-cleanup when storage is full - }, - cacheableResponse: { - statuses: [0, 200] - } - } - }, - - // 4. Images - CacheFirst for performance - { - urlPattern: /\.(?:png|jpg|jpeg|gif|webp|svg|ico)$/i, - handler: 'CacheFirst', - options: { - cacheName: 'image-cache', - expiration: { - maxEntries: 200, // More space for images - maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days - purgeOnQuotaError: true - }, - cacheableResponse: { - statuses: [0, 200] - }, - plugins: [ - { - handlerDidError: async () => { - // Return fallback image on error (use an existing icon) - return caches.match('/favicon.svg'); - } - } - ] - } - }, - - - // 5. JSON responses (local and API) - NetworkFirst with timeout - { - urlPattern: ({url}) => /\.json$/i.test(url.pathname) || /\/api\//i.test(url.pathname) || /^https:\/\/api\./i.test(url.href), - handler: 'NetworkFirst', - options: { - cacheName: 'api-cache', - networkTimeoutSeconds: 5, - expiration: { - maxEntries: 100, - maxAgeSeconds: 5 * 60 // 5 minutes for fresh API data - }, - cacheableResponse: { statuses: [0, 200] }, - matchOptions: { - ignoreSearch: false // Consider query params - } - } - }, - - // 8. Google Fonts - CacheFirst - { - urlPattern: /^https:\/\/fonts\.(?:googleapis|gstatic)\.com/, - handler: 'CacheFirst', - options: { - cacheName: 'google-fonts', - expiration: { - maxEntries: 30, - maxAgeSeconds: 365 * 24 * 60 * 60 // 1 year - }, - cacheableResponse: { - statuses: [0, 200] - } - } - } - ], - - // Service worker output - swDest: "dist/sw.js", - - // Disable sourcemaps in production - sourcemap: false, - - // Immediate activation - skipWaiting: true, - clientsClaim: true, - - // Additional improvements - cleanupOutdatedCaches: true, // Remove old caches automatically - navigateFallback: null, // No fallback since no precaching - - // Ignore specific query parameters - ignoreURLParametersMatching: [ - /^utm_/, // Marketing params - /^fbclid$/ // Facebook click ID - ], - - // Maximum file size to cache (15MB) - maximumFileSizeToCacheInBytes: 15 * 1024 * 1024, - - // Mode for generated SW - mode: 'production' -}; \ No newline at end of file