Velite Schemas
To use Zod in Velite, import the z
utility from 'velite'
. This is a re-export of the Zod library, and it supports all of the features of Zod.
See Zod's Docs for complete documentation on how Zod works and what features are available.
import { z } from 'velite'
// `z` is re-export of Zod
In addition, Velite has extended Zod schemas, added some commonly used features when building content models, you can import s
from 'velite'
to use these extended schemas.
import { s } from 'velite'
// `s` is extended from Zod with some custom schemas,
// `s` also includes all members of zod, so you can use `s` as `z`
s.isodate()
string => string
Format date string to ISO date string.
date: s.isodate()
// case 1. valid date string
// '2017-01-01' => '2017-01-01T00:00:00.000Z'
// case 2. valid datetime string
// '2017-01-01 10:10:10' => '2017-01-01T10:10:10.000Z'
// case 3. invalid date string
// 'foo bar invalid' => issue 'Invalid date string'
s.unique(by)
string => string
validate unique value in collections.
name: s.unique('taxonomies')
// case 1. unique value
// 'foo' => 'foo'
// case 2. non-unique value (in all unique by 'taxonomies')
// 'foo' => issue 'Already exists'
Parameters
by: unique identifier
- type:
string
- default:
'global'
s.slug(by, reserved)
string => string
base on s.unique()
, unique in collections, not allow reserved values, and validate slug format.
slug: s.slug('taxonomies', ['admin', 'login'])
// case 1. unique slug value
// 'hello-world' => 'hello-world'
// case 2. non-unique value (in all unique by 'taxonomies')
// 'hello-world' => issue 'Slug already exists'
// case 3. reserved slug value
// 'admin' => issue 'Slug is reserved'
// case 4. invalid slug value
// 'Hello World' => issue 'Invalid slug'
Parameters
by: unique identifier
- type:
string
- default:
'global'
reserved: reserved values
- type:
string[]
- default:
[]
s.file(options)
string => string
file path relative to this file, copy file to config.output.assets
directory and return the public url.
avatar: s.file()
// case 1. relative path
// 'avatar.png' => '/static/avatar-34kjfdsi.png'
// case 2. non-exists file
// 'not-exists.png' => issue 'File not exists'
// case 3. absolute path or full url (if allowed)
// '/icon.png' => '/icon.png'
// 'https://zce.me/logo.png' => 'https://zce.me/logo.png'
Parameters
options.allowNonRelativePath:
allow non-relative path, if true, the value will be returned directly, if false, the value will be processed as a relative path
- type:
boolean
- default:
true
s.image(options)
string => Image
image path relative to this file, like s.file()
, copy file to config.output.assets
directory and return the Image (image object with meta data).
avatar: s.image()
// case 1. relative path
// 'avatar.png' => {
// src: '/static/avatar-34kjfdsi.png',
// width: 100,
// height: 100,
// blurDataURL: 'data:image/png;base64,xxx',
// blurWidth: 8,
// blurHeight: 8
// }
// case 2. non-exists file
// 'not-exists.png' => issue 'File not exists'
// case 3. absolute path or full url (if allowed)
// '/icon.png' => { src: '/icon.png', width: 0, height: 0, blurDataURL: '', blurWidth: 0, blurHeight: 0 }
// 'https://zce.me/logo.png' => { src: 'https://zce.me/logo.png', width: 0, height: 0, blurDataURL: '', blurWidth: 0, blurHeight: 0 }
Parameters
options.absoluteRoot:
root path for absolute path, if provided, the value will be processed as an absolute path.
- type:
string
- default:
undefined
Types
/**
* Image object with metadata & blur image
*/
interface Image {
/**
* public url of the image
*/
src: string
/**
* image width
*/
width: number
/**
* image height
*/
height: number
/**
* blurDataURL of the image
*/
blurDataURL: string
/**
* blur image width
*/
blurWidth: number
/**
* blur image height
*/
blurHeight: number
}
s.metadata()
string => Metadata
parse input or document body as markdown content and return Metadata.
currently only support readingTime
& wordCount
.
metadata: s.metadata()
// document body => { readingTime: 2, wordCount: 100 }
Types
/**
* Document metadata.
*/
interface Metadata {
/**
* Reading time in minutes.
*/
readingTime: number
/**
* Word count.
*/
wordCount: number
}
s.excerpt(options)
string => string
parse input or document body as markdown content and return excerpt text.
excerpt: s.excerpt()
// document body => excerpt text
Parameters
options: excerpt options
options.length:
excerpt length.
- type:
number
- default:
260
s.markdown(options)
string => string
parse input or document body as markdown content and return html content. refer to Markdown Support for more information.
content: s.markdown()
// => html content
Parameters
options: markdown options
- type:
MarkdownOptions
, See MarkdownOptions - default:
{ gfm: true, removeComments: true, copyLinkedFiles: true }
s.mdx(options)
string => string
parse input or document body as mdx content and return component function-body. refer to MDX Support for more information.
code: s.mdx()
// => function-body
Parameters
options: mdx options
- type:
MdxOptions
, See MdxOptions - default:
{ gfm: true, removeComments: true, copyLinkedFiles: true }
s.raw()
string => string
return raw document body.
code: s.raw()
// => raw document body
s.toc(options)
string => TocEntry[] | TocTree
parse input or document body as markdown content and return the table of contents.
toc: s.toc()
// document body => table of contents
Parameters
options: toc options
- type:
TocOptions
, See Options
options.original:
keep the original table of contents.
- type:
boolean
- default:
false
Types
interface TocEntry {
/**
* Title of the entry
*/
title: string
/**
* URL that can be used to reach
* the content
*/
url: string
/**
* Nested items
*/
items: TocEntry[]
}
/**
* Tree for table of contents
*/
export interface TocTree {
/**
* Index of the node right after the table of contents heading, `-1` if no
* heading was found, `undefined` if no `heading` was given.
*/
index?: number
/**
* Index of the first node after `heading` that is not part of its section,
* `-1` if no heading was found, `undefined` if no `heading` was given, same
* as `index` if there are no nodes between `heading` and the first heading
* in the table of contents.
*/
endIndex?: number
/**
* List representing the generated table of contents, `undefined` if no table
* of contents could be created, either because no heading was found or
* because no following headings were found.
*/
map?: List
}
Refer to mdast-util-toc for more information about Result
and Options
.
s.path(options)
=> string
get flattened path based on the file path.
path: s.path()
// => flattened path, e.g. 'posts/2021-01-01-hello-world'
Parameters
options: flattening options
- type:
PathOptions
options.removeIndex:
Removes index
from the path.
- type:
boolean
- default:
true
Zod Primitive Types
In addition, all Zod's built-in schemas can be used normally, such as:
title: s.string().mix(3).max(100)
description: s.string().optional()
featured: s.boolean().default(false)
You can refer to https://zod.dev get complete support documentation.
Define a Custom Schema
Refer to Custom Schema for more information about custom schema.