From 913b2d428ee84e254b067d8f1172c6144478c403 Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Thu, 28 May 2026 23:33:40 +0300 Subject: [PATCH] fix: handle docs demo app route --- docs-site/public/_redirects | 6 ++ docs-site/public/demo/demo-shell.js | 59 +++++++++++++------ docs-site/scripts/materialize-demo-routes.mjs | 45 ++------------ docs-site/src/lib/demoRoutes.mjs | 44 ++++++++++++++ docs-site/src/pages/demo/[...path].astro | 34 +---------- 5 files changed, 98 insertions(+), 90 deletions(-) create mode 100644 docs-site/src/lib/demoRoutes.mjs diff --git a/docs-site/public/_redirects b/docs-site/public/_redirects index d2ea8ac..aa10399 100644 --- a/docs-site/public/_redirects +++ b/docs-site/public/_redirects @@ -1,7 +1,13 @@ # Cloudflare Pages rewrites for the static docs demo SPA. # Keep these scoped to app routes so runtime JS/CSS/assets are served directly. +/demo /demo/index.html 200 +/demo/ /demo/index.html 200 +/demo/app /demo/index.html 200 +/demo/app/ /demo/index.html 200 /demo/runtime /demo/runtime/app.html 200 /demo/runtime/ /demo/runtime/app.html 200 +/demo/runtime/app /demo/runtime/app.html 200 +/demo/runtime/app/ /demo/runtime/app.html 200 /demo/runtime/home /demo/runtime/app.html 200 /demo/runtime/home/* /demo/runtime/app.html 200 /demo/runtime/install /demo/runtime/app.html 200 diff --git a/docs-site/public/demo/demo-shell.js b/docs-site/public/demo/demo-shell.js index 1dfa0e2..4ebc541 100644 --- a/docs-site/public/demo/demo-shell.js +++ b/docs-site/public/demo/demo-shell.js @@ -2,6 +2,7 @@ const frame = document.getElementById("demo-frame"); const runtimeBase = "/demo/runtime"; const demoBase = "/demo"; const defaultMock = "tariffs"; +const publicRouteAliases = new Map([["/app", "/home"]]); const stateMocks = new Set([ "tariffs", "depleted", @@ -41,7 +42,8 @@ const routeFromPublicPath = () => { const publicRoute = pathname.slice(demoBase.length); if (!publicRoute || publicRoute.toLowerCase().startsWith("/runtime")) return ""; - return normalizePath(publicRoute); + const normalized = normalizePath(publicRoute); + return publicRouteAliases.get(normalized.toLowerCase()) || normalized; }; const routeFromParams = () => { @@ -88,15 +90,48 @@ const mockForRoute = (route) => { const initialMock = params.has("mock") ? normalizeRouteMock(params.get("mock")) : normalizeRouteMock(mockForRoute(initialRoute) || defaultMock); -if (initialMock === "trial" && initialRoute === "/trial") { - initialRoute = "/home"; +const materializedRouteFromRuntime = (route) => { + const normalized = normalizePath(route); + if (/^\/admin\/users\/-?\d+$/i.test(normalized)) return "/admin/users"; + if (/^\/admin\/payments\/\d+$/i.test(normalized)) return "/admin/payments"; + if (/^\/admin\/payments\/users\/-?\d+$/i.test(normalized)) + return "/admin/payments"; + if (/^\/admin\/support\/\d+$/i.test(normalized)) return "/admin/support"; + if (/^\/support\/\d+$/i.test(normalized)) return "/support"; + return normalized; +}; + +const publicPathFromRoute = (route) => + `${demoBase}${materializedRouteFromRuntime(route)}`; +const canonicalizeInitialPublicUrl = (route) => { + const pathname = window.location.pathname.replace(/\/+$/, "") || "/"; + const lowerPathname = pathname.toLowerCase(); + if ( + lowerPathname !== demoBase && + !publicRouteAliases.has(pathname.slice(demoBase.length).toLowerCase()) + ) { + return; + } const normalizedUrl = new URL(window.location.href); - normalizedUrl.pathname = `${demoBase}/home`; + normalizedUrl.pathname = publicPathFromRoute(route); window.history.replaceState( null, "", `${normalizedUrl.pathname}${normalizedUrl.search}${normalizedUrl.hash}`, ); +}; + +if (initialMock === "trial" && initialRoute === "/trial") { + initialRoute = "/home"; + const normalizedUrl = new URL(window.location.href); + normalizedUrl.pathname = publicPathFromRoute(initialRoute); + window.history.replaceState( + null, + "", + `${normalizedUrl.pathname}${normalizedUrl.search}${normalizedUrl.hash}`, + ); +} else { + canonicalizeInitialPublicUrl(initialRoute); } params.set("mock", initialMock); params.delete("path"); @@ -112,25 +147,11 @@ const routeFromRuntimeUrl = (url) => { const runtimePath = normalizePath( url.pathname.slice(runtimeBase.length) || "/home", ); - if (runtimePath === "/app.html") { + if (runtimePath === "/app" || runtimePath === "/app.html") { return normalizePath(url.searchParams.get("path") || "/home"); } return runtimePath; }; - -const materializedRouteFromRuntime = (route) => { - const normalized = normalizePath(route); - if (/^\/admin\/users\/-?\d+$/i.test(normalized)) return "/admin/users"; - if (/^\/admin\/payments\/\d+$/i.test(normalized)) return "/admin/payments"; - if (/^\/admin\/payments\/users\/-?\d+$/i.test(normalized)) - return "/admin/payments"; - if (/^\/admin\/support\/\d+$/i.test(normalized)) return "/admin/support"; - if (/^\/support\/\d+$/i.test(normalized)) return "/support"; - return normalized; -}; - -const publicPathFromRoute = (route) => - `${demoBase}${materializedRouteFromRuntime(route)}`; const routeForStateMock = (mock) => { if (mock === "devices") return "/devices"; if (mock === "auth") return "/login"; diff --git a/docs-site/scripts/materialize-demo-routes.mjs b/docs-site/scripts/materialize-demo-routes.mjs index 7ade645..239badb 100644 --- a/docs-site/scripts/materialize-demo-routes.mjs +++ b/docs-site/scripts/materialize-demo-routes.mjs @@ -1,49 +1,16 @@ import { copyFile, mkdir } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { + demoPublicRoutes, + demoRuntimeRoutes, +} from "../src/lib/demoRoutes.mjs"; const siteRoot = path.resolve(fileURLToPath(new URL("..", import.meta.url))); const distRoot = path.join(siteRoot, "dist"); -const userRoutes = [ - "home", - "install", - "trial", - "invite", - "devices", - "support", - "settings", - "login", - "login/password", -]; - -const adminRoutes = [ - "stats", - "users", - "payments", - "promos", - "ads", - "broadcast", - "logs", - "support", - "tariffs", - "appearance", - "translations", - "backups", - "settings", -]; - -const demoRoutes = [ - ...userRoutes.map((route) => `demo/${route}`), - "demo/admin", - ...adminRoutes.map((route) => `demo/admin/${route}`), -]; - -const runtimeRoutes = [ - ...userRoutes.map((route) => `demo/runtime/${route}`), - "demo/runtime/admin", - ...adminRoutes.map((route) => `demo/runtime/admin/${route}`), -]; +const demoRoutes = demoPublicRoutes.map((route) => `demo/${route}`); +const runtimeRoutes = demoRuntimeRoutes.map((route) => `demo/runtime/${route}`); async function copyHtml(source, route) { const targetDir = path.join(distRoot, route); diff --git a/docs-site/src/lib/demoRoutes.mjs b/docs-site/src/lib/demoRoutes.mjs new file mode 100644 index 0000000..1ab71dd --- /dev/null +++ b/docs-site/src/lib/demoRoutes.mjs @@ -0,0 +1,44 @@ +export const demoUserRoutes = [ + "home", + "install", + "trial", + "invite", + "devices", + "support", + "settings", + "login", + "login/password", +]; + +export const demoAdminRoutes = [ + "stats", + "users", + "payments", + "promos", + "ads", + "broadcast", + "logs", + "support", + "tariffs", + "appearance", + "translations", + "backups", + "settings", +]; + +export const demoPublicRouteAliases = ["app"]; +export const demoRuntimeRouteAliases = ["app"]; + +export const demoPublicRoutes = [ + ...demoPublicRouteAliases, + ...demoUserRoutes, + "admin", + ...demoAdminRoutes.map((route) => `admin/${route}`), +]; + +export const demoRuntimeRoutes = [ + ...demoRuntimeRouteAliases, + ...demoUserRoutes, + "admin", + ...demoAdminRoutes.map((route) => `admin/${route}`), +]; diff --git a/docs-site/src/pages/demo/[...path].astro b/docs-site/src/pages/demo/[...path].astro index 9605cc8..cc0bf04 100644 --- a/docs-site/src/pages/demo/[...path].astro +++ b/docs-site/src/pages/demo/[...path].astro @@ -1,39 +1,9 @@ --- import DemoShell from '../demo.astro'; +import { demoPublicRoutes } from '../../lib/demoRoutes.mjs'; export function getStaticPaths() { - const userRoutes = [ - 'home', - 'install', - 'trial', - 'invite', - 'devices', - 'support', - 'settings', - 'login', - 'login/password', - ]; - const adminRoutes = [ - 'stats', - 'users', - 'payments', - 'promos', - 'ads', - 'broadcast', - 'logs', - 'support', - 'tariffs', - 'appearance', - 'translations', - 'backups', - 'settings', - ]; - - return [ - ...userRoutes.map((path) => ({ params: { path } })), - { params: { path: 'admin' } }, - ...adminRoutes.map((section) => ({ params: { path: `admin/${section}` } })), - ]; + return demoPublicRoutes.map((path) => ({ params: { path } })); } ---