Skip to content

Commit

Permalink
fix: Fixes reroute behavior for PR previews
Browse files Browse the repository at this point in the history
  • Loading branch information
ShrimpCryptid committed Dec 17, 2024
1 parent cc77aa3 commit 5e4051c
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 16 deletions.
4 changes: 2 additions & 2 deletions public/gh-reroute/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { convertUrlToQueryStringPath } from "../../website/utils/gh_route_utils";
import { encodeGitHubPagesUrl } from "../../website/utils/gh_route_utils";

// Hide the default 404 page content and just show a blank screen.
// The content should only be shown if the browser doesn't support JavaScript.
Expand All @@ -10,6 +10,6 @@ window.onload = () => {
// Convert the current URL to a query string path and redirect the browser.
const location = window.location;
const locationUrl = new URL(location.toString());
const newUrl = convertUrlToQueryStringPath(locationUrl, 1);
const newUrl = encodeGitHubPagesUrl(locationUrl);
location.replace(newUrl);
console.log("Redirecting to " + newUrl.toString());
16 changes: 9 additions & 7 deletions public/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import React from "react";
import ReactDOM from "react-dom";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

import { decodeGitHubPagesUrl, isEncodedPathUrl, tryRemoveHashRouting } from "../website/utils/gh_route_utils";

import StyleProvider from "../src/aics-image-viewer/components/StyleProvider";
// Components
import AppWrapper from "../website/components/AppWrapper";
import LandingPage from "../website/components/LandingPage";
import ErrorPage from "../website/components/ErrorPage";
import { isQueryStringPath, convertQueryStringPathToUrl } from "../website/utils/gh_route_utils";
import StyleProvider from "../src/aics-image-viewer/components/StyleProvider";
import LandingPage from "../website/components/LandingPage";

import "./App.css";

// vars filled at build time using webpack DefinePlugin
Expand All @@ -18,11 +20,11 @@ console.log(`volume-viewer Version ${VOLUMEVIEWER_VERSION}`);

const basename = WEBSITE3DCELLVIEWER_BASENAME;

// Check for redirects in the query string, and update browser history state.
// Decode URL path if it was encoded for GitHub pages or uses hash routing.
const locationUrl = new URL(window.location.toString());
if (isQueryStringPath(locationUrl)) {
const url = convertQueryStringPathToUrl(locationUrl);
const newRelativePath = url.pathname + url.search + url.hash;
if (locationUrl.hash !== "" || isEncodedPathUrl(locationUrl)) {
const decodedUrl = tryRemoveHashRouting(decodeGitHubPagesUrl(locationUrl));
const newRelativePath = decodedUrl.pathname + decodedUrl.search + decodedUrl.hash;
console.log("Redirecting to " + newRelativePath);
// Replaces the query string path with the original path now that the
// single-page app has loaded. This lets routing work as normal below.
Expand Down
58 changes: 51 additions & 7 deletions website/utils/gh_route_utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const ESCAPED_AMPERSAND = "~and~";

/**
* Converts the path component of a URL into a query string. Used to redirect the browser
* Encodes the path component of a URL into a query string. Used to redirect the browser
* for single-page apps when the server is not configured to serve the app for all paths,
* e.g. GitHub pages.
*
Expand All @@ -23,7 +23,7 @@ const ESCAPED_AMPERSAND = "~and~";
*
* @returns The URL with the path converted to a query string, and the original query string escaped.
*/
export function convertUrlToQueryStringPath(url: URL, basePathSegments: number = 0): URL {
export function encodeUrlPathAsQueryString(url: URL, basePathSegments: number = 0): URL {
const pathSegments = url.pathname.split("/");
const basePath = pathSegments.slice(0, basePathSegments + 1).join("/");
const remainingPath = pathSegments.slice(basePathSegments + 1).join("/");
Expand All @@ -39,10 +39,6 @@ export function convertUrlToQueryStringPath(url: URL, basePathSegments: number =
return new URL(newUrl);
}

export function isQueryStringPath(url: URL): boolean {
return url.search !== "" && url.search.startsWith("?/");
}

/**
* Converts a query string back into a complete URL. Used in combination with `convertUrlToQueryStringPath()`.
* to redirect the browser for single-page apps when the server cannot be configured, e.g. GitHub pages.
Expand All @@ -51,7 +47,7 @@ export function isQueryStringPath(url: URL): boolean {
* @param url - The URL with a path converted to a query string, and the original query string escaped.
* @returns The original URL, with path instead of a query string.
*/
export function convertQueryStringPathToUrl(url: URL): URL {
export function decodeUrlQueryStringPath(url: URL): URL {
if (!url.search || !url.search.startsWith("?/")) {
return url;
}
Expand All @@ -64,3 +60,51 @@ export function convertQueryStringPathToUrl(url: URL): URL {

return new URL(`${url.origin}${url.pathname}${newPathAndQueryString}${url.hash}`);
}

export function isEncodedPathUrl(url: URL): boolean {
return url.search !== "" && url.search.startsWith("?/");
}

/**
* Encodes a URL for GitHub pages by converting the path to a query string.
* See `encodeUrlPathAsQueryString()` for more details.
*/
export function encodeGitHubPagesUrl(url: URL): URL {
url = new URL(url); // Clone the URL to avoid modifying the original
if (url.hostname === "allen-cell-animated.github.io") {
if (url.pathname.toString().includes("pr-preview")) {
return encodeUrlPathAsQueryString(url, 3);
}
// Redirect `/main` paths back to root `/`
if (url.pathname.toString().includes("main")) {
url.pathname = url.pathname.replace("/main", "");
}
return encodeUrlPathAsQueryString(url, 1);
}

return url;
}

/**
* Decodes a URL that was encoded for GitHub pages, e.g. by `encodeGitHubPagesUrl()`.
* See `decodeUrlQueryStringPath()` for more details.
*/
export function decodeGitHubPagesUrl(url: URL): URL {
return decodeUrlQueryStringPath(url);
}

/**
* Changes URLs with hash-based routing to path-based routing by removing the hash from
* the URL. Does nothing to URLs that do not use hash-based routing.
*/
export function tryRemoveHashRouting(url: URL): URL {
// Remove #/ from the URL path
if (url.hash.startsWith("#/")) {
const hashContents = url.hash.slice(2);
const [path, queryParams] = hashContents.split("?");
url.pathname += path;
url.search = queryParams ? `?${queryParams}` : "";
url.hash = "";
}
return url;
}

0 comments on commit 5e4051c

Please sign in to comment.