From f56397fb979597002165ac18817f41105692cea1 Mon Sep 17 00:00:00 2001 From: Maofeng Date: Tue, 29 Sep 2026 17:20:25 +0800 Subject: [PATCH] feat(docs): discover package metadata --- bun.lock | 1 + docs/package.json | 3 +- docs/src/content/registry.ts | 167 ++++++++++++---------------- docs/vite.config.ts | 27 ++++- packages/appearance/docs/meta.yaml | 5 + packages/blocks/docs/meta.yaml | 5 + packages/cropper/docs/meta.yaml | 5 + packages/i18n/docs/meta.yaml | 5 + packages/lexical/docs/meta.yaml | 5 + packages/media/docs/meta.yaml | 5 + packages/overlays/docs/meta.yaml | 5 + packages/page/docs/meta.yaml | 5 + packages/preferences/docs/meta.yaml | 5 + packages/record/docs/meta.yaml | 5 + packages/search/docs/meta.yaml | 5 + packages/ui/docs/meta.yaml | 5 + 16 files changed, 162 insertions(+), 96 deletions(-) create mode 100644 packages/appearance/docs/meta.yaml create mode 100644 packages/blocks/docs/meta.yaml create mode 100644 packages/cropper/docs/meta.yaml create mode 100644 packages/i18n/docs/meta.yaml create mode 100644 packages/lexical/docs/meta.yaml create mode 100644 packages/media/docs/meta.yaml create mode 100644 packages/overlays/docs/meta.yaml create mode 100644 packages/page/docs/meta.yaml create mode 100644 packages/preferences/docs/meta.yaml create mode 100644 packages/record/docs/meta.yaml create mode 100644 packages/search/docs/meta.yaml create mode 100644 packages/ui/docs/meta.yaml diff --git a/bun.lock b/bun.lock index 3c6bd98..b0324e9 100644 --- a/bun.lock +++ b/bun.lock @@ -89,6 +89,7 @@ "vite": "^8.3.0", "vite-plugin-satteri": "^0.3.5", "wrangler": "^4.135.0", + "yaml": "^2.9.1", }, }, "packages/appearance": { diff --git a/docs/package.json b/docs/package.json index bec4fde..68cbce3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -45,6 +45,7 @@ "typescript": "~6.0.2", "vite": "^8.3.0", "vite-plugin-satteri": "^0.3.5", - "wrangler": "^4.135.0" + "wrangler": "^4.135.0", + "yaml": "^2.9.1" } } \ No newline at end of file diff --git a/docs/src/content/registry.ts b/docs/src/content/registry.ts index 8ec44d6..34ada39 100644 --- a/docs/src/content/registry.ts +++ b/docs/src/content/registry.ts @@ -21,101 +21,23 @@ type DocContentModule = { type PackageDefinition = { key: string label: string - description: Translation + description: Record + order: number } type ParsedDocPage = DocPage & { packageKey: string } -const packageDefinitions: readonly PackageDefinition[] = [ - { - key: "blocks", - label: "Blocks", - description: { - zh: "构建应用外壳,并接入导航、通知、聊天和外观控制。", - us: "Build an application shell and add navigation, notifications, chat, and appearance controls.", - }, - }, - { - key: "appearance", - label: "Appearance", - description: { - zh: "使用原子化控件、主题词典和可组合偏好副作用构建应用外观设置。", - us: "Build application appearance settings with atomic controls, theme tokens, and composable preference effects.", - }, - }, - { - key: "i18n", - label: "I18n", - description: { - zh: "接入应用自有词典、本地化运行时、开发工具和完整翻译工作流。", - us: "Add application-owned catalogs, localized runtime rendering, development tools, and translation workflows.", - }, - }, - { - key: "lexical", - label: "Lexical", - description: { - zh: "从根节点和内容区域开始,逐步构建支持自定义操作与媒体的富文本编辑器。", - us: "Build a rich-text editor progressively from its root and content surface to custom actions and media.", - }, - }, - { - key: "media", - label: "Media", - description: { - zh: "通过存储 Adapter 构建媒体浏览、上传、目录管理和资源选择流程。", - us: "Build media browsing, uploads, folder management, and asset selection with a storage adapter.", - }, - }, - { - key: "overlays", - label: "Overlays", - description: { - zh: "使用统一的异步 API 编排 alert、confirm、prompt、modal、sheet、drawer 和 toast。", - us: "Orchestrate alerts, confirms, prompts, modals, sheets, drawers, and toasts through one asynchronous API.", - }, - }, - { - key: "page", - label: "Page", - description: { - zh: "组合页面标题、描述、操作、面包屑、路由标签和内容区,并按需将标题挂载到外部布局。", - us: "Compose page headings, actions, breadcrumbs, route tabs, and sections, with optional title portals into an external layout.", - }, - }, - { - key: "preferences", - label: "Preferences", - description: { - zh: "使用 SSR 快照、持久化回调和可组合副作用管理类型安全且可扩展的应用偏好。", - us: "Manage typed, extensible application preferences with SSR snapshots, persistence callbacks, and composable effects.", - }, - }, - { - key: "record", - label: "Record", - description: { - zh: "通过可组合上下文、类型安全字段路径和记录迭代器构建数据驱动界面。", - us: "Build data-driven interfaces with composable contexts, typed field paths, and record iteration.", - }, - }, - { - key: "search", - label: "Search", - description: { - zh: "通过可替换的 Adapter、分组结果、分页和搜索历史构建应用级搜索体验。", - us: "Build application search with a replaceable adapter, grouped results, pagination, and search history.", - }, - }, - { - key: "ui", - label: "UI", - description: { - zh: "配置共享 UI 层,并学习组合组件、Hooks、图标和本地化词典。", - us: "Set up the shared UI layer and learn how to compose its components, hooks, icons, and locale catalogs.", - }, - }, -] +const packageMetaModules = import.meta.glob( + "../../../packages/*/docs/meta.yaml", + { eager: true, import: "default" } +) + +const packageDefinitions = Object.entries(packageMetaModules) + .map(([path, metadata]) => parsePackageDefinition(path, metadata)) + .toSorted( + (left, right) => + left.order - right.order || left.key.localeCompare(right.key) + ) const docModuleLoaders = import.meta.glob( "../../../packages/*/docs/*/**/*.mdx", @@ -283,12 +205,47 @@ function createDocPackage( return { key: definition.key, label: definition.label, - description: trans(locale, definition.description), + description: definition.description[locale], locale, pages, } } +function parsePackageDefinition( + path: string, + value: unknown +): PackageDefinition { + const match = path.match(/\/packages\/([^/]+)\/docs\/meta\.yaml$/) + if (!match) { + throw new Error( + `Invalid package documentation metadata path "${path}". Expected packages//docs/meta.yaml.` + ) + } + + if (!isRecord(value)) { + throw new Error( + `Package documentation metadata must be an object: "${path}".` + ) + } + + const description = value.description + if (!isRecord(description)) { + throw new Error( + `Package documentation metadata requires a localized "description" object: "${path}".` + ) + } + + return { + key: match[1]!, + label: readMetaString(value, "label", path), + description: { + "zh-Hans": readMetaString(description, "zh-Hans", path), + "en-US": readMetaString(description, "en-US", path), + }, + order: readMetaNumber(value, "order", path), + } +} + function parseDocPage( path: string, frontmatter: Record, @@ -379,6 +336,30 @@ function readNumber(frontmatter: Record, key: string) { throw new Error(`Documentation frontmatter requires a number "${key}".`) } +function readMetaString( + metadata: Record, + key: string, + path: string +) { + const value = metadata[key] + if (typeof value === "string" && value.trim()) return value + throw new Error( + `Package documentation metadata requires a string "${key}": "${path}".` + ) +} + +function readMetaNumber( + metadata: Record, + key: string, + path: string +) { + const value = metadata[key] + if (typeof value === "number" && Number.isFinite(value)) return value + throw new Error( + `Package documentation metadata requires a number "${key}": "${path}".` + ) +} + function readToc(value: unknown): readonly DocTocItem[] { if (value === undefined) return [] if (!Array.isArray(value)) { @@ -399,5 +380,5 @@ function readToc(value: unknown): readonly DocTocItem[] { } function isRecord(value: unknown): value is Record { - return typeof value === "object" && value !== null + return typeof value === "object" && value !== null && !Array.isArray(value) } diff --git a/docs/vite.config.ts b/docs/vite.config.ts index a0f3354..7d9b016 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -7,12 +7,13 @@ import expressiveCode from "satteri-expressive-code" import { fileURLToPath } from "node:url" import { defineConfig, type Plugin } from "vite" import { satteri } from "vite-plugin-satteri" +import { parse } from "yaml" const packagesDirectory = fileURLToPath(new URL("../packages", import.meta.url)) /** - * Vite 默认监听 docs 根目录。现有的外部 MDX 会作为模块被监听,但新建 package - * 或新建 MDX 文件在首次进入模块图之前不会触发 import.meta.glob 重新计算。 + * Vite 默认监听 docs 根目录。现有的外部文档与元数据会作为模块被监听,但新建 + * package、meta.yaml 或 MDX 文件在首次进入模块图之前不会触发 glob 重新计算。 */ function watchPackageDocs(): Plugin { return { @@ -23,6 +24,27 @@ function watchPackageDocs(): Plugin { } } +function loadYamlModules(): Plugin { + return { + name: "load-yaml-modules", + enforce: "pre", + transform(source, id) { + if (!/\/meta\.ya?ml(?:\?|$)/.test(id)) return + + try { + return { + code: `export default ${JSON.stringify(parse(source))}`, + map: null, + } + } catch (error) { + this.error( + `Unable to parse ${id}: ${error instanceof Error ? error.message : String(error)}` + ) + } + }, + } +} + function loadDocSearchSources(): Plugin { const suffix = "?docs-search-raw" const virtualPrefix = "\0docs-search-raw:" @@ -60,6 +82,7 @@ function loadDocSearchSources(): Plugin { export default defineConfig({ plugins: [ watchPackageDocs(), + loadYamlModules(), loadDocSearchSources(), satteri({ features: { diff --git a/packages/appearance/docs/meta.yaml b/packages/appearance/docs/meta.yaml new file mode 100644 index 0000000..c28b587 --- /dev/null +++ b/packages/appearance/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 20 +label: Appearance +description: + zh-Hans: 使用原子化控件、主题词典和可组合偏好副作用构建应用外观设置。 + en-US: Build application appearance settings with atomic controls, theme tokens, and composable preference effects. diff --git a/packages/blocks/docs/meta.yaml b/packages/blocks/docs/meta.yaml new file mode 100644 index 0000000..33351c6 --- /dev/null +++ b/packages/blocks/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 10 +label: Blocks +description: + zh-Hans: 构建应用外壳,并接入导航、通知、聊天和外观控制。 + en-US: Build an application shell and add navigation, notifications, chat, and appearance controls. diff --git a/packages/cropper/docs/meta.yaml b/packages/cropper/docs/meta.yaml new file mode 100644 index 0000000..c7993bf --- /dev/null +++ b/packages/cropper/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 30 +label: Cropper +description: + zh-Hans: 通过可组合交互、几何计算和 Canvas 导出构建图片裁剪流程。 + en-US: Build image-cropping workflows with composable interactions, geometry utilities, and Canvas export. diff --git a/packages/i18n/docs/meta.yaml b/packages/i18n/docs/meta.yaml new file mode 100644 index 0000000..261d8f8 --- /dev/null +++ b/packages/i18n/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 40 +label: I18n +description: + zh-Hans: 接入应用自有词典、本地化运行时、开发工具和完整翻译工作流。 + en-US: Add application-owned catalogs, localized runtime rendering, development tools, and translation workflows. diff --git a/packages/lexical/docs/meta.yaml b/packages/lexical/docs/meta.yaml new file mode 100644 index 0000000..6e1764d --- /dev/null +++ b/packages/lexical/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 50 +label: Lexical +description: + zh-Hans: 从根节点和内容区域开始,逐步构建支持自定义操作与媒体的富文本编辑器。 + en-US: Build a rich-text editor progressively from its root and content surface to custom actions and media. diff --git a/packages/media/docs/meta.yaml b/packages/media/docs/meta.yaml new file mode 100644 index 0000000..1b18c58 --- /dev/null +++ b/packages/media/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 60 +label: Media +description: + zh-Hans: 通过存储 Adapter 构建媒体浏览、上传、目录管理和资源选择流程。 + en-US: Build media browsing, uploads, folder management, and asset selection with a storage adapter. diff --git a/packages/overlays/docs/meta.yaml b/packages/overlays/docs/meta.yaml new file mode 100644 index 0000000..0046d2f --- /dev/null +++ b/packages/overlays/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 70 +label: Overlays +description: + zh-Hans: 使用统一的异步 API 编排 alert、confirm、prompt、modal、sheet、drawer 和 toast。 + en-US: Orchestrate alerts, confirms, prompts, modals, sheets, drawers, and toasts through one asynchronous API. diff --git a/packages/page/docs/meta.yaml b/packages/page/docs/meta.yaml new file mode 100644 index 0000000..8fa4e27 --- /dev/null +++ b/packages/page/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 80 +label: Page +description: + zh-Hans: 组合页面标题、描述、操作、面包屑、路由标签和内容区,并按需将标题挂载到外部布局。 + en-US: Compose page headings, actions, breadcrumbs, route tabs, and sections, with optional title portals into an external layout. diff --git a/packages/preferences/docs/meta.yaml b/packages/preferences/docs/meta.yaml new file mode 100644 index 0000000..7ba4049 --- /dev/null +++ b/packages/preferences/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 90 +label: Preferences +description: + zh-Hans: 使用 SSR 快照、持久化回调和可组合副作用管理类型安全且可扩展的应用偏好。 + en-US: Manage typed, extensible application preferences with SSR snapshots, persistence callbacks, and composable effects. diff --git a/packages/record/docs/meta.yaml b/packages/record/docs/meta.yaml new file mode 100644 index 0000000..0665e23 --- /dev/null +++ b/packages/record/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 100 +label: Record +description: + zh-Hans: 通过可组合上下文、类型安全字段路径和记录迭代器构建数据驱动界面。 + en-US: Build data-driven interfaces with composable contexts, typed field paths, and record iteration. diff --git a/packages/search/docs/meta.yaml b/packages/search/docs/meta.yaml new file mode 100644 index 0000000..16c8e06 --- /dev/null +++ b/packages/search/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 110 +label: Search +description: + zh-Hans: 通过可替换的 Adapter、分组结果、分页和搜索历史构建应用级搜索体验。 + en-US: Build application search with a replaceable adapter, grouped results, pagination, and search history. diff --git a/packages/ui/docs/meta.yaml b/packages/ui/docs/meta.yaml new file mode 100644 index 0000000..ace9c87 --- /dev/null +++ b/packages/ui/docs/meta.yaml @@ -0,0 +1,5 @@ +order: 120 +label: UI +description: + zh-Hans: 配置共享 UI 层,并学习组合组件、Hooks、图标和本地化词典。 + en-US: Set up the shared UI layer and learn how to compose its components, hooks, icons, and locale catalogs.