Skip to content

定义内容合集

内容合集是内容优先应用中管理和创作内容的最佳方式。Velite 能帮助您组织和验证内容,并通过自动类型生成提供类型安全性。

什么是内容合集?

内容合集 是一组相关内容项的集合。例如,一个博客可能包含 文章 合集、作者 合集和 标签 合集。

每个合集应放置在项目 content 目录中的顶级目录中。

diff
content
├── authors # => authors 合集
│   ├── zce.yml
│   └── jane.yml
├── posts # => posts 合集
│   ├── hello-world.md
│   └── another-post.md
└── tags # => tags 合集
    └── all-in-one.yml

每个合集都由一个模式(schema)定义,该模式描述了合集中内容项的结构。

js
import { defineCollection, defineConfig, s } from 'velite'

const posts = defineCollection({
  /* 合集模式选项 */
})

const authors = defineCollection({
  /* 合集模式选项 */
})

const tags = defineCollection({
  /* 合集模式选项 */
})

export default defineConfig({
  collections: { authors, posts, tags }
})

合集模式选项

name

合集的名称。用于生成合集的类型名称。

js
const posts = defineCollection({
  name: 'Post'
})

类型名称通常是单数名词,但也可以是任何有效的 TypeScript 标识符。

pattern

用于查找合集内容文件的 glob 模式。

js
const posts = defineCollection({
  pattern: 'posts/**/*.md'
  // or pattern: ['posts/**/*.md', '!posts/private/**']
})

Velite 使用 fast-glob 来查找内容文件,因此您可以使用 fast-glob 支持的任何 glob 模式。

默认情况下,Velite 会忽略以 _. 开头的文件和目录。

single

是否应将合集视为单一项。这对于只有一个内容项的合集非常有用,例如站点的元数据。

js
const site = defineCollection({
  pattern: 'site/index.yml',
  single: true
})

schema

Velite 使用 Zod 来验证合集的内容项。schema 选项用于定义用于验证合集中内容项的 Zod 模式。

要在 Velite 中使用 Zod,请从 'velite' 导入 z 实用工具。这是 Zod 的 z 对象的重新导出,它支持 Zod 的所有功能。有关 Zod 的工作原理和可用功能的完整文档,请参阅 Zod 文档

js
import { z } from 'velite'

const posts = defineCollection({
  schema: z.object({
    title: z.string().max(99)
  })
})

TIP

模式通常是一个 ZodObject,用于验证内容项的结构。但它也可以是任何有效的 Zod 模式。

对于更复杂的模式,建议使用 Velite 扩展模式 s

  • s.slug():验证 slug 格式,在文章合集中保持唯一。
  • s.isodate():将日期字符串格式化为 ISO 日期字符串。
  • s.unique():验证合集中的唯一值。
  • s.image():输入图片相对路径,输出包含模糊图片的对象。
  • s.file():输入文件相对路径,输出文件公共路径。
  • s.metadata():提取 Markdown 的阅读时间、字数统计等元数据。
  • s.excerpt():Markdown 内容的摘要。
  • s.markdown():将 Markdown 转换为 HTML。
  • s.mdx():将 MDX 转换为函数代码。

例如:

js
import { s } from 'velite'

const posts = defineCollection({
  schema: s.object({
    slug: s.slug('posts'),
    date: s.isodate(),
    cover: s.image(),
    video: s.file().optional(),
    metadata: s.metadata(),
    excerpt: s.excerpt(),
    content: s.markdown()
  })
})

有关 Velite 扩展字段模式的更多信息,请参阅 Velite 模式

模式转换(计算字段)

可以使用 .transform() 方法转换 Zod 模式。这对于向合集中的内容项添加计算字段非常有用。

js
const posts = defineCollection({
  schema: s
    .object({
      slug: s.slug('posts')
    })
    .transform(data => ({
      ...data,
      // 计算字段
      permalink: `/blog/${data.slug}`
    }))
})

转换上下文元数据

transform() 函数可以接收第二个参数,即上下文对象。这对于向合集中的内容项添加计算字段非常有用。

js
const posts = defineCollection({
  schema: s
    .object({
      // 字段
    })
    .transform((data, { meta }) => ({
      ...data,
      // 计算字段
      path: meta.path // 或基于文件名的 slug 解析
    }))
})

meta 的类型是 ZodMeta,它扩展了 VeliteFile。更多信息,请参阅 自定义模式

内容正文

Velite 的内置加载器将内容的原始正文保留在 meta.content 中,纯文本正文保留在 meta.plain 中。

要将它们添加为字段,可以使用自定义模式。

js
const posts = defineCollection({
  schema: s.object({
    content: s.custom().transform((data, { meta }) => meta.content),
    plain: s.custom().transform((data, { meta }) => meta.plain)
  })
})

TIP

这将保留原始文档正文。在大多数情况下,应使用 s.markdown() / s.mdx() 模式来转换文档正文。

Markdown 与 MDX

除了验证合集中的内容项之外,Velite 还可以使用 Unified 处理内容正文。

js
const posts = defineCollection({
  schema: s.object({
    content: s.markdown() // 或 s.mdx()
  })
})

content 字段将从 markdown 转换为 html,结果将在内容项的 content 字段中可用。

参考

元数据

Velite 可以从内容文件中提取元数据。这对于向合集中的内容项添加计算字段非常有用。

js
const posts = defineCollection({
  schema: s.object({
    metadata: s.metadata() // 提取 Markdown 的阅读时间、字数统计等元数据
  })
})

参考

摘要

Velite 可以从内容文件中提取摘要。这对于向合集中的内容项添加计算字段非常有用。

js
const posts = defineCollection({
  schema: s.object({
    excerpt: s.excerpt({ length: 200 }) // markdown 正文的摘要
  })
})

参考

Distributed under the MIT License.