😸

[2023年6月版]Astro.js 小ネタ集 その7 記事をタグで検索

2023/06/26に公開

前回に引き続きAstro.jsでの小ネタを紹介していきます。

ここでは前回紹介したJSON コレクションを使ったブログ記事のタグ検索機能についてご紹介いたします。

タグ検索機能の追加

タグのコレクションが定義できましたので、続いてタグでの検索機能を追加してみます。
これは以下の公式のチュートリアルを参考にしております。

チュートリアルの src/pages/tags/[tag].astro を以下に再掲します。

src/pages/tags/[tag].astro
import BaseLayout from '../../layouts/BaseLayout.astro';

export async function getStaticPaths() {
  return [
    { params: { tag: "astro" } },
    { params: { tag: "successes" } },
    { params: { tag: "community" } },
    { params: { tag: "blogging" } },
    { params: { tag: "setbacks" } },
    { params: { tag: "learning in public" } },
  ];
}

const { tag } = Astro.params;
---
<BaseLayout pageTitle={tag}>
  <p>Posts tagged with {tag}</p>
</BaseLayout>

これの第一のミソはファイル名が [tag].astro となっている点です。これがgetStaticPaths()の戻り値の[{ params: { tag: 'astro' } }, ...]に対応しています。

ファイル名を [id].astro とした場合には [{ params: { id: ... } },] としなければなりません。
このようにparamsはファイルのパスのプレースホルダと対応しています。

例えばsrc/pages/[content]/[id].astrogetStaticPaths()では、[{ params: { content: 'sample' , id: '1' } }, ...] のようなデータを返す必要があります。

個人ブログのほうでは src/pages/tags/[id].astro としていますので、以下のようになっております。

src/pages/tags/[id].astro
...
export async function getStaticPaths() {
  return Promise.all([...(await getCollection('blog'))
    ...
  ].map(async (tag) => {
        const e = await getEntry('tags', tag);
        return e ? {
            params: {
                id: e.id,
            },
            props: {
                tag: e.id,
                tagName: e.data.title,
                icon: e.data.icon,
            }
          } : {
            params: {
                id: tag,
            },
            props: {
                tag,
                tagName: tag,
                icon: '',
            }
          }
    })
  );
}

interface Props {
    tag: string;
    tagName: string;
    icon: string;
};

const { tag, tagName, icon } = Astro.props as Props;
const blog = await getCollection('blog', (blog) => blog.data.tags.includes(tag));

のような感じで使用しています。
getStaticPaths() でユニークなタグのリストを生成するところは先ほどと同じで、続いて読み取ったJSONから { params:{id: e.id,}, props: {tag: e.id, tagName: e.data.title, icon: e.data.icon,}} 形式のオブジェクトに変換しています。

このオブジェクトの後半の props の箇所が、interface Props {...}; const { tag, tagName, icon } = Astro.props as Props; で渡されてきます。

そして最後のconst blog = await getCollection('blog', (blog) => blog.data.tags.includes(tag)); でタグが指定されているブログの一覧を作成しています。

今回はここまでといたします。

Discussion