Skip to content

Commit ba4f0fd

Browse files
committed
fix(blog): resolve 'Missing parameter: tag' deployment error
- feat: add [slugifyTag](cci:1://file:///Volumes/DATA/Astro/astro-batavia/src/i18n/utils.ts:86:0-95:1) utility to handle special characters (e.g., CI/CD) in tags - fix: ensure `getStaticPaths` generates valid, single-segment slugs for tags - fix: update tag links in `BlogCard` and `BlogPost` to use consistent slugification
1 parent 4bef909 commit ba4f0fd

5 files changed

Lines changed: 21 additions & 10 deletions

File tree

src/components/blog/BlogCard.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
import type { CollectionEntry } from "astro:content";
3-
import { formatDate, useTranslations, getPostUrl, getLocalizedPath } from "@/i18n/utils";
3+
import { formatDate, useTranslations, getPostUrl, getLocalizedPath, slugifyTag } from "@/i18n/utils";
44
import type { ui } from "@/i18n/ui";
55
66
export interface Props {
@@ -71,7 +71,7 @@ const excerptClasses = [
7171
<div class={`flex flex-wrap gap-2 mb-3 ${isFeatured ? "md:mb-4" : ""}`} role="group" aria-label="Post tags">
7272
{post.data.tags.slice(0, 3).map((tag: string) => (
7373
<a
74-
href={getLocalizedPath(`/blog/tags/${tag.toLowerCase().replace(/\s+/g, '-')}`, lang)}
74+
href={getLocalizedPath(`/blog/tags/${slugifyTag(tag)}`, lang)}
7575
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-200 hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors duration-200"
7676
>
7777
#{tag}

src/i18n/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,14 @@ export function getAvailableLanguages() {
8383
export function isValidLanguage(lang: string): lang is keyof typeof ui {
8484
return lang in ui;
8585
}
86+
87+
export function slugifyTag(tag: string) {
88+
return tag
89+
.toLowerCase()
90+
.replace(/\s+/g, '-')
91+
.replace(/\//g, '-')
92+
.replace(/[^\w-]+/g, '')
93+
.replace(/--+/g, '-')
94+
.replace(/^-+/, '')
95+
.replace(/-+$/, '');
96+
}

src/layouts/BlogPost.astro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Layout from './Layout.astro';
44
import Picture from '@/components/ui/Picture.astro';
55
import BlogPostNavigation from '@/components/navigation/BlogPostNavigation.astro';
66
import ShareButtons from '@/components/blog/ShareButtons.astro';
7-
import { formatDate, getLangFromUrl, useTranslations, getLocalizedPath, getPostUrl } from '@/i18n/utils';
7+
import { formatDate, getLangFromUrl, useTranslations, getLocalizedPath, getPostUrl, slugifyTag } from '@/i18n/utils';
88
import RelatedArticles from '@/components/blog/RelatedArticles.astro';
99
import TableOfContents from '@/components/blog/TableOfContents.astro';
1010
@@ -169,7 +169,7 @@ const relatedPosts = allLangPosts
169169
<div class="flex flex-wrap gap-2">
170170
{tags.map((tag: string) => (
171171
<a
172-
href={getLocalizedPath(`/blog/tags/${tag.toLowerCase().replace(/\s+/g, '-')}`, lang)}
172+
href={getLocalizedPath(`/blog/tags/${slugifyTag(tag)}`, lang)}
173173
class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-200 hover:bg-primary-200 dark:hover:bg-primary-800 transition-colors duration-200"
174174
>
175175
#{tag}

src/pages/[lang]/blog/tags/[tag].astro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { getCollection, type CollectionEntry } from 'astro:content';
33
import Layout from '@/layouts/Layout.astro';
44
import BlogCard from '@/components/blog/BlogCard.astro';
5-
import { useTranslations } from '@/i18n/utils';
5+
import { useTranslations, slugifyTag } from '@/i18n/utils';
66
import { ui } from '@/i18n/ui';
77
88
export async function getStaticPaths() {
@@ -15,7 +15,7 @@ export async function getStaticPaths() {
1515
validTags.map(tag => ({
1616
params: {
1717
lang,
18-
tag: tag.toLowerCase().replace(/\s+/g, '-')
18+
tag: slugifyTag(tag)
1919
},
2020
props: { tag }
2121
}))
@@ -31,7 +31,7 @@ const posts = await getCollection('blog', ({ id, data }: CollectionEntry<'blog'>
3131
if (!id.startsWith(`${lang}/`) || data.draft) return false;
3232
if (!data.tags) return false;
3333
34-
return data.tags.some(t => t.toLowerCase().replace(/\s+/g, '-') === Astro.params.tag);
34+
return data.tags.some(t => slugifyTag(t) === Astro.params.tag);
3535
});
3636
3737
// Sort posts by publication date (newest first)

src/pages/en/blog/tags/[tag].astro

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
import { getCollection, type CollectionEntry } from 'astro:content';
33
import Layout from '@/layouts/Layout.astro';
44
import BlogCard from '@/components/blog/BlogCard.astro';
5-
import { useTranslations } from '@/i18n/utils';
5+
import { useTranslations, slugifyTag } from '@/i18n/utils';
66
77
export async function getStaticPaths() {
88
const allPosts = await getCollection('blog');
99
const uniqueTags = [...new Set(allPosts.flatMap(post => post.data.tags || []))];
1010
const validTags = uniqueTags.filter(tag => tag && tag.trim().length > 0);
1111
1212
return validTags.map(tag => ({
13-
params: { tag: tag.toLowerCase().replace(/\s+/g, '-') },
13+
params: { tag: slugifyTag(tag) },
1414
props: { tag }
1515
}));
1616
}
@@ -25,7 +25,7 @@ const posts = await getCollection('blog', ({ id, data }: CollectionEntry<'blog'>
2525
if (!data.tags) return false;
2626
2727
// Check if any tag matches the slugified version (in case of case sensitivity or spaces)
28-
return data.tags.some(t => t.toLowerCase().replace(/\s+/g, '-') === Astro.params.tag);
28+
return data.tags.some(t => slugifyTag(t) === Astro.params.tag);
2929
});
3030
3131
// Sort posts by publication date (newest first)

0 commit comments

Comments
 (0)