update: migrate from content.ts to content.config.ts

This commit is contained in:
radishzzz 2025-03-30 00:57:33 +00:00
parent 9cfd0cb049
commit 4c8dff619e
10 changed files with 302 additions and 329 deletions

View file

@ -19,7 +19,7 @@
"@astrojs/sitemap": "^3.3.0", "@astrojs/sitemap": "^3.3.0",
"@waline/client": "^3.5.6", "@waline/client": "^3.5.6",
"astro": "^5.5.5", "astro": "^5.5.5",
"astro-compress": "^2.3.6", "astro-compress": "^2.3.7",
"astro-og-canvas": "^0.7.0", "astro-og-canvas": "^0.7.0",
"astro-robots-txt": "^1.0.0", "astro-robots-txt": "^1.0.0",
"canvaskit-wasm": "^0.39.1", "canvaskit-wasm": "^0.39.1",
@ -37,7 +37,7 @@
"@astrojs/check": "^0.9.4", "@astrojs/check": "^0.9.4",
"@types/markdown-it": "^14.1.2", "@types/markdown-it": "^14.1.2",
"@types/node": "^22.13.14", "@types/node": "^22.13.14",
"@types/sanitize-html": "^2.13.0", "@types/sanitize-html": "^2.15.0",
"@unocss/eslint-plugin": "66.1.0-beta.7", "@unocss/eslint-plugin": "66.1.0-beta.7",
"@unocss/preset-attributify": "66.1.0-beta.7", "@unocss/preset-attributify": "66.1.0-beta.7",
"@unocss/reset": "66.1.0-beta.7", "@unocss/reset": "66.1.0-beta.7",

573
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,7 @@ export interface Props {
function getPostPath(post: Post) { function getPostPath(post: Post) {
// Prioritize abbrlink over slug // Prioritize abbrlink over slug
const postPath = post.data.abbrlink || post.slug const postPath = post.data.abbrlink || post.id
// Add language prefix to URL if current page is in a language subdirectory and not the default language // Add language prefix to URL if current page is in a language subdirectory and not the default language
return lang && lang !== defaultLocale ? `/${lang}/posts/${postPath}/` : `/posts/${postPath}/` return lang && lang !== defaultLocale ? `/${lang}/posts/${postPath}/` : `/posts/${postPath}/`
} }
@ -40,7 +40,7 @@ function getPostPath(post: Post) {
class="hover:c-primary" class="hover:c-primary"
lg={isTag ? '' : 'font-medium text-4.5'} lg={isTag ? '' : 'font-medium text-4.5'}
href={getPostPath(post)} href={getPostPath(post)}
transition:name={`post-${post.data.abbrlink || post.slug}-${lang}`} transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
data-disable-transition-on-theme data-disable-transition-on-theme
> >
{post.data.title} {post.data.title}
@ -50,7 +50,7 @@ function getPostPath(post: Post) {
{/* mobile post time */} {/* mobile post time */}
<div <div
class="text-3.5 leading-6.875 font-time lg:hidden" class="text-3.5 leading-6.875 font-time lg:hidden"
transition:name={`time-${post.data.abbrlink || post.slug}-${lang}`} transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
data-disable-transition-on-theme data-disable-transition-on-theme
> >
<PostDate <PostDate
@ -62,7 +62,7 @@ function getPostPath(post: Post) {
{/* desktop post time */} {/* desktop post time */}
<div <div
class="hidden text-3.65 leading-6.875 font-time lg:(ml-2.5 inline)" class="hidden text-3.65 leading-6.875 font-time lg:(ml-2.5 inline)"
transition:name={`time-${post.data.abbrlink || post.slug}`} transition:name={`time-${post.data.abbrlink || post.id}`}
data-disable-transition-on-theme data-disable-transition-on-theme
> >
<PostDate <PostDate

View file

@ -1,8 +1,9 @@
import { allLocales } from '@/config' import { allLocales } from '@/config'
import { glob } from 'astro/loaders'
import { defineCollection, z } from 'astro:content' import { defineCollection, z } from 'astro:content'
// Posts Collection const posts = defineCollection({
const postsCollection = defineCollection({ loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/posts' }),
schema: z.object({ schema: z.object({
// required // required
title: z.string(), title: z.string(),
@ -23,14 +24,11 @@ const postsCollection = defineCollection({
}), }),
}) })
// About Page const about = defineCollection({
const aboutCollection = defineCollection({ loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/about' }),
schema: z.object({ schema: z.object({
lang: z.enum(['', ...allLocales]).optional().default(''), lang: z.enum(['', ...allLocales]).optional().default(''),
}), }),
}) })
export const collections = { export const collections = { posts, about }
posts: postsCollection,
about: aboutCollection,
}

View file

@ -1,7 +1,7 @@
--- ---
import { defaultLocale, moreLocales } from '@/config' import { defaultLocale, moreLocales } from '@/config'
import Layout from '@/layouts/Layout.astro' import Layout from '@/layouts/Layout.astro'
import { getCollection } from 'astro:content' import { getCollection, render } from 'astro:content'
export async function getStaticPaths() { export async function getStaticPaths() {
type PathItem = { type PathItem = {
@ -34,7 +34,7 @@ const { lang } = Astro.props
const allAboutEntries = await getCollection('about') const allAboutEntries = await getCollection('about')
const aboutEntry = allAboutEntries.find(entry => entry.data.lang === lang) const aboutEntry = allAboutEntries.find(entry => entry.data.lang === lang)
|| allAboutEntries.find(entry => entry.data.lang === '') || allAboutEntries.find(entry => entry.data.lang === '')
const { Content } = aboutEntry ? await aboutEntry.render() : { Content: null } const { Content } = aboutEntry ? await render(aboutEntry) : { Content: null }
--- ---
<Layout> <Layout>

View file

@ -9,7 +9,7 @@ import { getTagPath } from '@/i18n/path'
import Layout from '@/layouts/Layout.astro' import Layout from '@/layouts/Layout.astro'
import { checkPostSlugDuplication } from '@/utils/content' import { checkPostSlugDuplication } from '@/utils/content'
import { generateDescription } from '@/utils/description' import { generateDescription } from '@/utils/description'
import { getCollection } from 'astro:content' import { getCollection, render } from 'astro:content'
export async function getStaticPaths() { export async function getStaticPaths() {
const posts = await getCollection('posts') const posts = await getCollection('posts')
@ -24,7 +24,7 @@ export async function getStaticPaths() {
// Use a Map to store the relationship between post slugs and their supported languages // Use a Map to store the relationship between post slugs and their supported languages
// Set is used to store the supported languages for each post // Set is used to store the supported languages for each post
const slugToLangsMap = posts.reduce((map, post) => { const slugToLangsMap = posts.reduce((map, post) => {
const slug = post.data.abbrlink || post.slug const slug = post.data.abbrlink || post.id
const lang = post.data.lang const lang = post.data.lang
if (!map.has(slug)) { if (!map.has(slug)) {
@ -58,7 +58,7 @@ export async function getStaticPaths() {
posts.forEach((post: CollectionEntry<'posts'>) => { posts.forEach((post: CollectionEntry<'posts'>) => {
// Show drafts in dev mode only // Show drafts in dev mode only
if (import.meta.env.DEV || !post.data.draft) { if (import.meta.env.DEV || !post.data.draft) {
const slug = post.data.abbrlink || post.slug const slug = post.data.abbrlink || post.id
const lang = post.data.lang const lang = post.data.lang
if (lang === defaultLocale || lang === '') { if (lang === defaultLocale || lang === '') {
@ -79,7 +79,7 @@ export async function getStaticPaths() {
posts.forEach((post: CollectionEntry<'posts'>) => { posts.forEach((post: CollectionEntry<'posts'>) => {
// Process posts with matching language or no language specified // Process posts with matching language or no language specified
if ((import.meta.env.DEV || !post.data.draft) && (post.data.lang === lang || post.data.lang === '')) { if ((import.meta.env.DEV || !post.data.draft) && (post.data.lang === lang || post.data.lang === '')) {
const slug = post.data.abbrlink || post.slug const slug = post.data.abbrlink || post.id
paths.push({ paths.push({
params: { posts_slug: `${lang}/posts/${slug}/` }, params: { posts_slug: `${lang}/posts/${slug}/` },
props: { props: {
@ -97,13 +97,13 @@ export async function getStaticPaths() {
const { post, lang, supportedLangs } = Astro.props const { post, lang, supportedLangs } = Astro.props
const description = generateDescription(post, 'meta') const description = generateDescription(post, 'meta')
const { Content, headings, remarkPluginFrontmatter } = await post.render() const { Content, headings, remarkPluginFrontmatter } = await render(post)
--- ---
<Layout <Layout
postTitle={post.data.title} postTitle={post.data.title}
postDescription={description} postDescription={description}
postSlug={post.slug} postSlug={post.id}
supportedLangs={supportedLangs} supportedLangs={supportedLangs}
> >
<article class="heti mb-12.6"> <article class="heti mb-12.6">
@ -113,7 +113,7 @@ const { Content, headings, remarkPluginFrontmatter } = await post.render()
<!-- Title --> <!-- Title -->
<h1 class="post-title"> <h1 class="post-title">
<span <span
transition:name={`post-${post.data.abbrlink || post.slug}-${lang}`} transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
data-disable-transition-on-theme data-disable-transition-on-theme
> >
{post.data.title} {post.data.title}
@ -124,7 +124,7 @@ const { Content, headings, remarkPluginFrontmatter } = await post.render()
<!-- Date --> <!-- Date -->
<div <div
class="mb-16.3 block c-primary font-time" class="mb-16.3 block c-primary font-time"
transition:name={`time-${post.data.abbrlink || post.slug}-${lang}`} transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
data-disable-transition-on-theme data-disable-transition-on-theme
> >
<PostDate <PostDate

View file

@ -9,7 +9,7 @@ const blogEntries = await getCollection('posts')
// Convert blog entries into a lookup object with slug as key and title/description as value // Convert blog entries into a lookup object with slug as key and title/description as value
const pages = Object.fromEntries( const pages = Object.fromEntries(
blogEntries.map((post: CollectionEntry<'posts'>) => [ blogEntries.map((post: CollectionEntry<'posts'>) => [
post.slug, post.id,
{ {
title: post.data.title, title: post.data.title,
description: post.data.description || generateDescription(post, 'og'), description: post.data.description || generateDescription(post, 'og'),

View file

@ -1,6 +1,6 @@
import type { CollectionEntry } from 'astro:content' import type { CollectionEntry } from 'astro:content'
import { defaultLocale } from '@/config' import { defaultLocale } from '@/config'
import { getCollection } from 'astro:content' import { getCollection, render } from 'astro:content'
// Type definitions // Type definitions
export type Post = CollectionEntry<'posts'> & { export type Post = CollectionEntry<'posts'> & {
@ -11,7 +11,7 @@ export type Post = CollectionEntry<'posts'> & {
// Add metadata including reading time to post // Add metadata including reading time to post
async function addMetaToPost(post: CollectionEntry<'posts'>): Promise<Post> { async function addMetaToPost(post: CollectionEntry<'posts'>): Promise<Post> {
const { remarkPluginFrontmatter } = await post.render() const { remarkPluginFrontmatter } = await render(post)
return { ...post, remarkPluginFrontmatter: remarkPluginFrontmatter as { minutes: number } } return { ...post, remarkPluginFrontmatter: remarkPluginFrontmatter as { minutes: number } }
} }
@ -26,7 +26,7 @@ export async function checkPostSlugDuplication(posts: CollectionEntry<'posts'>[]
posts.forEach((post) => { posts.forEach((post) => {
const lang = post.data.lang const lang = post.data.lang
const slug = post.data.abbrlink || post.slug const slug = post.data.abbrlink || post.id
if (!slugMap.has(lang)) { if (!slugMap.has(lang)) {
slugMap.set(lang, new Set()) slugMap.set(lang, new Set())

View file

@ -70,5 +70,5 @@ export function generateDescription(
return post.data.description return post.data.description
const lang = (!post.data.lang || post.data.lang === '') ? defaultLocale : post.data.lang const lang = (!post.data.lang || post.data.lang === '') ? defaultLocale : post.data.lang
return generateExcerpt(post.body, scene, lang) return generateExcerpt(post.body || '', scene, lang)
} }

View file

@ -48,7 +48,7 @@ export async function generateRSS({ lang }: GenerateRSSOptions = {}) {
title: post.data.title, title: post.data.title,
// Generate URL with language prefix and abbrlink/slug // Generate URL with language prefix and abbrlink/slug
link: new URL( link: new URL(
`${post.data.lang !== defaultLocale && post.data.lang !== '' ? `${post.data.lang}/` : ''}posts/${post.data.abbrlink || post.slug}/`, `${post.data.lang !== defaultLocale && post.data.lang !== '' ? `${post.data.lang}/` : ''}posts/${post.data.abbrlink || post.id}/`,
url, url,
).toString(), ).toString(),
description: generateDescription(post, 'rss'), description: generateDescription(post, 'rss'),