diff --git a/docs/.vuepress/notes/zh/theme-guide.ts b/docs/.vuepress/notes/zh/theme-guide.ts index ac85c5c0..7ee8314c 100644 --- a/docs/.vuepress/notes/zh/theme-guide.ts +++ b/docs/.vuepress/notes/zh/theme-guide.ts @@ -42,6 +42,7 @@ export const themeGuide = defineNoteConfig({ 'card', 'steps', 'file-tree', + 'field', 'tabs', 'timeline', 'demo-wrapper', diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 1d98e043..2ca89ef2 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -31,6 +31,7 @@ export const theme: Theme = plumeTheme({ timeline: true, collapse: true, chat: true, + field: true, imageSize: 'all', pdf: true, caniuse: true, diff --git a/docs/notes/theme/config/markdown.md b/docs/notes/theme/config/markdown.md index e0a5bea5..89e424b2 100644 --- a/docs/notes/theme/config/markdown.md +++ b/docs/notes/theme/config/markdown.md @@ -155,6 +155,12 @@ export default defineUserConfig({ - **默认值**: `true` - **详情**: 是否启用文件树容器语法 +### field + +- **类型**: `boolean` +- **默认值**: `false` +- **详情**: 是否启用字段容器 + ### timeline - **类型**: `boolean` diff --git a/docs/notes/theme/guide/markdown/field.md b/docs/notes/theme/guide/markdown/field.md new file mode 100644 index 00000000..6604569e --- /dev/null +++ b/docs/notes/theme/guide/markdown/field.md @@ -0,0 +1,131 @@ +--- +title: 字段容器 +icon: solar:text-field-linear +createTime: 2025/04/29 09:55:17 +permalink: /guide/markdown/field/ +badge: 新 +--- + +## 概述 + +在 markdown 中,使用 `::: field` 容器,用于描述字段信息,包括字段名称、字段类型、是否必填、默认值、详情等信息。 + +它适用于 描述配置中的字段、组件的 Props 等场景。 + +还可以使用额外的 `:::: field-group` 容器,用于组合多个 `::: field`。 + +## 启用 + +该功能默认不启用,您需要在 `theme` 配置中启用它。 + +```ts title=".vuepress/config.ts" +export default defineUserConfig({ + theme: plumeTheme({ + markdown: { + field: true, // [!code ++] + }, + }) +}) +``` + +## 语法 + +```md + +::: field name="字段名" type="类型" required default="默认值" +字段描述信息 +::: + + +:::: field-group + +::: field name="字段名" type="类型" required default="默认值" +字段描述信息 +::: + +::: field name="字段名" type="类型" required default="默认值" +字段描述信息 +::: + +:::: +``` + +## 属性 + +::: field name="name" required type="string" +字段名称 +::: + +::: field name="type" type="string" optional +字段类型 +::: + +::: field name="required" type="boolean" optional +是否必填 +::: + +::: field name="optional" type="boolean" optional +是否可选 +::: + +::: field name="default" type="string" optional +默认值 +::: + +## 示例 + +**输入:** + +```md +::: field name="theme" type="ThemeConfig" required default="{}" +主题配置 +::: + +::: field name="enabled" type="boolean" optional default="true" +是否启用 +::: +``` + +**输出:** + +::: field name="theme" type="ThemeConfig" required default="{}" +主题配置 +::: + +::: field name="enabled" type="boolean" optional default="true" +是否启用 +::: + +**输入:** + +```md +:::: field-group +::: field name="theme" type="ThemeConfig" required default="{ base: '/' }" +主题配置 +::: + +::: field name="enabled" type="boolean" optional default="true" +是否启用 +::: + +::: field name="callback" type="(...args: any[]) => void" optional default="() => {}" +回调函数 +::: +:::: +``` + +**输出:** + +:::: field-group +::: field name="theme" type="ThemeConfig" required default="{ base: '/' }" +主题配置 +::: + +::: field name="enabled" type="boolean" optional default="true" +是否启用 +::: + +::: field name="callback" type="(...args: any[]) => void" optional default="() => {}" +回调函数 +::: +:::: diff --git a/plugins/plugin-md-power/src/client/components/VPField.vue b/plugins/plugin-md-power/src/client/components/VPField.vue new file mode 100644 index 00000000..3f8ba72b --- /dev/null +++ b/plugins/plugin-md-power/src/client/components/VPField.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/plugins/plugin-md-power/src/node/container/field.ts b/plugins/plugin-md-power/src/node/container/field.ts new file mode 100644 index 00000000..ada9dd79 --- /dev/null +++ b/plugins/plugin-md-power/src/node/container/field.ts @@ -0,0 +1,33 @@ +import type { Markdown } from 'vuepress/markdown' +import { isUndefined } from '@pengzhanbo/utils' +import { resolveAttrs } from '../utils/resolveAttrs.js' +import { stringifyAttrs } from '../utils/stringifyAttrs.js' +import { createContainerPlugin } from './createContainer.js' + +interface FieldAttrs { + name: string + type?: string + required?: boolean + optional?: boolean + default?: string +} + +export function fieldPlugin(md: Markdown) { + createContainerPlugin(md, 'field', { + before: (info) => { + const { attrs } = resolveAttrs(info) + const { name, type, required, optional, default: defaultValue } = attrs + const props = stringifyAttrs({ name, required, optional }) + return `` + }, + after: () => '', + }) + + createContainerPlugin(md, 'field-group', { + before: () => '
', + }) +} diff --git a/plugins/plugin-md-power/src/node/container/index.ts b/plugins/plugin-md-power/src/node/container/index.ts index 4f6fdc0b..4a3bd13f 100644 --- a/plugins/plugin-md-power/src/node/container/index.ts +++ b/plugins/plugin-md-power/src/node/container/index.ts @@ -8,6 +8,7 @@ import { chatPlugin } from './chat.js' import { codeTabs } from './codeTabs.js' import { collapsePlugin } from './collapse.js' import { demoWrapperPlugin } from './demoWrapper.js' +import { fieldPlugin } from './field.js' import { fileTreePlugin } from './fileTree.js' import { langReplPlugin } from './langRepl.js' import { npmToPlugins } from './npmTo.js' @@ -58,4 +59,7 @@ export async function containerPlugin( if (options.chat) chatPlugin(md) + + if (options.field) + fieldPlugin(md) } diff --git a/plugins/plugin-md-power/src/node/prepareConfigFile.ts b/plugins/plugin-md-power/src/node/prepareConfigFile.ts index d4c6ac66..f95e097d 100644 --- a/plugins/plugin-md-power/src/node/prepareConfigFile.ts +++ b/plugins/plugin-md-power/src/node/prepareConfigFile.ts @@ -120,6 +120,11 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp imports.add(`import '${CLIENT_FOLDER}styles/chat.css'`) } + if (options.field) { + imports.add(`import VPField from '${CLIENT_FOLDER}components/VPField.vue'`) + enhances.add(`app.component('VPField', VPField)`) + } + return app.writeTemp( 'md-power/config.js', `\ diff --git a/plugins/plugin-md-power/src/shared/plugin.ts b/plugins/plugin-md-power/src/shared/plugin.ts index 1a004cc5..4bbceb68 100644 --- a/plugins/plugin-md-power/src/shared/plugin.ts +++ b/plugins/plugin-md-power/src/shared/plugin.ts @@ -109,6 +109,12 @@ export interface MarkdownPowerPluginOptions { */ chat?: boolean + /** + * 是否启用 field / field-group 容器 + * + * @default false + */ + field?: boolean // video embed /** * 是否启用 bilibili 视频嵌入 diff --git a/theme/src/node/detector/fields.ts b/theme/src/node/detector/fields.ts index 697788eb..d51d8662 100644 --- a/theme/src/node/detector/fields.ts +++ b/theme/src/node/detector/fields.ts @@ -50,6 +50,7 @@ export const MARKDOWN_POWER_FIELDS: (keyof MarkdownPowerPluginOptions)[] = [ 'codepen', 'demo', 'fileTree', + 'field', 'icons', 'imageSize', 'jsfiddle',