Astroテーマにタグ機能を実装したい!

公開 : 2022.12.21
titleimage

Astroをブログライクにサイトを運用したくなると、タグ機能がほしいと思ったので実装しました。記事の前後にタグを挟み以下のようにタグ一覧ページを実装させたい。

タグ一覧

タグ一覧

すべてのタグはこちら

はじめに

Astro ではPaginate 機能が標準で用意されているのでそれを利用します。少し調べたところ公式docにも実装方法が書いてありましたが、日本語でまとめている記事があったので共有。

Astroチュートリアルメモ その5-2,3【動的ルーティングとタグ一覧ページ】

Astroチュートリアルメモ その5-2,3【動的ルーティングとタグ一覧ページ】

undefined

Generate tag pages

Generate tag pages

Tutorial: Build your first Astro blog — Use getStaticPaths() to create multiple pages (routes) at once

目標としては、タグ一覧と各々のタグで日付順にソートさせて記事を一覧表示させたい。 基本的には、Markdownヘッダーに”tags”という要素を作り、それを抽出し動的にページ作成を行う。また、その際にpubDateを活用し新しい記事順でソートも行う

---
pubDate: 2022-10-21
tags: [hoge, tag-test]
---

タグ一覧ページの実装

動的にページを生成するために、.Astroを作成する。今回は6要素ずつでページを区切り作成する。

export async function getStaticPaths({ paginate }) {
  const allPosts = await Astro.glob<PostFrontMatter>("../../posts/*.md");
  const alltags = allPosts
    .filter((f) => f.frontmatter.tags != undefined)
    .map((p) => p.frontmatter.tags);
  const sortedPosts = sortPostsByDate(allPosts);
  let alltagsUnique = [...new Set(alltags.flat())];
  return alltagsUnique.map((tag) => {
    const filteredPosts = sortedPosts.filter((post) => 
      post.frontmatter.tags.includes(tag) && post.frontmatter.draft != true
    );
    return paginate(filteredPosts, {
      params: { tag },
      pageSize: 6,
    });
  });
}

また、コンテンツ要素を表示させるためにhtml も実装しておく。

    <div class="content">
        {page.data.map((post) => (
            <BlogPostCard post={post} />
        ))}
    </div>

記事の上部や下部にタグ要素を表示させる

今回は “BlogTags.astro” というコンポーネントを作成し部品化しておく。ついでに当サイトはTailwindが使用できるためデザインも整える。また、ハッシュタグ風にタグの先頭文字に#をつける

---
const { tags } = Astro.props;
---
<div class="tags text-center">
    {tags.map((tag) => (
    <div class="text-xs inline-flex items-centerfont-bold leading-sm uppercase px-3 py-1 mx-2 mt-4 mb-0 
    bg-gray-300 text-gray-900 rounded-full  border
    hover:transform hover:duration-300 hover:scale-105 hover:-translate-y-0.5 !hover:text-blue-800">
        <a href={`/tags/${tag}`}>#{tag}</a></div>
    ))}
</div>

Propsでtags を呼び出し、要素を表示する。

---
interface Props {
	title: string,
	description: string,
	imgSrc: string,
	imgAlt: string,
	tags: string[],
}
const {title, description, imgSrc, imgAlt, tags} = Astro.props as Props;
---
    <BlogTags tags={tags} />
---

おわりに

思ったより簡単にできたのでよかったです。