umijs / dumi

📖 Static Site Generator for component library development
https://d.umijs.org
MIT License
3.6k stars 1.18k forks source link

feat: 更改主题的需求 #142

Closed aymonYU closed 4 years ago

aymonYU commented 4 years ago

Description

在文档里面没有体现到如何更改页面主题的相关说明

PeachScript commented 4 years ago

还在规划中,未来会开放主题包,目前只能通过 config.styles 来复写主题样式

PeachScript commented 4 years ago

主题扩展能力设想

从主题开发者的角度出发,如何才能开发一个 dumi 的主题?

问题 1:如何组织主题包的结构?

.
└── theme/
    ├── layout.tsx      # 主题布局组件
    ├── components      # 主题自身的组件,供 layout 组织使用
    |   ├── NavBar.tsx  # 导航头组件
    ├── builtins        # 内置组件,该文件夹下的全部 tsx 都会被自动注册,可直接在 md 中使用
    |   ├── Alert.tsx
    |   ├── Badge.tsx

问题 2:如何在 layout 中获取文档的元信息?

最新草案参考下方 API 设计,统一通过 context 来获取数据 主题有许多混乱的逻辑,比如获取当前页面应该展示的侧边栏是什么、获取当前页面的文档元信息之类,所以理想情况下应该直接给 layout 传递 props 来实现元信息获取的封装,主题开发者只需关心信息组装,类似这样:

// layout.tsx
export default ({ children, navs, menus, meta }) => {
  return (
    <>
      <NavBar data={navs} />
      <SideMenu data={menus} />
      <h1>当前文档的标题:{meta.title}</h1>
      {children}
    </>
  );
}

另外 dumi 应该自行包装一些能力,不被主题开发者感知,比如:

  1. 滚动页面锚点自动跟随
  2. 其他还没想到

问题 3:如何复写 dumi 的内置组件?

比如主题开发者希望能够自定义 Demo 预览器,但又不破坏原有的代码高亮、代码复制、多文件切换等能力。

计划将内置的能力 hooks 化,比如 useCodesandBoxuseCopy,让主题开发者可自行组合。

问题 4:如何应用主题?

包名统一为 dumi-theme-xxx,在 package.json 中将被自动挂载。

手动挂载以及主题传参的方式是个问题,theme 配置项已被当做 less 变量的传递入口,如何手动挂载本地没发包的主题,或者给某个主题传递参数做差异化,需要寻找一个解法。


如果有其他关键点,欢迎大家抛出来讨论、一起共建。

txp1035 commented 4 years ago

主题思路很棒 👍 ,我都想把hexo迁移过来了 😃

PeachScript commented 4 years ago

@ShawDanon 对于 3 和 4 有什么思路么

txp1035 commented 4 years ago

3是指如何服用内置最贱吗?4我觉得可以用插件包方式来引用啊没法包的主题,和umi引用插件一样可以用相对路径加载本地插件一样呢

HeyiMaster commented 4 years ago

@PeachScript

PeachScript commented 4 years ago

3 其实就是指一些内置能力希望也能暴露给主题开发者,避免重复建设,最好能通过暴露 hooks API 来做到,比如 copyHandler = useCopyCode(sourecode) 这种 4 如果没好办法就先自动挂载了,主要是担心后续主题能支持传参控制呈现,目前也没想到具体场景

HeyiMaster commented 4 years ago

@PeachScript 好的,目前已经考虑好实现方案了吗?有没有我这边可以支持的,其他 TODO-list也可以,希望加入一起把 dumi 打造得越来越好。

PeachScript commented 4 years ago

@HeyiMaster 那太好啦,你要是对主题有兴趣就可以专注做这个功能块?目前大致的设想就是分这几步走:

  1. 把内置能力给 hooks 化,我们需要先讨论下要把哪些内置能力抽取出来
  2. 把内置主题变成 dumi-theme-default 的独立包,基于 1 提取的 hooks 重新实现
  3. 提供 dumi-theme-mobile 专门应对移动端组件研发

如果在 dumi 钉钉群的话我们加一下?

PeachScript commented 4 years ago

默认提供且不暴露的内置能力:

  1. 锚点跟随
  2. context 的数据生成,使得内部可以直接 useContext
  3. 部分路由元数据的格式化,例如 updatedTime 根据 locale 格式化为当地时间

可通过 import { context } from 'dumi/theme' 获取的数据:

  1. config: { title, description, repoUrl, logo, navs, menus, locales, algolia },主题配置,不限制 key/value 值,其他主题可任意扩展除内置配置外的配置项
  2. currentMeta: 获取当前路由的全部元数据,比如 md 更新时间、标题列表等
  3. currentLocale: 获取当前多语言的选择状态

可通过 dumi/theme 导入的内置组件 or hooks:

  1. SlugLink: 类似 NavLink,用于锚点高亮跟随
  2. NavbarLink: 封装后的 NavLink 的,可兼容站外链接
  3. useSearch: 同时兼容 algolia 和内置搜索,如果是 algolia 则绑定 ref,如果是内置搜索则返回搜索结果,由主题开发者渲染
  4. useCodesandBox: 传递 Previewer 拿到的 props 进去,返回 open 函数,用于直接唤起在 codesandbox.io 中打开
  5. useCopy: 便于实现拷贝源代码或其他内容
  6. 还可以追加其他的 online editor hooks

需要提供给 dumi 消费的内置组件,如果不存在会 fallback 到默认主题的内置组件:

  1. SourceCode: 用来渲染源代码高亮的组件,代码块和 Demo 源代码区域都会用到
  2. Previewer: 用来渲染 Demo 的组件,dumi 会传递 React Component 和一堆 props 进去
  3. Alert: 渲染警告框
  4. Badge: 渲染标签
  5. Example: 渲染 examples 目录下的组件,一个壳,iframe 嵌套渲染(后续可能还是会改成直接渲染)

另外单测是个比较重要的优化,目前 theme 部分的单测覆盖率为 0 🤦‍♂️