-
+
{question}
-
+
{answer.split('\n\n').map((paragraph) => (
))}
diff --git a/data/blog/astrowind-template-in-depth.md b/src/content/blog/astrowind-template-in-depth.md
similarity index 100%
rename from data/blog/astrowind-template-in-depth.md
rename to src/content/blog/astrowind-template-in-depth.md
diff --git a/data/blog/get-started-website-with-astro-tailwind-css.md b/src/content/blog/get-started-website-with-astro-tailwind-css.md
similarity index 100%
rename from data/blog/get-started-website-with-astro-tailwind-css.md
rename to src/content/blog/get-started-website-with-astro-tailwind-css.md
diff --git a/data/blog/how-to-customize-astrowind-to-your-brand.md b/src/content/blog/how-to-customize-astrowind-to-your-brand.md
similarity index 100%
rename from data/blog/how-to-customize-astrowind-to-your-brand.md
rename to src/content/blog/how-to-customize-astrowind-to-your-brand.md
diff --git a/data/blog/markdown-elements-demo-post.mdx b/src/content/blog/markdown-elements-demo-post.mdx
similarity index 100%
rename from data/blog/markdown-elements-demo-post.mdx
rename to src/content/blog/markdown-elements-demo-post.mdx
diff --git a/data/blog/useful-resources-to-create-websites.md b/src/content/blog/useful-resources-to-create-websites.md
similarity index 100%
rename from data/blog/useful-resources-to-create-websites.md
rename to src/content/blog/useful-resources-to-create-websites.md
diff --git a/src/content/config.js b/src/content/config.js
new file mode 100644
index 0000000..e855425
--- /dev/null
+++ b/src/content/config.js
@@ -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,
+};
diff --git a/src/utils/permalinks.js b/src/utils/permalinks.js
index a2fa936..0882ad9 100644
--- a/src/utils/permalinks.js
+++ b/src/utils/permalinks.js
@@ -2,7 +2,7 @@ import slugify from 'limax';
import { SITE, BLOG } from '~/config.mjs';
-const trim = (str, ch) => {
+const trim = (str = "", ch) => {
let start = 0,
end = str.length || 0;
while (start < end && str[start] === ch) ++start;
diff --git a/src/utils/posts.js b/src/utils/posts.js
index 6f81fb4..b361085 100644
--- a/src/utils/posts.js
+++ b/src/utils/posts.js
@@ -1,44 +1,29 @@
+import { getCollection, getEntry } from 'astro:content';
+
const getNormalizedPost = async (post) => {
- const { frontmatter, Content, file } = post;
- const ID = file.split('/').pop().split('.').shift();
+ const { id, slug, data } = post;
+ const { Content, injectedFrontmatter } = await post.render();
return {
- id: ID,
-
- publishDate: frontmatter.publishDate,
- draft: frontmatter.draft,
-
- canonical: frontmatter.canonical,
- slug: frontmatter.slug || ID,
-
- title: frontmatter.title,
- description: frontmatter.description,
- image: frontmatter.image,
+ id: id,
+ slug: slug,
+ ...data,
Content: Content,
// or 'body' in case you consume from API
- excerpt: frontmatter.excerpt,
- authors: frontmatter.authors,
- category: frontmatter.category,
- tags: frontmatter.tags,
- readingTime: frontmatter.readingTime,
+ readingTime: injectedFrontmatter.readingTime,
};
};
const load = async function () {
- const posts = import.meta.glob(['~/../data/blog/**/*.md', '~/../data/blog/**/*.mdx'], {
- eager: true,
- });
-
- const normalizedPosts = Object.keys(posts).map(async (key) => {
- const post = await posts[key];
- return await getNormalizedPost(post);
- });
+ const posts = await getCollection('blog');
+ const normalizedPosts = posts.map(async (post) => await getNormalizedPost(post));
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);
+
return results;
};
@@ -52,19 +37,31 @@ export const fetchPosts = async () => {
};
/** */
-export const findPostsByIds = async (ids) => {
- if (!Array.isArray(ids)) return [];
+export const findPostsBySlugs = async (slugs) => {
+ if (!Array.isArray(slugs)) return [];
const posts = await fetchPosts();
- return ids.reduce(function (r, id) {
+ return slugs.reduce(function (r, slug) {
posts.some(function (post) {
- return id === post.id && r.push(post);
+ return slug === post.slug && r.push(post);
});
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 }) => {
const _count = count || 4;
diff --git a/tsconfig.json b/tsconfig.json
index d0a369f..7d01264 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,6 +2,7 @@
"extends": "astro/tsconfigs/base",
"compilerOptions": {
"types": ["astro/client"],
+ "strictNullChecks": true,
"allowJs": true,
"baseUrl": ".",
"paths": {