fix: make `base` in astro config work
This commit is contained in:
parent
9a3119cab4
commit
410902a767
|
@ -26,6 +26,7 @@ const oklchToHex = (str) => {
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: "https://fuwari.vercel.app/",
|
site: "https://fuwari.vercel.app/",
|
||||||
base: "/",
|
base: "/",
|
||||||
|
trailingSlash: "always",
|
||||||
integrations: [
|
integrations: [
|
||||||
tailwind(),
|
tailwind(),
|
||||||
swup({
|
swup({
|
||||||
|
|
|
@ -7,6 +7,7 @@ import NavMenuPanel from "./widget/NavMenuPanel.astro";
|
||||||
import Search from "./Search.svelte";
|
import Search from "./Search.svelte";
|
||||||
import {LinkPresets} from "../constants/link-presets";
|
import {LinkPresets} from "../constants/link-presets";
|
||||||
import LightDarkSwitch from "./LightDarkSwitch.svelte";
|
import LightDarkSwitch from "./LightDarkSwitch.svelte";
|
||||||
|
import {url} from "../utils/url-utils";
|
||||||
const className = Astro.props.class;
|
const className = Astro.props.class;
|
||||||
|
|
||||||
let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset): NavBarLink => {
|
let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset): NavBarLink => {
|
||||||
|
@ -20,7 +21,7 @@ let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset)
|
||||||
<div class:list={[
|
<div class:list={[
|
||||||
className,
|
className,
|
||||||
"card-base sticky top-0 overflow-visible max-w-[var(--page-width)] h-[4.5rem] rounded-t-none mx-auto flex items-center justify-between px-4"]}>
|
"card-base sticky top-0 overflow-visible max-w-[var(--page-width)] h-[4.5rem] rounded-t-none mx-auto flex items-center justify-between px-4"]}>
|
||||||
<a href="/" class="btn-plain h-[3.25rem] px-5 font-bold rounded-lg active:scale-95">
|
<a href={url('/')} class="btn-plain h-[3.25rem] px-5 font-bold rounded-lg active:scale-95">
|
||||||
<div class="flex flex-row text-[var(--primary)] items-center text-md">
|
<div class="flex flex-row text-[var(--primary)] items-center text-md">
|
||||||
<Icon name="material-symbols:home-outline-rounded" size={"1.75rem"} class="mb-1 mr-2" />
|
<Icon name="material-symbols:home-outline-rounded" size={"1.75rem"} class="mb-1 mr-2" />
|
||||||
{siteConfig.title}
|
{siteConfig.title}
|
||||||
|
@ -28,7 +29,7 @@ let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset)
|
||||||
</a>
|
</a>
|
||||||
<div class="hidden md:flex">
|
<div class="hidden md:flex">
|
||||||
{links.map((l) => {
|
{links.map((l) => {
|
||||||
return <a aria-label={l.name} href={l.url} target={l.external ? "_blank" : null}
|
return <a aria-label={l.name} href={l.external ? l.url : url(l.url)} target={l.external ? "_blank" : null}
|
||||||
class="btn-plain h-11 font-bold px-5 rounded-lg active:scale-95"
|
class="btn-plain h-11 font-bold px-5 rounded-lg active:scale-95"
|
||||||
>
|
>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
@ -101,9 +102,9 @@ document.addEventListener('astro:after-swap', () => {
|
||||||
}, { once: false });
|
}, { once: false });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{import.meta.env.PROD && <script is:raw>
|
{import.meta.env.PROD && <script is:inline define:vars={{scriptUrl: url('/pagefind/pagefind.js')}}>
|
||||||
async function loadPagefind() {
|
async function loadPagefind() {
|
||||||
const pagefind = await import('/pagefind/pagefind.js')
|
const pagefind = await import(scriptUrl)
|
||||||
await pagefind.options({
|
await pagefind.options({
|
||||||
'excerptLength': 20
|
'excerptLength': 20
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {formatDateToYYYYMMDD} from "../utils/date-utils";
|
||||||
import { Icon } from 'astro-icon/components';
|
import { Icon } from 'astro-icon/components';
|
||||||
import {i18n} from "../i18n/translation";
|
import {i18n} from "../i18n/translation";
|
||||||
import I18nKey from "../i18n/i18nKey";
|
import I18nKey from "../i18n/i18nKey";
|
||||||
|
import {url} from "../utils/url-utils";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
class: string;
|
class: string;
|
||||||
|
@ -32,7 +33,7 @@ const className = Astro.props.class;
|
||||||
<Icon name="material-symbols:menu-rounded" class="text-xl"></Icon>
|
<Icon name="material-symbols:menu-rounded" class="text-xl"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row flex-nowrap">
|
<div class="flex flex-row flex-nowrap">
|
||||||
<div><a href=`/archive/category/${category || 'uncategorized'}` aria-label=`View all posts in the ${category} category`
|
<div><a href={url(`/archive/category/${category || 'uncategorized'}/`)} aria-label=`View all posts in the ${category} category`
|
||||||
class="link-lg transition text-50 text-sm font-medium
|
class="link-lg transition text-50 text-sm font-medium
|
||||||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] whitespace-nowrap">
|
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] whitespace-nowrap">
|
||||||
{category || i18n(I18nKey.uncategorized)}
|
{category || i18n(I18nKey.uncategorized)}
|
||||||
|
@ -50,7 +51,7 @@ const className = Astro.props.class;
|
||||||
{(tags && tags.length > 0) && tags.map(tag => <div
|
{(tags && tags.length > 0) && tags.map(tag => <div
|
||||||
class="with-divider"
|
class="with-divider"
|
||||||
>
|
>
|
||||||
<a href=`/archive/tag/${tag}` aria-label=`View all posts with the ${tag} tag`
|
<a href={url(`/archive/tag/${tag}/`)} aria-label=`View all posts with the ${tag} tag`
|
||||||
class="link-lg transition text-50 text-sm font-medium
|
class="link-lg transition text-50 text-sm font-medium
|
||||||
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] whitespace-nowrap">
|
hover:text-[var(--primary)] dark:hover:text-[var(--primary)] whitespace-nowrap">
|
||||||
{tag}
|
{tag}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
|
import {url} from "@utils/url-utils.ts"
|
||||||
let keywordDesktop = ''
|
let keywordDesktop = ''
|
||||||
let keywordMobile = ''
|
let keywordMobile = ''
|
||||||
let result = []
|
let result = []
|
||||||
const fakeResult = [{
|
const fakeResult = [{
|
||||||
url: '/',
|
url: url('/'),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'This Is a Fake Search Result'
|
title: 'This Is a Fake Search Result'
|
||||||
},
|
},
|
||||||
excerpt: 'Because the search cannot work in the <mark>dev</mark> environment.'
|
excerpt: 'Because the search cannot work in the <mark>dev</mark> environment.'
|
||||||
}, {
|
}, {
|
||||||
url: '/',
|
url: url('/'),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'If You Want to Test the Search'
|
title: 'If You Want to Test the Search'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
import type { Page } from "astro";
|
import type { Page } from "astro";
|
||||||
import { Icon } from 'astro-icon/components';
|
import { Icon } from 'astro-icon/components';
|
||||||
|
import {url} from "../../utils/url-utils";
|
||||||
interface Props {
|
interface Props {
|
||||||
page: Page;
|
page: Page;
|
||||||
class?: string;
|
class?: string;
|
||||||
|
@ -49,19 +50,16 @@ if (r == page.lastPage - 2)
|
||||||
if (r < page.lastPage)
|
if (r < page.lastPage)
|
||||||
pages.push(page.lastPage);
|
pages.push(page.lastPage);
|
||||||
|
|
||||||
const parts: string[] = page.url.current.split('/');
|
|
||||||
const commonUrl: string = parts.slice(0, -1).join('/') + '/';
|
|
||||||
|
|
||||||
const getPageUrl = (p: number) => {
|
const getPageUrl = (p: number) => {
|
||||||
if (p == 1)
|
if (p == 1)
|
||||||
return commonUrl;
|
return '/';
|
||||||
return commonUrl + p;
|
return `/${p}/`;
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class:list={[className, "flex flex-row gap-3 justify-center"]} style={style}>
|
<div class:list={[className, "flex flex-row gap-3 justify-center"]} style={style}>
|
||||||
<a href={page.url.prev} aria-label={page.url.prev ? "Previous Page" : null}
|
<a href={url(page.url.prev)} aria-label={page.url.prev ? "Previous Page" : null}
|
||||||
class:list={["btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11",
|
class:list={["btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11",
|
||||||
{"disabled": page.url.prev == undefined}
|
{"disabled": page.url.prev == undefined}
|
||||||
]}
|
]}
|
||||||
|
@ -78,12 +76,12 @@ const getPageUrl = (p: number) => {
|
||||||
>
|
>
|
||||||
{p}
|
{p}
|
||||||
</div>
|
</div>
|
||||||
return <a href={getPageUrl(p)} aria-label=`Page ${p}`
|
return <a href={url(getPageUrl(p))} aria-label=`Page ${p}`
|
||||||
class="btn-card w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85]"
|
class="btn-card w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85]"
|
||||||
>{p}</a>
|
>{p}</a>
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<a href={page.url.next} aria-label={page.url.next ? "Next Page" : null}
|
<a href={url(page.url.next)} aria-label={page.url.next ? "Next Page" : null}
|
||||||
class:list={["btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11",
|
class:list={["btn-card overflow-hidden rounded-lg text-[var(--primary)] w-11 h-11",
|
||||||
{"disabled": page.url.next == undefined}
|
{"disabled": page.url.next == undefined}
|
||||||
]}
|
]}
|
||||||
|
|
|
@ -8,11 +8,13 @@ interface Props {
|
||||||
basePath?: string
|
basePath?: string
|
||||||
}
|
}
|
||||||
import { Image } from 'astro:assets';
|
import { Image } from 'astro:assets';
|
||||||
|
import {url} from "../../utils/url-utils";
|
||||||
|
|
||||||
const {id, src, alt, basePath = '/'} = Astro.props;
|
const {id, src, alt, basePath = '/'} = Astro.props;
|
||||||
const className = Astro.props.class;
|
const className = Astro.props.class;
|
||||||
|
|
||||||
const isLocal = !(src.startsWith('/') || src.startsWith('http') || src.startsWith('https') || src.startsWith('data:'));
|
const isLocal = !(src.startsWith('/') || src.startsWith('http') || src.startsWith('https') || src.startsWith('data:'));
|
||||||
|
const isPublic = src.startsWith('/');
|
||||||
|
|
||||||
// TODO temporary workaround for images dynamic import
|
// TODO temporary workaround for images dynamic import
|
||||||
// https://github.com/withastro/astro/issues/3373
|
// https://github.com/withastro/astro/issues/3373
|
||||||
|
@ -27,6 +29,6 @@ if (isLocal) {
|
||||||
<div class:list={[className, 'overflow-hidden relative']}>
|
<div class:list={[className, 'overflow-hidden relative']}>
|
||||||
<div class="transition absolute inset-0 dark:bg-black/10 bg-opacity-50 pointer-events-none"></div>
|
<div class="transition absolute inset-0 dark:bg-black/10 bg-opacity-50 pointer-events-none"></div>
|
||||||
{isLocal && <Image src={img} alt={alt || ""} class="w-full h-full object-center object-cover" />}
|
{isLocal && <Image src={img} alt={alt || ""} class="w-full h-full object-center object-cover" />}
|
||||||
{!isLocal && <img src={src} alt={alt || ""} class="w-full h-full object-center object-cover" />}
|
{!isLocal && <img src={isPublic ? url(src) : src} alt={alt || ""} class="w-full h-full object-center object-cover" />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
import ImageWrapper from "../misc/ImageWrapper.astro";
|
import ImageWrapper from "../misc/ImageWrapper.astro";
|
||||||
import {Icon} from "astro-icon/components";
|
import {Icon} from "astro-icon/components";
|
||||||
import {profileConfig} from "../../config";
|
import {profileConfig} from "../../config";
|
||||||
|
import {url} from "../../utils/url-utils";
|
||||||
|
|
||||||
const config = profileConfig;
|
const config = profileConfig;
|
||||||
---
|
---
|
||||||
<div class="card-base">
|
<div class="card-base">
|
||||||
<a aria-label="Go to About Page" href="/about"
|
<a aria-label="Go to About Page" href={url('/about/')}
|
||||||
class="group block relative mx-auto mt-4 lg:mx-3 lg:mt-3 mb-3
|
class="group block relative mx-auto mt-4 lg:mx-3 lg:mt-3 mb-3
|
||||||
max-w-[240px] lg:max-w-none overflow-hidden rounded-xl active:scale-95">
|
max-w-[240px] lg:max-w-none overflow-hidden rounded-xl active:scale-95">
|
||||||
<div class="absolute transition pointer-events-none group-hover:bg-black/30 group-active:bg-black/50
|
<div class="absolute transition pointer-events-none group-hover:bg-black/30 group-active:bg-black/50
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ButtonTag from "../control/ButtonTag.astro";
|
||||||
import {getTagList} from "../../utils/content-utils";
|
import {getTagList} from "../../utils/content-utils";
|
||||||
import {i18n} from "../../i18n/translation";
|
import {i18n} from "../../i18n/translation";
|
||||||
import I18nKey from "../../i18n/i18nKey";
|
import I18nKey from "../../i18n/i18nKey";
|
||||||
|
import {url} from "../../utils/url-utils";
|
||||||
|
|
||||||
const tags = await getTagList();
|
const tags = await getTagList();
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ const style = Astro.props.style
|
||||||
<WidgetLayout name={i18n(I18nKey.tags)} id="tags" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}>
|
<WidgetLayout name={i18n(I18nKey.tags)} id="tags" isCollapsed={isCollapsed} collapsedHeight={COLLAPSED_HEIGHT} class={className} style={style}>
|
||||||
<div class="flex gap-2 flex-wrap">
|
<div class="flex gap-2 flex-wrap">
|
||||||
{tags.map(t => (
|
{tags.map(t => (
|
||||||
<ButtonTag href={`/archive/tag/${t.name}`} label={`View all posts with the ${t.name} tag`}>
|
<ButtonTag href={url(`/archive/tag/${t.name}/`)} label={`View all posts with the ${t.name} tag`}>
|
||||||
{t.name}
|
{t.name}
|
||||||
</ButtonTag>
|
</ButtonTag>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -9,10 +9,10 @@ export const LinkPresets: { [key in LinkPreset]: NavBarLink } = {
|
||||||
},
|
},
|
||||||
[LinkPreset.About]: {
|
[LinkPreset.About]: {
|
||||||
name: i18n(I18nKey.about),
|
name: i18n(I18nKey.about),
|
||||||
url: '/about',
|
url: '/about/',
|
||||||
},
|
},
|
||||||
[LinkPreset.Archive]: {
|
[LinkPreset.Archive]: {
|
||||||
name: i18n(I18nKey.archive),
|
name: i18n(I18nKey.archive),
|
||||||
url: '/archive',
|
url: '/archive/',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {profileConfig, siteConfig} from "@/config";
|
||||||
import {Favicon} from "../types/config";
|
import {Favicon} from "../types/config";
|
||||||
import {defaultFavicons} from "../constants/icon";
|
import {defaultFavicons} from "../constants/icon";
|
||||||
import {LIGHT_MODE, DARK_MODE, AUTO_MODE, DEFAULT_THEME} from "../constants/constants";
|
import {LIGHT_MODE, DARK_MODE, AUTO_MODE, DEFAULT_THEME} from "../constants/constants";
|
||||||
|
import {url} from "../utils/url-utils";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -81,7 +82,7 @@ const favicons: Favicon[] = siteConfig.favicon.length > 0 ? siteConfig.favicon :
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
{favicons.map(favicon => (
|
{favicons.map(favicon => (
|
||||||
<link rel="icon"
|
<link rel="icon"
|
||||||
href={favicon.src}
|
href={favicon.src.startsWith('/') ? url(favicon.src) : favicon.src}
|
||||||
sizes={favicon.sizes}
|
sizes={favicon.sizes}
|
||||||
media={favicon.theme && `(prefers-color-scheme: ${favicon.theme})`}
|
media={favicon.theme && `(prefers-color-scheme: ${favicon.theme})`}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,19 +9,19 @@ export function pathsEqual(path1: string, path2: string) {
|
||||||
|
|
||||||
function joinUrl(...parts: string[]): string {
|
function joinUrl(...parts: string[]): string {
|
||||||
const joined = parts.join('/')
|
const joined = parts.join('/')
|
||||||
return joined.replace(/([^:]\/)\/+/g, '$1')
|
return joined.replace(/\/+/g, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPostUrlBySlug(slug: string): string | null {
|
export function getPostUrlBySlug(slug: string): string | null {
|
||||||
if (!slug) return null
|
if (!slug) return null
|
||||||
return `/posts/${slug}`
|
return url(`/posts/${slug}/`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCategoryUrl(category: string): string | null {
|
export function getCategoryUrl(category: string): string | null {
|
||||||
if (!category) return null
|
if (!category) return null
|
||||||
if (category === i18n(i18nKey.uncategorized))
|
if (category === i18n(i18nKey.uncategorized))
|
||||||
return '/archive/category/uncategorized'
|
return url('/archive/category/uncategorized/')
|
||||||
return `/archive/category/${category}`
|
return url(`/archive/category/${category}/`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDir(path: string): string {
|
export function getDir(path: string): string {
|
||||||
|
@ -31,3 +31,7 @@ export function getDir(path: string): string {
|
||||||
}
|
}
|
||||||
return path.substring(0, lastSlashIndex + 1)
|
return path.substring(0, lastSlashIndex + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function url(path: string) {
|
||||||
|
return joinUrl('', import.meta.env.BASE_URL, path)
|
||||||
|
}
|
Loading…
Reference in New Issue