Astro2.0のCollections

作成:
heroimage

Astro 2.0 Collections

tsconfig.json の compilerOptions に以下を追記する。
Markdown の要求されている frontmatter がちゃんと書かれているかのチェックが行われるようになる。

    "strictNullChecks": true

src/content フォルダを作成し Astro2.0 の Collection の定義は src/content/config.ts に記述する。

---
// `astro:content`から z defineCollection を読み込む
import { z, defineCollection } from "astro:content";

// Collection の定義
const blogCollection = defineCollection({
  schema: z.object({
    layout: z.string(),
    title: z.string(),
    date: z.string().transform((str) => new Date(str)),
    description: z.string().optional(),
    tags: z.array(z.string()).optional(),
    featured: z.string().optional(),
    heroImage: z.string().optional(),
    author: z.string().optional(),
    isDraft: z.boolean().optional(),
    updatedDate: z
      .string()
      .transform((str) => new Date(str))
      .optional(),
  }),
});
// 以下で Collection を割り当てる Collection を読み込む場合は
// getcollection(以下の文字列) で可能
export const collections = {
  blog: blogCollection,
  note: blogCollection,
};

上記のように Collection が定義されていると Markdown ファイルが src/content 以下に作成・更新されるたびに /.astro/types.d.ts に自動的に型が生成されていく。
(npm run dev してあれば常に /src/content を監視して生成してくれる)

---
// 以下は自動生成された types.d.ts の一部
 const entryMap: {
  "blog": {
"2011/2011-01-02.md": {
  id: "2011/2011-01-02.md",
  slug: "2011/2011-01-02",
  body: string,
  collection: "blog",
  data: InferEntrySchema<"blog">
},
"2011/2011-01-13.md": {
  id: "2011/2011-01-13.md",
  slug: "2011/2011-01-13",
  body: string,
  collection: "blog",
  data: InferEntrySchema<"blog">
},

Collection を読み込む

以前は glob で行っていたブログのオブジェクト読み出しは以下のようにできる

以前の方法

---
const posts = await Astro.glob("../pages/posts/**/*.md");

Astro2.0 の方法

読み込みたい Collection を文字列で指定できる。

---
const posts = await getCollection("blog");

サブディレクトリの処理

[slug].astro は […slug].astro とすればサブディレクトリも読み込む

逆にそうしないとサブディレクトリのコンテンツを生成しない

src/content の中のフォルダと Collection 名は一致させることが必要

“blog” をクラスとして読み込んでいるため 文字列 blog を直接書き込んでいるファイルがある

  • src/content/config.ts
---
export const collections = {
  blog: blogCollection,
};
  • src/components/BlogCard.astro
---
post: CollectionEntry<"blog">;
  • src/pages/[…page].astro
  • src/pages/[tag]/[…page].astro
  <CardList>
    {page.data.map((post: CollectionEntry<"blog">) => <Card post={post} />)}
  </CardList>

それ以外は src/config.ts で定義した BLOG_NAME を使用している

---
// Place any global data in this file.
// You can import this data from anywhere in your site by using the `import` keyword.

export const SITE_TITLE = "へび右曲がり";
export const SITE_DESCRIPTION = "へび右曲がりはubanisによるふたなりサイトです";
export const SITE_LANG = "ja";
export const SITE_DATE_LANG = "ja-JP";
export const SITE_DOUJIN_BASE_URL = "/doujin/";
export const BLOG_NAME = "blog";
export const BLOG_PAGESIZE = 10;