import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import path from "node:path"; import fs from "node:fs"; import type { Plugin } from "vite"; import { fileURLToPath } from "node:url"; interface RouteStub { slug: string; title: string; description: string; ogTitle: string; ogDescription: string; ogImage: string; } const ROUTE_STUBS: RouteStub[] = [ { slug: "mergekeys", title: "MergeKeys — AmneziaWG Architect", description: "Обновите обфускацию AWG-ключа или объедините несколько ключей Amnezia VPN в один.", ogTitle: "MergeKeys — AmneziaWG Architect", ogDescription: "Объединяй ключи Amnezia VPN, обновляй обфускацию — всё локально в браузере.", ogImage: "og-mergekeys.png", }, { slug: "about", title: "О проекте — AmneziaWG Architect", description: "Что такое AmneziaWG Architect? Это интерактивный инструмент для генерации сложных конфигураций обфускации трафика AmneziaWG. Создан для тех, кто хочет вернуть себе свободный интернет.", ogTitle: "О проекте — AmneziaWG Architect", ogDescription: "Твой протокол — твои правила. Разбор архитектуры, безопасности и принципов работы генератора.", ogImage: "og-about.png", }, { slug: "iaa", title: "IAA — Веб-панель VPN", description: "Быстрая адаптивная панель для управления Amnezia VPN и другими VPN-решениями.", ogTitle: "IAA — Веб-панель VPN", ogDescription: "Быстрая адаптивная панель для управления VPN-серверами. Amnezia, WireGuard, XRay.", ogImage: "og-iaa.png", }, ]; export type HostPlatform = "github" | "gitlab" | "cloudflare" | "generic"; export function detectHostPlatform(): HostPlatform { const platform = ( process.env.VITE_DEPLOY_PLATFORM || process.env.DEPLOY_PLATFORM || (process.env.GITHUB_ACTIONS && "github") || (process.env.GITLAB_CI && "gitlab") || (process.env.CF_PAGES && "cloudflare") || "generic" ) .toString() .toLowerCase(); if (platform.includes("gitlab")) return "gitlab"; if (platform.includes("cloudflare") || platform.includes("cf")) return "cloudflare"; if (platform.includes("github")) return "github"; return "generic"; } export function normalizeBase(input?: string | null): string { if (!input) return "/"; let base = input.trim(); if (base === "." || base === "./") return "./"; if (base === "/") return "/"; base = base.replace(/\\/g, "/"); if (!base.startsWith("/")) base = `/${base}`; if (!base.endsWith("/")) base += "/"; return base; } export function inferBase(): string { const explicit = process.env.VITE_BASE || process.env.BASE_URL || process.env.ASSET_BASE || process.env.PUBLIC_URL; if (explicit) return normalizeBase(explicit); const platform = detectHostPlatform(); if (platform === "cloudflare") { return "/"; } if (platform === "github") { const repo = process.env.GITHUB_REPOSITORY; if (repo) { const [, name] = repo.split("/"); if (name) { return `/${name}/`; } } return "/"; } if (platform === "gitlab") { const pagesUrl = process.env.CI_PAGES_URL; if (pagesUrl) { try { const urlObj = new URL(pagesUrl); return normalizeBase(urlObj.pathname); } catch (e) {} } return "/"; } return "./"; } export function inferSiteOrigin(): string { const explicit = process.env.VITE_SITE_ORIGIN || process.env.SITE_ORIGIN || process.env.VITE_PUBLIC_SITE_URL || process.env.PUBLIC_SITE_URL; if (explicit) return explicit.replace(/\/+$/, ""); const repo = process.env.GITHUB_REPOSITORY; if (repo && process.env.GITHUB_ACTIONS) { const [owner, name] = repo.split("/"); if (owner && name) { return `https://${owner.toLowerCase()}.github.io/${name}`; } } const gitlabProject = process.env.CI_PROJECT_PATH; const gitlabUrl = process.env.CI_PAGES_URL || process.env.PAGES_URL; if (gitlabUrl) return gitlabUrl.replace(/\/+$/, ""); if (gitlabProject && process.env.CI_SERVER_HOST) { return `https://${process.env.CI_SERVER_HOST}/${gitlabProject}`; } const cfUrl = process.env.CF_PAGES_URL || process.env.CLOUDFLARE_PAGES_URL || process.env.PAGES_URL; if (cfUrl) return cfUrl.replace(/\/+$/, ""); return ""; } export function makeAbsoluteUrl( siteOrigin: string, base: string, assetPath: string, ): string { const cleanAsset = assetPath.replace(/^\.?\//, ""); if (!siteOrigin) { return `${base}${cleanAsset}`.replace(/\/{2,}/g, "/").replace(":/", "://"); } return new URL( cleanAsset, siteOrigin.endsWith("/") ? siteOrigin : `${siteOrigin}/`, ).toString(); } export function buildStubHtml( template: string, route: RouteStub, siteOrigin: string, base: string, ): string { const absImage = makeAbsoluteUrl(siteOrigin, base, `assets/${route.ogImage}`); let html = template; html = html.replace(/