Astro v5 with new API

This commit is contained in:
L4Ph
2025-06-04 22:53:19 +09:00
parent d75412146b
commit e3168c5d5a
10 changed files with 26 additions and 17 deletions

View File

@@ -105,7 +105,7 @@ onMount(async () => {
{#each group.posts as post} {#each group.posts as post}
<a <a
href={getPostUrlBySlug(post.slug)} href={getPostUrlBySlug(post.id)}
aria-label={post.data.title} aria-label={post.data.title}
class="group btn-plain !block h-10 w-full rounded-lg hover:text-[initial]" class="group btn-plain !block h-10 w-full rounded-lg hover:text-[initial]"
> >

View File

@@ -1,6 +1,6 @@
--- ---
import path from "node:path"; import path from "node:path";
import type { CollectionEntry } from "astro:content"; import { type CollectionEntry, render } from "astro:content";
import { Icon } from "astro-icon/components"; import { Icon } from "astro-icon/components";
import I18nKey from "../i18n/i18nKey"; import I18nKey from "../i18n/i18nKey";
import { i18n } from "../i18n/translation"; import { i18n } from "../i18n/translation";
@@ -40,7 +40,7 @@ const hasCover = image !== undefined && image !== null && image !== "";
const coverWidth = "28%"; const coverWidth = "28%";
const { remarkPluginFrontmatter } = await entry.render(); const { remarkPluginFrontmatter } = await render(entry);
--- ---
<div class:list={["card-base flex flex-col-reverse md:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}> <div class:list={["card-base flex flex-col-reverse md:flex-col w-full rounded-[var(--radius-large)] overflow-hidden relative", className]} style={style}>
<div class:list={["pl-6 md:pl-9 pr-6 md:pr-2 pt-6 md:pt-7 pb-6 relative", {"w-full md:w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-full md:w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}> <div class:list={["pl-6 md:pl-9 pr-6 md:pr-2 pt-6 md:pt-7 pb-6 relative", {"w-full md:w-[calc(100%_-_52px_-_12px)]": !hasCover, "w-full md:w-[calc(100%_-_var(--coverWidth)_-_12px)]": hasCover}]}>

View File

@@ -17,7 +17,7 @@ const interval = 50;
category={entry.data.category} category={entry.data.category}
published={entry.data.published} published={entry.data.published}
updated={entry.data.updated} updated={entry.data.updated}
url={getPostUrlBySlug(entry.slug)} url={getPostUrlBySlug(entry.id)}
image={entry.data.image} image={entry.data.image}
description={entry.data.description} description={entry.data.description}
draft={entry.data.draft} draft={entry.data.draft}

View File

@@ -38,9 +38,10 @@ if (isLocal) {
console.error( console.error(
`\n[ERROR] Image file not found: ${normalizedPath.replace("../../", "src/")}`, `\n[ERROR] Image file not found: ${normalizedPath.replace("../../", "src/")}`,
); );
} } else {
img = await file(); img = await file();
} }
}
const imageClass = "w-full h-full object-cover"; const imageClass = "w-full h-full object-cover";
const imageStyle = `object-position: ${position}`; const imageStyle = `object-position: ${position}`;
@@ -50,4 +51,3 @@ const imageStyle = `object-position: ${position}`;
{isLocal && img && <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>

View File

@@ -34,7 +34,7 @@ const maxLevel = siteConfig.toc.depth;
{isPostsRoute && {isPostsRoute &&
<table-of-contents class:list={[className, "group"]}> <table-of-contents class:list={[className, "group"]}>
{headings.filter((heading) => heading.depth < minDepth + maxLevel).map((heading) => {headings.filter((heading) => heading.depth < minDepth + maxLevel).map((heading) =>
<a href={`#${heading.slug}`} class="px-2 flex gap-2 relative transition w-full min-h-9 rounded-xl <a href={`#${heading.id}`} class="px-2 flex gap-2 relative transition w-full min-h-9 rounded-xl
hover:bg-[var(--toc-btn-hover)] active:bg-[var(--toc-btn-active)] py-2 hover:bg-[var(--toc-btn-hover)] active:bg-[var(--toc-btn-active)] py-2
"> ">
<div class:list={["transition w-5 h-5 shrink-0 rounded-lg text-xs flex items-center justify-center font-bold", <div class:list={["transition w-5 h-5 shrink-0 rounded-lg text-xs flex items-center justify-center font-bold",

View File

@@ -1,6 +1,8 @@
import { defineCollection, z } from "astro:content"; import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";
const postsCollection = defineCollection({ const postsCollection = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/posts/" }),
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
published: z.date(), published: z.date(),
@@ -9,7 +11,7 @@ const postsCollection = defineCollection({
description: z.string().optional().default(""), description: z.string().optional().default(""),
image: z.string().optional().default(""), image: z.string().optional().default(""),
tags: z.array(z.string()).optional().default([]), tags: z.array(z.string()).optional().default([]),
category: z.string().optional().nullable().default(""), category: z.string().optional().default(""),
lang: z.string().optional().default(""), lang: z.string().optional().default(""),
/* For internal use */ /* For internal use */
@@ -19,6 +21,12 @@ const postsCollection = defineCollection({
nextSlug: z.string().default(""), nextSlug: z.string().default(""),
}), }),
}); });
const specCollection = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/content/spec/" }),
schema: z.object({}),
});
export const collections = { export const collections = {
posts: postsCollection, posts: postsCollection,
spec: specCollection,
}; };

View File

@@ -1,5 +1,6 @@
--- ---
import path from "node:path"; import path from "node:path";
import { render } from "astro:content";
import License from "@components/misc/License.astro"; import License from "@components/misc/License.astro";
import Markdown from "@components/misc/Markdown.astro"; import Markdown from "@components/misc/Markdown.astro";
import I18nKey from "@i18n/i18nKey"; import I18nKey from "@i18n/i18nKey";
@@ -17,15 +18,15 @@ import { formatDateToYYYYMMDD } from "../../utils/date-utils";
export async function getStaticPaths() { export async function getStaticPaths() {
const blogEntries = await getSortedPosts(); const blogEntries = await getSortedPosts();
return blogEntries.map((entry) => ({ return blogEntries.map((entry) => ({
params: { slug: entry.slug }, params: { slug: entry.id },
props: { entry }, props: { entry },
})); }));
} }
const { entry } = Astro.props; const { entry } = Astro.props;
const { Content, headings } = await entry.render(); const { Content, headings } = await render(entry);
const { remarkPluginFrontmatter } = await entry.render(); const { remarkPluginFrontmatter } = await render(entry);
const jsonLd = { const jsonLd = {
"@context": "https://schema.org", "@context": "https://schema.org",
@@ -104,7 +105,7 @@ const jsonLd = {
<Content /> <Content />
</Markdown> </Markdown>
{licenseConfig.enable && <License title={entry.data.title} slug={entry.slug} pubDate={entry.data.published} class="mb-6 rounded-xl license-container onload-animation"></License>} {licenseConfig.enable && <License title={entry.data.title} slug={entry.id} pubDate={entry.data.published} class="mb-6 rounded-xl license-container onload-animation"></License>}
</div> </div>
</div> </div>

View File

@@ -22,7 +22,7 @@ export async function GET(context: APIContext) {
title: post.data.title, title: post.data.title,
pubDate: post.data.published, pubDate: post.data.published,
description: post.data.description || "", description: post.data.description || "",
link: `/posts/${post.slug}/`, link: `/posts/${post.id}/`,
content: sanitizeHtml(parser.render(content), { content: sanitizeHtml(parser.render(content), {
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]), allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
}), }),

View File

@@ -15,11 +15,11 @@ export async function getSortedPosts() {
}); });
for (let i = 1; i < sorted.length; i++) { for (let i = 1; i < sorted.length; i++) {
sorted[i].data.nextSlug = sorted[i - 1].slug; sorted[i].data.nextSlug = sorted[i - 1].id;
sorted[i].data.nextTitle = sorted[i - 1].data.title; sorted[i].data.nextTitle = sorted[i - 1].data.title;
} }
for (let i = 0; i < sorted.length - 1; i++) { for (let i = 0; i < sorted.length - 1; i++) {
sorted[i].data.prevSlug = sorted[i + 1].slug; sorted[i].data.prevSlug = sorted[i + 1].id;
sorted[i].data.prevTitle = sorted[i + 1].data.title; sorted[i].data.prevTitle = sorted[i + 1].data.title;
} }

View File

@@ -12,8 +12,8 @@ function joinUrl(...parts: string[]): string {
return joined.replace(/\/+/g, "/"); return joined.replace(/\/+/g, "/");
} }
export function getPostUrlBySlug(slug: string): string { export function getPostUrlBySlug(id: string): string {
return url(`/posts/${slug}/`); return url(`/posts/${id}/`);
} }
export function getTagUrl(tag: string): string { export function getTagUrl(tag: string): string {