Commit e553559

HPCesia <me@hpcesia.com>
2026-03-11 18:02:56
Support base config
1 parent 08e527a
Changed files (6)
src/components/Header.astro
@@ -1,13 +1,14 @@
 ---
 import { SITE_CONFIG } from "@/config";
+import { url } from "@/utils/url";
 ---
 
 <header class="border-b-2 py-2">
   <nav class="flex justify-between">
-    <a href="/" class="text-2xl">{SITE_CONFIG.title}</a>
+    <a href={url("/")} class="text-2xl">{SITE_CONFIG.title}</a>
     <ul class="flex space-x-4 text-xl leading-[1.75]">
-      <li><a href="/posts">Posts</a></li>
-      <li><a href="/about">About</a></li>
+      <li><a href={url("/posts")}>Posts</a></li>
+      <li><a href={url("/about")}>About</a></li>
     </ul>
   </nav>
 </header>
src/components/PostsList.astro
@@ -2,6 +2,7 @@
 import type { CollectionEntry } from "astro:content";
 import { DateTime } from "luxon";
 import { SITE_CONFIG } from "@/config";
+import { url } from "@/utils/url";
 
 interface Props {
   posts: CollectionEntry<"posts">[];
@@ -19,7 +20,7 @@ const { posts } = Astro.props;
         });
         return (
           <li class="grid grid-rows-1 grid-cols-[1fr_auto] gap-2">
-            <a href={`/posts/${post.id}`}>{post.data.title}</a>
+            <a href={url(`/posts/${post.id}`)}>{post.data.title}</a>
             <time
               datetime={dt.toISO()}
               class="text-sm lg:text-base text-neutral-600 dark:text-neutral-400"
src/layouts/GlobalLayout.astro
@@ -3,6 +3,7 @@ import "@/styles/global.css";
 import Footer from "@/components/Footer.astro";
 import Header from "@/components/Header.astro";
 import { SITE_CONFIG } from "@/config";
+import { url } from "@/utils/url";
 
 interface Props {
   title?: string;
@@ -47,7 +48,7 @@ const {
       rel="alternate"
       type="application/atom+xml"
       title="Atom Feed"
-      href="/feed.atom"
+      href={url("/feed.atom")}
     />
 
     <link
src/types/config.d.ts
@@ -2,7 +2,7 @@ export type SiteConfig = {
   /**
    * A URL where your website deployed.
    */
-  website: string;
+  website: `${string}://${string}`;
   /**
    * Title of your website.
    */
src/utils/url.ts
@@ -0,0 +1,22 @@
+export function joinUrl(...parts: string[]): string {
+  const joined = parts.join("/");
+  return joined.replace(/\/+/g, "/");
+}
+
+export function pathsEqual(path1: string, path2: string) {
+  const normalizedPath1 = path1.replace(/^\/|\/$/g, "").toLowerCase();
+  const normalizedPath2 = path2.replace(/^\/|\/$/g, "").toLowerCase();
+  return normalizedPath1 === normalizedPath2;
+}
+
+export function pathMatch(regex: RegExp, path: string) {
+  return regex.test(path) || regex.test(getRelativeUrl(path));
+}
+
+export function getRelativeUrl(path: string) {
+  return joinUrl("/", path.replace(import.meta.env.BASE_URL, ""));
+}
+
+export function url(path: string) {
+  return joinUrl("", import.meta.env.BASE_URL, path);
+}
astro.config.ts
@@ -6,9 +6,14 @@ import { extractImage } from "./src/integrations/extract-image";
 import { rehypeCleanEndnotes } from "./src/plugins/rehype-clean-endnotes";
 import { rehypeExternalLinks } from "./src/plugins/rehype-external-links";
 
+const protocol = SITE_CONFIG.website.split("://")[0];
+const site = SITE_CONFIG.website.split("://")[1].split("/")[0];
+const base = SITE_CONFIG.website.split(site).slice(1).join("/") || undefined;
+
 // https://astro.build/config
 export default defineConfig({
-  site: SITE_CONFIG.website,
+  site: `${protocol}://${site}`,
+  base: base,
   integrations: [
     typst({
       options: {