diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index f7614a9..e86774a 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'vitepress' export default defineConfig({ title: 'Velite', - description: "Velite is a tool for building type-safe data layer, turn Markdown/MDX, YAML, JSON, or other files into app's data layer with Zod schema.", + description: "Velite is a tool for building type-safe data layer, turns Markdown/MDX, YAML, JSON, or other files into app's data layer with Zod schema.", lastUpdated: true, cleanUrls: true, head: [ diff --git a/docs/examples/basic.md b/docs/examples/basic.md index 177d25d..ab3b1d8 100644 --- a/docs/examples/basic.md +++ b/docs/examples/basic.md @@ -52,7 +52,7 @@ basic ```shell $ npm install # install dependencies -$ npm run dev # run build with watch mode +$ npm run dev # run build in watch mode $ npm run build # build content by velite ``` diff --git a/docs/examples/nextjs.md b/docs/examples/nextjs.md index deeda6c..899decd 100644 --- a/docs/examples/nextjs.md +++ b/docs/examples/nextjs.md @@ -69,7 +69,7 @@ nextjs ```shell $ npm install # install dependencies -$ npm run dev # run build with watch mode +$ npm run dev # run build in watch mode $ npm run build # build content by velite ``` diff --git a/docs/guide/code-highlighting.md b/docs/guide/code-highlighting.md index a01e78a..9497da4 100644 --- a/docs/guide/code-highlighting.md +++ b/docs/guide/code-highlighting.md @@ -1,8 +1,6 @@ # Code Highlighting -Considering that not all content contains code, and that syntax highlighting often comes with custom styles, Velite doesn't want to subjectively determine the final presentation of your content. So we don't include built-in code highlighting features. - -If you think code highlighting is necessary for your content, you can implement if by referring to the following methods. +Velite doesn't include built-in code highlighting features because not all content contains code, and that syntax highlighting often comes with custom styles. But you can easily implement it yourself with build-time plugins or client-side highlighters. ## rehype-pretty-code @@ -38,7 +36,7 @@ export default defineConfig({ }) ``` -Add some necessary styles, such as: +`rehype-pretty-code` creates the proper HTML structure for syntax highlighting, you can then add styles however you like. Here is an example stylesheet: ```css [data-rehype-pretty-code-figure] pre { @@ -78,7 +76,7 @@ Add some necessary styles, such as: } ``` -refer to [examples](https://github.com/zce/velite/blob/main/examples/nextjs/velite.config.ts) for more details. +Refer to [examples](https://github.com/zce/velite/blob/main/examples/nextjs/velite.config.ts) for more details. ## @shikijs/rehype @@ -165,9 +163,9 @@ export default defineConfig({ ## Client-side -Code highlighting in Client-side. You can use [prismjs](https://prismjs.com) or [shiki](https://shiki.matsu.io) to highlight code in client-side. +You can use [prismjs](https://prismjs.com) or [shiki](https://shiki.matsu.io) to highlight code on the client side. Client-side highlighting does not add build overhead to Velite. -for example: +For example: ```js import { codeToHtml } from 'https://esm.sh/shikiji' @@ -179,6 +177,6 @@ Array.from(document.querySelectorAll('pre code[class*="language-"]')).map(async ::: tip -This method is most recommended if there are a large number of documents that need to be processed frequently. Because syntax highlighting and parsing is very time-consuming, it will greatly affect the construction speed of Velite. +If you have a large of number of documents that need to be syntax highlighted, it is recommended to use the client-side method. Because syntax highlighting and parsing can be very time-consuming, and it will greatly affect the construction speed of Velite. ::: diff --git a/docs/guide/custom-loader.md b/docs/guide/custom-loader.md index 9bde01c..6eac26e 100644 --- a/docs/guide/custom-loader.md +++ b/docs/guide/custom-loader.md @@ -1,6 +1,6 @@ # Custom Loader -built-in loaders are: +Built-in loaders are: - `matter-loader`: parse frontmatter and provide content and data - `json-loader`: parse document as json diff --git a/docs/guide/custom-schema.md b/docs/guide/custom-schema.md index d3e4939..bcf1a69 100644 --- a/docs/guide/custom-schema.md +++ b/docs/guide/custom-schema.md @@ -2,7 +2,7 @@ > Schema is the core of Velite. It defines the structure and type of your content and validates it. > -> refer to [Velite Schemas](velite-schemas.md) for more information about built-in schema. +> Refer to [Velite Schemas](velite-schemas.md) for more information about built-in schema. Velite supports custom schema. A schema is a JavaScript function that returns a [Zod](https://zod.dev) schema object. @@ -33,7 +33,7 @@ export const hello = defineSchema(() => ) ``` -refer to [Zod documentation](https://zod.dev) for more information about Zod. +Refer to [Zod documentation](https://zod.dev) for more information about Zod. ## Define a Transformation Schema diff --git a/docs/guide/define-collections.md b/docs/guide/define-collections.md index 2be19f7..b924f73 100644 --- a/docs/guide/define-collections.md +++ b/docs/guide/define-collections.md @@ -1,6 +1,6 @@ # Define Collections -Content collections are the best way to manage and author content in content-first applications. Velite help to organize and validate your your contents, and provide automatic TypeScript type-safety for all of your contents. +Content collections are the best way to manage and author content in content-first applications. Velite helps you organize and validate your contents, and provides type-safety through automatic type generations. ## What is a Collection? @@ -86,7 +86,7 @@ const site = defineCollection({ Velite uses [Zod](https://zod.dev) to validate the content items in a collection. The `schema` option is used to define the Zod schema used to validate the content items in the collection. -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](https://zod.dev) for complete documentation on how Zod works and what features are available. +To use Zod in Velite, import the `z` utility from `'velite'`. This is a re-export of Zod's `z` object, and it supports all of the features of Zod. See [Zod's Docs](https://zod.dev) for a complete documentation on how Zod works and what features are available. ```js import { z } from 'velite' @@ -104,7 +104,7 @@ The schema is usually a `ZodObject`, validating the shape of the content item. B ::: -For more useful schemas, I recommend that you use [Velite extended schemas `s`](velite-schemas.md): +For more complex schemas, I recommend that you use [Velite extended schemas `s`](velite-schemas.md): - `s.slug()`: validate slug format, unique in posts collection. - `s.isodate()`: format date string to ISO date string. @@ -156,7 +156,7 @@ const posts = defineCollection({ ### Transform Context Metadata -The transform function can receive a second argument, which is the context object. This is useful for adding computed fields to the content items in a collection. +The `transform()` function can receive a second argument, which is the context object. This is useful for adding computed fields to the content items in a collection. ```js const posts = defineCollection({ @@ -176,9 +176,9 @@ the type of `meta` is `ZodMeta`, which extends [`VeliteFile`](../reference/types ## Content Body -Velite built-in Loader keep content raw body in `meta.content`, and plain text body in `meta.plain`. +Velite's built-in loader keeps content's raw body in `meta.content`, and the plain text body in `meta.plain`. -To extract the original content, you can customize a schema. +To add them as a field, you can use a custom schema. ```js const posts = defineCollection({ @@ -237,11 +237,11 @@ Velite can extract excerpt from content files. This is useful for adding compute ```js const posts = defineCollection({ schema: s.object({ - excerpt: s.excerpt() // excerpt of markdown content + excerpt: s.excerpt({ length: 200 }) // excerpt of the markdown body }) }) ``` #### Reference -- [`s.excerpt()`](velite-schemas.md#s-excerpt) +- [`s.excerpt(options)`](velite-schemas.md#s-excerpt) diff --git a/docs/guide/introduction.md b/docs/guide/introduction.md index 8dbe42b..e699288 100644 --- a/docs/guide/introduction.md +++ b/docs/guide/introduction.md @@ -2,7 +2,7 @@ ::: warning -🚧 this documentation is not yet complete currently. but the functionality is mostly stable, although there is still a possibility of significant changes being made. +🚧 This documentation is not yet complete currently. but the functionality is mostly stable, although there is still a possibility of significant changes being made. However, I have provided some [examples](https://github.com/zce/velite/tree/main/examples) for your consideration. @@ -10,7 +10,7 @@ However, I have provided some [examples](https://github.com/zce/velite/tree/main ## What is Velite? -Velite is a tool for building type-safe data layer, turn Markdown / MDX, YAML, JSON, or other files into app's data layer with Zod schema. +Velite is a tool for building type-safe data layer, turns Markdown / MDX, YAML, JSON, or other files into app's data layer with Zod schema. ![Velite Workflow](/assets/flow-dark.svg#dark 'Velite Workflow') ![Velite Workflow](/assets/flow.svg#light 'Velite Workflow') @@ -24,7 +24,7 @@ Velite is a tool for building type-safe data layer, turn Markdown / MDX, YAML, J ## Key Features - **Easy to use**: Move your contents into `content` folder, define collections schema, run `velite`, then use the output data in your application. -- **Type-safe**: Contents schema validation by [Zod](https://zod.dev), and generate type inference for TypeScript. +- **Type-safe**: Contents schema validation by [Zod](https://zod.dev), and generate type definitions for TypeScript. - **Framework Agnostic**: JSON & Entry & DTS output, out of the box support for any JavaScript framework or library. - **Light-weight**: Choose more native APIs instead of bloated NPM modules, less runtime dependencies, so it is fast and efficiently. - **Still powerful**: Built-in Markdown / MDX, YAML, JSON support, relative files & images processing, schema validation, etc. @@ -51,13 +51,13 @@ You can try Velite directly in your browser on StackBlitz, It runs Velite direct ### Type-Safe Contents -Velite validates your contents by [Zod](https://zod.dev) schema, and generates type inference for TypeScript. so you can use the output data in your application with confidence. +Velite validates your contents by [Zod](https://zod.dev) schema, and generates type definitions for TypeScript. so you can use the output data in your application with confidence. ### Full Type inference

-- auto-generate TypeScript type inference for each collection +- auto-generate TypeScript type definitions for each collection - support IDE IntelliSense, auto-completion & type checking & refactoring & etc. ### Full Controllable Content Transform diff --git a/docs/guide/last-modified.md b/docs/guide/last-modified.md index 779503b..b34d94e 100644 --- a/docs/guide/last-modified.md +++ b/docs/guide/last-modified.md @@ -1,24 +1,34 @@ # Last Modified Schema -We provide a last modified timestamp schema based on file stat and git timestamp. +You can create a custom schema to show the last modified time for your contents. This can be based on: + +- File stat + +- Git timestamp ## Based on file stat -create a timestamp schema based on file stat. +Create a timestamp schema based on file stat. ```ts -const timestamp = () => - s.custom(i => i === undefined || typeof i === 'string').transform(async (value, { meta, addIssue }) => { - if (value != null) { - addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the file modified timestamp' }) - } - - const stats = await stat(meta.path) - return stats.mtime.toISOString() - }) +import { stat } from 'fs/promises' +import { defineSchema } from 'velite' + +const timestamp = defineSchema(() => + s + .custom(i => i === undefined || typeof i === 'string') + .transform(async (value, { meta, addIssue }) => { + if (value != null) { + addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the file modified timestamp' }) + } + + const stats = await stat(meta.path) + return stats.mtime.toISOString() + }) +) ``` -use it in your schema +Use it in your schema ```ts const posts = defineCollection({ @@ -33,19 +43,26 @@ const posts = defineCollection({ ## Based on git timestamp ```ts +import { exec } from 'child_process' +import { promisify } from 'util' +import { defineSchema } from 'velite' + const execAsync = promisify(exec) -const timestamp = () => - s.custom(i => i === undefined || typeof i === 'string').transform(async (value, { meta, addIssue }) => { - if (value != null) { - addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the value from `git log -1 --format=%cd`' }) - } - const { stdout } = await execAsync(`git log -1 --format=%cd ${meta.path}`) - return new Date(stdout).toISOString() - }) +const timestamp = defineSchema(() => + s + .custom(i => i === undefined || typeof i === 'string') + .transform(async (value, { meta, addIssue }) => { + if (value != null) { + addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the value from `git log -1 --format=%cd`' }) + } + const { stdout } = await execAsync(`git log -1 --format=%cd ${meta.path}`) + return new Date(stdout).toISOString() + }) +) ``` -use it in your schema +Use it in your schema ```ts const posts = defineCollection({ diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md index 06bffed..37ebb23 100644 --- a/docs/guide/quick-start.md +++ b/docs/guide/quick-start.md @@ -179,9 +179,9 @@ echo '\npublic/static' >> .gitignore ::: -## Run Velite with Watch Mode +## Run Velite in Watch Mode -Run `velite dev` or `velite` with `--watch` option, then Velite will watch the contents files and rebuild them automatically when they are changed. +When the `--watch` flag is used with `velite dev` or `velite`, Velite will watch the contents files and rebuild them automatically when they are changed. ::: code-group diff --git a/docs/guide/using-markdown.md b/docs/guide/using-markdown.md index 11cb49d..11b4eb3 100644 --- a/docs/guide/using-markdown.md +++ b/docs/guide/using-markdown.md @@ -7,7 +7,7 @@ Markdown is a lightweight markup language with plain text formatting syntax. It ::: tip Markdown or MDX -Markdown is top-level supported in Velite, Although we also support MDX, I think that MDX is not the best choice for content creators. Although it is powerful and has stronger programmability, it is easy to lose the essence of writing and recording, and become addicted to technology. +Markdown has top-level support in Velite. Although we also support MDX, I think that MDX is not the best choice for content creators. Although it is powerful and has stronger programmability, it is easy to lose the essence of writing and recording, and become addicted to technology. - **Portable**: Markdown is portable, you can use it anywhere, even in the terminal. - **Simple**: Markdown is simple, you can learn it in 10 minutes, don't need to spend a lot of time to learn React. diff --git a/docs/guide/using-mdx.md b/docs/guide/using-mdx.md index ca47cf5..6d2c73c 100644 --- a/docs/guide/using-mdx.md +++ b/docs/guide/using-mdx.md @@ -9,7 +9,7 @@ Velite supports MDX out of the box. You can use MDX to write your content, and V ## Getting Started -For example, you have the following content structure: +For example, suppose you have the following content structure: ```diff {2,3,4} project-root @@ -21,7 +21,7 @@ project-root └── velite.config.js ``` -In your `./content/posts/hello-world.mdx`: +The`./content/posts/hello-world.mdx` document is a MDX document with the following content: ```mdx --- @@ -39,7 +39,7 @@ flood conditions in many of the nearby rivers. ``` -In your `./velite.config.js`: +Use the `s.mdx()` schema to add the compiled MDX code to your content collection. ```js {10} import { defineConfig, s } from 'velite' @@ -75,7 +75,7 @@ By default, Velite will compile the MDX content into a function-body string, whi ## Rendering MDX Content -First of all, you can create a component to render the MDX content: +First, you can create a generic component for rendering the compiled mdx code. It should accept the code and a list of components that are used in the MDX content. `./components/mdx-content.tsx`: @@ -128,7 +128,7 @@ export default function Post({ params: { slug } }) { ### How to import components in MDX? -Velite's built-in `s.mdx()` schema does not support importing components in MDX. The main reason is that I don't want a lot of repetition and redundancy in the output code. +You don't need to, since Velite's `s.mdx()` schema does not bundle those components at build time. There is no need to construct a import tree. This can help reduce output size for your contents. For example, suppose you extract a common component for multiple MDXs and import the component in these MDXs. @@ -167,9 +167,9 @@ import { Callout } from '../components/callout' ::: -If Velite uses bundling to compile MDX, the `Callout` component will be bundled into each MDX file, which will cause a lot of redundancy in the output code. +If Velite uses a bundler to comiple your MDX, the `Callout` component will be bundled into each MDX file, which will cause a lot of redundancy in the output code. -If you want to use components in MDX, you can use the following workaround: +Instead, simply use whatever components you want in your MDX files without a import. ::: code-group @@ -212,7 +212,7 @@ export default function Post({ params: { slug } }) { } ``` -or Global components: +You can also add global components so that they are available to all MDX files. ```tsx {3,7} import * as runtime from 'react/jsx-runtime' @@ -240,9 +240,9 @@ export const MDXContent = ({ code, components }: MDXProps) => { } ``` -### How to bundle MDX? +### What if I want to bundle MDX? -If your scenario can ignore the size of data and duplication of code, bundling MDX is really a better choice because it has better portability. +If you can make do with the increased output size, bundling MDX can be a good option for better portability. You can install the following packages to bundle MDX: diff --git a/docs/guide/velite-schemas.md b/docs/guide/velite-schemas.md index 7c1a82f..a326a05 100644 --- a/docs/guide/velite-schemas.md +++ b/docs/guide/velite-schemas.md @@ -23,7 +23,7 @@ import { s } from 'velite' `string => string` -format date string to ISO date string. +Format date string to ISO date string. ```ts date: s.isodate() diff --git a/docs/guide/with-nextjs.md b/docs/guide/with-nextjs.md index 812ce29..0fca111 100644 --- a/docs/guide/with-nextjs.md +++ b/docs/guide/with-nextjs.md @@ -2,7 +2,7 @@ Velite is a framework agnostic library, it can be used in any JavaScript framework or library, including Next.js. -Here is some recipes for help you better integrate Velite with Next.js. +Here are some recipes for help you better integrate Velite with Next.js. ## 🎊 Start Velite with Next.js Config 🆕 @@ -33,7 +33,7 @@ Note that this approach uses top-level await, so it only supports `next.config.m You can use the Next.js plugin to call Velite's programmatic API to start Velite with better integration. -in your `next.config.js`: +In `next.config.js`: ::: code-group diff --git a/docs/other/snippets.md b/docs/other/snippets.md index e1e535c..32c496b 100644 --- a/docs/other/snippets.md +++ b/docs/other/snippets.md @@ -5,15 +5,21 @@ ### Based on file stat ```ts -const timestamp = () => - s.custom(i => i === undefined || typeof i === 'string').transform(async (value, { meta, addIssue }) => { - if (value != null) { - addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the file modified timestamp' }) - } - - const stats = await stat(meta.path) - return stats.mtime.toISOString() - }) +import { stat } from 'fs/promises' +import { defineSchema } from 'velite' + +const timestamp = defineSchema(() => + s + .custom(i => i === undefined || typeof i === 'string') + .transform(async (value, { meta, addIssue }) => { + if (value != null) { + addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the file modified timestamp' }) + } + + const stats = await stat(meta.path) + return stats.mtime.toISOString() + }) +) // use it in your schema const posts = defineCollection({ @@ -28,16 +34,23 @@ const posts = defineCollection({ ### Based on git timestamp ```ts +import { exec } from 'child_process' +import { promisify } from 'util' +import { defineSchema } from 'velite' + const execAsync = promisify(exec) -const timestamp = () => - s.custom(i => i === undefined || typeof i === 'string').transform(async (value, { meta, addIssue }) => { - if (value != null) { - addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the value from `git log -1 --format=%cd`' }) - } - const { stdout } = await execAsync(`git log -1 --format=%cd ${meta.path}`) - return new Date(stdout).toISOString() - }) +const timestamp = defineSchema(() => + s + .custom(i => i === undefined || typeof i === 'string') + .transform(async (value, { meta, addIssue }) => { + if (value != null) { + addIssue({ fatal: false, code: 'custom', message: '`s.timestamp()` schema will resolve the value from `git log -1 --format=%cd`' }) + } + const { stdout } = await execAsync(`git log -1 --format=%cd ${meta.path}`) + return new Date(stdout).toISOString() + }) +) // use it in your schema const posts = defineCollection({ diff --git a/docs/reference/config.md b/docs/reference/config.md index 7e5efed..7560daf 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -25,7 +25,7 @@ Config file supports TypeScript & ESM & CommonJS. you can use the full power of ## Typed Config -For the better experience, Velite provides a `defineConfig` identity function to define the config file type. +For better typing, Velite provides a `defineConfig` identity function to define the config file type. ```js import { defineConfig } from 'velite' diff --git a/readme.md b/readme.md index 9ee3708..4018257 100644 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ ## What is Velite? -Velite is a tool for building type-safe data layer, turn Markdown / MDX, YAML, JSON, or other files into app's data layer with Zod schema. +Velite is a tool for building type-safe data layer, turns Markdown / MDX, YAML, JSON, or other files into app's data layer with Zod schema.