refactor: improve code quality
This commit is contained in:
		
							parent
							
								
									743d8dd9c2
								
							
						
					
					
						commit
						003c644146
					
				| 
						 | 
					@ -6,9 +6,9 @@ import I18nKey from "../i18n/i18nKey";
 | 
				
			||||||
import {UNCATEGORIZED} from "@constants/constants";
 | 
					import {UNCATEGORIZED} from "@constants/constants";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
    keyword: string;
 | 
					    keyword?: string;
 | 
				
			||||||
    tags: string[];
 | 
					    tags?: string[];
 | 
				
			||||||
    categories: string[];
 | 
					    categories?: string[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const { keyword, tags, categories} = Astro.props;
 | 
					const { keyword, tags, categories} = Astro.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,8 +27,8 @@ if (Array.isArray(categories) && categories.length > 0) {
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const groups = function () {
 | 
					const groups: {year: number, posts: typeof posts}[] = function () {
 | 
				
			||||||
    const groupedPosts = posts.reduce((grouped, post) => {
 | 
					    const groupedPosts = posts.reduce((grouped: {[year: number]: typeof posts}, post) => {
 | 
				
			||||||
        const year = post.data.published.getFullYear()
 | 
					        const year = post.data.published.getFullYear()
 | 
				
			||||||
        if (!grouped[year]) {
 | 
					        if (!grouped[year]) {
 | 
				
			||||||
            grouped[year] = []
 | 
					            grouped[year] = []
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,8 @@ const groups = function () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // convert the object to an array
 | 
					    // convert the object to an array
 | 
				
			||||||
    const groupedPostsArray = Object.keys(groupedPosts).map(key => ({
 | 
					    const groupedPostsArray = Object.keys(groupedPosts).map(key => ({
 | 
				
			||||||
        year: key,
 | 
					        year: parseInt(key),
 | 
				
			||||||
        posts: groupedPosts[key]
 | 
					        posts: groupedPosts[parseInt(key)]
 | 
				
			||||||
    }))
 | 
					    }))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // sort years by latest first
 | 
					    // sort years by latest first
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
import { Icon } from 'astro-icon/components';
 | 
					import { Icon } from 'astro-icon/components';
 | 
				
			||||||
import DisplaySettings from "./widget/DisplaySettings.svelte";
 | 
					import DisplaySettings from "./widget/DisplaySettings.svelte";
 | 
				
			||||||
import {LinkPreset, NavBarLink} from "../types/config";
 | 
					import {LinkPreset, type NavBarLink} from "../types/config";
 | 
				
			||||||
import {navBarConfig, siteConfig} from "../config";
 | 
					import {navBarConfig, siteConfig} from "../config";
 | 
				
			||||||
import NavMenuPanel from "./widget/NavMenuPanel.astro";
 | 
					import NavMenuPanel from "./widget/NavMenuPanel.astro";
 | 
				
			||||||
import Search from "./Search.svelte";
 | 
					import Search from "./Search.svelte";
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ let links: NavBarLink[] = navBarConfig.links.map((item: NavBarLink | LinkPreset)
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
                <div class="flex items-center">
 | 
					                <div class="flex items-center">
 | 
				
			||||||
                    {l.name}
 | 
					                    {l.name}
 | 
				
			||||||
                    {l.external && <Icon size="14" name="fa6-solid:arrow-up-right-from-square" class="transition -translate-y-[1px] ml-1 text-black/[0.2] dark:text-white/[0.2]"></Icon>}
 | 
					                    {l.external && <Icon size="0.875rem" name="fa6-solid:arrow-up-right-from-square" class="transition -translate-y-[1px] ml-1 text-black/[0.2] dark:text-white/[0.2]"></Icon>}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </a>;
 | 
					            </a>;
 | 
				
			||||||
        })}
 | 
					        })}
 | 
				
			||||||
| 
						 | 
					@ -80,22 +80,20 @@ function switchTheme() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function loadButtonScript() {
 | 
					function loadButtonScript() {
 | 
				
			||||||
    let switchBtn = document.getElementById("scheme-switch");
 | 
					    let switchBtn = document.getElementById("scheme-switch");
 | 
				
			||||||
    switchBtn.addEventListener("click", function () {
 | 
					    switchBtn!.addEventListener("click", function () {
 | 
				
			||||||
        switchTheme()
 | 
					        switchTheme()
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let settingBtn = document.getElementById("display-settings-switch");
 | 
					    let settingBtn = document.getElementById("display-settings-switch");
 | 
				
			||||||
    if (settingBtn) {
 | 
					    settingBtn!.addEventListener("click", function () {
 | 
				
			||||||
        settingBtn.addEventListener("click", function () {
 | 
					        let settingPanel = document.getElementById("display-setting");
 | 
				
			||||||
            let settingPanel = document.getElementById("display-setting");
 | 
					        settingPanel!.classList.toggle("float-panel-closed");
 | 
				
			||||||
            settingPanel.classList.toggle("float-panel-closed");
 | 
					    });
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let menuBtn = document.getElementById("nav-menu-switch");
 | 
					    let menuBtn = document.getElementById("nav-menu-switch");
 | 
				
			||||||
    menuBtn.addEventListener("click", function () {
 | 
					    menuBtn!.addEventListener("click", function () {
 | 
				
			||||||
        let menuPanel = document.getElementById("nav-menu-panel");
 | 
					        let menuPanel = document.getElementById("nav-menu-panel");
 | 
				
			||||||
        menuPanel.classList.toggle("float-panel-closed");
 | 
					        menuPanel!.classList.toggle("float-panel-closed");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ import I18nKey from "../i18n/i18nKey";
 | 
				
			||||||
import {getDir} from "../utils/url-utils";
 | 
					import {getDir} from "../utils/url-utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
    class: string;
 | 
					    class?: string;
 | 
				
			||||||
    entry: any;
 | 
					    entry: any;
 | 
				
			||||||
    title: string;
 | 
					    title: string;
 | 
				
			||||||
    url: string;
 | 
					    url: string;
 | 
				
			||||||
| 
						 | 
					@ -17,11 +17,10 @@ interface Props {
 | 
				
			||||||
    category: string;
 | 
					    category: string;
 | 
				
			||||||
    image: string;
 | 
					    image: string;
 | 
				
			||||||
    description: string;
 | 
					    description: string;
 | 
				
			||||||
    words: number;
 | 
					 | 
				
			||||||
    draft: boolean;
 | 
					    draft: boolean;
 | 
				
			||||||
    style: string;
 | 
					    style: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const { entry, title, url, published, tags, category, image, description, words, style } = Astro.props;
 | 
					const { entry, title, url, published, tags, category, image, description, style } = Astro.props;
 | 
				
			||||||
const className = Astro.props.class;
 | 
					const className = Astro.props.class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const hasCover = image !== undefined && image !== null && image !== '';
 | 
					const hasCover = image !== undefined && image !== null && image !== '';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,9 +10,9 @@ interface Props {
 | 
				
			||||||
    published: Date;
 | 
					    published: Date;
 | 
				
			||||||
    tags: string[];
 | 
					    tags: string[];
 | 
				
			||||||
    category: string;
 | 
					    category: string;
 | 
				
			||||||
    hideTagsForMobile: boolean;
 | 
					    hideTagsForMobile?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const {published, tags, category, hideTagsForMobile} = Astro.props;
 | 
					const {published, tags, category, hideTagsForMobile = false} = Astro.props;
 | 
				
			||||||
const className = Astro.props.class;
 | 
					const className = Astro.props.class;
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,9 +4,9 @@ interface Props {
 | 
				
			||||||
    url?: string
 | 
					    url?: string
 | 
				
			||||||
    label?: string
 | 
					    label?: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const { badge, url, name } = Astro.props
 | 
					const { badge, url, label } = Astro.props
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
<a href={url} aria-label={name}>
 | 
					<a href={url} aria-label={label}>
 | 
				
			||||||
    <button
 | 
					    <button
 | 
				
			||||||
        class:list={`
 | 
					        class:list={`
 | 
				
			||||||
            w-full
 | 
					            w-full
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ const getPageUrl = (p: number) => {
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<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={url(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}
 | 
				
			||||||
       ]}
 | 
					       ]}
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ const getPageUrl = (p: number) => {
 | 
				
			||||||
            >{p}</a>
 | 
					            >{p}</a>
 | 
				
			||||||
        })}
 | 
					        })}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <a href={url(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}
 | 
				
			||||||
       ]}
 | 
					       ]}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,9 @@ if (isLocal) {
 | 
				
			||||||
    const files = import.meta.glob<ImageMetadata>("../../**", { import: 'default' });
 | 
					    const files = import.meta.glob<ImageMetadata>("../../**", { import: 'default' });
 | 
				
			||||||
    let normalizedPath = path.normalize(path.join("../../", basePath, src)).replace(/\\/g, "/");
 | 
					    let normalizedPath = path.normalize(path.join("../../", basePath, src)).replace(/\\/g, "/");
 | 
				
			||||||
    img = await (files[normalizedPath])();
 | 
					    img = await (files[normalizedPath])();
 | 
				
			||||||
 | 
					    if (!img) {
 | 
				
			||||||
 | 
					        console.error(`No image found for path ${normalizedPath}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const imageClass = 'w-full h-full object-cover';
 | 
					const imageClass = 'w-full h-full object-cover';
 | 
				
			||||||
| 
						 | 
					@ -31,7 +34,7 @@ const imageStyle = `object-position: ${position}`
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
<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={imageClass} style={imageStyle}/>}
 | 
					    {isLocal && img && <Image src={img} alt={alt || ""} class={imageClass} style={imageStyle}/>}
 | 
				
			||||||
    {!isLocal && <img src={isPublic ? url(src) : src} alt={alt || ""} class={imageClass} style={imageStyle}/>}
 | 
					    {!isLocal && <img src={isPublic ? url(src) : src} alt={alt || ""} class={imageClass} style={imageStyle}/>}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,5 +40,5 @@ const postUrl = decodeURIComponent(Astro.url.toString());
 | 
				
			||||||
            <a href={licenseConf.url} target="_blank" class="link text-[var(--primary)] whitespace-nowrap">{licenseConf.name}</a>
 | 
					            <a href={licenseConf.url} target="_blank" class="link text-[var(--primary)] whitespace-nowrap">{licenseConf.name}</a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <Icon name="fa6-brands:creative-commons" class="transition absolute pointer-events-none right-6 top-1/2 -translate-y-1/2 text-black/5 dark:text-white/5" size="240"></Icon>
 | 
					    <Icon name="fa6-brands:creative-commons" class="transition absolute pointer-events-none right-6 top-1/2 -translate-y-1/2 text-black/5 dark:text-white/5" size="15rem"></Icon>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import WidgetLayout from "./WidgetLayout.astro";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {i18n} from "../../i18n/translation";
 | 
					import {i18n} from "../../i18n/translation";
 | 
				
			||||||
import I18nKey from "../../i18n/i18nKey";
 | 
					import I18nKey from "../../i18n/i18nKey";
 | 
				
			||||||
import {Category, getCategoryList} from "../../utils/content-utils";
 | 
					import {getCategoryList} from "../../utils/content-utils";
 | 
				
			||||||
import {getCategoryUrl} from "../../utils/url-utils";
 | 
					import {getCategoryUrl} from "../../utils/url-utils";
 | 
				
			||||||
import ButtonLink from "../control/ButtonLink.astro";
 | 
					import ButtonLink from "../control/ButtonLink.astro";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ const style = Astro.props.style
 | 
				
			||||||
    {categories.map((c) =>
 | 
					    {categories.map((c) =>
 | 
				
			||||||
        <ButtonLink
 | 
					        <ButtonLink
 | 
				
			||||||
            url={getCategoryUrl(c.name)}
 | 
					            url={getCategoryUrl(c.name)}
 | 
				
			||||||
            badge={c.count}
 | 
					            badge={String(c.count)}
 | 
				
			||||||
            label=`View all posts in the ${c.name} category`
 | 
					            label=`View all posts in the ${c.name} category`
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            {c.name}
 | 
					            {c.name}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
import {NavBarLink} from "../../types/config";
 | 
					import {type NavBarLink} from "../../types/config";
 | 
				
			||||||
import {Icon} from "astro-icon/components";
 | 
					import {Icon} from "astro-icon/components";
 | 
				
			||||||
import {url} from "../../utils/url-utils";
 | 
					import {url} from "../../utils/url-utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,11 +20,11 @@ const links = Astro.props.links;
 | 
				
			||||||
                {link.name}
 | 
					                {link.name}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            {!link.external && <Icon name="material-symbols:chevron-right-rounded"
 | 
					            {!link.external && <Icon name="material-symbols:chevron-right-rounded"
 | 
				
			||||||
                  class="transition text-[var(--primary)]" size="20"
 | 
					                  class="transition text-[var(--primary)]" size="1.25rem"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
            </Icon>}
 | 
					            </Icon>}
 | 
				
			||||||
            {link.external && <Icon name="fa6-solid:arrow-up-right-from-square"
 | 
					            {link.external && <Icon name="fa6-solid:arrow-up-right-from-square"
 | 
				
			||||||
                  class="transition text-black/25 dark:text-white/25 -translate-x-1" size="12"
 | 
					                  class="transition text-black/25 dark:text-white/25 -translate-x-1" size="0.75rem"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
            </Icon>}
 | 
					            </Icon>}
 | 
				
			||||||
        </a>
 | 
					        </a>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ const config = profileConfig;
 | 
				
			||||||
                  class="transition opacity-0 scale-90 group-hover:scale-100 group-hover:opacity-100 text-white text-5xl">
 | 
					                  class="transition opacity-0 scale-90 group-hover:scale-100 group-hover:opacity-100 text-white text-5xl">
 | 
				
			||||||
            </Icon>
 | 
					            </Icon>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <ImageWrapper src={config.avatar} alt="Profile Image of the Author" class="mx-auto lg:w-full h-full lg:mt-0 "></ImageWrapper>
 | 
					        <ImageWrapper src={config.avatar || ""} alt="Profile Image of the Author" class="mx-auto lg:w-full h-full lg:mt-0 "></ImageWrapper>
 | 
				
			||||||
    </a>
 | 
					    </a>
 | 
				
			||||||
    <div class="px-2">
 | 
					    <div class="px-2">
 | 
				
			||||||
        <div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition">{config.name}</div>
 | 
					        <div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition">{config.name}</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ const {
 | 
				
			||||||
const className = Astro.props.class
 | 
					const className = Astro.props.class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
<widget-layout data-id={id} data-is-collapsed={isCollapsed} class={"pb-4 card-base " + className} style={style}>
 | 
					<widget-layout data-id={id} data-is-collapsed={String(isCollapsed)} class={"pb-4 card-base " + className} style={style}>
 | 
				
			||||||
    <div class="font-bold transition text-lg text-neutral-900 dark:text-neutral-100 relative ml-8 mt-4 mb-2
 | 
					    <div class="font-bold transition text-lg text-neutral-900 dark:text-neutral-100 relative ml-8 mt-4 mb-2
 | 
				
			||||||
        before:w-1 before:h-4 before:rounded-md before:bg-[var(--primary)]
 | 
					        before:w-1 before:h-4 before:rounded-md before:bg-[var(--primary)]
 | 
				
			||||||
        before:absolute before:left-[-16px] before:top-[5.5px]">{name}</div>
 | 
					        before:absolute before:left-[-16px] before:top-[5.5px]">{name}</div>
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ const className = Astro.props.class
 | 
				
			||||||
    {isCollapsed && <div class="expand-btn px-4 -mb-2">
 | 
					    {isCollapsed && <div class="expand-btn px-4 -mb-2">
 | 
				
			||||||
        <button class="btn-plain rounded-lg w-full h-9">
 | 
					        <button class="btn-plain rounded-lg w-full h-9">
 | 
				
			||||||
            <div class="text-[var(--primary)] flex items-center justify-center gap-2 -translate-x-2">
 | 
					            <div class="text-[var(--primary)] flex items-center justify-center gap-2 -translate-x-2">
 | 
				
			||||||
                <Icon name="material-symbols:more-horiz" size={28}></Icon> {i18n(I18nKey.more)}
 | 
					                <Icon name="material-symbols:more-horiz" size="1.75rem"></Icon> {i18n(I18nKey.more)}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
    </div>}
 | 
					    </div>}
 | 
				
			||||||
| 
						 | 
					@ -48,15 +48,15 @@ const className = Astro.props.class
 | 
				
			||||||
        constructor() {
 | 
					        constructor() {
 | 
				
			||||||
            super();
 | 
					            super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.dataset.isCollapsed === undefined || this.dataset.isCollapsed === false)
 | 
					            if (this.dataset.isCollapsed !== "true")
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const id = this.dataset.id;
 | 
					            const id = this.dataset.id;
 | 
				
			||||||
            const btn = this.querySelector('.expand-btn');
 | 
					            const btn = this.querySelector('.expand-btn');
 | 
				
			||||||
            const wrapper = this.querySelector(`#${id}`)
 | 
					            const wrapper = this.querySelector(`#${id}`)
 | 
				
			||||||
            btn.addEventListener('click', () => {
 | 
					            btn!.addEventListener('click', () => {
 | 
				
			||||||
                wrapper.classList.remove('collapsed');
 | 
					                wrapper!.classList.remove('collapsed');
 | 
				
			||||||
                btn.classList.add('hidden');
 | 
					                btn!.classList.add('hidden');
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,11 +4,17 @@ const postsCollection = defineCollection({
 | 
				
			||||||
  schema: z.object({
 | 
					  schema: z.object({
 | 
				
			||||||
    title: z.string(),
 | 
					    title: z.string(),
 | 
				
			||||||
    published: z.date(),
 | 
					    published: z.date(),
 | 
				
			||||||
    draft: z.boolean().optional(),
 | 
					    draft: z.boolean().optional().default(false),
 | 
				
			||||||
    description: z.string().optional(),
 | 
					    description: z.string().optional().default(""),
 | 
				
			||||||
    image: z.string().optional(),
 | 
					    image: z.string().optional().default(""),
 | 
				
			||||||
    tags: z.array(z.string()).optional(),
 | 
					    tags: z.array(z.string()).optional().default([]),
 | 
				
			||||||
    category: z.string().optional(),
 | 
					    category: z.string().optional().default(""),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* For internal use */
 | 
				
			||||||
 | 
					    prevTitle: z.string().default(""),
 | 
				
			||||||
 | 
					    prevSlug: z.string().default(""),
 | 
				
			||||||
 | 
					    nextTitle: z.string().default(""),
 | 
				
			||||||
 | 
					    nextSlug: z.string().default(""),
 | 
				
			||||||
  }),
 | 
					  }),
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export const collections = {
 | 
					export const collections = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,14 +8,14 @@ import ImageWrapper from "@components/misc/ImageWrapper.astro";
 | 
				
			||||||
import {pathsEqual} from "@utils/url-utils";
 | 
					import {pathsEqual} from "@utils/url-utils";
 | 
				
			||||||
import ConfigCarrier from "@components/ConfigCarrier.astro";
 | 
					import ConfigCarrier from "@components/ConfigCarrier.astro";
 | 
				
			||||||
import {profileConfig, siteConfig} from "@/config";
 | 
					import {profileConfig, siteConfig} from "@/config";
 | 
				
			||||||
import {Favicon} from "../types/config";
 | 
					import {type 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";
 | 
					import {url} from "../utils/url-utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
	title: string;
 | 
						title?: string;
 | 
				
			||||||
	banner: string;
 | 
						banner?: string;
 | 
				
			||||||
	description?: string;
 | 
						description?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,8 +23,6 @@ let { title, banner, description } = Astro.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const isHomePage = pathsEqual(Astro.url.pathname, '/');
 | 
					const isHomePage = pathsEqual(Astro.url.pathname, '/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const testPathName = Astro.url.pathname;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const anim = {
 | 
					const anim = {
 | 
				
			||||||
	old: {
 | 
						old: {
 | 
				
			||||||
		name: 'fadeIn',
 | 
							name: 'fadeIn',
 | 
				
			||||||
| 
						 | 
					@ -73,7 +71,7 @@ const siteLang = siteConfig.lang.replace('_', '-')
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang={siteLang} isHome={isHomePage} pathname={testPathName} class="bg-[var(--page-bg)] transition text-[14px] md:text-[16px]">
 | 
					<html lang={siteLang} data-isHome={String(isHomePage)} class="bg-[var(--page-bg)] transition text-[14px] md:text-[16px]">
 | 
				
			||||||
	<head>
 | 
						<head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<title>{pageTitle}</title>
 | 
							<title>{pageTitle}</title>
 | 
				
			||||||
| 
						 | 
					@ -232,13 +230,14 @@ function setClickOutsideToClose(panel: string, ignores: string[]) {
 | 
				
			||||||
	document.addEventListener("click", event => {
 | 
						document.addEventListener("click", event => {
 | 
				
			||||||
		let panelDom = document.getElementById(panel);
 | 
							let panelDom = document.getElementById(panel);
 | 
				
			||||||
		let tDom = event.target;
 | 
							let tDom = event.target;
 | 
				
			||||||
 | 
							if (!(tDom instanceof Node)) return;		// Ensure the event target is an HTML Node
 | 
				
			||||||
		for (let ig of ignores) {
 | 
							for (let ig of ignores) {
 | 
				
			||||||
			let ie = document.getElementById(ig)
 | 
								let ie = document.getElementById(ig)
 | 
				
			||||||
			if (ie == tDom || (ie?.contains(tDom))) {
 | 
								if (ie == tDom || (ie?.contains(tDom))) {
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		panelDom.classList.add("float-panel-closed");
 | 
							panelDom!.classList.add("float-panel-closed");
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
setClickOutsideToClose("display-setting", ["display-setting", "display-settings-switch"])
 | 
					setClickOutsideToClose("display-setting", ["display-setting", "display-settings-switch"])
 | 
				
			||||||
| 
						 | 
					@ -257,7 +256,8 @@ function loadHue() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setBannerHeight() {
 | 
					function setBannerHeight() {
 | 
				
			||||||
	const banner = document.getElementById('banner-wrapper');
 | 
						const banner = document.getElementById('banner-wrapper');
 | 
				
			||||||
	if (document.documentElement.hasAttribute('isHome')) {
 | 
						if (!banner) return
 | 
				
			||||||
 | 
						if (document.documentElement.dataset.isHome === "true") {
 | 
				
			||||||
		banner.classList.remove('banner-else');
 | 
							banner.classList.remove('banner-else');
 | 
				
			||||||
		banner.classList.add('banner-home');
 | 
							banner.classList.add('banner-home');
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -267,11 +267,13 @@ function setBannerHeight() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function initCustomScrollbar() {
 | 
					function initCustomScrollbar() {
 | 
				
			||||||
 | 
						const bodyElement = document.querySelector('body');
 | 
				
			||||||
 | 
						if (!bodyElement) return;
 | 
				
			||||||
	OverlayScrollbars(
 | 
						OverlayScrollbars(
 | 
				
			||||||
		// docs say that a initialization to the body element would affect native functionality like window.scrollTo
 | 
							// docs say that a initialization to the body element would affect native functionality like window.scrollTo
 | 
				
			||||||
		// but just leave it here for now
 | 
							// but just leave it here for now
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			target: document.querySelector('body'),
 | 
								target: bodyElement,
 | 
				
			||||||
			cancel: {
 | 
								cancel: {
 | 
				
			||||||
				nativeScrollbarsOverlaid: true,    // don't initialize the overlay scrollbar if there is a native one
 | 
									nativeScrollbarsOverlaid: true,    // don't initialize the overlay scrollbar if there is a native one
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ import BackToTop from "@components/control/BackToTop.astro";
 | 
				
			||||||
import {siteConfig} from "@/config";
 | 
					import {siteConfig} from "@/config";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
    title: string;
 | 
					    title?: string;
 | 
				
			||||||
    banner?: string;
 | 
					    banner?: string;
 | 
				
			||||||
    description?: string;
 | 
					    description?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ export async function getStaticPaths() {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { category } = Astro.params;
 | 
					const category = Astro.params.category as string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,6 @@ import ArchivePanel from "@components/ArchivePanel.astro";
 | 
				
			||||||
import {i18n} from "@i18n/translation";
 | 
					import {i18n} from "@i18n/translation";
 | 
				
			||||||
import I18nKey from "@i18n/i18nKey";
 | 
					import I18nKey from "@i18n/i18nKey";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function getStaticPaths() {
 | 
					export async function getStaticPaths() {
 | 
				
			||||||
    let posts = await getSortedPosts()
 | 
					    let posts = await getSortedPosts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +24,7 @@ export async function getStaticPaths() {
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tag } = Astro.params;
 | 
					const tag= Astro.params.tag as string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,21 +108,23 @@ const jsonLd = {
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="flex flex-col md:flex-row justify-between mb-4 gap-4 overflow-hidden w-full">
 | 
					    <div class="flex flex-col md:flex-row justify-between mb-4 gap-4 overflow-hidden w-full">
 | 
				
			||||||
        <a href={getPostUrlBySlug(entry.data.nextSlug)} class="w-full font-bold overflow-hidden active:scale-95">
 | 
					        <a href={entry.data.nextSlug ? getPostUrlBySlug(entry.data.nextSlug) : "#"}
 | 
				
			||||||
 | 
					           class:list={["w-full font-bold overflow-hidden active:scale-95", {"pointer-events-none": !entry.data.nextSlug}]}>
 | 
				
			||||||
            {entry.data.nextSlug && <div class="btn-card rounded-2xl w-full h-[3.75rem] max-w-full px-4 flex items-center justify-start gap-4" >
 | 
					            {entry.data.nextSlug && <div class="btn-card rounded-2xl w-full h-[3.75rem] max-w-full px-4 flex items-center justify-start gap-4" >
 | 
				
			||||||
                <Icon name="material-symbols:chevron-left-rounded" size={32} class="text-[var(--primary)]" />
 | 
					                <Icon name="material-symbols:chevron-left-rounded" size="2rem" class="text-[var(--primary)]" />
 | 
				
			||||||
                <div class="overflow-hidden transition overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_3rem)] text-black/75 dark:text-white/75">
 | 
					                <div class="overflow-hidden transition overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_3rem)] text-black/75 dark:text-white/75">
 | 
				
			||||||
                    {entry.data.nextTitle}
 | 
					                    {entry.data.nextTitle}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>}
 | 
					            </div>}
 | 
				
			||||||
        </a>
 | 
					        </a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <a href={getPostUrlBySlug(entry.data.prevSlug)} class="w-full font-bold overflow-hidden active:scale-95">
 | 
					        <a href={entry.data.prevSlug ? getPostUrlBySlug(entry.data.prevSlug) : "#"}
 | 
				
			||||||
 | 
					           class:list={["w-full font-bold overflow-hidden active:scale-95", {"pointer-events-none": !entry.data.prevSlug}]}>
 | 
				
			||||||
            {entry.data.prevSlug && <div class="btn-card rounded-2xl w-full h-[3.75rem] max-w-full px-4 flex items-center justify-end gap-4">
 | 
					            {entry.data.prevSlug && <div class="btn-card rounded-2xl w-full h-[3.75rem] max-w-full px-4 flex items-center justify-end gap-4">
 | 
				
			||||||
                <div class="overflow-hidden transition overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_3rem)] text-black/75 dark:text-white/75">
 | 
					                <div class="overflow-hidden transition overflow-ellipsis whitespace-nowrap max-w-[calc(100%_-_3rem)] text-black/75 dark:text-white/75">
 | 
				
			||||||
                    {entry.data.prevTitle}
 | 
					                    {entry.data.prevTitle}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <Icon name="material-symbols:chevron-right-rounded" size={32} class="text-[var(--primary)]" />
 | 
					                <Icon name="material-symbols:chevron-right-rounded" size="2rem" class="text-[var(--primary)]" />
 | 
				
			||||||
            </div>}
 | 
					            </div>}
 | 
				
			||||||
        </a>
 | 
					        </a>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,11 +14,11 @@ export function getHue(): number {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function setHue(hue: number): void {
 | 
					export function setHue(hue: number): void {
 | 
				
			||||||
  localStorage.setItem('hue', String(hue))
 | 
					  localStorage.setItem('hue', String(hue))
 | 
				
			||||||
  const r = document.querySelector(':root')
 | 
					  const r = document.querySelector(':root') as HTMLElement
 | 
				
			||||||
  if (!r) {
 | 
					  if (!r) {
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  r.style.setProperty('--hue', hue)
 | 
					  r.style.setProperty('--hue', String(hue))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,13 +12,11 @@ function joinUrl(...parts: string[]): string {
 | 
				
			||||||
  return joined.replace(/\/+/g, '/');
 | 
					  return joined.replace(/\/+/g, '/');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getPostUrlBySlug(slug: string): string | null {
 | 
					export function getPostUrlBySlug(slug: string): string {
 | 
				
			||||||
  if (!slug) return null
 | 
					 | 
				
			||||||
  return url(`/posts/${slug}/`)
 | 
					  return url(`/posts/${slug}/`)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getCategoryUrl(category: string): string | null {
 | 
					export function getCategoryUrl(category: string): string {
 | 
				
			||||||
  if (!category) return null
 | 
					 | 
				
			||||||
  if (category === i18n(i18nKey.uncategorized))
 | 
					  if (category === i18n(i18nKey.uncategorized))
 | 
				
			||||||
    return url('/archive/category/uncategorized/')
 | 
					    return url('/archive/category/uncategorized/')
 | 
				
			||||||
  return url(`/archive/category/${category}/`)
 | 
					  return url(`/archive/category/${category}/`)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue