From f83615bc83e1cd9edc1dcbf42f2373e3f8db08e5 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sat, 18 Jun 2022 15:07:25 +0800 Subject: [PATCH] Allow dynamic modules for description --- registry/lib/docs/components-doc.ts | 6 ++--- registry/lib/docs/plugins-doc.ts | 6 ++--- registry/lib/docs/third-party.ts | 4 ++-- src/components/description.ts | 35 +++++++++++++++-------------- src/components/types.ts | 4 ++-- src/core/common-types.ts | 4 +++- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/registry/lib/docs/components-doc.ts b/registry/lib/docs/components-doc.ts index f181710b5..52bb6f9e9 100644 --- a/registry/lib/docs/components-doc.ts +++ b/registry/lib/docs/components-doc.ts @@ -20,7 +20,7 @@ export const getComponentsDoc: DocSource = async rootPath => { return undefined }) .filter(it => it !== undefined) - .map(it => { + .map(async it => { const root = `${rootPath}components/` const fullRelativePath = `${root}${getId(root, it.path.replace(/^\.?\//, ''))}.js` const fullAbsolutePath = fullRelativePath.replace(/^(\.\.?\/)*/, '') @@ -28,7 +28,7 @@ export const getComponentsDoc: DocSource = async rootPath => { name, displayName, } = it.component - const description = getDescriptionMarkdown(it.component) + const description = await getDescriptionMarkdown(it.component) return { type: 'component', name, @@ -41,6 +41,6 @@ export const getComponentsDoc: DocSource = async rootPath => { .concat(thirdPartyComponents.map(getThirdPartyDescription)) return { title: '组件', - items: componentsPaths, + items: await Promise.all(componentsPaths), } } diff --git a/registry/lib/docs/plugins-doc.ts b/registry/lib/docs/plugins-doc.ts index 5b3cd5a94..3ba038cb7 100644 --- a/registry/lib/docs/plugins-doc.ts +++ b/registry/lib/docs/plugins-doc.ts @@ -20,7 +20,7 @@ export const getPluginsDoc: DocSource = async rootPath => { return undefined }) .filter(it => it !== undefined) - .map(it => { + .map(async it => { const root = `${rootPath}plugins/` const fullRelativePath = `${root}${getId(root, it.path.replace(/^\.?\//, ''))}.js` const fullAbsolutePath = fullRelativePath.replace(/^(\.\.?\/)*/, '') @@ -28,7 +28,7 @@ export const getPluginsDoc: DocSource = async rootPath => { name, displayName, } = it.plugin - const description = getDescriptionMarkdown(it.plugin) + const description = await getDescriptionMarkdown(it.plugin) return { type: 'plugin', name, @@ -41,6 +41,6 @@ export const getPluginsDoc: DocSource = async rootPath => { .concat(thirdPartyPlugins.map(getThirdPartyDescription)) return { title: '插件', - items: pluginsPaths, + items: await Promise.all(pluginsPaths), } } diff --git a/registry/lib/docs/third-party.ts b/registry/lib/docs/third-party.ts index 98bbd612a..dd22e12fd 100644 --- a/registry/lib/docs/third-party.ts +++ b/registry/lib/docs/third-party.ts @@ -17,10 +17,10 @@ export const thirdPartyPlugins: DocSourceItem[] = [ ] // FIXME: 在线拉取 metadata 用 getDescriptionMarkdown 生成才能有最完整的信息, 现在这实现只能拿到主 owner, 链接也不能确定 -export const getThirdPartyDescription = (item: DocSourceItem) => { +export const getThirdPartyDescription = async (item: DocSourceItem) => { const ownerText = item.owner ? `by ${item.owner}\n\n` : '' return { ...item, - description: ownerText + getDescriptionMarkdown(item), + description: ownerText + await getDescriptionMarkdown(item), } } diff --git a/src/components/description.ts b/src/components/description.ts index dac2d5ac6..55fcdede2 100644 --- a/src/components/description.ts +++ b/src/components/description.ts @@ -2,6 +2,7 @@ import marked from 'marked' import { languageNameToCode } from '@/core/utils/i18n' import { ComponentMetadata } from './component' import { getSelectedLanguage } from './i18n/helpers' +import { Executable } from '@/core/common-types' type ItemWithDescription = Pick @@ -9,7 +10,7 @@ type ItemWithDescription = Pick * 读取功能的 `description` 和 `author`, 生成描述 (Markdown) * @param item 功能 */ -export const getDescriptionMarkdown = (item: ItemWithDescription) => { +export const getDescriptionMarkdown = async (item: ItemWithDescription) => { const { description, author } = item const authorPrefix = (() => { if (!author) { @@ -20,22 +21,22 @@ export const getDescriptionMarkdown = (item: ItemWithDescription) => { } return `by [@${author.name}](${author.link})\n\n` })() - const descriptionText = (() => { + const descriptionText = await (async () => { if (!description) { - // if (options && Object.keys(options).length > 0) { - // const count = Object.keys(options).length - // return `${count}个选项` - // } return '暂无描述.' - // return '' } - if (typeof description === 'string') { - return description + const parseDescriptionInput = async (input: string | Executable) => { + if (typeof input === 'string') { + return input + } + return input() } - return ( - description[languageNameToCode(getSelectedLanguage())] - || description['zh-CN'] - ) + if (typeof description === 'object') { + const currentLanguage = languageNameToCode(getSelectedLanguage()) + const input = description[currentLanguage] ?? description['zh-CN'] + return parseDescriptionInput(input) + } + return parseDescriptionInput(description) })() return authorPrefix + descriptionText } @@ -44,15 +45,15 @@ export const getDescriptionMarkdown = (item: ItemWithDescription) => { * 同 `getDescriptionMarkdown`, 将最后的 Markdown 转为 HTML string * @param item 功能 */ -export const getDescriptionHTML = (item: ItemWithDescription) => marked( - getDescriptionMarkdown(item), +export const getDescriptionHTML = async (item: ItemWithDescription) => marked( + await getDescriptionMarkdown(item), ) /** * 同 `getDescriptionMarkdown`, 将最后的 Markdown 转为纯文本 (innerText) * @param item 功能 */ -export const getDescriptionText = (item: ItemWithDescription) => { - const html = getDescriptionHTML(item) +export const getDescriptionText = async (item: ItemWithDescription) => { + const html = await getDescriptionHTML(item) const div = document.createElement('div') div.innerHTML = html return div.innerText diff --git a/src/components/types.ts b/src/components/types.ts index 8b7422c75..c14d60658 100644 --- a/src/components/types.ts +++ b/src/components/types.ts @@ -212,6 +212,8 @@ export interface FunctionalMetadata< urlInclude?: TestPattern /** 设置不匹配的URL, 不匹配则不运行此组件, 优先级高于`urlInclude` */ urlExclude?: TestPattern + /** i18n 数据 */ + i18n?: Record> } /** ComponentMetadata 的类型参数,用于表达其可选参数 options 的类型 */ @@ -237,8 +239,6 @@ export interface ComponentMetadata< hidden?: boolean /** 组件子选项 */ options?: Om - /** i18n 数据 */ - i18n?: Record> /** 是否支持热重载 */ // allowHotReload?: boolean } diff --git a/src/core/common-types.ts b/src/core/common-types.ts index 57dfb9c67..4fbfc2bf0 100644 --- a/src/core/common-types.ts +++ b/src/core/common-types.ts @@ -12,7 +12,9 @@ export type VueModule = | { default: Component } | VueConstructor | { default: VueConstructor } -export type I18nDescription = string | { 'zh-CN': string; [key: string]: string } + +type DescriptionInput = string | Executable +export type I18nDescription = DescriptionInput | { 'zh-CN': DescriptionInput; [key: string]: DescriptionInput } export type WithName = { name: string displayName: string