Migrate blog to new astro Content Collections
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -20,4 +20,6 @@ pnpm-debug.log*
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
|
||||||
|
src/content/types.generated.d.ts
|
@ -55,4 +55,8 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
experimental: {
|
||||||
|
contentCollections: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@onwidget/astrowind",
|
"name": "@onwidget/astrowind",
|
||||||
"description": "A template to make your website using Astro + Tailwind CSS.",
|
"description": "A template to make your website using Astro + Tailwind CSS.",
|
||||||
"version": "0.8.7",
|
"version": "0.9.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
|
@ -4,10 +4,10 @@ import Grid from '~/components/blog/Grid.astro';
|
|||||||
import { findPostsByIds } from '~/utils/posts';
|
import { findPostsByIds } from '~/utils/posts';
|
||||||
|
|
||||||
const ids = [
|
const ids = [
|
||||||
'get-started-website-with-astro-tailwind-css',
|
'get-started-website-with-astro-tailwind-css.md',
|
||||||
'how-to-customize-astrowind-to-your-brand',
|
'how-to-customize-astrowind-to-your-brand.md',
|
||||||
'useful-resources-to-create-websites',
|
'useful-resources-to-create-websites.md',
|
||||||
'astrowind-template-in-depth',
|
'astrowind-template-in-depth.md',
|
||||||
];
|
];
|
||||||
const posts = await findPostsByIds(ids);
|
const posts = await findPostsByIds(ids);
|
||||||
---
|
---
|
||||||
|
@ -54,10 +54,10 @@ const items = [
|
|||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
{subitems.map(({ question, answer }) => (
|
{subitems.map(({ question, answer }) => (
|
||||||
<div>
|
<div>
|
||||||
<p class="mb-4 text-xl font-bold">
|
<h3 class="mb-4 text-xl font-bold">
|
||||||
<Icon name="tabler:arrow-down-right" class="w-7 h-7 text-primary-500 inline-block" />
|
<Icon name="tabler:arrow-down-right" class="w-7 h-7 text-primary-500 inline-block" />
|
||||||
{question}
|
{question}
|
||||||
</p>
|
</h3>
|
||||||
{answer.split('\n\n').map((paragraph) => (
|
{answer.split('\n\n').map((paragraph) => (
|
||||||
<p class="text-gray-700 dark:text-gray-400 mb-2" set:html={paragraph} />
|
<p class="text-gray-700 dark:text-gray-400 mb-2" set:html={paragraph} />
|
||||||
))}
|
))}
|
||||||
|
27
src/content/config.js
Normal file
27
src/content/config.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { z, defineCollection } from 'astro:content';
|
||||||
|
|
||||||
|
const blog = defineCollection({
|
||||||
|
schema: {
|
||||||
|
title: z.string(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
image: z.string().optional(),
|
||||||
|
|
||||||
|
canonical: z.string().url().optional(),
|
||||||
|
permalink: z.string().optional(),
|
||||||
|
|
||||||
|
publishDate: z.string().transform((str) => new Date(str)),
|
||||||
|
draft: z.boolean().optional(),
|
||||||
|
|
||||||
|
excerpt: z.string().optional(),
|
||||||
|
category: z.string().optional(),
|
||||||
|
tags: z.array(z.string()).optional(),
|
||||||
|
authors: z.array(z.string()).optional(),
|
||||||
|
},
|
||||||
|
slug: ({ defaultSlug, data }) => {
|
||||||
|
return data.permalink || defaultSlug;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const collections = {
|
||||||
|
blog: blog,
|
||||||
|
};
|
@ -2,7 +2,7 @@ import slugify from 'limax';
|
|||||||
|
|
||||||
import { SITE, BLOG } from '~/config.mjs';
|
import { SITE, BLOG } from '~/config.mjs';
|
||||||
|
|
||||||
const trim = (str, ch) => {
|
const trim = (str = "", ch) => {
|
||||||
let start = 0,
|
let start = 0,
|
||||||
end = str.length || 0;
|
end = str.length || 0;
|
||||||
while (start < end && str[start] === ch) ++start;
|
while (start < end && str[start] === ch) ++start;
|
||||||
|
@ -1,44 +1,29 @@
|
|||||||
|
import { getCollection, getEntry } from 'astro:content';
|
||||||
|
|
||||||
const getNormalizedPost = async (post) => {
|
const getNormalizedPost = async (post) => {
|
||||||
const { frontmatter, Content, file } = post;
|
const { id, slug, data } = post;
|
||||||
const ID = file.split('/').pop().split('.').shift();
|
const { Content, injectedFrontmatter } = await post.render();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: ID,
|
id: id,
|
||||||
|
slug: slug,
|
||||||
publishDate: frontmatter.publishDate,
|
...data,
|
||||||
draft: frontmatter.draft,
|
|
||||||
|
|
||||||
canonical: frontmatter.canonical,
|
|
||||||
slug: frontmatter.slug || ID,
|
|
||||||
|
|
||||||
title: frontmatter.title,
|
|
||||||
description: frontmatter.description,
|
|
||||||
image: frontmatter.image,
|
|
||||||
|
|
||||||
Content: Content,
|
Content: Content,
|
||||||
// or 'body' in case you consume from API
|
// or 'body' in case you consume from API
|
||||||
|
|
||||||
excerpt: frontmatter.excerpt,
|
readingTime: injectedFrontmatter.readingTime,
|
||||||
authors: frontmatter.authors,
|
|
||||||
category: frontmatter.category,
|
|
||||||
tags: frontmatter.tags,
|
|
||||||
readingTime: frontmatter.readingTime,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const load = async function () {
|
const load = async function () {
|
||||||
const posts = import.meta.glob(['~/../data/blog/**/*.md', '~/../data/blog/**/*.mdx'], {
|
const posts = await getCollection('blog');
|
||||||
eager: true,
|
const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post));
|
||||||
});
|
|
||||||
|
|
||||||
const normalizedPosts = Object.keys(posts).map(async (key) => {
|
|
||||||
const post = await posts[key];
|
|
||||||
return await getNormalizedPost(post);
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = (await Promise.all(normalizedPosts))
|
const results = (await Promise.all(normalizedPosts))
|
||||||
.sort((a, b) => new Date(b.publishDate).valueOf() - new Date(a.publishDate).valueOf())
|
.sort((a, b) => b.publishDate.valueOf() - a.publishDate.valueOf())
|
||||||
.filter((post) => !post.draft);
|
.filter((post) => !post.draft);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,19 +37,31 @@ export const fetchPosts = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const findPostsByIds = async (ids) => {
|
export const findPostsBySlugs = async (slugs) => {
|
||||||
if (!Array.isArray(ids)) return [];
|
if (!Array.isArray(slugs)) return [];
|
||||||
|
|
||||||
const posts = await fetchPosts();
|
const posts = await fetchPosts();
|
||||||
|
|
||||||
return ids.reduce(function (r, id) {
|
return slugs.reduce(function (r, slug) {
|
||||||
posts.some(function (post) {
|
posts.some(function (post) {
|
||||||
return id === post.id && r.push(post);
|
return slug === post.slug && r.push(post);
|
||||||
});
|
});
|
||||||
return r;
|
return r;
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** */
|
||||||
|
export const findPostsByIds = async (ids) => {
|
||||||
|
if (!Array.isArray(ids)) return [];
|
||||||
|
|
||||||
|
return await Promise.all(
|
||||||
|
ids.map(async (id) => {
|
||||||
|
const post = await getEntry('blog', id);
|
||||||
|
return await getNormalizedPost(post);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
export const findLatestPosts = async ({ count }) => {
|
export const findLatestPosts = async ({ count }) => {
|
||||||
const _count = count || 4;
|
const _count = count || 4;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"extends": "astro/tsconfigs/base",
|
"extends": "astro/tsconfigs/base",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"types": ["astro/client"],
|
"types": ["astro/client"],
|
||||||
|
"strictNullChecks": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
Reference in New Issue
Block a user