diff --git a/.dumi/theme/builtins/Tree.less b/.dumi/theme/builtins/Tree.less new file mode 100644 index 0000000000..913b876809 --- /dev/null +++ b/.dumi/theme/builtins/Tree.less @@ -0,0 +1,22 @@ +@import (reference) '~dumi-theme-default/src/style/variables.less'; + +.__dumi-site-tree { + padding: 16px; + border: 1px solid @c-border; + border-radius: 2px; + background-color: @c-light-bg; + + small { + padding-left: 24px; + font-size: 14px; + color: @c-secondary; + + &::before { + content: '# '; + } + } + + .ant-tree-switcher { + background: transparent; + } +} diff --git a/.dumi/theme/builtins/Tree.tsx b/.dumi/theme/builtins/Tree.tsx new file mode 100644 index 0000000000..82663ec7c6 --- /dev/null +++ b/.dumi/theme/builtins/Tree.tsx @@ -0,0 +1,58 @@ +import React, { useEffect, useState, ReactNode, ComponentProps } from 'react'; +import { Tree } from 'antd'; +import { TreeProps } from 'antd/es/tree'; +import './Tree.less'; + +function getTreeFromList(nodes: ReactNode, prefix = '') { + const data: TreeProps['treeData'] = []; + + [].concat(nodes).forEach((node, i) => { + const key = `${prefix ? `${prefix}-` : ''}${i}`; + + switch (node.type) { + case 'ul': + const parent = data[data.length - 1]?.children || data; + const ulLeafs = getTreeFromList(node.props.children || [], key); + + parent.push(...ulLeafs); + break; + + case 'li': + const liLeafs = getTreeFromList(node.props.children, key); + + data.push({ + title: [].concat(node.props.children).filter(child => child.type !== 'ul'), + key, + children: liLeafs, + isLeaf: !liLeafs.length, + }); + break; + + default: + } + }); + + return data; +} + +const useListToTree = (nodes: ReactNode) => { + const [tree, setTree] = useState(getTreeFromList(nodes)); + + useEffect(() => { + setTree(getTreeFromList(nodes)); + }, [nodes]); + + return tree; +}; + +export default (props: ComponentProps<'div'>) => { + const data = useListToTree(props.children); + + return ', children: data }]} + defaultExpandAll + />; +}; diff --git a/.gitignore b/.gitignore index dc2c82fb77..b427a70b55 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ dist .umi-production .umi-test .now +/docs/.upstream diff --git a/config/config.js b/config/config.js index 5389dc04b7..ec74f3f27b 100644 --- a/config/config.js +++ b/config/config.js @@ -4,60 +4,6 @@ export default { title: 'dumi', mode: 'site', favicon: 'https://img.alicdn.com/tfs/TB1YHEpwUT1gK0jSZFhXXaAtVXa-28-27.svg', - menus: { - '/zh-CN/guide': [ - { - title: '介绍', - children: ['guide/index', 'guide/getting-started'], - }, - { - title: '写组件 Demo', - children: ['guide/demo-principle', 'guide/demo-types', 'guide/control-demo-render'], - }, - { - title: '控制菜单和路由生成', - children: [ - 'guide/control-route-generate', - 'guide/control-menu-generate', - 'guide/control-nav-generate', - ], - }, - { - title: '更多用法', - children: ['guide/mode', 'guide/multi-language', 'guide/seo'], - }, - { - title: '其他', - children: ['guide/migration', 'guide/faq'], - }, - ], - '/guide': [ - { - title: 'Introducation', - children: ['guide/index', 'guide/getting-started'], - }, - { - title: 'How to write a demo', - children: ['guide/demo-principle', 'guide/demo-types', 'guide/control-demo-render'], - }, - { - title: 'Control and generate', - children: [ - 'guide/control-route-generate', - 'guide/control-menu-generate', - 'guide/control-nav-generate', - ], - }, - { - title: 'More usage', - children: ['guide/mode', 'guide/multi-language', 'guide/seo'], - }, - { - title: 'Others', - children: ['guide/migration', 'guide/faq'], - }, - ], - }, navs: { 'en-US': [ null, diff --git a/docs/demo/Hello/index.tsx b/docs/.demos/Hello/index.tsx similarity index 62% rename from docs/demo/Hello/index.tsx rename to docs/.demos/Hello/index.tsx index 3bdb02e59a..96ccae91bb 100644 --- a/docs/demo/Hello/index.tsx +++ b/docs/.demos/Hello/index.tsx @@ -2,10 +2,15 @@ import React from 'react'; export interface IHelloProps { /** - * extra CSS className for this component + * Extra CSS className for this component * @description.zh-CN 组件额外的 CSS className */ className?: string; + /** + * I'm required + * @description.zh-CN 我是一个必选属性 + */ + type: string; } const Hello: React.FC = () => <>Hello World!; diff --git a/docs/demo/modal-content.jsx b/docs/.demos/modal/content.jsx similarity index 100% rename from docs/demo/modal-content.jsx rename to docs/.demos/modal/content.jsx diff --git a/docs/demo/modal.jsx b/docs/.demos/modal/modal.jsx similarity index 81% rename from docs/demo/modal.jsx rename to docs/.demos/modal/modal.jsx index 46debebbd6..4f047e0c36 100644 --- a/docs/demo/modal.jsx +++ b/docs/.demos/modal/modal.jsx @@ -1,11 +1,13 @@ /** - * title: 基础 Modal - * desc: 这是 antd Modal 组件的基础示例 + * title: Basic Modal + * title.zh-CN: 基础 Modal + * desc: This is a basic example of the antd Modal component + * desc.zh-CN: 这是 antd Modal 组件的基础示例 */ import React from 'react'; import { Button, Modal } from 'antd'; -import ModalContent from './modal-content'; +import ModalContent from './content'; import './modal.less'; class App extends React.Component { diff --git a/docs/demo/modal.less b/docs/.demos/modal/modal.less similarity index 100% rename from docs/demo/modal.less rename to docs/.demos/modal/modal.less diff --git a/docs/assets/locale-menu.gif b/docs/assets/locale-menu.gif deleted file mode 100644 index 32f02bdb3f..0000000000 Binary files a/docs/assets/locale-menu.gif and /dev/null differ diff --git a/docs/config/frontmatter.md b/docs/config/frontmatter.md index 98d524d712..51d1b4c3d6 100644 --- a/docs/config/frontmatter.md +++ b/docs/config/frontmatter.md @@ -1,39 +1,42 @@ --- -title: FrontMatter toc: menu --- # FrontMatter -Like most documentation tools, in order to enable Markdown files to perform configurations capabilities, dumi also provides some FrontMatter configurations; There are some specials that dumi not only supports Markdown files for FrontMatter configuration, but also supports FrontMatter configuration of TSX/JSX imported by external demos. +FrontMatter refers to the part where the text is configured at the **top of the file**. In dumi, FrontMatter is written in YAML syntax; in addition to the Markdown file, dumi also supports the configuration of FrontMatter for demo display in the demo. Let’s look at two Examples: -The FrontMatter for Markdown files is as follows: +Write FrontMatter in Markdown file: -
---
-title: title content
+
---
+title: The title content
 ---
 
-The FrontMatter for TSX/JSX files is as follows: +Write FrontMatter in the demo: -
+
 /**
- * title: title content
+ * title: The title content
  */
 
-## The FrontMatter configurations supported by Markdown +Both the form of code blocks and external demos support FrontMatter. The external demos not only support configuration in the source code, but also add attributes to the `code` tag for configuration, such as: + +```html + +``` + +## Markdown configurations ### title - Type: `String` -- Default: `null` +- Default: The first heading of the body - Details: Configure the page title, which will be used as the subtitle of the page title and the left menu. -If the user does not configure, the website title will only present the main title; The name of the left menu defaults to the file name of the Markdown file (without suffix). - ### sidemenu - Type: `Boolean` @@ -216,7 +219,7 @@ Configure the footer of the current page. It is recommended to configure the hom Whether to present the 『Help Translation』 prompt at the top of the page. -### hide 1.1.0-beta.30+ +### hide 1.1.0+ - Type: `Boolean` - Default: `false` @@ -224,7 +227,7 @@ Whether to present the 『Help Translation』 prompt at the top of the page. You can hide specific documentation that you do not want to display on the webpack in production env, and this option does not affect the development env. -## FrontMatter configurations supported by TSX/JSX +## Demo configurations ### title @@ -282,7 +285,7 @@ It is used to control whether the demo wrapper sets the CSS value of `transform` It is used to control whether the demo wrapper expands the presentation of source code by default. -### debug 1.1.0-beta.30+ +### debug 1.1.0+ - Type: `Boolean` - Default: `false` @@ -320,18 +323,10 @@ Configure via frontmatter: // Both of the above methods can be identified ``` -### iframe 1.1.0-beta.30+ +### iframe 1.1.0+ - Type: `Boolean | Number` - Default: `false` - Details: -Use iframe mode to render this demo, it is very useful for layout demo, we can control the iframe height via pass a number value, check out [iframe mode](/guide/control-demo-render#iframe-mode) to get more informations. - -### Controlled by `code` tag - -All configurations supported by TSX/JSX can also be used when importing external demos using the `code` tag, like this: - -```html - -``` +Use iframe mode to render this demo, it is very useful for layout demo, we can control the iframe height via pass a number value, check out [iframe mode](/guide/basic#iframe-mode) to get more informations. diff --git a/docs/config/frontmatter.zh-CN.md b/docs/config/frontmatter.zh-CN.md index c5b0af8844..92ba541a61 100644 --- a/docs/config/frontmatter.zh-CN.md +++ b/docs/config/frontmatter.zh-CN.md @@ -1,39 +1,42 @@ --- -title: FrontMatter toc: menu --- # FrontMatter -和大多数文档工具一样,为了使 Markdown 文件能发挥出配置能力,dumi 也不能免俗地提供了一些 FrontMatter 的配置;有些特殊的是,dumi 不仅支持 Markdown 文件进行 FrontMatter 配置,也支持外部 Demo 引入的 TSX/JSX 文件的 FrontMatter 配置。 +FrontMatter 是指**文件最顶部**对正文进行配置的部分,在 dumi 中,FrontMatter 均以 YAML 语法进行编写;除了 Markdown 文件,dumi 也支持在 demo 中配置用于 demo 展示的 FrontMatter,来看两个范例: -Markdown 文件的 FrontMatter 编写方法如下: +在 Markdown 文件中编写 FrontMatter: -
---
+
---
 title: 标题内容
 ---
 
-TSX/JSX 文件的 FrontMatter 编写方法如下: +在 demo 中编写 FrontMatter: -
+
 /**
  * title: 标题内容
  */
 
-## Markdown 支持的 FrontMatter 配置项 +无论是代码块的形式还是外部 demo,均支持 FrontMatter,外部 demo 不仅支持在源代码中进行配置,也可以给 `code` 标签添加属性进行配置,比如: + +```html + +``` + +## Markdown 配置项 ### title - 类型:`String` -- 默认值:`null` +- 默认值:正文第一个标题 - 详细: 用于配置该页面的标题,将会被用作该页面标题的子标题以及左侧菜单。 -如果用户不进行配置,网站标题将会仅显示主标题;左侧菜单项名称默认为该 Markdown 文件的文件名(不含后缀)。 - ### sidemenu - 类型:`Boolean` @@ -195,8 +198,8 @@ hero: ```yaml features: - icon: 图标的 URL 地址,建议切图尺寸为 144 * 144(可选) - title: 特性标题 - link: 可以配置跳转链接 + title: 性能强大 + link: 可为标题配置超链接 desc: 可以配置 `markdown` 文本 ``` @@ -216,7 +219,7 @@ features: 是否在该页面顶部展示『帮助翻译』的提示框。 -### hide 1.1.0-beta.30+ +### hide 1.1.0+ - 类型:`Boolean` - 默认值:`false` @@ -224,7 +227,7 @@ features: 如果你暂时不希望在生产环境的站点中展示某些文档,可以打开这个配置临时隐藏它,该配置不会影响开发环境的渲染。 -## TSX/JSX 支持的 FrontMatter 配置项 +## demo 配置项 ### title @@ -282,7 +285,7 @@ features: 用于控制当前 demo 的包裹容器是否默认展开源代码显示。 -### debug 1.1.0-beta.30+ +### debug 1.1.0+ - 类型:`Boolean` - 默认值:`false` @@ -320,18 +323,10 @@ features: // 以上两种方式均可识别 ``` -### iframe 1.1.0-beta.30+ +### iframe 1.1.0+ - 类型:`Boolean | Number` - 默认值:`false` - 详细: -使用 iframe 模式渲染当前 demo,对于渲染 layout 型的 demo 非常有用,当我们传递数值时可以控制 iframe 的高度,访问 [iframe 模式](/zh-CN/guide/control-demo-render#iframe-模式) 了解更多。 - -### 通过 `code` 标签控制 - -所有 TSX/JSX 支持的配置项,在使用 `code` 标签引入外部 demo 时也可以使用,就像这样: - -```html - -``` +使用 iframe 模式渲染当前 demo,对于渲染 layout 型的 demo 非常有用,当我们传递数值时可以控制 iframe 的高度,访问 [iframe 模式](/zh-CN/guide/basic#iframe-模式) 了解更多。 diff --git a/docs/config/index.md b/docs/config/index.md index 6bff3ca257..7c399b3b60 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -1,108 +1,61 @@ --- +title: Config order: 1 +toc: menu nav: - order: 2 title: Config -toc: menu + order: 3 --- - -Tip:dumi is based on Umi, which means not only supports the configurations mentioned on this page, but also supports all configurations of Umi and the plugins of Umi - - # Configuration -Dumi is based on Umi, and the configuration way is the same as the Umi. It can be configured in `.umirc.js` or `config/config.js`. The content is as follows: +Create a `.umirc.ts` or `config/config.ts` file in the project root directory to configure dumi: -```js -// configuration content +```ts +// Configuration content export default { - // configuration items + // Configuration items }; ``` +Currently dumi supports the following configuration items. + ## algolia - Type: `Object` - Default: `null` - Details: -To set Algolia's [DocSearch](https://docsearch.algolia.com/) service. +Configure Algolia's [DocSearch](https://docsearch.algolia.com/) service, usually you will need to enable the automatic generation of sitemap.xml in order to access Algolia smoothly, refer to [Configuration Item - sitemap](#sitemap). -For example: +Example: ```js { algolia: { - apiKey: 'yourapikey', + apiKey: 'Your api key', indexName: 'dumi', } } ``` -## base - -- Type: `string` -- Default: `/` -- Details: - -To set the routing prefix, usually used to deploy to a non-root directory. - ## description - Type: `String` - Default: `null` - Details: -To set the description of the document, which will be presented below the sidebar menu, only works in `doc` mode. - -## dynamicImport - -- Type: `object` -- Default: `false` -- Details: - -Whether to enable load-on-demand, which means whether to split the build productions, and download additional JS and execute it when needed. - -More: [the Configurations of Umi - dynamicImport](https://umijs.org/config#dynamicimport); - -## exportStatic - -- Type: `object` -- Details: - -To set the output format of html, and only output `index.html` by default. - -If you enable `exportStatic`, html files will be output for each route. - -More: [the Configurations of Umi - exportStatic](https://umijs.org/config#exportstatic); - -## favicon - -- Type: `string` -- Details: - -To set the favicon address (href attribute). - -For example, - -```js -export default { - favicon: '/assets/favicon.ico', -}; -``` - -> If you want to use local images, please put them in the `public` directory +The introduction of the configuration document will be displayed under the sidebar menu title, only available in `doc` mode. ## logo - Type: `String` - Default: The LOGO of Umi -- Details: +- Details: To set the LOGO of the document. -> If you want to use a local image, such as `/public/images/xxx.png`, then configure `/images/xx.png` to import it. +> If you are using a local image, such as `/public/images/xxx.png`, then configure `/images/xx.png` to import it. ## locales @@ -110,9 +63,9 @@ To set the LOGO of the document. - Default: `[['en-US', 'English'], ['zh-CN', '中文']]` - Details: -The configuration is a two-dimensional array, and the first item of array will be the default locale of the site. +The configuration is a two-dimensional array, and the first configuration will be the default locale of the site. -Each item of configuration is an array of length 2. The first item value of the array represents the name of the locale, which will be used to splice the routing prefix and detect the locale of the file name. The second value represents the label of the locale, which will be used presented options when switching languages. +Each configuration is an array of length 2. The first value of the array represents the name of the locale, which will be used for splicing routing prefixes and detecting which locale the file name belongs to. The second value represents the label of the locale, which will be used Display options when switching languages. The file name suffix of the default locale is optional. For example, in the default configuration, `index.md` and `index.en-US.md` are equivalent. @@ -122,46 +75,100 @@ The file name suffix of the default locale is optional. For example, in the defa - Default: `doc` - Details: -This configuration is used to set the document presented mode. The default is document mode (left menu + right content). It can be switched to site mode (navigation header + left menu + right content) by configured it as `site`. If you want to modify the text and order of the navigation menu items, you can refer to the `nav` configurations in the frontmatter. +It's used to set the document display mode. The default is document mode. When it is configured as `site`, it can be seamlessly switched to site mode. If you want to display the text and order of the navigation menu items, please refer to the `nav` configuration item in the frontmatter configuration + +The effects of the two modes are as follows, document mode: + +![](https://gw.alipayobjects.com/zos/bmw-prod/86ddc125-75e0-49e0-920b-f9497e806cf1/k7iyfr0t_w2600_h1754.png) + +Site mode: -The effects of the two modes can be seen in [Guide - Modes](/guide/mode)。 +![](https://gw.alipayobjects.com/zos/bmw-prod/7ce6770d-df19-48fa-853e-64cbbf41b762/k7iyfarw_w2600_h1754.png) ## menus - Type: `Object` -- Default: `automatic generated` +- Default: `Auto-generated menu` - Details: -This configuration is used to customize the present of the side menu. It currently only works in the `site` mode, which has multi-language mode and single-language mode. Please refer to [Guide - Configurate side menu](/guide/control-menu-generate#configurate-side-menu). +This configuration item is used to customize the display of the side menu, currently only available in the `site` mode, divided into multi-language mode and single-language mode, usage: + +```ts +// config/config.ts or .umirc.ts +export default { + menus: { + // Need to customize the path of the side menu, the path without configuration will still use the automatically generated configuration + '/guide': [ + { + title: 'Menu item', + path: 'Menu routing (optional)', + children: [ + // Menu item (optional) + 'guide/index.md', // The corresponding Markdown file, the path is recognized relative to the resolve.includes directory + ], + }, + ], + // If the path has other languages, you need to add the language prefix in front, which must be consistent with the path in the locales configuration + '/zh-CN/guide': [ + // Omit, the same as above + ], + }, +}; +``` ## navs - Type: `Object | Array` -- Default: `automatic generated` +- Default: `Auto-generated navigation` - Details: -This configuration is used to customize the present of the navigation bar. It only works in the `site` mode, which has multi-language mode and single-language mode. Please refer to [Guide - Configurate navigation](/guide/control-nav-generate#configurate-navigation). - -The sub-navigation menu can be nested in the following forms, and currently does not support more levels of nesting: +This configuration item is used to customize the display of the navigation bar. It is only available in the `site` mode, divided into multi-language mode and single-language mode. How to use it: -```js +```ts +// config/config.ts or .umirc.ts export default { + // Single language configuration is as follows navs: [ + null, // A null value means to retain the conventionally generated navigation and only do incremental configuration + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, { - title: 'IHaveSubNavigation', - path: 'path is optional', + title: 'I have secondary navigation', + path: 'Link optional', + // The two-level navigation menu can be nested in the following form. Currently, more levels of nesting are not supported: children: [ - { title: 'firstItem', path: 'https://d.umijs.org' }, - { title: 'secondItem', path: '/guide' }, + { title: 'First item', path: 'https://d.umijs.org' }, + { title: 'Second item', path: '/guide' }, ], }, ], + + // Multi-language configuration is as follows + navs: { + // The multi-language key value must be consistent with the key in the locales configuration + 'en-US': [ + null, // A null value means to retain the conventionally generated navigation and only do incremental configuration + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, + ], + 'zh-CN': [ + null, // A null value means to retain the conventionally generated navigation and only do incremental configuration + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, + ], + }, }; ``` ## resolve -`resolve` is an `Object` type with the following configuration: +`resolve` is an `Object` type, used to configure dumi's resolution behavior, including the following configuration: ### includes @@ -169,7 +176,7 @@ export default { - Default: `['docs', 'src']` or `['docs', 'packages/pkg/src']` - Details: -Configure the document directory for dumi sniffing. Dumi will try to recursively find markdown files in the configured directory. The default values are the `docs` directory and the `src` directory (common projects). If it is the lerna project, the `src` directory will change to the `packages/pkg/src` directory and usually does not need to be configured, unless the automatic sniffing get『injuryed』. +Configure the document directory for dumi sniffing. Dumi will try to recursively find markdown files in the configured directory. The default values are the `docs` directory and the `src` directory (common projects). If the environment is the lerna project, the `src` directory will change It is the `packages/pkg/src` directory, and usually does not need to be configured, unless the automatic sniffing appears 『injuryed』. ### previewLangs @@ -177,77 +184,30 @@ Configure the document directory for dumi sniffing. Dumi will try to recursively - Default: `['jsx', 'tsx']` - Details: -Configure the code block that will be converted to ReactComponent by dumi. If you don't want to do any conversion such as a pure site like Umi's official website, you can set this item to an empty array. - -## publicPath - -- Type: `String` -- Default: `/` -- Details: - -Configure the publicPath of webpack. Webpack will add the value of `publicPath` in front of the static file path when packaging. When you need to modify the static file address, like using CDN deployment, set the value of `publicPath` to the value of CDN. - -## routes - -- Type: `Array` -- Default: `null` -- Details: +The configuration dumi will be converted to the code block rendered by the ReactComponent component by default. If you don't want to do any conversion, such as a pure site like Umi's official website, then set this item to an empty array. -Configuration routing, the configuration method is the same as Umi, and can set it in `meta` to pass through to [frontmatter](/config/frontmatter) - -## ssr - -- Type: `object` -- Default: `false` -- Details: - -Configure whether to enable SSR. All routes will be pre-rendered as HTML after setting it to true, which is good for search engine crawler. - -More: [the configurations of Umi - ssr](https://umijs.org/config#ssr); - -## scripts - -- Type: `Array` -- Default: `[]` - -Same as [headScripts](https://umijs.org/config#headscripts), configure additional scripts in ``. - -## sitemap 1.1.0-beta.30+ +## sitemap - Type: `{ hostname: string, excludes?: string[] }` - Default: `null` -Enable auto-generate `sitemap.xml` feature. The `hostname` option for configure hostname of item url in sitemap, the `excludes` options for exclude some route paths in sitemap. +Enable the automatic generation feature of `sitemap.xml`. The `hostname` configuration item is used to specify the domain name prefix of the URL, and the `excludes` configuration item is used to ignore certain routes that do not need to be included in the sitemap. ## title - Type: `String` -- Default: `package.name` +- Default: `{package.name}` - Details: -The name of the configuration document, generally the name of the developed component. +Configure the name of the document on the navigation bar or sidebar. -## theme +## themeConfig - Type: `Object` -- Default: `default theme` +- Default: `{}` - Details: -The theme color variable names refer to https://github.com/umijs/dumi/blob/master/packages/theme-default/src/style/variables.less - -```js - theme: { - '@c-primary': '#ff652f', - } -``` - -## targets - -- Type: `object` -- Default: `{ chrome: 49, firefox: 64, safari: 10, edge: 13, ios: 10 }` - -Configure minimum compatibled version of the browser, and the polyfill and syntax conversion will be automatically imported. - -## Others +It's used to configure the theme package currently used. The specific configuration items depend on which configuration the theme package provides. You can visit [Theme list](/theme) to view the currently available themes. -More: [the configurations of Umi](https://umijs.org/config) + + diff --git a/docs/config/index.zh-CN.md b/docs/config/index.zh-CN.md index 791ae526f8..fdcc4f5ef6 100644 --- a/docs/config/index.zh-CN.md +++ b/docs/config/index.zh-CN.md @@ -1,33 +1,31 @@ --- order: 1 +toc: menu nav: - order: 2 title: 配置项 -toc: menu + order: 3 --- - -提示:dumi 基于 Umi,即除了本页提到的配置项以外,还支持 所有 Umi 的配置项,并且也支持 Umi 生态的插件。 - - # Config -dumi 基于 Umi,配置的方式与 Umi 项目一致,使用 `.umirc.js` 或 `config/config.js` 都可进行配置,内容大致如下: +在项目根目录创建 `.umirc.ts` 或 `config/config.ts` 文件,都可对 dumi 进行配置: -```js -// 配置文件内容 +```ts +// 配置文件 export default { - // 配置项 + // 具体配置项 }; ``` +目前 dumi 支持以下配置项。 + ## algolia - 类型: `Object` - 默认值:`null` - 详细: -配置 Algolia 的 [DocSearch](https://docsearch.algolia.com/) 服务。 +配置 Algolia 的 [DocSearch](https://docsearch.algolia.com/) 服务,通常你会需要启用 sitemap.xml 的自动生成,以便顺利接入 Algolia,参考 [配置项 - sitemap](#sitemap)。 示例: @@ -40,13 +38,6 @@ export default { } ``` -## base - -- Type: `string` -- Default: `/` - -设置路由前缀,通常用于部署到非根目录。 - ## description - 类型:`String` @@ -55,41 +46,6 @@ export default { 配置文档的介绍,会显示在侧边栏菜单标题的下方,仅 `doc` 模式下可用。 -## dynamicImport - -- Type: `object` -- Default: `false` - -是否启用按需加载,即是否把构建产物进行拆分,在需要的时候下载额外的 JS 再执行。 - -详见:[Umi 配置 - dynamicImport](https://umijs.org/zh-CN/config#dynamicimport); - -## exportStatic - -- Type: `object` - -配置 html 的输出形式,默认只输出 `index.html`。 - -如果开启 `exportStatic`,则会针对每个路由输出 html 文件。 - -详见:[Umi 配置 - exportStatic](https://umijs.org/zh-CN/config#exportstatic); - -## favicon - -- Type: `string` - -配置 favicon 地址(href 属性)。 - -比如, - -```js -export default { - favicon: '/assets/favicon.ico', -}; -``` - -> 如果要使用本地的图片,图片请放到 `public` 目录 - ## logo - 类型:`String` @@ -118,9 +74,15 @@ export default { - 默认值:`doc` - 详细: -用于设定文档的展现模式,默认为文档模式(左侧菜单 + 右侧内容),配置为 `site` 时可无缝切换为站点模式(导航头 + 左侧菜单 + 右侧内容)。如果希望对导航菜单项展示的文本和顺序,可参考 frontmatter 配置中的 `nav` 配置项。 +用于设定文档的展现模式,默认为文档模式,配置为 `site` 时可无缝切换为站点模式。如果希望对导航菜单项展示的文本和顺序,可参考 frontmatter 配置中的 `nav` 配置项。 + +两种模式的效果如下,文档模式: -两种模式的效果可见 [指南 - 多种呈现模式](/zh-CN/guide/mode)。 +![](https://gw.alipayobjects.com/zos/bmw-prod/86ddc125-75e0-49e0-920b-f9497e806cf1/k7iyfr0t_w2600_h1754.png) + +站点模式: + +![](https://gw.alipayobjects.com/zos/bmw-prod/7ce6770d-df19-48fa-853e-64cbbf41b762/k7iyfarw_w2600_h1754.png) ## menus @@ -128,7 +90,30 @@ export default { - 默认值:`自动生成的菜单` - 详细: -该配置项用于自定义侧边菜单的展示,目前仅 `site` 模式下可用,分多语言模式和单语言模式,使用方式详见 [指南 - 配置式侧边菜单](/zh-CN/guide/control-menu-generate#配置式侧边菜单)。 +该配置项用于自定义侧边菜单的展示,目前仅 `site` 模式下可用,分多语言模式和单语言模式,使用方式: + +```ts +// config/config.ts 或 .umirc.ts +export default { + menus: { + // 需要自定义侧边菜单的路径,没有配置的路径还是会使用自动生成的配置 + '/guide': [ + { + title: '菜单项', + path: '菜单路由(可选)', + children: [ + // 菜单子项(可选) + 'guide/index.md', // 对应的 Markdown 文件,路径是相对于 resolve.includes 目录识别的 + ], + }, + ], + // 如果该路径有其他语言,需在前面加上语言前缀,需与 locales 配置中的路径一致 + '/zh-CN/guide': [ + // 省略,配置同上 + ], + }, +}; +``` ## navs @@ -136,28 +121,53 @@ export default { - 默认值:`自动生成的导航` - 详细: -该配置项用于自定义导航栏的展示,仅 `site` 模式下可用,分多语言模式和单语言模式,使用方式详见 [指南 - 配置式导航](/zh-CN/guide/control-nav-generate#配置式导航)。 - -可通过如下形式嵌套二级导航菜单,目前暂不支持更多层级嵌套: +该配置项用于自定义导航栏的展示,仅 `site` 模式下可用,分多语言模式和单语言模式,使用方式: -```js +```ts +// config/config.ts 或 .umirc.ts export default { + // 单语言配置方式如下 navs: [ + null, // null 值代表保留约定式生成的导航,只做增量配置 + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, { title: '我有二级导航', path: '链接是可选的', + // 可通过如下形式嵌套二级导航菜单,目前暂不支持更多层级嵌套: children: [ { title: '第一项', path: 'https://d.umijs.org' }, { title: '第二项', path: '/guide' }, ], }, ], + + // 多语言配置方式如下 + navs: { + // 多语言 key 值需与 locales 配置中的 key 一致 + 'en-US': [ + null, // null 值代表保留约定式生成的导航,只做增量配置 + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, + ], + 'zh-CN': [ + null, // null 值代表保留约定式生成的导航,只做增量配置 + { + title: 'GitHub', + path: 'https://github.com/umijs/dumi', + }, + ], + }, }; ``` ## resolve -`resolve` 是一个 `Object` 类型,包含如下配置: +`resolve` 是一个 `Object` 类型,用于配置 dumi 的解析行为,包含如下配置: ### includes @@ -175,38 +185,7 @@ export default { 配置 dumi 默认会转换为 ReactComponent 组件渲染的代码块,如果不希望做任何转换,例如类似 Umi 官网的纯站点,那么将该项设置为空数组即可。 -## publicPath - -- Type: `String` -- Default: `/` - -配置 webpack 的 publicPath。当打包的时候,webpack 会在静态文件路径前面添加 `publicPath` 的值,当你需要修改静态文件地址时,比如使用 CDN 部署,把 `publicPath` 的值设为 CDN 的值就可以。 - -## routes - -- 类型:`Array` -- 默认值:`null` -- 详细: - -配置式路由,配置方式与 Umi 一致,可通过 `meta` 属性传递支持的 [frontmatter](/zh-CN/config/frontmatter) 属性。 - -## ssr - -- Type: `object` -- Default: `false` - -配置是否开启服务端渲染,开启后所有路由会预渲染为 HTML,有利于搜索引擎爬取。 - -详见:[Umi 配置 - ssr](https://umijs.org/zh-CN/config#ssr); - -## scripts - -- Type: `Array` -- Default: `[]` - -同 [headScripts](https://umijs.org/config#headscripts),配置 `` 里的额外脚本。 - -## sitemap 1.1.0-beta.30+ +## sitemap - Type: `{ hostname: string, excludes?: string[] }` - Default: `null` @@ -216,32 +195,18 @@ export default { ## title - 类型:`String` -- 默认值:`package.name` +- 默认值:`{package.name}` - 详细: -配置文档的名称,通常是所开发的组件的名称。 +配置文档的名称,导航栏或侧边栏上。 -## theme +## themeConfig - 类型:`Object` -- 默认值:`默认主题` +- 默认值:`{}` - 详细: -主题颜色变量名称参照 https://github.com/umijs/dumi/blob/master/packages/theme-default/src/style/variables.less - -```js - theme: { - '@c-primary': '#ff652f', - } -``` - -## targets - -- Type: `object` -- Default: `{ chrome: 49, firefox: 64, safari: 10, edge: 13, ios: 10 }` - -配置需要兼容的浏览器最低版本,会自动引入 polyfill 和做语法转换。 - -## 其他配置 +用于配置当前使用的主题包,具体配置项取决于主题包提供哪些配置,可访问 [主题列表](/zh-CN/theme) 查看目前可用的主题。 -详见 Umi 的 [官方文档](https://umijs.org/zh-CN/config)。 + + diff --git a/docs/demo/show-preview.tsx b/docs/demo/show-preview.tsx deleted file mode 100644 index 7a73fa3ac4..0000000000 --- a/docs/demo/show-preview.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/** - * title: 通过code标签引入 - * desc: 设置 hideAction 属性,例:hideActions='["CSB", "EXTERNAL"]' - */ - -import React from 'react'; -import { Button } from 'antd'; - -type MsgType = string; - -function hello(msg: MsgType) { - alert(msg); -} - -export default () => ( - -); diff --git a/docs/demo/typescript.tsx b/docs/demo/typescript.tsx deleted file mode 100644 index aadd70b3ae..0000000000 --- a/docs/demo/typescript.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/** - * title: 源代码类型转换 - * desc: 如果我们的 demo 是采用 TSX 编写的,在展开源代码后,点击一旁的语言切换按钮,可切换显示成 JSX 的代码 - */ - -import React from 'react'; -import { Button } from 'antd'; - -type MsgType = string; - -function hello(msg: MsgType) { - alert(msg); -} - -export default () => ( - -); diff --git a/docs/demo/users.tsx b/docs/demo/users.tsx deleted file mode 100644 index 2901345a0a..0000000000 --- a/docs/demo/users.tsx +++ /dev/null @@ -1,92 +0,0 @@ -/* eslint-disable react/jsx-no-target-blank */ - -import React from 'react'; - -const USERS = [ - { - name: 'UmiJS', - link: 'https://umijs.org', - logo: - 'https://gw.alipayobjects.com/zos/bmw-prod/598d14af-4f1c-497d-b579-5ac42cd4dd1f/k7bjua9c_w132_h130.png', - }, - { - link: 'https://ahooks.js.org/', - logo: 'https://ahooks.js.org/logo.svg', - }, - { - name: 'Pro Layout', - link: 'https://prolayout.ant.design', - logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg', - }, - { - name: 'Pro Table', - link: 'https://protable.ant.design', - logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg', - }, - { - name: 'react-component', - link: 'https://github.com/react-component', - logo: 'https://avatars3.githubusercontent.com/u/9441414?s=200&v=4', - }, - { - name: 'GGEditor', - link: 'https://ggeditor.com', - logo: 'https://img.alicdn.com/tfs/TB1FFA1CFP7gK0jSZFjXXc5aXXa-214-200.png', - }, - { - name: 'Remax', - link: 'https://remaxjs.org', - logo: 'https://gw.alipayobjects.com/mdn/rms_b5fcc5/afts/img/A*1NHAQYduQiQAAAAAAAAAAABkARQnAQ', - }, - { - name: 'LightProxy', - link: 'https://lightproxy.org', - logo: - 'https://user-images.githubusercontent.com/5436704/81533849-83e00f00-9399-11ea-943d-ac5fd4653906.png', - }, - { - name: 'juejin-im', - link: 'https://juejin-im.github.io/open-source/', - logo: 'https://avatars3.githubusercontent.com/u/69633008?s=200&v=4', - }, -]; - -export default () => { - return ( - - ); -}; diff --git a/docs/examples.md b/docs/examples.md deleted file mode 100644 index 3807069831..0000000000 --- a/docs/examples.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Examples -legacy: /example -nav: - order: 3 - title: Examples -toc: menu ---- - -# examples - -This page lists various Markdown styles and demos rendered by dumi. - -## For Demo - -### Embed Code - -```jsx -import React from 'react'; -import { Button } from 'antd'; - -export default () => ; -``` - -### Translate TS to JS - - - -### Multiple dependencies - - - -### Functional Buttons - - - -```jsx -/** - * title: Code Block - * desc: 'setting by comments in code block. For examples: hideActions: ["CSB", "EXTERNAL"]' - * hideActions: ["CSB", "EXTERNAL"] - */ -import React from 'react'; -import { Button } from 'antd'; - -export default () => ; -``` - -# Header One - -## Header Two - -### Header Three - -#### Header Four - -##### Header Five - -###### Header Six - -## Horizon Line - ---- - -## Emphasize - -**Blod Font** - -_Italics Font_ - -~~Delete~~ - -## Blockquotes - -> Blockquotes can nested -> -> > Blockquotes can nested Blockquotes - -## Lists - -unordered List - -- To create an unordered list, preface each item in the list with `+`、`-` or `*` -- list can nest another list, remember to indent sub-list - - here is sub-list - -ordered list - -1. dumi is not based on father -2. dumi is based on Umi -3. the core of dumi is a plugin for Umi - -## Code - -inline `code` - -Code Block: - -``` -// some code here -``` - -Highlight - -```js -console.log('Hello World!'); -``` - -## Mathematica - -Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation. - -$$ -L = \frac{1}{2} \rho v^2 S C_L -$$ - -## Table - -| nouns | explanations | -| ------ | ---------------------------------------------------------------------------- | -| father | Library toolkit based on rollup, docz, storybook, jest, prettier and eslint. | -| Umi | Pluggable enterprise-level react application framework. | - -cell to right aligned - -| nouns | explanations | -| -----: | ---------------------------------------------------------------------------: | -| father | Library toolkit based on rollup, docz, storybook, jest, prettier and eslint. | -| Umi | Pluggable enterprise-level react application framework. | - -## Links - -[visit Umi official site](https://umijs.org) - -automatic transform into Links https://umijs.org diff --git a/docs/examples.zh-CN.md b/docs/examples.zh-CN.md deleted file mode 100644 index 1c50ad69eb..0000000000 --- a/docs/examples.zh-CN.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: 文档示例 -legacy: /example -nav: - order: 3 - title: 渲染示例 -toc: menu ---- - -# 文档示例 - -此页面列举了 dumi 渲染各项 Markdown 样式以及 Demo 的效果。 - -## 渲染 Demo - -### 代码块嵌入 - -```jsx -import React from 'react'; -import { Button } from 'antd'; - -export default () => ; -``` - -### TS 转 JS - - - -### 多文件依赖 - - - -### 控制 Demo 预览器的功能按钮 - - - -```jsx -/** - * title: 代码块 - * desc: '代码块中通过块注释指定,例:hideActions: ["CSB", "EXTERNAL"]' - * hideActions: ["CSB", "EXTERNAL"] - */ -import React from 'react'; -import { Button } from 'antd'; - -export default () => ; -``` - -# 一级标题 - -## 二级标题 - -### 三级标题 - -#### 四级标题 - -##### 五级标题 - -###### 六级标题 - -## 水平线 - ---- - -## 强调样式 - -**字体加粗** - -_斜体样式_ - -~~删除线样式~~ - -## 引用 - -> 引用可以被嵌套 -> -> > 只要引用符号比上一级多就能产生嵌套 - -## 列表 - -无序列表 - -- 使用 `+`、`-` 或 `*` 来创建无序列表 -- 列表可以嵌套,嵌套会产生缩进 - - 我是子列表项 - -有序列表 - -1. dumi 不基于 father -2. dumi 基于 Umi -3. dumi 核心是一个 Umi 插件 - -## 代码 - -行内 `code` - -代码块: - -``` -// some code here -``` - -语法高亮 - -```js -console.log('Hello World!'); -``` - -## 数学公式 - -Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation. - -$$ -L = \frac{1}{2} \rho v^2 S C_L -$$ - -## 表格 - -| 名词 | 解释 | -| ------ | ---------------------------------------------------------------------------- | -| father | Library toolkit based on rollup, docz, storybook, jest, prettier and eslint. | -| Umi | Pluggable enterprise-level react application framework. | - -单元格右对齐 - -| 名词 | 解释 | -| -----: | ---------------------------------------------------------------------------: | -| father | Library toolkit based on rollup, docz, storybook, jest, prettier and eslint. | -| Umi | Pluggable enterprise-level react application framework. | - -## 超链接 - -[前往 Umi 官网](https://umijs.org/zh-CN) - -自动转换超链接 https://umijs.org/zh-CN diff --git a/docs/guide/advanced.md b/docs/guide/advanced.md new file mode 100644 index 0000000000..053d08d1ed --- /dev/null +++ b/docs/guide/advanced.md @@ -0,0 +1,248 @@ +--- +title: Advanced +order: 3 +toc: menu +--- + +## Multi-language + +Making the documentation site multilingual is out of the box for dumi users. + +For example, we wrote `docs/index.md` in English as the homepage of the site. + +Now we want to increase the Chinese version of the site. Just create a Markdown file of the same name with the `zh-CN` locale suffix: + + +
    +
  • + docs +
      +
    • + index.md + Existing English homepage +
    • +
    • + index.zh-CN.md + Newly created Chinese homepage +
    • +
    +
  • +
+
+ +In this way, dumi will render the English homepage when visiting `www.example.com`, while rendering the Chinese homepage when visiting `www.example.com/zh-CN`. + +It's same for other pages, just like the official website of dumi you are browsing now. + +### Default language + +In the default configuration of dumi, `en-US` is the default language, and `zh-CN` is the second language. + +If you need to modify this configuration, like modifying the default language or adding more languages, please check [Configuration Items - locales](/config#locales). + +### Missing translation + +The translation of documents is usually carried out gradually, and there is bound to be a transition period of 『document translation in half』. + +To make this transition period more friendly, **dumi will use the documents in the default language as the untranslated language documents**, for example: + + +
    +
  • + docs +
      +
    • index.md
    • +
    • index.zh-CN.md
    • +
    • missing.md
    • +
    +
  • +
+
+ +Obviously `missing.zh-CN.md` is missing. + +When a user visits `www.example.com/zh-CN/missing`, dumi will present the content of `missing.md` to the user. + +## Umi integrated mode + +In addition to independent component libraries, most of our projects will also have their own internal components. + +It's usually troublesome to manage these internal component libraries. + +There is no need to publish a separate npm package, but also need to be iterated, updated, Description, handover. + +In order to make the management of the project's internal component library easier, dumi launched the Umi project integration mode: + +- **Automatic detection**: When `dependencies` or `devDependencies` contains `umi` and `@umijs/preset-dumi`, it will open the integrated mode automaticly (you no longer need to install the `dumi` package) +- **Isolated**: All dumi documents will be centralized under the `/~docs` route, which is isolated from the original project and does not interfere with each other. It can be understood that the standard dumi documents have a specific routing prefix, including the user's navigation and menu routing configuration +- **No effect on production**: Only works when `NODE_ENV` is `development`, and does not affect the production build of the project +- **Built separately**: If you want to build a document separately for deployment, you can execute `umi build --dumi` to get a dumi site product in non-integrated mode. `--dumi` is also available under the `umi dev` command + +The usage is very simple: + +Install `@umijs/preset-dumi` in the existing Umi project into `devDependencies`, and then configure `resolve.includes` as needed (for example, the `src/components` directory usually conventional defined as business component libraries and the documents corresponding to libraries). + +## UI assets meta data + +How to understand assets meta data? From the developer's perspective, in a narrow sense, any entity that can be produced to help downstream improve efficiency can be called an asset, such as components, documents, component APIs, component demos & etc. + +In the process of component development, we create assets all the time. The released npm package is naturally an asset, but the written TypeScript type definitions and carefully prepared component library demos are also assets. Now only one command is needed to digitize the assets completed by dumi and the developer. This data can Follow the npm package iteration, release, and then transfer to downstream tools. + +We select Umi UI for example, the usage process is shown in the figure below: + +

+ +

+ +### 1. Initialize the dumi component development project + +```bash +$ mkdir dumi-lib && cd dumi-lib +$ npx @umijs/create-dumi-lib +``` + +### 2. Add asset meta information for demo + +Take the demo of the initial project as an example, open `src/Foo/index.md` and add the following frontmatter configuration: + +
+// src/Foo/index.md
+
+```jsx
++ /**
++  * title: Foo demo
++  * thumbnail: [URL address of thumbnail]
++  * previewUrl: [URL address of preview]
++  */
+import React from 'react';
+import { Foo } from 'dumi-lib';
+
+export default () => ;
+```
+
+ +In addition to writing frontmatter in the source code, adding attributes to the `code` tag of the external demo can also add meta-information: + +```html + +``` + +### 3. Enable metadata generation capabilities + +Add an npm script to `package.json` and declare the `dumiAssets` field. Umi UI will find asset metadata files based on this field: + +```diff +{ + "scripts": { ++ "postversion": "dumi assets" + }, ++ "dumiAssets": "assets.json" +} +``` + +Since `assets.json` does not need to participate in version control, please add `assets.json` to `gitignore`. + +### 4. Build and generate asset metadata + +If it's just for testing, you can use `npm version` instead of `npm publish`, and then use link for local play: + +```bash +$ npm run build +$ npm version patch -m "build: bump version to %s" +``` + +### 5. Used in Umi UI + +Initialize the Umi application, install Umi UI and link the component library we just made: + +```bash +$ mkdir umi-app && cd umi-app +$ npx @umijs/create-dumi-app +$ npm i @umijs/preset-ui -D +$ npm link path/to/dumi/lib +``` + +In the `package.json` of the Umi application, manually add the component library as a dependency: + +```diff +{ + "dependencies": { + // Other dependencies ++ "your-lib-package-name": "*" + } +} +``` + +Then start the Umi project as usual, you can see the demo assets in the dumi-lib project in the mini bubble of Umi UI, and can be directly inserted into the page for use: + +

+ +

+ +## Mobile component development + +The usage is very simple. After initializing the dumi project, install `dumi-theme-mobile` into `devDependencies`, and dumi will switch from the default PC component library development to mobile component library development. + +Mobile theme preview effect + +Visit [Theme List - mobile](/theme#dumi-theme-mobile) to learn more about the features and HD solutions of mobile themes. + +## Automatic component API generation + +Now, we can realize the automatic generation of component API through JS Doc annotation + TypeScript type definition! + +### Types and annotations in component source code + +The premise of automatic component API generation is to ensure that dumi can deduce the content of the API through TypeScript type definition + annotations, such as the source code of the `Hello` component: + +```tsx | pure +import React from 'react'; + +export interface IHelloProps { + /** + * You can write the attribute description like this + * @description You can also explicitly add a description name + * @description.zh-CN Also supports different locale suffixes to achieve multi-language description + * @default Support for defining default values + */ + className?: string; // Support for identifying TypeScript optional types as optional attributes +} + +const Hello: React.FC = () => <>Hello World!; + +export default Hello; +``` + +The type analysis tool dumi based is `react-docgen-typescript`. + +For more types and annotation usage, please refer to [documentation](https://github.com/styleguidist/react-docgen-typescript#example). + +### Show the API in the documentation + +With the source code that can derive the API, we can render the API table through the built-in components of `API` in Markdown: + +```md + + + + + + + + + + + +``` + +The effect is roughly as follows: + + + +### Custom API table rendering + +Like other built-in components, the `API` component also supports override through the theme API. + +You only need to create a `.dumi/theme/builtins/API.tsx` (local theme) or create a theme package containing `API.tsx`, combining with the `useApiData` hook exposed by `dumi/theme`, you can control the rendering of the API table yourself. + +Please refer to the [API component implementation](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx) of the dumi default theme. diff --git a/docs/guide/advanced.zh-CN.md b/docs/guide/advanced.zh-CN.md new file mode 100644 index 0000000000..e19f4bb4a3 --- /dev/null +++ b/docs/guide/advanced.zh-CN.md @@ -0,0 +1,222 @@ +--- +title: 进阶使用 +order: 3 +toc: menu +--- + +## 多语言 + +让文档站点变成多语言这件事,对 dumi 用户来说是开箱即用的。比如我们使用英文编写了 `docs/index.md` 作为站点的首页,现在希望增加站点的中文版本,只需要创建一个带 `zh-CN` locale 后缀的同名 Markdown 文件即可: + + +
    +
  • + docs +
      +
    • + index.md + 已有的英文版首页 +
    • +
    • + index.zh-CN.md + 新创建的中文版首页 +
    • +
    +
  • +
+
+ +这样一来,当用户访问 `www.example.com` 时 dumi 会渲染英文版首页,访问 `www.example.com/zh-CN` 时 dumi 会渲染中文版首页,对于其他页面也是一样的,就像你正在浏览的 dumi 的官网一样。 + +### 默认语言 + +在 dumi 的默认配置中,`en-US` 是默认语言,`zh-CN` 是第二种语言,如果你需要修改这个配置,比如修改默认语言、或者添加更多语言,请查看 [配置项 - locales](/zh-CN/config#locales) 配置项。 + +### 翻译缺失 + +文档的翻译工作通常都是渐进式进行的,势必会存在『文档翻译到一半』的过渡期,为了让这个过渡期更加友好,**dumi 会将默认语言的文档作为未翻译语言的兜底文档**,举个例子: + + +
    +
  • + docs +
      +
    • index.md
    • +
    • index.zh-CN.md
    • +
    • missing.md
    • +
    +
  • +
+
+ +很显然 `missing.zh-CN.md` 是缺失的,用户在访问 `www.example.com/zh-CN/missing` 时,dumi 会把 `missing.md` 的内容呈现给用户。 + +## Umi 项目集成模式 + +除了独立的组件库以外,我们大多数的项目还会有自己的内部组件,这些内部的组件库管理通常是一个很头疼的问题,既不需要发布单独的 npm 包,又需要进行迭代、更新、说明、交接;为了让项目内部组件库管理这件事变得更加轻松,dumi 推出了 Umi 项目集成模式: + +- **自动探测**:当 `dependencies` 或 `devDependencies` 中包含 `umi` 和 `@umijs/preset-dumi` 时,进入集成模式(不再需要单独安装 `dumi` 这个包) +- **相互隔离**:所有 dumi 文档都会集中在 `/~docs` 路由下,与原项目相互隔离、互不干扰,可以理解为标准 dumi 文档都加了一个特定路由前缀,也包括用户的导航和菜单路由配置 +- **不影响生产**:仅在 `NODE_ENV` 是 `development` 时集成,不影响项目的生产构建 +- **可单独构建**:如果需要单独构建文档做部署,可执行 `umi build --dumi`,即可得到一份非集成模式的 dumi 站点产物,`--dumi` 在 `umi dev` 命令下也是可用的 + +使用方式很简单:在已有 Umi 项目中安装 `@umijs/preset-dumi` 到 `devDependencies` 中,再根据需要配置 `resolve.includes` 即可(比如约定 `src/components` 目录下为业务组件库和组件库对应的文档)。 + +## UI 资产数据化 + +如何理解资产?从开发者视角狭义的理解,只要是生产出来可以帮助下游提效的实体,都可以称之为资产,比如组件、文档、组件 API、组件 demo 等等。 + +我们在组件研发的过程中,无时无刻不在创建着资产。发布的 npm 包自然是资产,但编写的 TypeScript 类型定义、精心准备的组件库 demo 也都是资产,现在只需一行命令,即可将 dumi 与开发者共同完成的资产数据化,这份数据可以跟随 npm 包迭代、发布,进而流转给下游工具使用。 + +此处拿下游工具——Umi UI 作为例子演示资产数据化的使用流程,如下图所示: + +

+ +

+ +### 1. 初始化 dumi 组件开发项目 + +```bash +$ mkdir dumi-lib && cd dumi-lib +$ npx @umijs/create-dumi-lib +``` + +### 2. 为 demo 添加资产元信息 + +以初始化项目的 demo 为例,打开 `src/Foo/index.md`,添加如下 frontmatter 配置: + +
+// src/Foo/index.md
+
+```jsx
++ /**
++  * title: Foo demo
++  * thumbnail: [缩略图的 URL 地址]
++  * previewUrl: [预览的 URL 地址]
++  */
+import React from 'react';
+import { Foo } from 'dumi-lib';
+
+export default () => ;
+```
+
+ +除了在源代码中编写 frontmatter 以外,给外部 demo 的 `code` 标签添加属性,也能实现元信息的添加: + +```html + +``` + +### 3. 启用元数据生成能力 + +在 `package.json` 中添加一条 npm script,并声明 `dumiAssets` 字段,Umi UI 会根据此字段查找资产元数据文件: + +```diff +{ + "scripts": { ++ "postversion": "dumi assets" + }, ++ "dumiAssets": "assets.json" +} +``` + +由于 `assets.json` 不需要参与版本控制,请在 `gitignore` 中添加 `assets.json`。 + +### 4. 构建并生成资产元数据 + +如果只是用于测试,可以用 `npm version` 来代替 `npm publish`,随后用 link 进行本地玩耍: + +```bash +$ npm run build +$ npm version patch -m "build: bump version to %s" +``` + +### 5. 在 Umi UI 中使用 + +初始化 Umi 应用,安装 Umi UI 并 link 我们刚刚的组件库: + +```bash +$ mkdir umi-app && cd umi-app +$ npx @umijs/create-dumi-app +$ npm i @umijs/preset-ui -D +$ npm link path/to/dumi/lib +``` + +在 Umi 应用的 `package.json` 中,手动添加组件库为依赖: + +```diff +{ + "dependencies": { + // 其他依赖 ++ "your-lib-package-name": "*" + } +} +``` + +然后和往常一样启动 Umi 项目,即可在 Umi UI 的迷你气泡中看到 dumi-lib 项目中的 demo 资产,并可直接插入到页面中使用: + +

+ +

+ +## 移动端组件研发 + +使用方式很简单,初始化 dumi 项目后、安装 `dumi-theme-mobile` 到 `devDependencies` 中即可,dumi 将会从默认的 PC 组件库研发切换为移动端组件研发。 + +移动端主题预览效果 + +访问 [主题列表 - mobile](/zh-CN/theme#dumi-theme-mobile) 了解更多移动端主题的特性及高清方案。 + +## 组件 API 自动生成 + +现在,我们可以通过 JS Doc 注解 + TypeScript 类型定义的方式实现组件 API 的自动生成了! + +### 组件源码中的类型和注解 + +组件 API 自动生成的前提是,确保 dumi 能够通过 TypeScript 类型定义 + 注解推导出 API 的内容,例如 `Hello` 组件的源代码: + +```tsx | pure +import React from 'react'; + +export interface IHelloProps { + /** + * 可以这样写属性描述 + * @description 也可以显式加上描述名 + * @description.zh-CN 还支持不同的 locale 后缀来实现多语言描述 + * @default 支持定义默认值 + */ + className?: string; // 支持识别 TypeScript 可选类型为非必选属性 +} + +const Hello: React.FC = () => <>Hello World!; + +export default Hello; +``` + +dumi 后背的类型解析工具是 `react-docgen-typescript`,更多类型和注解的用法可参考 [它的文档](https://github.com/styleguidist/react-docgen-typescript#example)。 + +### 在文档中展示 API + +有了能够推导 API 的源代码,我们就可以在 Markdown 中通过 `API` 内置组件来渲染 API 表格: + +```md + + + + + + + + + + + +``` + +效果大致如下: + + + +### 自定义 API 表格渲染 + +和其他内置组件一样,`API` 组件也支持通过 theme API 进行复写,只需要创建 `.dumi/theme/builtins/API.tsx`(本地主题)或者创建一个包含 `API.tsx` 的主题包,结合 `dumi/theme` 暴露的 `useApiData` hook,即可自行控制 API 表格的渲染,可参考 dumi 默认主题的 [API 组件实现](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx)。 diff --git a/docs/guide/basic.md b/docs/guide/basic.md new file mode 100644 index 0000000000..2100ecb5c4 --- /dev/null +++ b/docs/guide/basic.md @@ -0,0 +1,495 @@ +--- +title: Basic +order: 2 +toc: menu +--- + +## Directory Structure + +### Common project + +The directory structure of a common component library that based on dumi is roughly as follows: + + +
    +
  • + docs + Component library document directory +
      +
    • + index.md + Documentation Home (If it does not exist, it will fallback to README.md) +
    • +
    • + guide + Component library document other routing (Signal) +
        +
      • index.md
      • +
      • sample.md
      • +
      • help.md
      • +
      +
    • +
    +
  • +
  • + src + Source code directory +
      +
    • + Button + Single component +
        +
      • + index.tsx + Single component +
      • +
      • + index.less + Component style +
      • +
      • + index.md + Component documentation +
      • +
      +
    • +
    • + index.ts + Component library entry file +
    • +
    +
  • +
  • + .umirc.ts + dumi configuration file (Can also be config/config.ts) +
  • +
  • + .fatherrc.ts + father-build configuration file, used for component library packaging +
  • +
+
+ +If it is a pure document site without component source code, just ignore the `src` directory above. + +Note that only the directory structure is explained here. + +If you want to initialize a dumi project, it is recommended to directly use the scaffolding of `@umijs/create-dumi-lib` or `@umijs/create-dumi-app` to create it. + +### lerna project + +In most cases, we will gather the documentation of all lerna sub-packages in the same documentation site. + +The directory structure is usually like this: + + +
    +
  • + docs + Public documents +
      +
    • + index.md + Documentation Home (If it does not exist, it will fallback to README.md) +
    • +
    • + guide + Component library document other routing (Signal) +
        +
      • index.md
      • +
      • sample.md
      • +
      • help.md
      • +
      +
    • +
    +
  • +
  • + packages +
      +
    • + a + Subpackage a +
        +
      • + src + Source directory of subpackage a +
          +
        • + Button + Single component +
            +
          • + index.tsx + Source code +
          • +
          • + index.less + Component style +
          • +
          • + index.md + Component documentation +
          • +
          +
        • +
        • + index.ts + Component library entry file +
        • +
        +
      • +
      +
    • +
    • + b + Subpackage b +
        +
      • + src + Source directory of subpackage b +
          +
        • + Table + Single component +
            +
          • + index.tsx + Source code +
          • +
          • + index.less + Component style +
          • +
          • + index.md + Component documentation +
          • +
          +
        • +
        • + index.ts + Component library entry file +
        • +
        +
      • +
      +
    • +
    +
  • +
  • + .umirc.ts + dumi configuration file (Can also be config/config.ts) +
  • +
  • + .fatherrc.ts + father-build configuration file, used for component library packaging +
  • +
+
+ +By default, dumi will search for the Markdown documents of all sub-packages and generate routes based on the path `packages/[package name]/src`. + +There is currently no scaffolding for the lerna project. You can check [ahooks](https://github.com/alibaba/hooks) project as a reference. + +## Conventional routing + +As shown in the figure below, dumi's conventional routing rules are very simple: + + + +Give a few examples to facilitate understanding: + +| Disk path/mode | doc mode | site mode | +| --- | --- | --- | +| /path/to/src/index.md | - group: none
- page routing: / | - navigate: none
- group: none
- page routing: / | +| /path/to/src/hello.md | - group: none
- page routing: /hello | - navigate: none
- group: none
- page routing: /hello | +| /path/to/src/hello/index.md | - group: /hello
- page routing: /hello | - navigate: /hello
- group:/hello
- page routing: /hello | +| /path/to/src/hello/world.md | - group: /hello
- page routing: /hello/world | - navigate: /hello
- group: /hello
- page routing: /hello/world | +| /path/to/src/hello/world/dumi.md | - group: /hello/world
- page routing: /hello/world/dumi | - navigate: /hello
- group: /hello/world
- page routing: /hello/world/dumi | + +It should be noted that the routes generated by files with the same disk path under multiple base paths will conflict with each other. + +Which means that only one of `docs/index.md` and `src/index.md` will be recognized in the default configuration. + +### Customize navigation, grouping and titles + +If you want to control the generation of navigation/grouping/titles, you can control it by **writing FrontMatter at the top of the Markdown file**: + + +```markdown +--- +title: Custom page name +nav: + path: /Custom navigation route + title: Custom navigation name + order: Control the navigation order, the smaller the number, the higher the order, the default is to sort by path length and dictionary order +group: + path: /Custom group routing, note that group routing = navigation routing + yourself + title: Custom group name + order: Control the grouping order, the smaller the number, the higher the order, the default is to sort by path length and dictionary order +--- + + +``` + +In site mode, we can also incrementally customize the navigation and left menu through configuration items. + +Please refer to [Configuration Item-navs]() and [Configuration Item-menus](). + +## Write component demo + +dumi provides two ways to write demos to deal with different scenarios. + +### Code block + +If our demo is very lightweight, it is recommended to write code blocks directly, such as: + +
+```jsx
+import React from 'react';
+
+export default () => 

Hello dumi!

; +``` +
+ +The code blocks of `jsx` and `tsx` will be parsed as React components by dumi, and the above code blocks will be rendered as: + +```jsx +import React from 'react'; + +export default () =>

Hello dumi!

; +``` + +If we want a block of `jsx`/`tsx` code to be rendered as source code, we can use the `pure` modifier to tell dumi: + +
+```jsx | pure
+// I will not be rendered as a React component
+```
+
+ +### External demo + +If our demo is very complicated and may even have many external files, then it is recommended to use an external demo: + +```markdown + +``` + +Like the code block demo, the above code will also be rendered as a react component. + +And the source code of the external demo and other dependent source codes can be viewed by users, like this: + + + +### Control demo rendering + +dumi provides some FrontMatter properties to meet different demo rendering requirements, just configure it at the top of the source code: + +
+```jsx
+/**
+ * [Configuration item name]: [value]
+ */
+```
+
+ +For the external demo, these FrontMatter attributes can be written in the source code, but also on the attributes of the `code` tag: + +```html + +``` + +dumi currently supports the following demo control capabilities. + +#### Capture the `fixed` element + +Set `transform` to `true` to position the internal `position: fixed;` element relative to the Demo wrapper: + +```jsx +/** + * transform: true + * defaultShowCode: true + */ +/** + * transform: true + */ + +import React from 'react'; + +export default () => ( +

It won't fly out

+); +``` + +#### Modify the background color + +Through the `background` configuration item, you can modify its background color, gradient and even add a background image. + +Dumi will treat it as a CSS property value. For example, configure `background` to `'#f6f7f9'`: + +```jsx +/** + * background: '#f6f7f9' + * defaultShowCode: true + */ +/** + * background: '#f6f7f9' + */ + +import React from 'react'; + +export default () => null; +``` + +#### No padding required + +Configure `compact` to `true`, all padding will be removed: + +```jsx +/** + * compact: true + * defaultShowCode: true + */ +/** + * compact: true + */ + +import React from 'react'; + +export default () => 'It will welt'; +``` + +#### Title and introduction + +Configure the title and introduction of the demo through `title` and `desc`: + +```jsx +/** + * title: I am the title + * desc: I’m a profile, I can use `Markdown` to write + * defaultShowCode: true + */ +/** + * title: I am the title + * desc: I’m a profile, I can use `Markdown` to write + */ + +import React from 'react'; + +export default () => null; +``` + +#### Embed the document directly + +Configure `inline` to `true`, the wrapper will not be displayed, and the demo will be embedded directly in the document: + +
+```jsx
+/**
+ * inline: true
+ */
+
+import React from 'react';
+
+export default () => 'It will be directly embedded';
+```
+
+ +Like this: + +```jsx +/** + * inline: true + */ + +import React from 'react'; + +export default () => 'It will be directly embedded'; +``` + +#### Debug demo + +Set `debug` to true, the demo will only be displayed in the development environment, and there will be a special mark: + +```jsx +/** + * inline: true + */ +import React from 'react'; +import Previewer from 'dumi-theme-default/src/builtins/Previewer'; + +export default () => ( + 'I only show in the development environment';" } }} dependencies={{}} debug defaultShowCode> + I only show in the development environment + +); +``` + +#### iframe mode + +Setting `iframe` to `true` will use `iframe` to render the demo, which can be completely isolated from the document. + +It is usually used for layout components. In this case, [`compact`](/config/frontmatter#compact) The configuration defaults to `true`: + +```jsx +/** + * iframe: 150 + * defaultShowCode: true + */ +/** + * iframe: true // Set to a numeric value to control the height of the iframe + */ +import React from 'react'; + +export default () => ( +

iframe mode

+); +``` + +## Use built-in components + +dumi provides a series of built-in components as a supplement to Markdown syntax. + +In addition to the `code` we have used above, it also supports these: + +### Alert + +Use `Alert` to create an alert box, `type` can be `warning`, `info`, `success`, `error`, and the default is `info`. + +```html + + Note: only HTML can be written internally for now + +``` + + + Note: only HTML can be written internally for now + + +### Badge + +Use `Badge` to create a label: + +```markdown +#### Badge test Hello +``` + +#### Badge test Hello + +### embed + +dumi has extended the HTML default `embed` tag to embed the content of another Markdown document in a Markdown document: + +```html + + + + + + + + +``` + +We can also use the theme API provided by dumi to replicate and add built-in components. Visit [Theme-Theme Development](/theme/development) to learn more. diff --git a/docs/guide/basic.zh-CN.md b/docs/guide/basic.zh-CN.md new file mode 100644 index 0000000000..093e9c9c97 --- /dev/null +++ b/docs/guide/basic.zh-CN.md @@ -0,0 +1,476 @@ +--- +title: 基础使用 +order: 2 +toc: menu +--- + +## 目录结构 + +### 普通项目 + +一个普通的、使用 dumi 做研发的组件库目录结构大致如下: + + +
    +
  • + docs + 组件库文档目录 +
      +
    • + index.md + 组件库文档首页(如果不存在,会 fallback 到 README.md) +
    • +
    • + guide + 组件库文档其他路由(示意) +
        +
      • index.md
      • +
      • sample.md
      • +
      • help.md
      • +
      +
    • +
    +
  • +
  • + src + 组件库源码目录 +
      +
    • + Button + 单个组件 +
        +
      • + index.tsx + 组件源码 +
      • +
      • + index.less + 组件样式 +
      • +
      • + index.md + 组件文档 +
      • +
      +
    • +
    • + index.ts + 组件库入口文件 +
    • +
    +
  • +
  • + .umirc.ts + dumi 配置文件(也可以是 config/config.ts) +
  • +
  • + .fatherrc.ts + father-build 的配置文件,用于组件库打包 +
  • +
+
+ +如果是单纯的文档站点、不包含组件源码,忽略上面的 `src` 目录结构即可。 + +注意,此处仅对目录结构做说明,如果要初始化一个 dumi 项目,建议直接使用 `@umijs/create-dumi-lib` 或 `@umijs/create-dumi-app` 的脚手架进行创建。 + +### lerna 项目 + +大多数情况下,我们会将所有 lerna 子包的文档集中在同一个文档站点中,目录结构通常是这样的: + + +
    +
  • + docs + 仓库公共文档 +
      +
    • + index.md + 组件库文档首页(如果不存在,会 fallback 到 README.md) +
    • +
    • + guide + 组件库文档其他路由(示意) +
        +
      • index.md
      • +
      • sample.md
      • +
      • help.md
      • +
      +
    • +
    +
  • +
  • + packages +
      +
    • + a + 子包 a +
        +
      • + src + 子包 a 的源码目录 +
          +
        • + Button + 单个组件 +
            +
          • + index.tsx + 组件源码 +
          • +
          • + index.less + 组件样式 +
          • +
          • + index.md + 组件文档 +
          • +
          +
        • +
        • + index.ts + 组件库入口文件 +
        • +
        +
      • +
      +
    • +
    • + b + 子包 b +
        +
      • + src + 子包 b 的源码目录 +
          +
        • + Table + 单个组件 +
            +
          • + index.tsx + 组件源码 +
          • +
          • + index.less + 组件样式 +
          • +
          • + index.md + 组件文档 +
          • +
          +
        • +
        • + index.ts + 组件库入口文件 +
        • +
        +
      • +
      +
    • +
    +
  • +
  • + .umirc.ts + dumi 配置文件(也可以是 config/config.ts) +
  • +
  • + .fatherrc.ts + father-build 的配置文件,用于组件库打包 +
  • +
+
+ +dumi 默认会以 `packages/[包名]/src` 为基础路径搜寻所有子包的 Markdown 文档并生成路由,目前没有 lerna 项目的脚手架,可以查看 [ahooks](https://github.com/alibaba/hooks) 项目作为参考。 + +## 约定式路由 + +如下图所示,dumi 的约定式路由规则非常简单: + + + +举几个例子方便理解: + +| 磁盘路径/模式 | doc 模式 | site 模式 | +| --- | --- | --- | +| /path/to/src/index.md | - 分组:无
- 页面路由:/ | - 导航:无
- 分组:无
- 页面路由:/ | +| /path/to/src/hello.md | - 分组:无
- 页面路由:/hello | - 导航:无
- 分组:无
- 页面路由:/hello | +| /path/to/src/hello/index.md | - 分组:/hello
- 页面路由:/hello | - 导航:/hello
- 分组:/hello
- 页面路由:/hello | +| /path/to/src/hello/world.md | - 分组:/hello
- 页面路由:/hello/world | - 导航:/hello
- 分组:/hello
- 页面路由:/hello/world | +| /path/to/src/hello/world/dumi.md | - 分组:/hello/world
- 页面路由:/hello/world/dumi | - 导航:/hello
- 分组:/hello/world
- 页面路由:/hello/world/dumi | + +需要注意的是,**多个基础路径下相同磁盘路径的文件生成的路由会相互冲突**,这意味着在默认配置下 `docs/index.md` 和 `src/index.md` 只有其中 1 个会被识别。 + +### 自定义导航、分组和标题 + +如果希望控制导航/分组/页面标题的生成,可以通过**在 Markdown 文件顶部**编写 FrontMatter 实现: + +```markdown +--- +title: 自定义页面名称 +nav: + path: /自定义导航路由 + title: 自定义导航名称 + order: 控制导航顺序,数字越小越靠前,默认以路径长度和字典序排序 +group: + path: /自定义分组路由,注意,分组路由 = 导航路由 + 自己 + title: 自定义分组名称 + order: 控制分组顺序,数字越小越靠前,默认以路径长度和字典序排序 +--- + + +``` + +在 site 模式下,我们也可以通过配置项对导航和左侧菜单进行增量自定义,请参考 [配置项 - navs]() 以及 [配置项 - menus]()。 + +## 写组件 demo + +dumi 提供了两种编写 demo 的方式,分别应对不同的场景。 + +### 代码块 + +如果我们的 demo 非常轻量,建议直接编写代码块,比如: + +
+```jsx
+import React from 'react';
+
+export default () => 

Hello dumi!

; +``` +
+ +`jsx` 和 `tsx` 的代码块将会被 dumi 解析为 React 组件,以上代码块将会被渲染成: + +```jsx +import React from 'react'; + +export default () =>

Hello dumi!

; +``` + +如果我们希望某段 `jsx`/`tsx` 代码块被渲染为源代码,可以使用 `pure` 修饰符告诉 dumi: + +
+```jsx | pure
+// 我不会被渲染为 React 组件
+```
+
+ +### 外部 demo + +如果我们的 demo 非常复杂,甚至可能有很多外部文件,那么建议使用外部 demo: + +```markdown + +``` + +和代码块 demo 一样,上述代码也会被渲染为 React 组件,并且外部 demo 的源代码及其他依赖的源代码都可以被用户查看,就像这样: + + + +### 控制 demo 渲染 + +dumi 提供了一些 FrontMatter 属性,以满足不同的 demo 渲染需求,在**源代码顶部**配置即可: + +
+```jsx
+/**
+ * [配置项名称]: [值]
+ */
+```
+
+ +对于外部 demo,这些 FrontMatter 属性除了写在源代码里,也可以写在 `code` 标签的属性上: + +```html + +``` + +dumi 目前支持如下 demo 控制能力。 + +#### 捕获 `fixed` 元素 + +设置 `transform` 为 `true`,可使得内部 `position: fixed;` 元素相对于 Demo 包裹器定位: + +```jsx +/** + * transform: true + * defaultShowCode: true + */ +/** + * transform: true + */ + +import React from 'react'; + +export default () => ( +

我不会飞出去

+); +``` + +#### 修改背景色 + +通过 `background` 配置项,可以修改它的背景颜色、渐变甚至加上背景图片,dumi 会将其当做 CSS 属性值处理,比如配置 `background` 为 `'#f6f7f9'`: + +```jsx +/** + * background: '#f6f7f9' + * defaultShowCode: true + */ +/** + * background: '#f6f7f9' + */ + +import React from 'react'; + +export default () => null; +``` + +#### 不需要内边距 + +配置 `compact` 为 `true`,则会移除所有内边距: + +```jsx +/** + * compact: true + * defaultShowCode: true + */ +/** + * compact: true + */ + +import React from 'react'; + +export default () => '我会贴边站'; +``` + +#### 标题与简介 + +通过 `title` 和 `desc` 配置 demo 的标题和简介: + +```jsx +/** + * title: 我是标题 + * desc: 我是简介,我可以用 `Markdown` 来编写 + * defaultShowCode: true + */ +/** + * title: 我是标题 + * desc: 我是简介,我可以用 `Markdown` 来编写 + */ + +import React from 'react'; + +export default () => null; +``` + +#### 直接嵌入文档 + +配置 `inline` 为 `true` 则不会展示包裹器、直接在文档里嵌入 demo: + +
+```jsx
+/**
+ * inline: true
+ */
+
+import React from 'react';
+
+export default () => '我会被直接嵌入';
+```
+
+ +就像这样: + +```jsx +/** + * inline: true + */ + +import React from 'react'; + +export default () => '我会被直接嵌入'; +``` + +#### 调试型 demo + +设置 `debug` 为true,则该 demo 仅在开发环境下展示、且会有一个特殊标记: + +```jsx +/** + * inline: true + */ +import React from 'react'; +import Previewer from 'dumi-theme-default/src/builtins/Previewer'; + +export default () => ( + '我仅在开发环境下展示';" } }} dependencies={{}} debug defaultShowCode> + 我仅在开发环境下展示 + +); +``` + +#### iframe 模式 + +设置 `iframe` 为 `true`,将会使用 `iframe` 渲染 demo,可实现和文档的完全隔离,通常用于布局型组件,此时 [`compact`](/zh-CN/config/frontmatter#compact) 配置默认为 `true`: + +```jsx +/** + * iframe: 150 + * defaultShowCode: true + */ +/** + * iframe: true // 设置为数值可控制 iframe 高度 + */ +import React from 'react'; + +export default () => ( +

iframe 模式

+); +``` + +## 使用内置组件 + +dumi 提供了一系列内置组件作为 Markdown 语法的补充,除了上面我们已经用到过的 `code` 以外,还支持这些: + +### Alert + +使用 `Alert` 创建一个提示框,`type` 可选 `warning`、`info`、`success`、`error`,默认为 `info`。 + +```html + + 注意,内部暂时只能编写 HTML + +``` + + + 注意,内部暂时只能编写 HTML + + +### Badge + +使用 `Badge` 可以创建一个标签: + +```markdown +#### 标签测试 Hello +``` + +#### 标签测试 Hello + +### embed + +dumi 对 HTML 默认的 `embed` 标签做了扩展,可以在一个 Markdown 文档中嵌入另一个 Markdown 文档的内容: + +```html + + + + + + + + +``` + +我们也可以通过 dumi 提供的主题 API 实现内置组件的复写和新增,可访问 [主题 - 主题开发](/zh-CN/theme/development) 了解更多。 diff --git a/docs/guide/control-demo-render.md b/docs/guide/control-demo-render.md deleted file mode 100644 index 27819a58e1..0000000000 --- a/docs/guide/control-demo-render.md +++ /dev/null @@ -1,177 +0,0 @@ -# Render of demos - -The render of demo is controlled by dumi's built-in `Previewer`. This component exports some `props`, so that we can configurate through FrontMatter, for example: - -
-```jsx
-/**
- * title: title
- */
-
-// content
-```
-
- -Dumi will remove FrontMatter from the source code and will not present it to users. If it is an external imported demo, we can not only configurate FrontMatter in the external demo file as above, but also can directly transfer `props` to the `code` tag: - -```html - -``` - -At present, the built-in `Previewer` component provides control configurations for the following scenarios. - -## `fixed` Element - -If our demo contains elements which have the `position: fixed` property, it must 『overflow』 of the demo wrapper when rendering. However, in some scenarios, we still want it to be positioned relative to the demo wrapper. Therefore, the `Previewer` provides a configuration item of `transform`. Once set it to true, the `transform` property will be set in the demo wrapper to change the CSS containing block of the `position: fixed` element to demo wrapper, like this: - -
-```jsx
-/**
- * transform: true
- */
-
-// content
-```
-
- -## Background - -The background color of the demo wrapper is white by default, but there are some demos need a dark background.You can change its background color, background gradient, or even add a background image by changing the configuration item of `background`. The `previewer` will consider it as a CSS property: - -
-```jsx
-/**
- * background: '#f6f7f9'
- */
-
-import React from 'react';
-
-export default () => null;
-```
-
- -like this: - -```jsx -/** - * background: '#f6f7f9' - */ - -import React from 'react'; - -export default () => null; -``` - -## No Padding - -In order to present the art of blank, the demo wrapper has `padding` by default to ensure that the demo will not be presented on the edge; however, for some demos, we want it to be presented on the edge, such as navigation, sidebar, etc. Dumi provides a configuration item of `compact` to control the paddings. Once set it to `true`, all paddings will be removed - -
-```jsx
-/**
- * compact: true
- */
-
-import React from 'react';
-
-export default () => 'I\'ll on the edge';
-```
-
- -like this: - -```jsx -/** - * compact: true - */ - -import React from 'react'; - -export default () => "I'll on the edge"; -``` - -## Title & Desc - -If we want to add some informations, such as title and description, to the demo, we can configure it by `title` and `desc`: - -
-```jsx
-/**
- * title: Here is title
- * desc: Here is description, could coded in `Markdown`
- */
-
-import React from 'react';
-
-export default () => null;
-```
-
- -Like this: - -```jsx -/** - * title: Here is title - * desc: Here is description, could coded in `Markdown` - */ - -import React from 'react'; - -export default () => null; -``` - -## Embeded in documents - -Render demo in embedded mode, please refer to [The Types of demos - embedded mode](/guide/demo-types#embedded-mode)。 - -## debug demo 1.1.0-beta.30+ - -If we just want to render some demos in development mode for debug, we can use the `debug` option, details: [FrontMatter - debug](/config/frontmatter#debug) - -## iframe mode 1.1.0-beta.30+ - -If we want to render demo in an iframe element, we can use `iframe` option to implement absolute isolation between demo and docs, it is usually used for layout component, now [`compact`](/config/frontmatter#compact) option will be `true` by default: - -
-```jsx
-/**
- * iframe: true
- * iframe: 300 // control iframe height via number value
- */
-import React from 'react';
-
-export default () => (
-  

- iframe mode -

-); -``` -
- -Like this: - -```jsx -/** - * iframe: 150 - */ -import React from 'react'; - -export default () => ( -

iframe mode

-); -``` - -## Render as a code block - -Sometime we hope to write a `JSX` source code, but dumi will try to render it as React component, at this time, we can tell dumi to render it as a code block via `pure` modifier: - -
-```jsx | pure
-// I will not be rendered
-```
-
diff --git a/docs/guide/control-demo-render.zh-CN.md b/docs/guide/control-demo-render.zh-CN.md deleted file mode 100644 index ace366b5e3..0000000000 --- a/docs/guide/control-demo-render.zh-CN.md +++ /dev/null @@ -1,177 +0,0 @@ -# 控制 Demo 渲染 - -Demo 的渲染是由 dumi 内置的 `Previewer` 控制的,该组件暴露了一些 `props`,我们可以通过 FrontMatter 来进行设置,例如: - -
-```jsx
-/**
- * title: 标题内容
- */
-
-// 组件内容
-```
-
- -dumi 会对源代码中的 FrontMatter 进行剔除,不会展示给用户。如果是引入的外部 Demo,我们除了可以直接在外部 Demo 的文件中像上面一样配置 FrontMatter 之外,还可以直接向 `code` 标签传递 `props`: - -```html - -``` - -目前,内置的 `Previewer` 组件为如下场景提供了控制配置项。 - -## `fixed` 定位元素 - -倘若我们的 Demo 包含 `position: fixed;` 的元素,那么它在渲染的时候必然会『飞出』Demo 包裹器;可有些场景下,我们仍然是希望它相对于 Demo 包裹器定位的,所以 `Previewer` 提供了 `transform` 的配置项,一旦设置为 true,则会为 Demo 包裹器加上 `transform` 用于更改 `position: fixed` 元素的 CSS 包含块 为 Demo 包裹器,就像这样: - -
-```jsx
-/**
- * transform: true
- */
-
-// 组件内容
-```
-
- -## 修改背景色 - -默认情况下 Demo 包裹器的背景色为白色,但有些 Demo 需要有深色的背景,通过 `background` 配置项,可以修改它的背景颜色、渐变甚至加上背景图片,`Previewer` 会将其当做 CSS 属性值处理: - -
-```jsx
-/**
- * background: '#f6f7f9'
- */
-
-import React from 'react';
-
-export default () => null;
-```
-
- -效果如下: - -```jsx -/** - * background: '#f6f7f9' - */ - -import React from 'react'; - -export default () => null; -``` - -## 不需要内边距 - -为了体现留白的艺术,Demo 包裹器默认有 `padding`,以确保 Demo 不会贴边展示;但有些 Demo 我们却是希望它贴边展示的,比如导航头、侧边栏等等。dumi 提供了 `compact` 配置项来控制内边距,一旦设置为 `true`,则会移除所有内边距: - -
-```jsx
-/**
- * compact: true
- */
-
-import React from 'react';
-
-export default () => '我会贴边站';
-```
-
- -效果如下: - -```jsx -/** - * compact: true - */ - -import React from 'react'; - -export default () => '我会贴边站'; -``` - -## 标题与简介 - -如果我们希望为当前 Demo 加上描述信息,例如标题与简介,可以通过 `title` 和 `desc` 进行配置: - -
-```jsx
-/**
- * title: 我是标题
- * desc: 我是简介,我可以用 `Markdown` 来编写
- */
-
-import React from 'react';
-
-export default () => null;
-```
-
- -效果如下: - -```jsx -/** - * title: 我是标题 - * desc: 我是简介,我可以用 `Markdown` 来编写 - */ - -import React from 'react'; - -export default () => null; -``` - -## 直接嵌入文档 - -将 Demo 以嵌入形式呈现,请参考 [Demo 的类型 - 嵌入式](/zh-CN/guide/demo-types#嵌入式)。 - -## 调试型 demo 1.1.0-beta.30+ - -如果某些 demo 我们只希望在开发模式下展示,可使用 `debug` 参数标记,详见 [FrontMatter 配置项 - debug](/zh-CN/config/frontmatter#debug) - -## iframe 模式 1.1.0-beta.30+ - -如果我们希望以 iframe 嵌套的形式来渲染当前 demo,可以通过 `iframe` 进行配置,可实现 demo 和 文档的完全隔离,通常用于布局型组件,此时 [`compact`](/zh-CN/config/frontmatter#compact) 配置默认为 `true`: - -
-```jsx
-/**
- * iframe: true
- * iframe: 300 // 设置为数值可控制 iframe 高度
- */
-import React from 'react';
-
-export default () => (
-  

- iframe 模式 -

-); -``` -
- -效果如下: - -```jsx -/** - * iframe: 150 - */ -import React from 'react'; - -export default () => ( -

iframe 模式

-); -``` - -## 渲染为代码块 - -有时候我们就是希望展示一段 `JSX` 源代码,但 dumi 又默认会将其当做 React 组件进行渲染;这时候我们可以通过 `pure` 修饰符告诉 dumi 这是一段不需要渲染的源代码: - -
-```jsx | pure
-// 我不会被渲染
-```
-
diff --git a/docs/guide/control-menu-generate.md b/docs/guide/control-menu-generate.md deleted file mode 100644 index f59b2793f7..0000000000 --- a/docs/guide/control-menu-generate.md +++ /dev/null @@ -1,74 +0,0 @@ -# Control menu generate - -## Convention menu rules - -Dumi's document menu is based on the routing structure. The nested relationship of routes will be resolved into menu groups by dumi. First, let's see how dumi identifies the routing structure - -```bash -/ # ungrouped -/guide # go into guide group -/guide/help # go into guide group -/other # go into other group -/very/very/deep/child # Attention, it will go into /very/very/deep group -``` - -Then the recognition result will be presented as follows: - -- root -- guide - - guide - - help -- other -- very/very/deep - - child - -It's basically the same as expected, but there is a problem here: it is very strange to present `very/very/deep` as a group when there is only one subitem. In order to satisfy the the requirements of special scenarios (it does necessary to group single subitems indeed) and normal scenarios (omitting grouping), dumi has a setting: - -**When the group title is consistent with the subroute title and there is only one subroute**, the item will not be presented as a group, just like the `other` group. But how do you configure group title? Please keep looking down. - -### Group title - -The default rule of generating group title is to take the route name of the group, and remove `/` and capitalize it. For example, if the route is `/guide/help`, dumi will remove the last segment of route which is `/help`, take `/guide` as a group title, and remove `/` and capitalize it to `Guide`. - -If you want to control the group title in manual way, you can configurate it through [the frontmatter configrations of `group.title`](/config/frontmatter#grouptitle) - -### Group path - -The default rule of generating the group path is to remove the last segment of the route, and the previous segment will be used as the group path no matter how long it is. For example, if the route is `/very/very/deep/child`, then `very/very/deep` will be used as the group path. - -If you want to control the group path in manual way, you can configurate it through [the frontmatter configrations of `group.path`](/config/frontmatter#grouppath) - -### Group order - -The default rule of group order is: firstly, compare the length of `path`, for example `/guide` must be in front of `/guide/help`, and then compare the ASCII of group name. For example, `Guide` must be in front of `Help`. - -If you want to control the group order in manual way, you can configurate it through [the frontmatter configrations of `group.order`](/config/frontmatter#grouporder). The smaller the number, the more previous the rank will be. - -## Configurate side menu - -Attention:only works in site mode for now - -If found that the convention cannot satisfy the requirements, you can **increment customize** the side menu through [`menus`](/config#menus) - -```ts -// config/config.ts or .umirc.ts -export default { - menus: { - // You need to customize the path of the side menu. Non-configurated path will still use the configuration generated automatically - '/guide': [ - { - title: 'menu title', - path: 'menu path(optional)', - children: [ - // submenu item(optional) - 'guide/index.md', // corresponding markdown file, the path is recognized relative to resolve.includes - ], - }, - ], - // If there are other languages, the language prefix should be added before the path, which should be consistent with the path in the locales configuration - '/zh-CN/guide': [ - // same as above - ], - }, -}; -``` diff --git a/docs/guide/control-menu-generate.zh-CN.md b/docs/guide/control-menu-generate.zh-CN.md deleted file mode 100644 index 2152aac45e..0000000000 --- a/docs/guide/control-menu-generate.zh-CN.md +++ /dev/null @@ -1,74 +0,0 @@ -# 控制菜单生成 - -## 约定式菜单规则 - -dumi 的文档菜单是建立在路由结构上的。路由的嵌套关系会被 dumi 解析为菜单分组,先看看 dumi 会怎么识别路由结构: - -```bash -/ # 未分组 -/guide # 指南分组 -/guide/help # 指南分组 -/other # 其他分组 -/very/very/deep/child # 注意,/very/very/deep 会被整个识别为分组 -``` - -然后这个识别结果会被展示为: - -- 根路径 -- guide - - guide - - help -- other -- very/very/deep - - child - -和预期基本一致,但这里有个问题:`very/very/deep` 下面只有一个子项的时候还展示为分组非常奇怪,为了满足特殊场景(真的需要对单独子项做分组)和常规场景(省略分组),dumi 有个设定: - -**当分组名与子路由标题一致且只有一个子路由时**,该项就不会展示为分组了,就像 `other` 分组一样。但如何配置分组名呢?请接着往下看。 - -### 控制分组名称 - -分组名称的默认生成规则是,取分组的路由名称去掉 `/` 并首字母大写。比如,路由是 `/guide/help`,dumi 将会去掉末端路由 `/help` 将 `/guide` 当做分组,并且去掉 `/` 再首字母大写变成 `Guide`。 - -如果希望手动控制分组名称,可以使用 [名为 `group.title` 的 frontmatter 配置项](/zh-CN/config/frontmatter#grouptitle) 进行配置。 - -### 控制分组路径 - -分组路径的默认生成规则是,将路由的最后一段去掉,前面无论多长都会作为分组路径。比如,路由是 `/very/very/deep/child`,那么 `very/very/deep` 则会作为分组路径。 - -如果希望手动控制分组路径,可以使用 [名为 `group.path` 的 frontmatter 配置项](/zh-CN/config/frontmatter#grouppath) 进行配置。 - -### 控制分组排序 - -分组的默认排序规则为,先对比 `path` 的长度,例如 `/guide` 肯定排在 `/guide/help` 前面,其次对比分组名称的 ASCII 码,比如 `Guide` 肯定排在 `Help` 前面。 - -如果希望手动控制分组顺序,可以使用 [名为 `group.order` 的 frontmatter 配置项](/zh-CN/config/frontmatter#grouporder) 进行配置,数字越小越靠前。 - -## 配置式侧边菜单 - -注意:目前仅 site 模式下可用。 - -如果发现约定式无法满足需要,可通过 [`menus` 配置项](/zh-CN/config#menus) 对侧边菜单进行**增量自定义**: - -```ts -// config/config.ts 或 .umirc.ts -export default { - menus: { - // 需要自定义侧边菜单的路径,没有配置的路径还是会使用自动生成的配置 - '/guide': [ - { - title: '菜单项', - path: '菜单路由(可选)', - children: [ - // 菜单子项(可选) - 'guide/index.md', // 对应的 Markdown 文件,路径是相对于 resolve.includes 目录识别的 - ], - }, - ], - // 如果该路径有其他语言,需在前面加上语言前缀,需与 locales 配置中的路径一致 - '/zh-CN/guide': [ - // 省略,配置同上 - ], - }, -}; -``` diff --git a/docs/guide/control-nav-generate.md b/docs/guide/control-nav-generate.md deleted file mode 100644 index 7f1c6f3569..0000000000 --- a/docs/guide/control-nav-generate.md +++ /dev/null @@ -1,111 +0,0 @@ -# Control navigation generate - - -Attention:only works in site mode for now - - -## The rules of convention navigation - -Like menu items and menu groups, dumi navigation is based on the routing structure. The nested relationship of routes will be resolved by dumi into navigation and menu groups in navigation. Then, let's see how dumi identifies the routing structure: - -```bash -/ # index page -/guide # Guide page + index page of Guide page -/guide/help # Guide page + Help page of Guide page -/other # Other page -/very/very/deep/child # Very page + Very/deep group of Very page -``` - -Then the recognition result will be presented like: - -```bash -# Navigation -LOGO Guide | Other | Very ------------------------------ - -# Side menu of Guide page ------ -Guide ------ -Help ------ - -# Side menu of Other page ------ -Other ------ - -# Side menu of Very page ------ -Very/deep ------ - Child ------ -``` - -In a conclusion: **the first level nesting of the folder will be used as the navigation, from the second level to the last but one will be used as the side menu, and the last level will be used as the page; All the menus and pages under the first level will be grouped in the navigation**. - -However, it's often not enough to rely on automatic rules. We usually have requirements about customizing navigation header text and order: - -### Navigation title - -The default rule of generating navigation title is to take the route name of current navigation, remove `/` and capitalize it. For example, if the route is `/guide`, dumi will take `guide` and capitalize it to `Guide`. - -If you want to control the navigation title in manual way, you can configure it through [`nav.title`](/config/frontmatter#navtitle). **Attention, you only need to configure it in any markdown file in the same folder, it will take effect all** - -### Navigation path - -The default rule of generating navigation path is to take the first level nesting of routes. For example, if the route is `/very/very/deep/child`, then `very` will be used as the navigation path. - -If you want to control the navigation path in manual way, you can configure it through [`nav.path`](/config/frontmatter#navpath). - -It's different from `nav.title`, `nav.path` is a unique identifier. Because of it, manual control needs each markdown file to be set even these files in the same folder. Therefore, it is generally recommended to organize navigation by folder instead of manual control. - -### Navigation order - -The default rule of navigation order is: firstly, compare the length of `path`, for example `/guide` must be in front of `/guide/help`, and then compare the ASCII of navigation name, for example, `Guide` must be in front of `Help`. - -If you want to control the navigation order in manual way, you can configure it through [`nav.order`](/config/frontmatter#navorder). The smaller the number, the more previous the rank will be. As same as `nav.title`, you only need to configure it in any markdown file in the same folder, it will take effect all. - -### Menu generation - -Please refer to [Control menu generate](/guide/control-menu-generate), **it should be noticed that in the `site` mode, since navigation is the first level of nesting, the automatic parsing of menus starts from the second level of nesting**. - -## Configurate navigation - -In most scenarios, we need to customize the content presented on the navigation, such as adding repo links to GitHub or links to old versions of documents or etc. We can configure it through [`navs`](/config#navs): - -```ts -// config/config.ts or .umirc.ts -export default { - // The configuration of single language is as follows - navs: [ - null, // The null means dumi should reserve the convention navigation and only make an incremental configuration - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - - // The configuration of multiple languages is as follows - navs: { - //The multi-languages key should be consistent with the key in the locales configuration - 'en-US': [ - null, // The null means dumi should reserve the convention navigation and only make an incremental configuration - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - 'zh-CN': [ - null, // The null means dumi should reserve the convention navigation and only make an incremental configuration - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - }, -}; -``` - -However, this configuration is only used for the presentation of custom navigation header, and **does not affect the generation of routes**. If you want to customize the routing path, please configurate it in Markdown throught frontmatter configuration refered [above](#navigation-path). diff --git a/docs/guide/control-nav-generate.zh-CN.md b/docs/guide/control-nav-generate.zh-CN.md deleted file mode 100644 index 1091a59985..0000000000 --- a/docs/guide/control-nav-generate.zh-CN.md +++ /dev/null @@ -1,111 +0,0 @@ -# 控制导航生成 - - -注意:导航仅在 site 模式下可用。 - - -## 约定式导航规则 - -和菜单项及菜单分组一样,dumi 的导航也是建立在路由结构上生成的。路由的嵌套关系会被 dumi 解析为导航及导航下的菜单分组,还是看看 dumi 会怎么识别路由结构: - -```bash -/ # 首页 -/guide # 指南导航 + 指南导航的首页 -/guide/help # 指南导航 + 指南导航的帮助分组 -/other # 其他导航 -/very/very/deep/child # very 导航 + very/deep 分组 -``` - -然后这个识别结果会被展示为: - -```bash -# 导航头 -LOGO Guide | Other | Very ------------------------------ - -# 指南的侧边菜单 ------ -Guide ------ -Help ------ - -# 其他的侧边菜单 ------ -Other ------ - -# Very 的侧边菜单 ------ -Very/deep ------ - Child ------ -``` - -总结一下约定式生成的逻辑:**文件夹的第一级嵌套会作为导航,第二级至倒数第二级嵌套会作为侧边菜单,最后一级是页面;第一级嵌套下的所有菜单和页面会被归集到该导航下**。 - -但仅依靠自动规则往往是不够的,我们通常还有定制导航头文字和顺序的需要: - -### 控制导航名称 - -导航名称的默认生成规则是,取当前导航的路由名称去掉 `/` 并首字母大写。比如,路由是 `/guide`,dumi 将会取 `guide` 并首字母大写变成 `Guide`。 - -如果希望手动控制导航名称,可以使用 [`nav.title`](/zh-CN/config/frontmatter#navtitle) 的 frontmatter 配置项进行配置;**注意,同一导航文件夹下只需要在任意 Markdown 文件中配置,则会全体生效**。 - -### 控制导航路径 - -导航路径的默认生成规则是,取路由的第一级嵌套。比如,路由是 `/very/very/deep/child`,那么 `very` 则会作为导航路径。 - -如果希望手动控制导航路径,可以使用 [`nav.path`](/zh-CN/config/frontmatter#navpath) 的 frontmatter 配置项进行配置。 - -不同于 `nav.title`,由于 `nav.path` 作为唯一标识符,手动控制的话即便同一文件夹下也需要每个 Markdown 文件都设置,所以通常还是建议用文件夹来组织导航而不是手动控制。 - -### 控制导航顺序 - -导航的默认排序规则为,先对比 `path` 的长度,例如 `/guide` 肯定排在 `/guide/help` 前面,其次对比导航名称的 ASCII 码,比如 `Guide` 肯定排在 `Help` 前面。 - -如果希望手动控制导航顺序,可以使用 [`nav.order`](/zh-CN/config/frontmatter#navorder) 的 frontmatter 配置项进行配置,数字越小越靠前;和 `nav.title` 一样,同一导航文件夹下只需要在任意 Markdown 文件中配置,就会全体生效。 - -### 控制菜单生成 - -请参考 [控制菜单生成](/zh-CN/guide/control-menu-generate),**需要注意的是,在 `site` 模式下,由于导航作为第一级嵌套,菜单的自动解析都是从第二级嵌套开始的**。 - -## 配置式导航 - -在大部分场景下,我们都需要对导航上展示的内容做定制,例如添加 GitHub 的仓库链接、旧版文档的链接等等,可以使用 [`navs` 配置项](/zh-CN/config#navs) 来实现: - -```ts -// config/config.ts 或 .umirc.ts -export default { - // 单语言配置方式如下 - navs: [ - null, // null 值代表保留约定式生成的导航,只做增量配置 - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - - // 多语言配置方式如下 - navs: { - // 多语言 key 值需与 locales 配置中的 key 一致 - 'en-US': [ - null, // null 值代表保留约定式生成的导航,只做增量配置 - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - 'zh-CN': [ - null, // null 值代表保留约定式生成的导航,只做增量配置 - { - title: 'GitHub', - path: 'https://github.com/umijs/dumi', - }, - ], - }, -}; -``` - -但此配置项只用于自定义导航头的展示项,**并不会影响路由的生成**,如果希望自定义路由路径,请 [参考上方](#控制导航路径) 在 Markdown 文件中通过 frontmatter 配置项进行控制。 diff --git a/docs/guide/control-route-generate.md b/docs/guide/control-route-generate.md deleted file mode 100644 index b8f11719fb..0000000000 --- a/docs/guide/control-route-generate.md +++ /dev/null @@ -1,51 +0,0 @@ -# Control route generate - -## Convention Routing rules - -As same as Umi, dumi has a set of routing generation conventions. - -Dumi will generate routes based on the base detection path which is taken by the value of the configuration item of [`resolve.includes`](/config#includes). If we do not configure this value, dumi will detect the `docs`, `src`(normal projects), `packages/pkg/src`(lerna projects) directory by default. - -It is assumed that `docs` has the following directory structure, dumi will identify it like this: - -```bash -. -└── docs/ - ├── index.md # generate '/' route - ├── index.zh-CN.md # generate '/zh-CN' route - ├── examples.md # generate '/examples' route - ├── guide - | ├── README.md # generate '/guide' route - | ├── help.md # generate '/guide/help' route -``` - -It can be found that, except for the multi-language part, it is very similar to rules of Umi for identifying `tsx/jsx` Convention routes. - -In addition, dumi will convert camel cased(camelCased) to kebab case(kebab-case), for example, `docs/gettingStarted` will be converted to `docs/getting-started`. - -### Page title - -The default rule of generating page title is to take the last segment of the current route and capitalize it. For example, if the route is `/guide/help`, dumi will take the end route `help` and capitalize it to `Help`. - -If you want to control the page title in manual way, you can configure it through [The frontmatter configuration of `title`](/config/frontmatter#title) - -### Page order - -In the side menu, the pages will be sorted according to the rules. - -The default rule of the page sorting is: firstly, compare the length of `path`, for example `/guide` must be in front of `/guide/help`, and then compare the ASCII of page name, for example, `Guide` must be in front of `Help`. - -If you want to control the page order in manual way, you can configure it through [The frontmatter configuration of `order`](/config/frontmatter#order). The smaller the number, the more previous the rank will be. - -### Page route - -At present, the route of the page itself cannot be customized. Dumi will abide by the agreement that name is route. If you want to change the route of the page, for example, changing the `help` in `/guide/help` to `other`, it is recommended that change `help.md` to `other.md`. - -However, except the route of the page itself, the route of the menu and navigation to which the page belongs can be changed. For more, please refer to [Control menu generate](/guide/control-menu-generate#group-title) and [Control navigation generate](/guide/control-nav-generate#navigation-path). - -## Configuring Routing - -Generally, it is recommended to use the conventional routing directly. If it can not satisfy the requirements, can also configure through [`config.routes`](/config#routes). The usage is the same as Umi, but there are two points to notice: - -1. Only support to configure `.md` as a routing component for now. The standard `module` will be supported in the future -2. To traversal of routes at runtime, dumi flattens all nested routes. If there are parent components in nested routes, it will be wrapped through the Umi's configuration of [`wrappers`](https://umijs.org/docs/routing#wrappers) diff --git a/docs/guide/control-route-generate.zh-CN.md b/docs/guide/control-route-generate.zh-CN.md deleted file mode 100644 index 5be8f88ea2..0000000000 --- a/docs/guide/control-route-generate.zh-CN.md +++ /dev/null @@ -1,51 +0,0 @@ -# 控制路由生成 - -## 约定式路由规则 - -dumi 和 Umi 一样,有一套路由生成的约定。 - -生成均以 [`resolve.includes`](/zh-CN/config#includes) 配置项的值作为基础检测路径,倘若我们不配置该值,则会默认探测 `docs` 目录、`src` 目录(普通项目)、`packages/pkg/src` 目录(lerna 项目)。 - -假定 `docs` 有如下目录结构,dumi 会这么进行识别: - -```bash -. -└── docs/ - ├── index.md # 生成 / 路由 - ├── index.zh-CN.md # 生成 /zh-CN 路由 - ├── examples.md # 生成 /examples 路由 - ├── guide - | ├── README.md # 生成 /guide 路由 - | ├── help.md # 生成 /guide/help 路由 -``` - -可以发现,除了多语言的部分,和 Umi 对 `tsx/jsx` 约定式路由的识别规则非常类似。 - -另外,dumi 会将驼峰命名(camelCased)转换为短横线命名(kebab-case),例如 `docs/gettingStarted` 会被转化为 `docs/getting-started`。 - -### 控制页面名称 - -页面名称的默认生成规则是,取当前路由的最后一段并首字母大写。比如,路由是 `/guide/help`,dumi 将会取末端路由 `help` 并首字母大写变成 `Help`。 - -如果希望手动控制页面名称,可以使用 [名为`title` 的 frontmatter 配置项](/zh-CN/config/frontmatter#title) 进行配置。 - -### 控制页面排序 - -在侧边菜单中,各页面会按照规则进行排序展示。 - -页面的默认排序规则为,先对比 `path` 的长度,例如 `/guide` 肯定排在 `/guide/help` 前面,其次对比页面名称的 ASCII 码,比如 `Guide` 肯定排在 `Help` 前面。 - -如果希望手动控制页面顺序,可以使用 [名为`order` 的 frontmatter 配置项](/zh-CN/config/frontmatter#order) 进行配置,数字越小越靠前。 - -### 控制页面路由 - -目前,页面自身的路由无法自定义,dumi 会保留名称即路由的约定,如果希望修改页面的路由,例如将 `/guide/help` 中的 `help` 修改为 `other`,那么建议把 `help.md` 改为 `other.md`。 - -但除开页面自己的路由,页面所属菜单分组和导航分组的路由是可以修改的,详见 [控制菜单分组路径](/zh-CN/guide/control-menu-generate#控制分组路径) 以及 [控制导航分组路径](/zh-CN/guide/control-nav-generate#控制导航路径)。 - -## 配置式路由 - -通常推荐直接使用约定式路由,倘若不能满足需要,也可以通过 [`config.routes`](/zh-CN/config#routes) 配置项来进行配置,用法和 Umi 一样,但有两点需要注意: - -1. 目前仅支持配置 `.md` 作为路由组件,后续会进行扩展支持标准的 `module` -2. 为了便于在运行时对路由进行遍历,dumi 会把所有嵌套式路由拉平,如果嵌套的路由有父级组件,会通过 Umi 的 [`wrappers`](https://umijs.org/docs/routing#wrappers) 路由配置项进行包裹 diff --git a/docs/guide/demo-principle.md b/docs/guide/demo-principle.md deleted file mode 100644 index bba50a98a5..0000000000 --- a/docs/guide/demo-principle.md +++ /dev/null @@ -1,56 +0,0 @@ -# Ideals of demos - -Dumi has only one ideal, **developer should write demos like user** - -How to understand this? The user's demo is actual project. Writting demo from the perspective of users means that demos can directly used in actual project, therefore, it must have following principles. - -## Principle one: enable to view & use - -While we are writting a demo for component, it's usual to write like this: - -```jsx | pure -import React from 'react'; -import Component from './'; // Wrong: do not imitate - -export default () => ; -``` - -Obviously, this demo can run as expected, but if user found that this demo could used for developing the project and when user prepared to copy source code into the project, he/she would find that it couldn't recognize the dependence about `./` compeletely. So, some demos like this, **only enable to view but disable to use**. - -For dealing with this embarrassed problem, dumi uses alias for current project's package automatically for developer, By the way, dumi uses aliases for all packages if project is based on lerna. It means we could reference dependencies of libraries, like this: - -```jsx | pure -import { Component } from 'library-name'; -``` - -Such demo, not only could be used in project directly, but also works while opening in codesandbox.io - -## Principle two: clear dependencies - -Since umi helps us to import React automatically, it can works well even we don't import React in JSX. - -```jsx | pure -export default () => <>Hello World; // It works -``` - -But such demos don't work in online editor or other non-umi framework projects. So, we assume such demos have unclear dependencies. We should import React as long as we use in JSX. - -```jsx | pure -import React from 'react'; - -export default () => <>Hello World; // It works too -``` - -## Principle three: easy to maintained - -Will user write projects in Markdown? Absolutely no. The reason why we directly write demos in Markdown is simple and convenience in this way. But if there was a complex demo, and we were determined to write in Markdown. It would be a nightmare when writting and maintaining, same as we still have to use Windows Notepad to code in 2020. - -In order to let developers to code and maintain demos as same as developing components, dumi support to import demo from external, something like this: - -```html - -``` - -Meanwhile, for enabling demos to view and use, dumi will show origin source code which needed to show to user! This not only doesn't affect experiences of user, but also makes developers to enjoy the powerful functions such as Code Snipperts, ESLint, prettier and so on brought by the editor. - -If a demo coded by developer didn't work with directly coping, the demo is able to『view, but not to use』.If developers coded demos from the perspective of users, the demo must be able to 『view and use』 diff --git a/docs/guide/demo-principle.zh-CN.md b/docs/guide/demo-principle.zh-CN.md deleted file mode 100644 index f9e8cf5060..0000000000 --- a/docs/guide/demo-principle.zh-CN.md +++ /dev/null @@ -1,56 +0,0 @@ -# dumi 的 Demo 理念 - -dumi 只有一个理念——**开发者应该像用户一样写 Demo**。 - -这句话如何理解?用户的 Demo 就是实际项目,像用户一样写 Demo 意味着这个 Demo 能直接为实际项目所用,所以它必定要满足下面几个原则。 - -## 原则一:能看能用 - -我们在为组件写 Demo 的时候,很容易写成这样: - -```jsx | pure -import React from 'react'; -import Component from './'; // 错误示例,请勿模仿 - -export default () => ; -``` - -这个 Demo 当然能够如预期一般正常运行,但如果用户觉得这个 Demo 可以被用于项目开发、准备拷贝 Demo 源码至项目中的时候,他会发现这个 `./` 的依赖完全无法识别。所以,这样的 Demo,是 **只能看、不能用** 的。 - -为了解决这个尴尬的问题,dumi 会为开发者自动 alias 当前项目的包,如果是 lerna 项目则会 alias 全部的包,这意味着,我们完全可以像用户一样去引用组件库的依赖,就像这样: - -```jsx | pure -import { Component } from 'library-name'; -``` - -这样的 Demo,不仅能让用户直接在项目中使用,也能使得 Demo 在 codesandbox.io 中打开时,也能正常工作。 - -## 原则二:依赖清晰 - -由于 Umi 会自动帮我们引入 React,即便我们不引入 React,也能够正常使用 JSX: - -```jsx | pure -export default () => <>Hello World; // 这样写也是跑得起来的 -``` - -但这样的 Demo 在 online editor 或者其他非 Umi 框架的项目中是无法正常运行的。所以,这样的 Demo 我们认为是**依赖不清晰的**,只要使用了 JSX,我们就应当引入 React: - -```jsx | pure -import React from 'react'; - -export default () => <>Hello World; // 这样写也是跑得起来的 -``` - -## 原则三:易于维护 - -用户会在 Markdown 中写项目吗?显然不会。我们之所以选择直接在 Markdown 中写 Demo,是因为它简单、方便,但倘若某个组件的 Demo 特别复杂,我们却执意在 Markdown 中进行编写,那编写和维护的过程就成了噩梦,就像在 2020 年了我们仍然要使用 Windows 记事本去编程一样。 - -为了能让开发者能和开发组件一样去编写、维护 Demo,dumi 支持从外部引入一个 Demo,就像这样: - -```html - -``` - -同时为了使得它既能看、也能用,在用户需要展示 Demo 源代码的时候,dumi 仍然会为用户展示真正的源代码!这样一来,不仅用户的体验丝毫不受影响,开发者也能享受到编辑器带来的 Code Snippets、ESLint、prettier 等强大的功能。 - -如果开发者写的 Demo 用户拷贝过去无法直接运行,那这个 Demo 是『只能看,不能用的』;如果开发者像用户一样写 Demo,那这个 Demo 必定是『既能看,也能用的』。 diff --git a/docs/guide/demo-types.md b/docs/guide/demo-types.md deleted file mode 100644 index 7c74043a7b..0000000000 --- a/docs/guide/demo-types.md +++ /dev/null @@ -1,61 +0,0 @@ -# Types of demos - -There are three types for demo in dumi - -## Code block - -dumi render the code block with `jsx` and `tsx` as React Component. This code block, as same as common module, needs to have `export default` like this: - -
-```jsx
-import React from 'react';
-
-export default () => 

Hello World!

; -``` -
- -It rendered by dumi like: - -```jsx -import React from 'react'; - -export default () =>

Hello World!

; -``` - -Of course, if you don't want dumi to render code block at all, or want to render other code block languages as React Component, you can configurate [`config.resolve.previewLangs`](/config#previewlangs) - -## External import - -For being able to easy to code and maintain complex demo, dumi supports to render a React Component as demo from external, only need to use the `code` tag to achieve: - -```html - -``` - -## Embedded mode - -Strictly speaking, this is a presentation rather than a demo type. Sometimes we want to present a demo to users directly instead of being wrapped in a demo container, like this: - -```jsx | inline -import React from 'react'; - -export default () =>

Hello World!

; -``` - -It can be found that it is completely an embeded mode presentation of the demo above, which also means that we can insert any required components into the document page through the embedded mode demo, breaking away from the limitation of dumi's native theme ability. - -Both of the above two demos can become embedded mode. You only need to use the `inline` attribute to control it - -
-// code block type in embedded mode
-```jsx | inline
-import React from 'react';
-
-export default () => 

Hello World!

; -``` -
- -```jsx | pure -/* external demo in embedded mode */ - -``` diff --git a/docs/guide/demo-types.zh-CN.md b/docs/guide/demo-types.zh-CN.md deleted file mode 100644 index a5ff0226bd..0000000000 --- a/docs/guide/demo-types.zh-CN.md +++ /dev/null @@ -1,61 +0,0 @@ -# Demo 的类型 - -在 dumi 中,一共有 3 种 Demo 类型。 - -## 代码块 - -dumi 默认会将 `jsx` 和 `tsx` 语言的代码块当做 React Component 进行渲染,该代码块和普通的 module 一样,都需要具备 `export default` 导出,就像这样: - -
-```jsx
-import React from 'react';
-
-export default () => 

Hello World!

; -``` -
- -它会被 dumi 渲染为这样: - -```jsx -import React from 'react'; - -export default () =>

Hello World!

; -``` - -当然,如果你完全不希望 dumi 渲染代码块、又或者希望把别的代码块语言当做 React Component 渲染,可以通过 [`config.resolve.previewLangs`](/zh-CN/config#previewlangs) 配置项进行配置。 - -## 外部引入 - -为了使得重型 Demo 也能够利于编写和维护,dumi 支持从外部引入一个 React Component 作为 Demo 进行渲染,只需要利用 `code` 标签即可实现: - -```html - -``` - -## 嵌入式 - -严格来说这不算一种 Demo 类型,而是一种呈现形式。有时候我们希望能够直接为用户呈现一个 Demo,而不是被包裹在一个 Demo 展示容器中,就像这样: - -```jsx | inline -import React from 'react'; - -export default () =>

Hello World!

; -``` - -可以发现它完全是上面这个 Demo 的嵌入式呈现,这也意味着我们可以通过嵌入式 Demo 对文档页面插入任何需要的组件,脱离 dumi 原生主题能力的限制。 - -上面两种 Demo 都可以变成嵌入式 Demo,只需要使用 `inline` 属性进行控制即可: - -
-// 代码块类型做嵌入式
-```jsx | inline
-import React from 'react';
-
-export default () => 

Hello World!

; -``` -
- -```jsx | pure -/* 外部 Demo 做嵌入式 */ - -``` diff --git a/docs/guide/faq.md b/docs/guide/faq.md index 24c31ec465..fcdb5a25ad 100644 --- a/docs/guide/faq.md +++ b/docs/guide/faq.md @@ -1,5 +1,6 @@ --- title: FAQ +order: 4 --- ## What is the relationship between dumi and Umi? diff --git a/docs/guide/faq.zh-CN.md b/docs/guide/faq.zh-CN.md index 8cdeb784ae..8814e8f12b 100644 --- a/docs/guide/faq.zh-CN.md +++ b/docs/guide/faq.zh-CN.md @@ -1,5 +1,6 @@ --- -title: FAQ +title: 常见问题 +order: 4 --- ## dumi 和 Umi 的关系是什么? diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md deleted file mode 100644 index d0b2b792be..0000000000 --- a/docs/guide/getting-started.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Getting Started -order: 9 -nav: - order: 10 ---- - -## Environment setup - -First, you should have [node](https://nodejs.org/en/), and ensure that the node version is 10.13 or above - -```bash -$ node -v -v10.13.0 -``` - -## Initial scaffold - -For convenience of usage, dumi provides two different scaffolds, differences between the two scaffolds can view [Guide-Mode](/guide/mode). First, we need to find a place to make an empty directory, and then use scaffold: - -```bash -$ mkdir myapp && cd myapp -``` - -### Scaffold for components - -Scaffold for components includes not only dumi and basic docs, but also a simple component, umi-test, father-build. which can implement processes of developing components, writting docs, coding test cases, build components. - -```bash -$ npx @umijs/create-dumi-lib # initial a scaffold for components in doc mode -# or -$ yarn create @umijs/dumi-lib - -$ npx @umijs/create-dumi-lib --site # initial a scaffold for components in site mode -# or -$ yarn create @umijs/dumi-lib --site -``` - -### Scaffold for static site - -Scaffold for static site is a scaffold in multi-language site mode, which only includes docs - -```bash -$ npx @umijs/create-dumi-app -# or -$ yarn create @umijs/dumi-app -``` - -## Initial in manual way - -### Install - -Create an empty directory, and then execute following command in the directory to install: - -```bash -$ npm i dumi -D -``` - -### Start to write docs - -Dumi will search markdown files which are in the `docs`, `src` (or `src` of each lerna package) directory automatically, we could create a simplest doc first: - -```bash -$ mkdir src && echo '# Hello dumi!' > src/index.md -``` - -And then execute `npx dumi dev`, the doc will appear in front of you: - -![](https://gw.alipayobjects.com/zos/bmw-prod/ed83bd75-06c5-4aa5-a149-5918b072cbee/k7a3kkzb_w1978_h1330.png) - -### Try to write a demo - -Dumi will consider `jsx/tsx` code block as React Component to render, then take it into demo wrapper, We could modify to following content in `src/index.md`: - -
-# Hello dumi!
-
-```jsx
-import React from 'react';
-
-export default () => 

First Demo

; -``` -
- -Our first demo is running after saving: - -![](https://gw.alipayobjects.com/zos/bmw-prod/a74b9643-b1db-48b0-83b1-67d15e13b6fc/k7a3sl0s_w1988_h1310.png) - -Is it simple? However, is's easy to write a demo but difficult to write a good demo. Dumi has some ideals and principles that want to share with you about how to write a demo: [Ideals of demos](/guide/demo-principle). diff --git a/docs/guide/getting-started.zh-CN.md b/docs/guide/getting-started.zh-CN.md deleted file mode 100644 index f65344a305..0000000000 --- a/docs/guide/getting-started.zh-CN.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: 快速上手 -order: 9 -nav: - order: 10 ---- - -## 环境准备 - -首先得有 [node](https://nodejs.org/en/),并确保 node 版本是 10.13 或以上。 - -```bash -$ node -v -v10.13.0 -``` - -## 脚手架初始化 - -为了方便使用,dumi 提供了两种不同的脚手架,两者的区别可以查看 [指南-多种呈现模式](/zh-CN/guide/mode)。我们需要先找个地方建个空目录,然后再使用脚手架: - -```bash -$ mkdir myapp && cd myapp -``` - -### 组件开发脚手架 - -组件库开发脚手架除了包含 dumi 和基础的文档外,还包含一个简单的组件、umi-test 和 father-build,可轻松实现开发组件、编写文档、编写测试用例、打包组件的全流程。 - -```bash -$ npx @umijs/create-dumi-lib # 初始化一个文档模式的组件库开发脚手架 -# or -$ yarn create @umijs/dumi-lib - -$ npx @umijs/create-dumi-lib --site # 初始化一个站点模式的组件库开发脚手架 -# or -$ yarn create @umijs/dumi-lib --site -``` - -### 静态站点脚手架 - -静态站点脚手架即一个多语言的站点模式脚手架,仅包含文档。 - -```bash -$ npx @umijs/create-dumi-app -# or -$ yarn create @umijs/dumi-app -``` - -## 手动初始化 - -### 安装 - -建立一个空文件夹,然后在文件夹下执行以下命令进行安装: - -```bash -$ npm i dumi -D -``` - -### 开始写文档 - -dumi 默认会自动搜寻 `docs`、`src`(或各 lerna 包下的 `src`)目录下的 markdown 文件,我们先来一篇最简单的文档: - -```bash -$ mkdir src && echo '# Hello dumi!' > src/index.md -``` - -然后执行 `npx dumi dev`,文档将会呈现在你眼前: - -![](https://gw.alipayobjects.com/zos/bmw-prod/ed83bd75-06c5-4aa5-a149-5918b072cbee/k7a3kkzb_w1978_h1330.png) - -### 写个 Demo 试试看 - -dumi 会将 `jsx/tsx` 代码块当做 React Component 进行渲染然后放入 Demo 包裹器中,我们将 `src/index.md` 修改为如下内容: - -
-# Hello dumi!
-
-```jsx
-import React from 'react';
-
-export default () => 

First Demo

; -``` -
- -保存之后我们的第一个 Demo 就运行起来了: - -![](https://gw.alipayobjects.com/zos/bmw-prod/a74b9643-b1db-48b0-83b1-67d15e13b6fc/k7a3sl0s_w1988_h1310.png) - -是不是非常简单?但写 Demo 易写好 Demo 难,关于写 Demo 这件事,dumi 有些理念和原则,也想与你分享一下:[dumi 的 Demo 理念](/zh-CN/guide/demo-principle)。 diff --git a/docs/guide/index.md b/docs/guide/index.md index 1f274df521..a46f7e3318 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -1,6 +1,7 @@ --- title: Introducation order: 1 +toc: menu nav: title: Guide order: 1 @@ -8,35 +9,71 @@ nav: ## What's dumi? -dumi, temporarilty pronounced like [duːmɪ], is a Umi-based doc tool that especially for developing libraries & writting docs.It can provide one-stop component development experience for developer with [father](https://github.com/umijs/father), in which **father for building and dumi for component development & writting docs**. +dumi, pronounced like [duːmɪ], is a documentation tool for developing libraries. It can provide one-stop component development experience for developer with [father](https://github.com/umijs/father), in which **father for building and dumi for component development & writting docs**. -Similar with Umi, dumi is based on routing too, which will generate appropriate navigators, menus and routers according to directory structrue & FrontMatter. Meanwhile, dumi is also support to configuring routing for customization requirement; Moreover, in order to convenient for developing component and showing component demo, dumi produces a powerful and wonderful Mardown compiler based on remarkjs, which makes us code demo conveniently, even copuld import demo into Markdown.As well as plenty of presets or plugins of Umi, dumi can assist us to deal with various complex scene. +## Features - +- 📦 Out of the box, focus on component development and documentation +- 📋 Rich Markdown extensions, more than just rendering component demo +- 🏷 Automatically generate component API based on TypeScript type definition +- 🎨 Easily customize the theme, and create your own Markdown components +- 📱 Support mobile component library development, built-in mobile HD rendering solution +- 📡 One-line command digitizes component assets and connects them with downstream productivity tools -## Features +## Getting Started +### Environment setup + +First, you should have [node](https://nodejs.org/en/), and ensure that the node version is 10.13 or above. + +```bash +$ node -v +v10.13.0 +``` + +### Initial scaffold + +For convenience of usage, dumi provides two different scaffolds, differences between the two scaffolds can view [Guide - Mode](/config#mode). First, we need to find a place to make an empty directory, and then use scaffold: + +```bash +$ mkdir myapp && cd myapp +``` + +#### Scaffold for components + +Scaffold for components includes not only dumi and basic docs, but also a simple component, umi-test, father-build. which can implement processes of developing components, writting docs, coding test cases, build components. + +```bash +$ npx @umijs/create-dumi-lib # initial a scaffold for components in doc mode +# or +$ yarn create @umijs/dumi-lib -- 📦 Out of the box, focus on development & documentation -- 🚀 Based on [Umi 3](https://umijs.org), high-performance & extensible -- 📋 Powerful Markdown extensions, support to embed demo or import external demo & inline demo - -## Contributing - -Welcome to contribute to dumi, please visit https://github.com/umijs/dumi. - -```jsx | inline -import React from 'react'; - -export default () => ( - <> - - - -); +$ npx @umijs/create-dumi-lib --site # initial a scaffold for components in site mode +# or +$ yarn create @umijs/dumi-lib --site ``` + +#### Scaffold for static site + +Scaffold for static site is a scaffold in multi-language site mode, which only includes docs. + +```bash +$ npx @umijs/create-dumi-app +# or +$ yarn create @umijs/dumi-app +``` + +### Repository template initialization + +We can also use the `dumi-template` repository for initialization, visit https://github.com/umijs/dumi-template to learn more. + +![](https://gw.alipayobjects.com/zos/bmw-prod/91791904-cdde-4408-959d-72fd0c9049b1/kj80x6lv_w1918_h352.png) + +### Start development + +Execute `npm run dev` or `npx dumi dev` to start debugging components or writing documents: + +![](https://gw.alipayobjects.com/zos/bmw-prod/a74b9643-b1db-48b0-83b1-67d15e13b6fc/k7a3sl0s_w1988_h1310.png) + +### Build and deploy + +Execute `npm run build` or `npx dumi build` to build our documentation site. The build product will be output to the `dist` directory by default. We can deploy the `dist` directory to now.sh, GitHub Pages, etc. On a static site hosting platform or a certain server. diff --git a/docs/guide/index.zh-CN.md b/docs/guide/index.zh-CN.md index 06c6019224..e91a0a639c 100644 --- a/docs/guide/index.zh-CN.md +++ b/docs/guide/index.zh-CN.md @@ -1,6 +1,7 @@ --- title: 介绍 order: 1 +toc: menu nav: title: 指南 order: 1 @@ -8,35 +9,71 @@ nav: ## 什么是 dumi? -dumi,暂时就叫它**嘟米**吧,是一款基于 Umi 打造、为组件开发场景而生的文档工具,与 [father](https://github.com/umijs/father) 一起为开发者提供一站式的组件开发体验,**father 负责构建,而 dumi 负责组件开发及组件文档生成**。 +dumi,中文发音**嘟米**,是一款为组件开发场景而生的文档工具,与 [father](https://github.com/umijs/father) 一起为开发者提供一站式的组件开发体验,**father 负责构建,而 dumi 负责组件开发及组件文档生成**。 -和 Umi 类似,dumi 也是以路由为基础的,会自动根据目录结构和 FrontMatter 生成对应的文档导航、菜单和路由,同时也支持配置式路由以满足自定义需要;另外,为了便于开发组件和展示组件 demo,dumi 基于 remarkjs 打造了强大、贴心的 Markdown 编译器,使我们能非常方便地在 Markdown 中编写 demo、甚至往 Markdown 中导入 demo;加上 Umi 丰富的 preset、plugin 生态,能帮我们应对各种复杂场景。 +## 特性 - +- 📦 开箱即用,将注意力集中在组件开发和文档编写上 +- 📋 丰富的 Markdown 扩展,不止于渲染组件 demo +- 🏷 基于 TypeScript 类型定义,自动生成组件 API +- 🎨 主题轻松自定义,还可创建自己的 Markdown 组件 +- 📱 支持移动端组件库研发,内置移动端高清渲染方案 +- 📡 一行命令将组件资产数据化,与下游生产力工具串联 -## 特性 +## 快速上手 +### 环境准备 + +首先得有 [node](https://nodejs.org/en/),并确保 node 版本是 10.13 或以上。 + +```bash +$ node -v +v10.13.0 +``` + +### 脚手架初始化 + +为了方便使用,dumi 提供了两种不同的脚手架,两者的区别可以查看 [Config - mode](/zh-CN/config#mode)。我们需要先找个地方建个空目录,然后再使用脚手架: + +```bash +$ mkdir myapp && cd myapp +``` + +#### 组件开发脚手架 + +组件库开发脚手架除了包含 dumi 和基础的文档外,还包含一个简单的组件、umi-test 和 father-build,可轻松实现开发组件、编写文档、编写测试用例、打包组件的全流程。 + +```bash +$ npx @umijs/create-dumi-lib # 初始化一个文档模式的组件库开发脚手架 +# or +$ yarn create @umijs/dumi-lib -- 📦 开箱即用,让所有注意力都放在文档编写和组件开发 -- 🚀 基于 [Umi 3](https://umijs.org/zh-CN),天生高性能、可扩展 -- 📋 强大的 Markdown 扩展,可嵌入 Demo、可导入外部 Demo 甚至插入自定义 React 组件 - -## 参与贡献 - -欢迎加入到 dumi 的建设队伍中来,请访问 https://github.com/umijs/dumi 。 - -```jsx | inline -import React from 'react'; - -export default () => ( - <> - - - -); +$ npx @umijs/create-dumi-lib --site # 初始化一个站点模式的组件库开发脚手架 +# or +$ yarn create @umijs/dumi-lib --site ``` + +#### 静态站点脚手架 + +静态站点脚手架即一个多语言的站点模式脚手架,仅包含文档。 + +```bash +$ npx @umijs/create-dumi-app +# or +$ yarn create @umijs/dumi-app +``` + +### 仓库模板初始化 + +我们也可以使用 `dumi-template` 仓库进行初始化,访问 https://github.com/umijs/dumi-template 了解更多。 + +![](https://gw.alipayobjects.com/zos/bmw-prod/91791904-cdde-4408-959d-72fd0c9049b1/kj80x6lv_w1918_h352.png) + +### 开始开发 + +执行 `npm run dev` 或 `npx dumi dev` 即可开始调试组件或编写文档: + +![](https://gw.alipayobjects.com/zos/bmw-prod/a74b9643-b1db-48b0-83b1-67d15e13b6fc/k7a3sl0s_w1988_h1310.png) + +### 构建及部署 + +执行 `npm run build` 或 `npx dumi build` 即可对我们的文档站点做构建,构建产物默认会输出到 `dist` 目录下,我们可以将 `dist` 目录部署在 now.sh、GitHub Pages 等静态站点托管平台或者某台服务器上。 diff --git a/docs/guide/migration.md b/docs/guide/migration.md deleted file mode 100644 index 1ad1cb1535..0000000000 --- a/docs/guide/migration.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -legacy: /migration ---- - -# Migrate from father-doc - -Attention, The `father-doc` here is not the part of `father doc` in the original `father` tools. This manual is only applicable to the migration of `father-doc` - -Father-doc is the predecessor of dumi. The first alpha version was released on October 23, 2019. Thanks to the partners who used to use and contributed to father-doc. Now father-doc has been officially renamed to dumi and has done a lot of uncompatible changes, we sincerely invite everyone to migrate. It only takes 3 minutes to get it done. - -## Configuration changed - -All configurations have been moved from the original `config.doc` to the `config`, which means they are all to the outermost, and some configurations have also been renamed. The detailed changes are as follows: - -### Change comparison table - -| **New configuration name** | **Old configuration name** | **effect** | -| ------------------------------ | -------------------------- | --------------------------------------------------------------------- | -| title | doc.title | Set the title of the website, the default value is `package.name` | -| description | doc.desc | Set the description of the website, only works in doc mode for now | -| logo | doc.logo | Set the logo of the website | -| mode | doc.mode | Set the mode of site | -| locales | doc.locales | Set the locales of the website | -| menus | doc.menus | Set the sidebar menus of the website | -| navs | doc.navs | Set the navigations of the website | -| resolve.includes | doc.include | Set the detected directory of the website | -| resolve.previewLangs | doc.previewLangs | Set which code block will be rendered as React Component | - -### API changed - -It should be noticed that there are two APIs not only be moved, but also renamed, they are: - -- `desc` changed to `description`:non-abbreviated -- `include` changed to `includes`:improve grammar of singular and plural - -## FrontMatter Changed - -For the FrontMatter configuration of Markdown files, dumi has also made changes, the details are as follows: - -### `order` reverse - -The sorting rule of `order` is changed from the bigger the number, the previous the rank is, to **the smaller the number, the previous the rank is**. - -In the beginning, the `order` rules for routes, menus, and navigations are that the higher the `order` number, the previous the rank is, but it is very inconvenient for everyone to use it in actual project. With the number of pages increasing, we need to increase the `order` number of the first document. So it’s reversed. - -### Deprecated `slugs` and use `toc` instead - -Previously, father-doc used `slugs: false` to turn off the anchor menu prsented on the right. In dumi, it controlled via the `toc` configuration, and there are 3 values: `false` means off, `menu` means integrated into the menu on the right, `content` means presented in the content area (default value). - -### `sidebar` changed to `sidemenu` - -For correcting the semantics, our scene is `sidemenu` indeed. - -### `hero.text` changed to `hero.title` - -For correcting the semantics, the HERO area of the homepage should be `title`. - -## Others - -### `gitignore` - -Since the temporary file directory of Umi 3 has been moved from the `pages` folder to the root directory, if there is `pages/.umi` in `gitignore`, it needs to be modified to `.umi`. \ No newline at end of file diff --git a/docs/guide/migration.zh-CN.md b/docs/guide/migration.zh-CN.md deleted file mode 100644 index 185680984d..0000000000 --- a/docs/guide/migration.zh-CN.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -legacy: /migration ---- - -# 从 father-doc 迁移 - -注意,此处的 `father-doc` 并非原有 `father` 工具集中的 `father doc` 部分,本手册仅适用于 `father-doc` 的迁移 - -father-doc 是 dumi 的前身,在 2019 年 10 月 23 日发出了第一个 alpha 版本,感谢曾经使用和贡献 father-doc 的伙伴们,如今 father-doc 已正式更名为 dumi,且做了很多不兼容的变更,真诚邀请大家进行迁移,只需要 3 分钟即可快速搞定。 - -## 配置项变更 - -所有配置项都从原有的 `config.doc` 层级提升到了 `config` 层级,即全部到最外层了,部分配置项也做了更名,详细变化如下: - -### 变更对照表 - -| **新配置项名称** | **原配置项名称** | **作用** | -| -------------------- | ---------------- | ----------------------------------------------- | -| title | doc.title | 设置网站的标题,默认值为 `package.name` | -| description | doc.desc | 设置网站的介绍文字,目前仅 doc 模式下有用 | -| logo | doc.logo | 设置网站的 LOGO | -| mode | doc.mode | 设置网站的类型 | -| locales | doc.locales | 设置网站的多语言配置 | -| menus | doc.menus | 配置网站的侧边栏菜单 | -| navs | doc.navs | 配置网站的导航菜单 | -| resolve.includes | doc.include | 设置文档的探测目录 | -| resolve.previewLangs | doc.previewLangs | 设置哪些代码块语言会被当做 React Component 渲染 | - -### API 改名 - -需要注意的是,上述有两个 API 除了提升层级外,还做了改名,分别是: - -- `desc` 修改为 `description`:不用缩写 -- `include` 修改为 `includes`:修正单复数 - -## FrontMatter 变更 - -对于 Markdown 文件的 FrontMatter 配置,dumi 也做了修改,详细情况如下: - -### `order` 的排序规则反向 - -`order` 的排序规则由越大越靠前修改为**越小越靠前**。 - -一开始路由、菜单和导航的 `order` 规则都是 `order` 值越大越靠前,但大家实际使用下来很不方便,随着页面的增多经常需要把第一篇文档的 `order` 值再改大一些,所以做了反序。 - -### 废弃 `slugs` 改用 `toc` - -此前 father-doc 用 `slugs: false` 来关闭右侧的锚点菜单展示,在 dumi 中,改用 `toc` 配置项来控制,且存在 3 种值:`false` 关闭、`menu` 集成到右侧菜单、`content` 展示在内容区域(默认值)。 - -### `sidebar` 改为 `sidemenu` - -修正语义,我们这个场景确实是 `sidemenu`。 - -### `hero.text` 改为 `hero.title` - -修正语义,首页 HERO 区域应为 `title`。 - -## 其他杂项 - -### `gitignore` - -由于 Umi 3 的临时文件目录从 `pages` 文件夹提升到了根目录,所以如果原有 `gitignore` 中存在 `pages/.umi`,需要修改为 `.umi`。 diff --git a/docs/guide/mode.md b/docs/guide/mode.md deleted file mode 100644 index 6c16394977..0000000000 --- a/docs/guide/mode.md +++ /dev/null @@ -1,40 +0,0 @@ -# Modes - -For now, dumi supports two modes: document mode and site mode. It's very simple to switch between the two modes - -```ts -// config/config.ts or .umirc.ts -export default { - // document mode(default) - mode: 'doc', - // site mode - mode: 'site', -}; -``` - -When the component library is light and does not need complicated documents, it can be presented in document mode; when it is perfect and needs a tutorial, it is recommended to be presented in site mode. Taking dumi's official website as an example, the display effects are as follows: - -## Document mode - -![](https://gw.alipayobjects.com/zos/bmw-prod/86ddc125-75e0-49e0-920b-f9497e806cf1/k7iyfr0t_w2600_h1754.png) - -The characteristics of document mode are: - -- No navigation -- No search input -- No customized home page -- Support to present introduction through `description` configuration -- Support to present the Github Stars number automatically through `repository` in `package.json` -- Support to present the links to `Edit this doc on GitHub` in the `footer` of `markdown` file automatically through `repository` in `package.json` -- Support to change the branch of this link ,`Edit this doc on GitHub`,through `repository.branch` in `package.json`,the default is `master` branch - -## Site mode - -![](https://gw.alipayobjects.com/zos/bmw-prod/7ce6770d-df19-48fa-853e-64cbbf41b762/k7iyfarw_w2600_h1754.png) - -The characteristics of site mode are: - -- Navigation -- Search input -- Support to [config home page](/config/frontmatter#hero) through `hero` and `features` -- Support to [config footer](/config/frontmatter#footer) through `footer` diff --git a/docs/guide/mode.zh-CN.md b/docs/guide/mode.zh-CN.md deleted file mode 100644 index 090c228afd..0000000000 --- a/docs/guide/mode.zh-CN.md +++ /dev/null @@ -1,40 +0,0 @@ -# 多种呈现模式 - -目前,dumi 支持两种呈现模式,分别是文档模式和站点模式。在两种模式之间切换也非常地简单: - -```ts -// config/config.ts 或 .umirc.ts -export default { - // 文档模式(默认值) - mode: 'doc', - // 站点模式 - mode: 'site', -}; -``` - -在组件库比较轻量、不需要繁杂文档的时候,可以以文档模式呈现;在它羽翼丰满、需要有教程和周边生态时,建议以站点模式呈现。以 dumi 的官网为例展示效果分别如下: - -## 文档模式 - -![](https://gw.alipayobjects.com/zos/bmw-prod/86ddc125-75e0-49e0-920b-f9497e806cf1/k7iyfr0t_w2600_h1754.png) - -文档模式的特点是: - -- 没有导航头 -- 没有搜索框 -- 没有定制化的首页 -- 支持 `description` 配置项展示简介 -- 支持通过 `package.json` 中的 `repository` 配置自动展示 GitHub Stars 数 -- 支持通过 `package.json` 中的 `repository` 配置自动展示 `markdown` 文件 `footer` 中 `Edit this doc on GitHub` 的超链接 -- 支持通过 `package.json` 中的 `repository.branch` 配置可修改 `Edit this doc on GitHub` 该超链接跳转的分支,默认为 `master` 分支 - -## 站点模式 - -![](https://gw.alipayobjects.com/zos/bmw-prod/7ce6770d-df19-48fa-853e-64cbbf41b762/k7iyfarw_w2600_h1754.png) - -官网模式的特点是: - -- 有导航头 -- 有搜索框 -- 支持通过 `hero` 和 `features` [配置首页](/zh-CN/config/frontmatter#hero) -- 支持通过 `footer` [配置页脚](/zh-CN/config/frontmatter#footer) diff --git a/docs/guide/multi-language.md b/docs/guide/multi-language.md deleted file mode 100644 index 65466b9d43..0000000000 --- a/docs/guide/multi-language.md +++ /dev/null @@ -1,72 +0,0 @@ -# Multi-language - -Generally, our component documents are written in more than one language to satisfy the requirements of developers in different countries and regions. Based on dumi, you are able to switch multi-language mode for your documents by adding the suffix locale to `.md`. - -## Examples - -If our file directory structure is like this: - -``` -. -└── src/ - ├── index.en-US.md # if the defualt locale is en-US, index.md is equal with index.en-US.md - ├── index.zh-CN.md -``` - -Then in the default configuration, the generated routes will ne looked like this: - -```js -[ - { - path: '/', - // ... - }, - { - path: '/zh-CN', - // ... - }, -]; -``` - -The left side menu will change with the switch of the locale - - - -That's all about this example. - -## Default language and missing translation - -In the default configuration of dumi, the default language is `en-US` and the second language is `zh-CN`. If you need to change this configuration, such as changing the default language or adding more languages, please check the [Config - locales](/config#locales). - -During the process of actual document writing, it is likely to be **incrementally** and **gradually**, for example, firstly, writing all the documents in the default language, and then translating them into other languages gradually, which will inevitably lead to a transition period of 『document translation to half』. - -In order to make this transition period more smooth and friendly, **dumi will use the default language as the language of untranslated document**, which may be difficult to understand. Let's see a case. - -Suppose the directory structure is as follows: - -``` -. -└── src/ - ├── missing/ - | ├── index.md - ├── index.md - ├── index.zh-CN.md -``` - -Obviously, the Chinese translation of the document `missing` is missing, What means the content of `/zh-CN/missing` does not exist. So, dumi will automatically render the content of `/zh-CN/missing` to the content of the default language, which is the content of `/missing` route, so that to ensure that the document is accessible. - -In the future, it is planned to add the prompt of missing translation to guide visitors to contribute translation for the document. - -## Other agreements - -### Locale suffix is optional - -If a `.md` file does not have a locale suffix, it will be recognized by dumi as the default locale. For example, the default locale is `en-US`, then `abc.md` will be considered as `abc.en-US.md` by dumi. - -### Validity of locale - -If the locale is configured as `en-US` (default) and `zh-CN`, but dumi cannot find the suffix `zh-CN` in any `.md` file, then the locale of `zh-CN` will be deemed invalid by dumi and will not be presented to users on the site. - -### Multi-language of `README.md` - -If a site does not have a root route (It means there is no `index.md` or `README.md` in any root directory of `include`), dumi will render the `README.md` that in the project root directory as the root route; If it is in multi-language mode at same time, it will try to find `README.{locale}.md`, or it will fallback to `README.md`. diff --git a/docs/guide/multi-language.zh-CN.md b/docs/guide/multi-language.zh-CN.md deleted file mode 100644 index 803e4dc8bb..0000000000 --- a/docs/guide/multi-language.zh-CN.md +++ /dev/null @@ -1,72 +0,0 @@ -# 多语言支持 - -通常我们的组件文档都会编写不止一种语言,以覆盖不同国家、地区开发者的需要。基于 dumi,仅需给 `.md` 添加 locale 后缀,即可为你的文档启用多语言切换功能。 - -## 最小示例 - -如果我们的文件目录结构是这样: - -``` -. -└── src/ - ├── index.en-US.md # 如果 en-US 为默认 locale,则 index.md 和 index.en-US.md 等价 - ├── index.zh-CN.md -``` - -那么在默认配置下,生成的路由表将会变成这样: - -```js -[ - { - path: '/', - // ... - }, - { - path: '/zh-CN', - // ... - }, -]; -``` - -左侧菜单的将会随着 locale 的切换而变化: - - - -此时我们的最小多语言示例就完成了。 - -## 默认语言和翻译缺失 - -在 dumi 的默认配置中,`en-US` 是默认语言,`zh-CN` 是第二种语言,如果你需要修改这个配置,比如修改默认语言、或者添加更多语言,请查看 [Config - locales](/zh-CN/config#locales) 配置项。 - -在实际的文档编写过程中,我们很可能是**增量**、**渐进式**进行的,例如先把默认语言的所有文档写好,然后增量翻译为其他语言,这势必会存在一个『文档翻译到一半』的过渡期。 - -为了让这个过渡期更加平滑和友好,**dumi 会将默认语言作为未翻译语言的兜底文档**,理解起来可能有些许困难,让我们看一个案例。 - -假设目录结构如下: - -``` -. -└── src/ - ├── missing/ - | ├── index.md - ├── index.md - ├── index.zh-CN.md -``` - -很显然我们 `missing` 这篇文档的中文翻译是缺失的,也就是说 `/zh-CN/missing` 的内容是不存在的,此时 dumi 会自动将 `/zh-CN/missing` 的内容渲染为默认语言的内容,即 `/missing` 路由的内容,以确保文档是可访问的。 - -后续会计划添加翻译缺失的提示,引导浏览者为文档贡献翻译。 - -## 其他约定 - -### 默认 locale 文件后缀可选 - -如果某个 `.md` 文件没有 locale 后缀,那么它会被 dumi 识别为默认 locale。例如默认 locale 为 `en-US`,那么 `abc.md` 则会被 dumi 当作 `abc.en-US.md`。 - -### locale 的有效性 - -如果 locale 配置为 `en-US`(默认)和 `zh-CN`,但 dumi 没能在任意 `.md` 文件中找到 `zh-CN` 后缀,则此时 `zh-CN` 的 locale 会被 dumi 认定为无效 locale,不会在站点中呈现给用户。 - -### `README.md` 的多语言 - -如果一个站点没有根路由(即任意 `include` 根目录下都没有 `index.md` or `README.md`),dumi 会将项目根目录的 `README.md` 作为根路由渲染;如果同时启用了多语言,那么会尝试去寻找 `README.{locale}.md`,如果找不到,则会 fallback 到 `README.md`。 diff --git a/docs/guide/seo.md b/docs/guide/seo.md deleted file mode 100644 index 30faeb2473..0000000000 --- a/docs/guide/seo.md +++ /dev/null @@ -1,17 +0,0 @@ -# SEO - -Dumi generates a single page application (SPA) in default. For some scenarios with strong SEO requirements, you can enable the `ssr` and `exportStatic` configuration, as follows: - -```js -// config/config.ts or .umirc.ts -export default { - ssr: {}, - exportStatic: {}, -}; -``` - -The generated site will be more friendly to SEO - - - -> It is recommended to turn it on, because the developed component library naturally supports to [SSR](https://umijs.org/docs/ssr) diff --git a/docs/guide/seo.zh-CN.md b/docs/guide/seo.zh-CN.md deleted file mode 100644 index 927f481fc9..0000000000 --- a/docs/guide/seo.zh-CN.md +++ /dev/null @@ -1,17 +0,0 @@ -# SEO 支持 - -默认情况下,dumi 站点生成单页应用(SPA),对有 SEO 有强需求的场景,可以开启 `ssr` 和 `exportStatic` 配置,如下: - -```js -// config/config.ts 或 .umirc.ts -export default { - ssr: {}, - exportStatic: {}, -}; -``` - -这样生成的站点,对 SEO 支持会更加友好 - - - -> 建议开启,这样开发出来的组件库天然支持[服务端渲染](https://umijs.org/zh-CN/docs/ssr) diff --git a/docs/index.md b/docs/index.md index 6a922416fc..fdf7d35bc8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,50 +1,41 @@ --- -title: dumi - A Umi-based doc tool can assist you to develop libraries & write docs. +title: dumi - A doc tool can assist you to develop libraries & write docs. order: 10 hero: title: dumi - desc: A Umi-based doc tool can assist you to develop libraries & write docs. + desc: 📖 A doc tool can assist you to develop libraries & write docs. actions: - text: Getting Started - link: /guide/getting-started + link: /guide features: - icon: https://gw.alipayobjects.com/zos/bmw-prod/881dc458-f20b-407b-947a-95104b5ec82b/k79dm8ih_w144_h144.png title: Out of the box desc: Elegant default configrations and convention routing assist developers to get started as simple as possible, that focus all attentions on developing libraries & writting docs - - icon: https://gw.alipayobjects.com/zos/bmw-prod/d60657df-0822-4631-9d7c-e7a869c2f21c/k79dmz3q_w126_h126.png - title: high-performance - desc: Based on powerful Umi, dumi is not only high-performance & extensible, but also could use mostly plugins based on Umi - icon: https://gw.alipayobjects.com/zos/bmw-prod/d1ee0c6f-5aed-4a45-a507-339a4bfe076c/k7bjsocq_w144_h144.png title: For developing libraries - desc: Powerful Markdown extensions, that could embed demos or import external demos or even insert custom React components, make docs beautiful & better to use + desc: Rich Markdown extensions are not limited to rendering component demos, making component documents not only easy to write and manage, but also beautiful and easy to use + - icon: https://gw.alipayobjects.com/zos/bmw-prod/b8570f4d-c1b1-45eb-a1da-abff53159967/kj9t990h_w144_h144.png + title: Theme system + desc: Progressive custom theme capabilities, ranging from expanding your own Markdown tags to customizing complete theme packages, are up to you + - icon: https://gw.alipayobjects.com/zos/bmw-prod/b3e102cd-5dad-4046-a02a-be33241d1cc7/kj9t8oji_w144_h144.png + title: API automatically generated + desc: Component API can be automatically generated based on TypeScript type definitions, and components will always be『the same in appearance』 + - icon: https://gw.alipayobjects.com/zos/bmw-prod/3863e74a-7870-4874-b1e1-00a8cdf47684/kj9t7ww3_w144_h144.png + title: Mobile component library development + desc: Install the theme package to quickly enable mobile component R&D capabilities, built-in mobile HD rendering solution + - icon: https://gw.alipayobjects.com/zos/bmw-prod/f093e060-726e-471c-a53e-e988ed3f560c/kj9t9sk7_w144_h144.png + title: Asset dataization capabilities + desc: One-line command digitizes component assets, and standardized asset data can be connected with downstream productivity tools footer: Open-source MIT Licensed | Copyright © 2019-present
Powered by self --- -## Getting Started - -Create first doc in manual way - -```bash -// Create dir for libraries -$ mkdir library && cd library - -// Install dumi -$ npm i dumi - -// Create docs -$ mkdir docs && echo '# Hello dumi!' > docs/index.md - -// Preview docs -$ npx dumi dev -``` - ## Who are using - + ## Feedback -Please visit [GitHub](https://github.com/umijs/dumi) or join the discuss group +Please visit [GitHub](https://github.com/umijs/dumi) or join the discuss group: - + diff --git a/docs/index.zh-CN.md b/docs/index.zh-CN.md index 11a0d88475..56a0c62a77 100644 --- a/docs/index.zh-CN.md +++ b/docs/index.zh-CN.md @@ -1,50 +1,41 @@ --- -title: dumi - 基于 Umi、为组件开发场景而生的文档工具 +title: dumi - 为组件开发场景而生的文档工具 order: 10 hero: title: dumi - desc: 基于 Umi、为组件开发场景而生的文档工具 + desc: 📖 为组件开发场景而生的文档工具 actions: - text: 快速上手 - link: /zh-CN/guide/getting-started + link: /zh-CN/guide features: - icon: https://gw.alipayobjects.com/zos/bmw-prod/881dc458-f20b-407b-947a-95104b5ec82b/k79dm8ih_w144_h144.png title: 开箱即用 desc: 考究的默认配置和约定式的目录结构,帮助开发者零成本上手,让所有注意力都能放在文档编写和组件开发上 - - icon: https://gw.alipayobjects.com/zos/bmw-prod/d60657df-0822-4631-9d7c-e7a869c2f21c/k79dmz3q_w126_h126.png - title: 高性能 - desc: 有强大的 Umi 做底座,天生高性能、可扩展,且可使用 Umi 生态中的大部分插件 - icon: https://gw.alipayobjects.com/zos/bmw-prod/d1ee0c6f-5aed-4a45-a507-339a4bfe076c/k7bjsocq_w144_h144.png title: 为组件开发而生 - desc: 独特的 Markdown 扩展,可嵌入 Demo、可导入外部 Demo 甚至插入自定义 React 组件,使得组件的文档不仅能看,还好用 + desc: 丰富的 Markdown 扩展,不止于渲染组件 demo,使得组件的文档不仅易于编写、管理,还好看、好用 + - icon: https://gw.alipayobjects.com/zos/bmw-prod/b8570f4d-c1b1-45eb-a1da-abff53159967/kj9t990h_w144_h144.png + title: 主题系统 + desc: 渐进式的自定义主题能力,小到扩展自己的 Markdown 标签,大到自定义完整主题包,全由你定 + - icon: https://gw.alipayobjects.com/zos/bmw-prod/b3e102cd-5dad-4046-a02a-be33241d1cc7/kj9t8oji_w144_h144.png + title: API 自动生成 + desc: 可基于 TypeScript 类型定义自动生成组件 API,组件永远『表里如一』 + - icon: https://gw.alipayobjects.com/zos/bmw-prod/3863e74a-7870-4874-b1e1-00a8cdf47684/kj9t7ww3_w144_h144.png + title: 移动端组件库研发 + desc: 安装主题包即可快速启用移动端组件研发能力,内置移动端高清渲染方案 + - icon: https://gw.alipayobjects.com/zos/bmw-prod/f093e060-726e-471c-a53e-e988ed3f560c/kj9t9sk7_w144_h144.png + title: 资产数据化能力 + desc: 一行命令将组件资产数据化,标准化的资产数据可与下游生产力工具串联 footer: Open-source MIT Licensed | Copyright © 2019-present
Powered by self --- -## 轻松上手 - -手动创建第一篇文档 - -```bash -// 创建组件开发的目录 -$ mkdir library && cd library - -// 安装 dumi -$ npm i dumi - -// 创建文档 -$ mkdir docs && echo '# Hello dumi!' > docs/index.md - -// 预览文档 -$ npx dumi dev -``` - ## 谁在使用 - + ## 反馈与共建 请访问 [GitHub](https://github.com/umijs/dumi) 或加入讨论群: - + diff --git a/docs/lab/index.md b/docs/lab/index.md index 73dd9a2923..b0b29e4d7d 100644 --- a/docs/lab/index.md +++ b/docs/lab/index.md @@ -1,120 +1,17 @@ --- -title: Lab nav: title: Lab + order: 5 sidemenu: false --- -The functions of the laboratory are only works in the next version, you can use npm i dumi@next to install the experimental version for experience; The experimental functions are unstable, please do not use it in production; If you have any suggestions, welcome to feedback and exchanges in the discussion group ❤ +The experimental functions are unstable, please do not use it in production. If you have any suggestions, welcome to feedback and exchanges in the discussion group ❤ -## Umi inregrated mode - -**Dependent version:**`dumi@1.1.0-beta.28+` - -When we are working a business project, it is a big headache for us to manage the components within project, because these components no need to release a npm package, but also need to be iterated, updated, documented, and handed over; The Umi interagted mode was born for this scene, it includes: - -- **Auto-detecting**: The integrated mode will be activated when the `dependencies` or `devDependencies` includes `umi` & `@umijs/preset-dumi` (`dumi` pacakge no longer needed) -- **Routes isolation**: All the dumi docs will be created under the `/~docs` route, it is isolated from the original project, just like prefix a specific path for all the dumi routes, user's menus and user's navs -- **Only development**: The Integrated moode only activate when the `NODE_ENV` is `development`, does not includes in the production bundle -- **Solo support**: We can get the non-integrated docs bundle for deployment via `umi build --dumi`, also available in `umi dev` - -To use the integrated mode, we can install the `@umijs/preset-dumi` into `devDependencies`, and configure `resolve.includes` as project needed (for example, use `src/components` as project's components directory). - -## Auto-gen component API - -**Dependent version:**`dumi@1.1.0-beta.27+` - -Now, we can get auto-gen component API tables via JS Doc + TypeScript definitions! - -### Type & doc comment in source code - -For generating API automatically, we need to ensure that dumi can devise the content of API via correct TypeScript definitions and doc comments. For example the `Hello` component: - -```tsx | pure -import React from 'react'; - -export interface IHelloProps { - /** - * write description here - * @description also can write description with property name - * @description.zh-CN support to write description for different locales - * @default support to set default value - */ - className?: string; // support to mark not required via TypeScript optional type -} - -const Hello: React.FC = () => <>Hello World!; - -export default Hello; -``` - -The API parse behind dumi is `react-docgen-typescript`,check out its [documentation](https://github.com/styleguidist/react-docgen-typescript#example) to get more definitions & comments usage. - -### Show API in documentation - -Based on the correct source code, we can render the API table via `API` builtin component in Markdown: - -```md - - - - - - - - - - - -``` - -After that, we will get: - - - -### Control API table rendering - -Like other builtin components, we can also override the `API` builtin component via theme API, just need to create a `.dumi/theme/builtins/API.tsx` (local theme), or create a theme package that contains the `API.tsx`, and import `useApiData` hook from `dumi/theme`, then we can control rendering as you like. Please refer the implementation of default [API component](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx). - -## Markdown file embed - -**Dependent version:**`dumi@1.1.0-beta.25+` - -In any markdown file, we can embed part or all of the another Markdown file via `embed` tag, it is better to manage our docs: - -```md - - - - - - - - - - - -``` - -## Develop mobile library - -**Dependent versions:**`dumi@1.1.0-beta.18+` & `dumi-theme-mobile` - -It is easy to use, just make sure you are using the beta version of dumi, and have been installed the `dumi-theme-mobile` into your dependencies, then dumi will switch to the mobile library development mode. This mode includes the following features: - -1. Mobile simulated container with CSS sticky + iframe embedded demo -2. Auto-enable rem ability (Base on [750 mode](https://github.com/umijs/umi-hd#%E6%95%B4%E4%BD%93%E4%BB%8B%E7%BB%8D) of umi-hd) -3. QRCode for preview on the real device - -Mobile theme preview - ## Motions -**Dependent version:**`dumi@1.1.0-beta.13+` - -The name has not been thought out yet, it can be understood as a Demo action. If the developer writes `motions` in advanced when writing a Demo, for example, write it like this: +It can be understood as a Demo action. If the developer writes motions in advanced when writing a Demo, for example, write it like this: ```tsx | pure /** @@ -136,7 +33,7 @@ export default () => { - @@ -144,7 +41,8 @@ export default () => { }; ``` -You will get the following Demo, try to click the play button on the operation bar, the `motions` predefined by developer will be executed in sequence: +You will get the following Demo, try to click the play button on the operation bar, the motions predefined by developer will be executed in sequence: + ```tsx /** @@ -166,7 +64,7 @@ export default () => { - @@ -174,192 +72,12 @@ export default () => { }; ``` -Currently supports the following `motion` syntax: +Currently supports the following motion syntax: -- `autoplay`: The motion will be executed automatically in the first place, and `loop` will be supported in the future -- `click:selector`: here is a CSS selector, which is used to click on a selector -- `timeout:number`: here is a number, which is used to wait for a time before executing the next step, such as waiting for the transition animation to complete -- `capture:selector`: here is a CSS selector, which is used for `postMessage`. This selector can be extended in the future in combination with snapshots and other scenarios. The content of the message data sent is like: +- `autoplay`: The motion will be executed automatically in the first place, and loop will be supported in the future +- `click:selector`: Following the colon is a CSS selector, which is used to click on a selector +- `timeout:number`: Following the colon is a number, which is used to wait for a certain time before executing the next step, such as waiting for the transition animation to complete +- `capture:selector`: Following the colon is a CSS selector, which is used for `postMessage`. This selector can be extended in the future in combination with snapshots and other scenarios. The content of the message data sent is: ```js { type: 'dumi:capture-element', value: 'selector' } ``` - -## Custom theme - -**Dependent version:**`dumi@1.1.0-beta.7+` - -### Development - -#### Directory Structure - -Method one, Create a package starting with `dumi-theme-` or `@group/dumi-theme-`, here takes a theme using the default as an example: - -```bash -. -├── package.json -└── src - ├── builtins # [Convention] Built-in component folder, dumi will look for `j|tsx` in **first-level directory** to mount, the components in this folder can be used directly in md - ├── components # [Non-Convention] The components extracted by the theme package in this folder. The folder name is customized by the developer - ├── layout.tsx # [Convention] You can custom your own layout component, props.children is the content of each markdown, developers can control the navigation, sidebar and content rendering by themselves - ├── layouts # [Convention] A custom layouts directory, used when you need to customize multiple layouts - │ ├── index.tsx # [Convention] Same as src/layout.tsx, choose one of the two methods, layout.tsx has higher priority - │ └── demo.tsx # [Convention] Separate route (~demos/:uuid) layout for custom component demo - └── style # [Non-Convention] Theme package style sheet -``` - -Here, `[Convention]` means a necessary structure for the theme package, and `[Non-Convention]` means that developers can control according to their own habits. - -Method two, create a `.dumi/theme` folder in the local project, **consider this folder as the `src` directory above, and write a custom theme directly**, for example, create `.dumi/theme/layout.tsx` to customize the layout; This method is suitable for theme packages that do not need to be released, which is easier to debug. - -#### Component Guarantee - -It supports components that partially cover the official theme. If the theme package is not provided in `builtins`, dumi will guarantee to the default theme `Previewer` component. The components that will be guaranteed are as follows: - -1. `Previewer.tsx` - For demo wrapper -2. `SourceCode.tsx` - For code block and highlighting it -3. `Alert.tsx` - For alert box -4. `Badge.tsx` - For badge - -In addition, `layout.tsx` (or `layouts/index.tsx`) will also be guaranteed. If you only want to control the rendering of the text area, you can choose to wrap the `layout` of the default theme, and code the `children` of `layout` to achieve. For example, add a feedback button to the text area: - -```tsx | pure -// src/layout.tsx -import React from 'react'; -import Layout from 'dumi-theme-default/src/layout'; - -export default ({ children, ...props }) => ( - - <> - - {children} - - -); -``` - -#### Theme API - -In order to customize the theme, dumi provides a set of theme APIs, you can import the following from `dumi/theme`: - -1. `context` - You can get the configurations of dumi, meta information of the current route, international language options, etc. The detailed definition of the context can be viewd source code -2. `Link` - The wrapped umi `Link` can render external links -3. `NavLink` - The wrapped umi `NavLink` can render external links -4. `AnchorLink` - The wrapped umi `NavLink` can be used for links with anchor points, and can be highlighted -5. `useCodeSandbox` - Generate a function based on the props of `Previewer`, and open the demo in codesandbox.io -6. `useCopy` - Provide copy function and copy status to achieve to copy source code -7. `useSearch` - Automatically provide algolia binding functions according to configuration or return search results according to keywords -8. `useLocaleProps` - Automatically filter props according to locale to achieve to the definition of international frontmatter. For example, `title.zh-CN` will be converted to `title` in Chinese language -9. `useDemoUrl` - Get the single demo page url via demo identifier, for example, `useDemoUrl(props.identifier)` may return like `http://example.com/~demos/demo-id` -10. `useApiData` - Get API meta data for specific component, please refer the implementation of default [API component](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx) -11. `useTSPlaygroundUrl` - Get the TypeScript Playground url, to transform TSX to JSX via the Playground site - -### Debug and usage - -If the developed theme package is a npm package, take the developed theme package npm link (debugging) or npm install (used) into the project, and make sure that it is declared in `devDependencies` or `dependencies`, dumi will automatically mount this theme, for example: - -```json -{ - "dependencies": { - "dumi-theme-default": "0.0.0" - } -} -``` - -If the developed theme package is in the form of the `.dumi/theme` directory, dumi will automatically mount it and you can debug directly. - -## Use with Umi UI - -**Dependent versions:**`dumi@1.1.0-beta.0+` & `@umijs/preset-ui@2.2.0+` - -The usage process is shown in the figure below: - -

- -

- -### Usage - -#### 1. Initialize the dumi component to develop project - -```bash -$ mkdir dumi-lib && cd dumi-lib -$ npx @umijs/create-dumi-lib -``` - -#### 2. Add asset meta information for Demo - -Take the demo of the getting-started project as an example, open `src/Foo/index.md` and add the following frontmatter configuration: - -
-// src/Foo/index.md
-
-```jsx
-+ /**
-+  * title: Foo Demo
-+  * thumbnail: [The url of thumbnail]
-+  * previewUrl: [The url of preview]
-+  */
-import React from 'react';
-import { Foo } from 'dumi-lib';
-
-export default () => ;
-```
-
- -In addition to writing frontmatter in the source code, adding attributes to the `code` tag of the external Demo can also add meta information: - -```html - -``` - -#### 3. Enable metadata generation capabilities - -Add an script to `package.json` and declare the `dumiAssets` field, Umi UI will find asset metadata files based on this field: - -```diff -{ - "scripts": { -+ "postversion": "dumi assets" - }, -+ "dumiAssets": "assets.json" -} -``` - -Since `assets.json` does not need to control versions , please add `assets.json` to `gitignore`. - -#### 4. Build and generate asset metadata - -If it is just for testing, you can use `npm version` instead of `npm publish`, and then use link for testing: - -```bash -$ npm run build -$ npm version patch -m "build: bump version to %s" -``` - -#### 5. Use in Umi UI - -Initialize the Umi application, install Umi UI and link the component library we just made: - -```bash -$ mkdir umi-app && cd umi-app -$ npx @umijs/create-umi-app -$ npm i @umijs/preset-ui -D -$ npm link path/to/dumi-lib -``` - -In the `package.json` of the Umi application, manually add the component library as a dependency: - -```diff -{ - "dependencies": { - // other dependencies -+ "your-lib-package-name": "*" - } -} -``` - -Then start the Umi project as usual, you can see the Demo assets in the dumi-lib project in the floating bubble of Umi UI, and can be directly inserted into the page for using: - -

- -

diff --git a/docs/lab/index.zh-CN.md b/docs/lab/index.zh-CN.md index 7586504eec..41d3418ea7 100644 --- a/docs/lab/index.zh-CN.md +++ b/docs/lab/index.zh-CN.md @@ -1,119 +1,16 @@ --- -title: 实验室 nav: title: 实验室 + order: 5 sidemenu: false --- -实验室的功能仅在 next 版本中提供,可以使用 npm i dumi@next 安装实验版本进行体验;实验性质的功能可能不稳定,请谨慎用于生产;如果体验后有任何建议,欢迎在讨论群中进行反馈和交流 ❤ +实验性质的功能可能不稳定,请谨慎用于生产;如果体验后有任何建议,欢迎在讨论群中进行反馈和交流 ❤ -## Umi 项目集成模式 - -**依赖版本:**`dumi@1.1.0-beta.28+` - -在进行项目研发时,项目内部的组件库管理通常是一个很头疼的问题,既不需要发布单独的 npm 包,又需要进行迭代、更新、说明、交接;为了让项目内部组件库管理这件事变得更加轻松,dumi 推出了 Umi 项目集成模式: - -- **自动探测**:当 `dependencies` 或 `devDependencies` 中包含 `umi` 和 `@umijs/preset-dumi` 时,进入集成模式(不再需要单独安装 `dumi` 这个包) -- **相互隔离**:所有 dumi 文档都会集中在 `/~docs` 路由下,与原项目相互隔离、互不干扰,可以理解为标准 dumi 文档都加了一个特定路由前缀,也包括用户的导航和菜单路由配置 -- **不影响生产**:仅在 `NODE_ENV` 是 `development` 时集成,不影响项目的生产构建 -- **可单独构建**:如果需要单独构建文档做部署,可执行 `umi build --dumi`,即可得到一份非集成模式的 dumi 站点产物,`--dumi` 在 `umi dev` 命令下也是可用的 - -使用方式很简单:在已有 Umi 项目中安装 `@umijs/preset-dumi` 到 `devDependencies` 中,再根据需要配置 `resolve.includes` 即可(比如约定 `src/components` 目录下为业务组件库和组件库对应的文档)。 - -## 组件 API 自动生成 - -**依赖版本:**`dumi@1.1.0-beta.27+` - -现在,我们可以通过 JS Doc 注解 + TypeScript 类型定义的方式实现组件 API 的自动生成了! - -### 组件源码中的类型和注解 - -组件 API 自动生成的前提是,确保 dumi 能够通过 TypeScript 类型定义 + 注解推导出 API 的内容,例如 `Hello` 组件的源代码: - -```tsx | pure -import React from 'react'; - -export interface IHelloProps { - /** - * 可以这样写属性描述 - * @description 也可以显式加上描述名 - * @description.zh-CN 还支持不同的 locale 后缀来实现多语言描述 - * @default 支持定义默认值 - */ - className?: string; // 支持识别 TypeScript 可选类型为非必选属性 -} - -const Hello: React.FC = () => <>Hello World!; - -export default Hello; -``` - -dumi 后背的类型解析工具是 `react-docgen-typescript`,更多类型和注解的用法可参考 [它的文档](https://github.com/styleguidist/react-docgen-typescript#example)。 - -### 在文档中展示 API - -有了能够推导 API 的源代码,我们就可以在 Markdown 中通过 `API` 内置组件来渲染 API 表格: - -```md - - - - - - - - - - - -``` - -效果大致如下: - - - -### 自定义 API 表格渲染 - -和其他内置组件一样,`API` 组件也支持通过 theme API 进行复写,只需要创建 `.dumi/theme/builtins/API.tsx`(本地主题)或者创建一个包含 `API.tsx` 的主题包,结合 `dumi/theme` 暴露的 `useApiData` hook,即可自行控制 API 表格的渲染,可参考 dumi 默认主题的 [API 组件实现](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx)。 - -## Markdown 文件嵌入 - -**依赖版本:**`dumi@1.1.0-beta.25+` - -我们可以通过 `embed` 标签在 Markdown 文件中引用另一个 Markdown 文件的部分或全部内容,可以使得文档组织和管理更加灵活: - -```md - - - - - - - - - - - -``` - -## 移动端组件研发 - -**依赖版本:**`dumi@1.1.0-beta.18+` & `dumi-theme-mobile` - -使用方式很简单,确保项目是 dumi 最新的 beta 版且安装 `dumi-theme-mobile` 到 `devDependencies` 中即可,dumi 将会从默认的 PC 组件库研发切换为移动端组件研发。目前包含如下能力: - -1. sticky 手机模拟容器 + iframe 预览 demo -2. 预览 demo 时自动处理 rem(基于 umi-hd 的 [750 模式](https://github.com/umijs/umi-hd#%E6%95%B4%E4%BD%93%E4%BB%8B%E7%BB%8D)) -3. 提供二维码便于真机预览 - -移动端主题预览效果 - ## Motions -**依赖版本:**`dumi@1.1.0-beta.13+` - 中文名还没想好,可以理解为 Demo 动作,开发者如果在编写 Demo 的时候预先写好 `motions`,比如这么写: ```tsx | pure @@ -136,7 +33,7 @@ export default () => { - @@ -166,7 +63,7 @@ export default () => { - @@ -183,183 +80,3 @@ export default () => { ```js { type: 'dumi:capture-element', value: 'selector' } ``` - -## 自定义主题 - -**依赖版本:**`dumi@1.1.0-beta.7+` - -### 开发方式 - -#### 目录结构 - -方式一,创建包名为 `dumi-theme-` or `@group/dumi-theme-` 开头的包,目录结构以默认主题为例: - -```bash -. -├── package.json -└── src - ├── builtins # [约定] 内置组件文件夹,dumi 会寻找**一级目录**下的 `j|tsx` 进行挂载,该文件夹下的组件可直接在 md 中使用 - ├── components # [非约定] 主题包自身为了可维护性抽取出来的组件,文件夹名称随开发者自定义 - ├── layout.tsx # [约定] 自定义的 layout 组件,props.children 即每个 md 的内容,开发者可自行控制导航、侧边栏及内容渲染 - ├── layouts # [约定] 自定义的 layouts 目录,在需要自定义多个 layout 时使用 - │ ├── index.tsx # [约定] 等同于 src/layout.tsx,两种方式二选一,layout.tsx 优先级更高 - │ └── demo.tsx # [约定] 自定义组件 demo 单独路由(~demos/:uuid)的 layout - └── style # [非约定] 主题包的样式表 -``` - -其中 `[约定]` 意味着是主题生效的必备结构,`[非约定]` 则意味着开发者可以根据自己的习惯进行控制。 - -方式二,在本地项目中创建 `.dumi/theme` 文件夹,**将该文件夹当做上面的 `src` 目录,直接编写自定义主题即可**,例如,创建 `.dumi/theme/layout.tsx` 以自定义 layout;此方式适用于不需要发布的主题包,也更容易进行调试。 - -#### 组件兜底 - -支持部分覆盖官方主题的组件,如果主题包没有在 `builtins` 下面提供,dumi 则会兜底到默认主题的 `Previewer` 组件。会进行兜底的组件如下: - -1. `Previewer.tsx` - 渲染 demo 包裹器 -2. `SourceCode.tsx` - 渲染代码块并高亮 -3. `Alert.tsx` - 渲染提示框 -4. `Badge.tsx` - 渲染标签 - -另外,`layout.tsx`(或 `layouts/index.tsx`)也会进行兜底,如果只希望控制正文区域的渲染,可以选择包裹默认主题的 `layout`、控制 `layout` 的 `children` 来实现。例如,给正文区域增加一个反馈按钮: - -```tsx | pure -// src/layout.tsx -import React from 'react'; -import Layout from 'dumi-theme-default/src/layout'; - -export default ({ children, ...props }) => ( - - <> - - {children} - - -); -``` - -#### 主题 API - -为了便于自定义主题,dumi 提供了一套主题 API,可以从 `dumi/theme` 中 import 出以下内容: - -1. `context` - 可获取到 dumi 的配置项、当前路由的 meta 信息、国际化语言选择项等等,context 的详细定义可 查看源代码 -2. `Link` - 包装后的 umi `Link`,可渲染外链 -3. `NavLink` - 包装后的 umi `NavLink`,可渲染外链 -4. `AnchorLink` - 包装后的 umi `NavLink`,用于带锚点的链接,且可高亮 -5. `useCodeSandbox` - 根据 `Previewer` 的 props 生成一个函数,执行后可在 codesandbox.io 打开该 demo -6. `useCopy` - 提供复制函数及复制的状态,便于实现源代码复制 -7. `useSearch` - 根据配置自动提供 algolia 的绑定函数或者根据关键字返回内置搜索的检索结果 -8. `useLocaleProps` - 根据 locale 自动过滤 props,便于实现国际化 frontmatter 的定义,比如 `title.zh-CN` 在中文语言下会被转换为 `title` -9. `useDemoUrl` - 获取单独打开 demo 的页面地址,例如 `useDemoUrl(props.identifier)` 会返回类似 `http://example.com/~demos/demo-id` 的 URL -10. `useApiData` - 获取指定组件的 API 元数据,可参考 dumi 默认主题的 [API 组件实现](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx) -11. `useTSPlaygroundUrl` - 获取当前 TypeScript 官网 Playground 的链接,用于将 TSX 代码提交到 Playground 中展示 JSX 代码 - -### 调试及使用 - -如果开发的主题包是 npm 包的形式,将开发好的主题包 npm link(调试)或 npm install(使用)到项目里,并确保它在 `devDependencies` 或者 `dependencies` 中有声明,dumi 将会自动挂载该主题,例如: - -```json -{ - "dependencies": { - "dumi-theme-default": "0.0.0" - } -} -``` - -如果开发的主题包是本地主题 `.dumi/theme` 目录的形式,dumi 会自动挂载,可直接进行调试。 - -## 和 Umi UI 一起使用 - -**依赖版本:**`dumi@1.1.0-beta.0+` & `@umijs/preset-ui@2.2.0+` - -使用流程如下图所示: - -

- -

- -### 使用方式 - -#### 1. 初始化 dumi 组件开发项目 - -```bash -$ mkdir dumi-lib && cd dumi-lib -$ npx @umijs/create-dumi-lib -``` - -#### 2. 为 Demo 添加资产元信息 - -以初始化项目的 Demo 为例,打开 `src/Foo/index.md`,添加如下 frontmatter 配置: - -
-// src/Foo/index.md
-
-```jsx
-+ /**
-+  * title: Foo Demo
-+  * thumbnail: [缩略图的 URL 地址]
-+  * previewUrl: [预览的 URL 地址]
-+  */
-import React from 'react';
-import { Foo } from 'dumi-lib';
-
-export default () => ;
-```
-
- -除了在源代码中编写 frontmatter 以外,给外部 Demo 的 `code` 标签添加属性,也能实现元信息的添加: - -```html - -``` - -#### 3. 启用元数据生成能力 - -在 `package.json` 中添加一条 npm script,并声明 `dumiAssets` 字段,Umi UI 会根据此字段查找资产元数据文件: - -```diff -{ - "scripts": { -+ "postversion": "dumi assets" - }, -+ "dumiAssets": "assets.json" -} -``` - -由于 `assets.json` 不需要参与版本控制,请在 `gitignore` 中添加 `assets.json`。 - -#### 4. 构建并生成资产元数据 - -如果只是用于测试,可以用 `npm version` 来代替 `npm publish`,随后用 link 进行本地玩耍: - -```bash -$ npm run build -$ npm version patch -m "build: bump version to %s" -``` - -#### 5. 在 Umi UI 中使用 - -初始化 Umi 应用,安装 Umi UI 并 link 我们刚刚的组件库: - -```bash -$ mkdir umi-app && cd umi-app -$ npx @umijs/create-dumi-app -$ npm i @umijs/preset-ui -D -$ npm link path/to/dumi/lib -``` - -在 Umi 应用的 `package.json` 中,手动添加组件库为依赖: - -```diff -{ - "dependencies": { - // 其他依赖 -+ "your-lib-package-name": "*" - } -} -``` - -然后和往常一样启动 Umi 项目,即可在 Umi UI 的迷你气泡中看到 dumi-lib 项目中的 Demo 资产,并可直接插入到页面中使用: - -

- -

diff --git a/docs/plugin/index.md b/docs/plugin/index.md new file mode 100644 index 0000000000..169e2b15d7 --- /dev/null +++ b/docs/plugin/index.md @@ -0,0 +1,232 @@ +--- +toc: menu +nav: + title: Plugin + order: 4 +--- + +# Plugin + +## How to use + +Install the plugin npm package to the `devDependencies` of the project to enable the plugin, for example: + +```bash +$ npm i @umijs/plugin-name -D +``` + +If the plug-in provides configuration items, please configure in `config/config.ts` or `.umirc.ts`, for example: + +```ts +export default { + // Other configuration items + field: {}, +} +``` + +## Plugin list + +Behind dumi is Umi. **This means that most of the plugins in the Umi ecosystem can work with dumi**. + +Here is only a list of plugins that may be used in component development. For more plugins, please visit [Umi's official document](https://umijs.org/plugins/plugin-access). + +### `@umijs/plugin-analytics` + +- **Introduction:** Enable [Google Analytics](https://analytics.google.com/analytics/web) or [Baidu Statistics](https://tongji.baidu.com) for documents +- **Configuration:** + +```ts +export default { + analytics: { + // Google Analytics code, will be enabled after configuration + ga: 'google analytics code', + // Baidu statistics code, will be enabled after configuration + baidu: '5a66cxxxxxxxxxx9e13', + }, +} +``` + +For more information, please visit: [Umi plugin - @umijs/plugin-analytics](https://umijs.org/zh-CN/plugins/plugin-analytics). + +### `@umijs/plugin-sass` + +- **Introduction:** Enable Sass compilation support during component library development. **Note that whether the plugin is enabled or not has nothing to do with the component library building tool (father-build)**. If the component library itself uses Sass, we also need to enable father-build [Sass compilation support](https://github.com/umijs/father#sassinrollupmode) +- **Configuration:** + +```ts +export default { + sass: { + // The default value is Dart Sass. If you want to use Node Sass instead, you can install the node-sass dependency and use this configuration item + implementation: require('node-sass'), + // The configuration item passed to Dart Sass or Node Sass can be a Function + sassOptions: {}, + }, +} +``` + +For more information, please visit: [Umi plugin - @umijs/plugin-sass](https://umijs.org/zh-CN/plugins/plugin-sass). + +### `@umijs/plugin-esbuild` + +- **Introduction:** Use esbuild as the compressor of the document site product. It is an experimental feature and may have pits, but the compression speed effect is outstanding +- **Configuration:** + +```ts +export default { + esbuild: {}, // Enable esbuild compression +} +``` + +For more information, please visit: [Umi plugin - @umijs/plugin-esbuild](https://umijs.org/zh-CN/plugins/plugin-esbuild). + +## Plugin development + +If the existing plugins cannot meet the needs, or you want to customize some behaviors of dumi, you can develop your own plug-in to achieve this, and create a `plugin.ts` in the project: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default (api: IApi) => { + // Write plugin content +} +``` + +Then enable it in the dumi configuration file: + +```ts +export default { + plugins: ['/path/to/plugin.ts'], +} +``` + +## Plugin API + +The basic plugin API is provided by Umi and includes the following APIs. + + + +In addition, in order to facilitate plugin developers to customize dumi's behavior, dumi provides the following plugin APIs. + +### `dumi.getRootRoute` + +Used to get the root route of the document part in the `routes` configuration. + +**This API is only used to get routes**. If you need to modify it, please use the `modifyRoutes` API below. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default async (api: IApi) => { + const rootRoute = await api.applyPlugins({ + key: 'dumi.getRootRoute', + type: api.ApplyPluginsType.modify, + initialValue: routes, + }); +} +``` + +### `dumi.modifyAssetsMeta` + +Used to modify the asset metadata produced by the `dumi assets` command. + +If you don’t know what asset metadata is, you can visit [Advanced - UI assets meta data](/guide/advanced#ui-assets-meta-data). + +This API is usually used to customize the asset metadata content of your team. For example, there is an internal service that automatically generates demo thumbnails. + +You can use this method to modify the asset metadata that is finally entered into the npm package. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import IAssetsPackage from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.modifyAssetsMeta', + fn(pkg: IAssetsPackage) { + // Process pkg and return new pkg + return pkg; + }, + }); +} +``` + +### `dumi.detectCodeBlock` + +When dumi is parsing Markdown, if it finds a React code block, it will trigger this hook and pass in the code block information. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { ExampleBlockAsset } from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectCodeBlock', + fn(block: ExampleBlockAsset) { + // You can do statistics, storage, etc. on the block + }, + }); +} +``` + +### `dumi.detectAtomAsset` + +When dumi is parsing Markdown, if the corresponding component asset is detected, this hook will be triggered and the information of the component will be passed in. + +For example, `src/Button/index.tsx` is a component asset. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { AtomAsset } from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectAtomAsset', + fn(atom: AtomAsset) { + // Statistics and storage of atom can be done + }, + }); +} +``` + +### `dumi.detectApi` + +When dumi is parsing Markdown, if it detects that it is automatically generated using API, this hook will be triggered and related API data will be transmitted. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectApi', + fn({ identifier, data }) { + // identifier is the API export identifier, data is the API attribute data + }, + }); +} +``` + +### `dumi.modifyThemeResolved` + +Used to modify the analysis result of dumi's theme package, usually used to customize unique theme behavior, such as adding built-in components through API. Calling method: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { IThemeLoadResult } from '@umijs/preset-dumi/lib/theme/loader'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.modifyThemeResolved', + fn(resolved: IThemeLoadResult) { + // Modify resolved and return + return resolved; + }, + }); +} +``` diff --git a/docs/plugin/index.zh-CN.md b/docs/plugin/index.zh-CN.md new file mode 100644 index 0000000000..0d90f1eee5 --- /dev/null +++ b/docs/plugin/index.zh-CN.md @@ -0,0 +1,222 @@ +--- +toc: menu +nav: + title: 插件 + order: 4 +--- + +# 插件 + +## 如何使用 + +安装插件 npm 包到项目的 `devDependencies` 即可启用该插件,例如: + +```bash +$ npm i @umijs/plugin-name -D +``` + +如果插件有提供配置项,请在 `config/config.ts` 或者 `.umirc.ts` 中进行配置,例如: + +```ts +export default { + // 其他配置项 + field: {}, +} +``` + +## 插件列表 + +dumi 的背后是 Umi,**这意味 Umi 生态的绝大部分插件都能和 dumi 一起工作**,这里仅列举组件研发可能会用到的插件列表,更多插件可以访问 [Umi 的官方文档](https://umijs.org/plugins/plugin-access)。 + +### `@umijs/plugin-analytics` + +- **简介:** 为文档启用 [Google Analytics](https://analytics.google.com/analytics/web) 或 [百度统计](https://tongji.baidu.com) +- **配置:** + +```ts +export default { + analytics: { + // Google Analytics 代码,配置后会启用 + ga: 'google analytics code', + // 百度统计代码,配置后会启用 + baidu: '5a66cxxxxxxxxxx9e13', + }, +} +``` + +更多信息可访问:[Umi 插件 - @umijs/plugin-analytics](https://umijs.org/zh-CN/plugins/plugin-analytics)。 + +### `@umijs/plugin-sass` + +- **简介:** 启用组件库开发期间的 Sass 编译支持,**注意,该插件启用与否与组件库构建工具(father-build)无关**,如果组件库本身使用了 Sass,我们还需要开启 father-build 的 [Sass 编译支持](https://github.com/umijs/father#sassinrollupmode) +- **配置:** + +```ts +export default { + sass: { + // 默认值 Dart Sass,如果要改用 Node Sass,可安装 node-sass 依赖,然后使用该配置项 + implementation: require('node-sass'), + // 传递给 Dart Sass 或 Node Sass 的配置项,可以是一个 Function + sassOptions: {}, + }, +} +``` + +更多信息可访问:[Umi 插件 - @umijs/plugin-sass](https://umijs.org/zh-CN/plugins/plugin-sass)。 + +### `@umijs/plugin-esbuild` + +- **简介:** 使用 esbuild 作为文档站点产物的压缩器,试验性功能,可能有坑,但压缩提速效果拔群 +- **配置:** + +```ts +export default { + esbuild: {}, // 启用 esbuild 压缩 +} +``` + +更多信息可访问:[Umi 插件 - @umijs/plugin-esbuild](https://umijs.org/zh-CN/plugins/plugin-esbuild)。 + +## 插件开发 + +如果现有的插件无法满足需求,或者你希望定制 dumi 的一些行为,则可以开发一个自己的插件来实现,在项目中创建一个 `plugin.ts`: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default (api: IApi) => { + // 编写插件内容 +} +``` + +然后在 dumi 配置文件中启用它即可: + +```ts +export default { + plugins: ['/path/to/plugin.ts'], +} +``` + +## 插件 API + +基础插件 API 由 Umi 提供,包含如下 API。 + + + +除此之外,为了便于插件开发者定制 dumi 的行为,dumi 提供了如下插件 API。 + +### `dumi.getRootRoute` + +用于在 `routes` 配置中拿到文档部分的根路由,**该 API 仅用于获取路由**,如果需要修改,请使用下方的 `modifyRoutes` API。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default async (api: IApi) => { + const rootRoute = await api.applyPlugins({ + key: 'dumi.getRootRoute', + type: api.ApplyPluginsType.modify, + initialValue: routes, + }); +} +``` + +### `dumi.modifyAssetsMeta` + +用于修改 `dumi assets` 命令产出的资产元数据,如果不了解什么是资产元数据,可访问 [进阶使用 - UI 资产数据化](/zh-CN/guide/advanced#ui-资产数据化)。 + +该 API 通常用于定制自己团队的资产元数据内容,比如内部有个自动生成 demo 缩略图的服务,可以通过该方式修改最终打进 npm 包的资产元数据。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import IAssetsPackage from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.modifyAssetsMeta', + fn(pkg: IAssetsPackage) { + // 处理 pkg 并返回新的 pkg + return pkg; + }, + }); +} +``` + +### `dumi.detectCodeBlock` + +dumi 在解析 Markdown 时、如果发现了 React 代码块,则会触发此钩子,并将该代码块的信息传入。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { ExampleBlockAsset } from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectCodeBlock', + fn(block: ExampleBlockAsset) { + // 可以对 block 做统计、存储等 + }, + }); +} +``` + +### `dumi.detectAtomAsset` + +dumi 在解析 Markdown 时、如果检测到对应的组件资产,会触发此钩子,并将该组件的信息传入,比如 `src/Button/index.tsx` 就是一个组件资产。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { AtomAsset } from 'dumi-assets-types'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectAtomAsset', + fn(atom: AtomAsset) { + // 可以对 atom 做统计、存储等 + }, + }); +} +``` + +### `dumi.detectApi` + +dumi 在解析 Markdown 时,如果检测到有使用 API 自动生成,会触发此钩子,并将相关 API 数据传。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.detectApi', + fn({ identifier, data }) { + // identifier 是 API 导出标识符,data 是 API 属性数据 + }, + }); +} +``` + +### `dumi.modifyThemeResolved` + +用于修改 dumi 的主题包解析结果,通常用于定制特有的主题行为,比如想通过 API 新增内置组件等。调用方式: + +```ts +// /path/to/plugin.ts +import { IApi } from 'dumi'; +import { IThemeLoadResult } from '@umijs/preset-dumi/lib/theme/loader'; + +export default (api: IApi) => { + api.register({ + key: 'dumi.modifyThemeResolved', + fn(resolved: IThemeLoadResult) { + // 修改 resolved 并返回 + return resolved; + }, + }); +} +``` diff --git a/docs/theme/api.md b/docs/theme/api.md new file mode 100644 index 0000000000..077aded933 --- /dev/null +++ b/docs/theme/api.md @@ -0,0 +1,114 @@ +--- +order: 3 +toc: menu +--- + +# Theme API + +In order to customize the theme, dumi provides a set of theme API, we can import the following from `dumi/theme`. + +## context + +You can get the configuration items of dumi, meta information of the current routing, international language options, etc. + +The detailed definition of context can be View source code. + +## Link + +The packaged umi `Link` can render external links and automatically add external link icons. + +## NavLink + +The packaged umi `NavLink` can render external links and automatically add external link icons. + +## AnchorLink + +The packaged umi `NavLink` is used for links with anchor points and can be highlighted. + +## useCodeSandbox + +- **props:** `Object`. The props received by the theme `Previewer` component +- **return:** `Function`. Open the execution function of the demo in CodeSandbox.io + +Generate a function based on the props of `Previewer`, and open the demo in [codesandbox.io](https://codesandbox.io) after execution, for example: + +```jsx | pure +// builtins/Previewer.tsx +import React from 'react'; +import { useCodeSandbox } from 'dumi/theme'; + +export default (props) => { + const openCSB = useCodeSandbox(props); + + return +} +``` + +## useCopy + +- **props:** none +- **return:** + - copyCode: `Function`. Copy the execution function, the text passed in during execution will be copied to the clipboard + - copyStatus: `'ready' |'copied'`. The default value is `ready`, it will become `copied` after the copy is executed, and then return to `ready` after 2s, which is convenient for developers to control the prompt message of successful copy + +Provide copy function and copy status to facilitate source code copy and status display, for example: + +```jsx | pure +// builtins/Previewer.tsx +import React from 'react'; +import { useCopy } from 'dumi/theme'; + +export default (props) => { + const [copyCode, copyStatus] = useCopy(); + + return ( + + ) +} + +``` + +## useSearch + +- **props:** `String`. The keyword of the current input box +- **return:** + - `Function`. If the user opens algolia, it will return to the binding function of algolia, and just pass in the CSS selector of the input box, and all subsequent filtering and rendering work will be handed over to algolia + - `Array`. If the user does not open algolia, it will return the keyword-based built-in search results, currently only the title can be searched + +According to the configuration, automatically provide algolia's binding function or return the search results of the built-in search according to the keyword. + +For specific usage, please refer to the [SearchBar component](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/components/SearchBar.tsx#L9) of dumi built-in themes. + +## useLocaleProps + +- **props:** + - locale:`String`. Current locale value + - props:`Object`. Props that need to be filtered and converted +- **return:** `Object`. Props after filtering and transformation + +Automatically filter and convert props according to locale to facilitate the realization of the internationalization of FrontMatter definitions. For example, `title.zh-CN` will be converted to `title` in Chinese language. + +For specific usage, please refer to the [Previewer component](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/Previewer.tsx#L72) of dumi built-in themes. + +## useDemoUrl + +- **props:** `String`. The `identifier` parameter received by the theme `Previewer` component, the unique identifier of the demo +- **return:** `String`. The address of the demo page opened separately + +Get the URL of the page that opened the demo separately. For example, `useDemoUrl(props.identifier)` will return a URL similar to `http://example.com/~demos/demo-id`. + +## useApiData + +- **props:** `String`. The `identifier` parameter received by the subject `API` component, the unique identifier of the API +- **return:** `Array`. Props property list + +To get the API metadata of the specified component, please refer to the [API component implementation](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx) of the dumi default theme. + +## useTSPlaygroundUrl + +- **props:** + - locale:`String`. Current language options + - code:`String`. The TSX code to be converted in TypeScript Playground +- **return:** `String`. The url go to TypeScript Playground + +Get the link to the Playground of the current TypeScript official website to submit the TSX code to the Playground to display the JSX code. diff --git a/docs/theme/api.zh-CN.md b/docs/theme/api.zh-CN.md new file mode 100644 index 0000000000..3652b59426 --- /dev/null +++ b/docs/theme/api.zh-CN.md @@ -0,0 +1,108 @@ +--- +order: 3 +toc: menu +--- + +# 主题 API + +为了便于自定义主题,dumi 提供了一套主题 API,我们可以从 `dumi/theme` 中 import 出以下内容。 + +## context + +可获取到 dumi 的配置项、当前路由的 meta 信息、国际化语言选择项等等,context 的详细定义可 查看源代码 + +## Link + +包装后的 umi `Link`,可渲染外链,自动加上外部链接图标。 + +## NavLink + +包装后的 umi `NavLink`,可渲染外链,自动加上外部链接图标。 + +## AnchorLink + +包装后的 umi `NavLink`,用于带锚点的链接,且可高亮。 + +## useCodeSandbox + +- **参数:** `Object`。主题 `Previewer` 组件接收到的 props +- **返回:** `Function`。在 CodeSandbox.io 打开 demo 的执行函数 + +根据 `Previewer` 的 props 生成一个函数,执行后可在 [codesandbox.io](https://codesandbox.io) 打开该 demo,例如: + +```jsx | pure +// builtins/Previewer.tsx +import React from 'react'; +import { useCodeSandbox } from 'dumi/theme'; + +export default (props) => { + const openCSB = useCodeSandbox(props); + + return +} +``` + +## useCopy + +- **参数:** 无 +- **返回:** + - copyCode:`Function`。拷贝执行函数,执行时传入的文本会被拷贝到剪贴板 + - copyStatus:`'ready' | 'copied'`。默认值为 `ready`,在执行拷贝后会变成 `copied`,2s 后再变回 `ready`,便于开发者控制复制成功的提示信息 + +提供复制函数及复制的状态,便于实现源代码复制和状态展示,例如: + +```jsx | pure +// builtins/Previewer.tsx +import React from 'react'; +import { useCopy } from 'dumi/theme'; + +export default (props) => { + const [copyCode, copyStatus] = useCopy(); + + return ( + + ) +} + +``` + +## useSearch + +- **参数:** `String`。当前输入框的关键字 +- **返回:** + - `Function`。如果用户开启 algolia,则返回 algolia 的绑定函数,将输入框的 CSS 选择器传入即可,后续筛选、呈现工作全部交给 algolia + - `Array`。如果用户未开启 algolia,则返回基于关键字的内置搜索结果,目前只能搜索标题 + +根据配置自动提供 algolia 的绑定函数或者根据关键字返回内置搜索的检索结果,具体用法可参考 dumi 内置主题的 [SearchBar 组件](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/components/SearchBar.tsx#L9)。 + +## useLocaleProps + +- **参数:** + - locale:`String`。当前 locale 值 + - props:`Object`。需要过滤、转换的 props +- **返回:** `Object`。过滤、转换之后的 props + +根据 locale 自动过滤、转换 props,便于实现国际化 FrontMatter 的定义,比如 `title.zh-CN` 在中文语言下会被转换为 `title`,具体示例可参考 dumi 内置主题的 [Previewer 组件](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/Previewer.tsx#L72)。 + +## useDemoUrl + +- **参数:** `String`。主题 `Previewer` 组件接收到的 `identifier` 参数,demo 的唯一标识符 +- **返回:** `String`。demo 单独打开的页面地址 + +获取单独打开 demo 的页面地址,例如 `useDemoUrl(props.identifier)` 会返回类似 `http://example.com/~demos/demo-id` 的 URL。 + +## useApiData + +- **参数:** `String`。主题 `API` 组件接收到的 `identifier` 参数,API 的唯一标识符 +- **返回:** `Array`。Props 属性列表 + +获取指定组件的 API 元数据,可参考 dumi 默认主题的 [API 组件实现](https://github.com/umijs/dumi/blob/master/packages/theme-default/src/builtins/API.tsx)。 + +## useTSPlaygroundUrl + +- **参数:** + - locale:`String`。当前的语言选项 + - code:`String`。要在 TypeScript Playground 中转换的 TSX 代码 +- **返回:** `String`。前往 TypeScript Playground 的 url + +获取当前 TypeScript 官网 Playground 的链接,用于将 TSX 代码提交到 Playground 中展示 JSX 代码。 diff --git a/docs/theme/development.md b/docs/theme/development.md new file mode 100644 index 0000000000..17ba11f214 --- /dev/null +++ b/docs/theme/development.md @@ -0,0 +1,108 @@ +--- +order: 2 +toc: menu +--- + +# Theme development + +It is very easy to develop dumi themes. + +To cope with different scenarios, dumi provides two theme development methods: + +1. Create a `.dumi/theme` folder in the root directory of the dumi project, usually used for special customization in the project, regardless of reusability +2. Create an npm package starting with `@group/dumi-theme-` or `dumi-theme-`, which is usually used to develop a complete theme package for easy sharing with other projects + +There is no barrier between the two methods, which means that we can debug the theme package in the first method first, and send a separate npm package after the theme package is stable. + +## Directory Structure + +Let's take a look at the standard dumi theme package structure: + + +
    +
  • + builtins + Built-in component folder, dumi will look for j|tsx under first-level directory to mount, the components under this folder can be used directly in md +
  • +
  • + components + [Non-agreement] The theme package itself is a component extracted for maintainability, the folder name is customized by the developer +
  • +
  • + style + [Non-agreement] Theme package style sheet +
  • +
  • + layout.tsx + Custom layout component, props.children is the content of each md, developers can control the navigation, sidebar and content rendering by themselves +
  • +
  • + layouts + Custom layouts directory, used when you need to customize multiple layouts +
      +
    • + index.tsx + Same as src/layout.tsx, choose one of the two methods, layout.tsx has higher priority +
    • +
    • + demo.tsx + Custom component demo separate routing (~demos/:uuid) layout +
    • +
    +
  • +
+
+ +## Incremental customization + +The directory structure does not seem simple? + +In fact, all the above content can be customized incrementally.If a necessary file is not provided in the theme package, the default theme of dumi will be found. + +The following files will be included: + +1. `builtins/Previewer.tsx` - Render demo wrapper +2. `builtins/SourceCode.tsx` - Render code block and highlight +3. `builtins/Alert.tsx` - Render alert +4. `builtins/Badge.tsx` - Render badge +5. `layout.tsx` - The default global layout + +## Custom body area + +If you only want to control the rendering of the text area, you can choose the `layout` that wraps the default theme and the `children` that controls the `layout`. + +For example, add a feedback button to the text area: + +```tsx | pure +// src/layout.tsx +import React from 'react'; +import Layout from 'dumi-theme-default/src/layout'; + +export default ({ children, ...props }) => ( + + <> + + {children} + + +); +``` + +## Development, debugging and use + +The so-called theme development is essentially writing React components, but in order to reduce the cost of writing components, dumi provides a set of theme APIs and opens many dumi's built-in capabilities and data, which can help us quickly complete the theme development, see [Theme-Theme API](/theme/api). + +Constant debugging is required during the development of the theme. + +For local themes, dumi is fully automatically detected. As long as the `.dumi/theme` folder exists, dumi will be mounted during build; for independent theme npm packages, it needs to be written into `devDependencies `And link the npm package to the project, dumi will automatically mount the theme, for example: + +```json +{ + "dependencies": { + "dumi-theme-default": "0.0.0" + } +} +``` + +- Local theme: The use and debugging of the theme is similar +- npm package: The user only needs to execute `npm install dumi-theme-[name] -D` to complete the installation of the theme package and start dumi When the theme will be automatically mounted diff --git a/docs/theme/development.zh-CN.md b/docs/theme/development.zh-CN.md new file mode 100644 index 0000000000..3f71bdbf47 --- /dev/null +++ b/docs/theme/development.zh-CN.md @@ -0,0 +1,98 @@ +--- +order: 2 +toc: menu +--- + +# 主题开发 + +开发 dumi 主题非常容易,为了应对不同的场景,dumi 提供了两种主题开发方式: + +1. 在 dumi 项目根目录创建 `.dumi/theme` 文件夹,通常用于项目中的特殊自定义,不考虑复用性 +2. 创建 `@group/dumi-theme-` 或 `dumi-theme-` 开头的 npm 包 ,通常用于研发完整的主题包,便于共享给其他项目使用 + +这两种方式之间并无隔阂,这意味着我们初期可以先走第一种方式调试主题包,待主题包稳定后单独发一个 npm 包即可。 + +## 目录结构 + +先来看一下标准的 dumi 主题包结构: + + +
    +
  • + builtins + 内置组件文件夹,dumi 会寻找一级目录下的 j|tsx 进行挂载,该文件夹下的组件可直接在 md 中使用 +
  • +
  • + components + [非约定] 主题包自身为了可维护性抽取出来的组件,文件夹名称随开发者自定义 +
  • +
  • + style + [非约定] 主题包的样式表 +
  • +
  • + layout.tsx + 自定义的 layout 组件,props.children 即每个 md 的内容,开发者可自行控制导航、侧边栏及内容渲染 +
  • +
  • + layouts + 自定义的 layouts 目录,在需要自定义多个 layout 时使用 +
      +
    • + index.tsx + 等同于 src/layout.tsx,两种方式二选一,layout.tsx 优先级更高 +
    • +
    • + demo.tsx + 自定义组件 demo 单独路由(~demos/:uuid)的 layout +
    • +
    +
  • +
+
+ +## 增量自定义 + +目录结构看起来并不简单?其实上述所有内容都可以增量自定义,如果某个必要文件该主题包没有提供,则会兜底到 dumi 的默认主题,会进行兜底的文件如下: + +1. `builtins/Previewer.tsx` - 渲染 demo 包裹器 +2. `builtins/SourceCode.tsx` - 渲染代码块并高亮 +3. `builtins/Alert.tsx` - 渲染提示框 +4. `builtins/Badge.tsx` - 渲染标签 +5. `layout.tsx` - 默认的全局 layout + +## 自定义正文区域 + +如果只希望控制正文区域的渲染,可以选择包裹默认主题的 `layout`、控制 `layout` 的 `children` 来实现。例如,给正文区域增加一个反馈按钮: + +```tsx | pure +// src/layout.tsx +import React from 'react'; +import Layout from 'dumi-theme-default/src/layout'; + +export default ({ children, ...props }) => ( + + <> + + {children} + + +); +``` + +## 开发、调试及使用 + +所谓的主题开发,本质上还是写 React 组件,但为了降低写组件的成本,dumi 提供了一套主题 API、开放了许多 dumi 内置的能力和数据,可以帮我们快速完成主题的开发,详见 [主题 - 主题 API](/zh-CN/theme/api)。 + +主题开发的过程中需要不断调试。对于本地主题而言,dumi 是完全自动检测的,只要存在 `.dumi/theme` 文件夹,dumi 就会在构建时进行挂载;对于独立的主题 npm 包而言,需要将其写入 `devDependencies`,并且将该 npm 包 link 到项目下,dumi 将会自动挂载该主题,例如: + +```json +{ + "dependencies": { + "dumi-theme-default": "0.0.0" + } +} +``` + +- 本地主题:使用和调试是类似的 +- npm 包:用户只需要执行 `npm install dumi-theme-[name] -D` 即可完成主题包的安装,启动 dumi 时主题将会被自动挂载 diff --git a/docs/theme/index.md b/docs/theme/index.md new file mode 100644 index 0000000000..43a0b8cd2c --- /dev/null +++ b/docs/theme/index.md @@ -0,0 +1,59 @@ +--- +title: Theme list +order: 1 +toc: menu +nav: + title: Theme + order: 2 +--- + +## `dumi-theme-default` + +- **Code address:** [dumi/packages/theme-default](https://github.com/umijs/dumi/tree/master/packages/theme-default) +- **Experience address:** [dumi official website](https://d.umijs.org) +- **Theme introduction:** Built-in themes of dumi + +## `dumi-theme-mobile` + +- **Code address:** [dumi/packages/theme-mobile](https://github.com/umijs/dumi/tree/master/packages/theme-mobile) +- **Experience address:** (Missing) +- **Theme introduction:** The mobile terminal research and development theme based on the dumi default theme extension +It will have the following characteristics: + 1. Sticky mobile phone simulation container + iframe preview demo + 2. Based on [umi-hd](https://github.com/umijs/umi-hd) provide automatic settings of `viewport` and root `font-size` for demo preview + 3. Provide QR code for real machine preview + +Mobile theme preview effect + +It should be noted that if you use the responsive scheme of rem, the rem unit should also be used in the style source code. + +It is recommended to refer to the antd-mobile scheme and set the Less variable as [the basic unit](https://github.com/ant-design/ant-design-mobile/blob/next/packages/antd-mobile-styles/src/base/variables.less#L4), and then as needed configure [HD variables at compile time](https://github.com/ant-design/ant-design-mobile/blob/next/config/config.ts#L96) control the final rendering value. + +The HD solution can be switched through the `themeConfig` configuration item in the dumi configuration file, the configuration method is as follows: + +```ts +// .umirc.ts +export default { + // ... + themeConfig: { + hd: { + // umi-hd 750 HD solution (default value) + [{ mode: 'vw', options: [100, 750] }], + // Disable HD + rules: [], + // Switch HD schemes according to different device screen width breakpoints + rules: [ + { maxWidth: 375, mode: 'vw', options: [100, 750] }, + { minWidth: 376, maxWidth: 750, mode: 'vw', options: [100, 1500] }, + ], + // More rule: https://github.com/umijs/dumi/blob/master/packages/theme-mobile/src/typings/config.d.ts#L7 + } + } +} +``` + +## Vacant + +If you have created a good dumi theme and want to share it with everyone. + +Please send your theme information through Pull Request [to this document](https://github.com/umijs/dumi/edit/master/docs/theme/index.md). diff --git a/docs/theme/index.zh-CN.md b/docs/theme/index.zh-CN.md new file mode 100644 index 0000000000..38f342ee9d --- /dev/null +++ b/docs/theme/index.zh-CN.md @@ -0,0 +1,54 @@ +--- +title: 主题列表 +order: 1 +toc: menu +nav: + title: 主题 + order: 2 +--- + +## `dumi-theme-default` + +- **仓库地址:** [dumi/packages/theme-default](https://github.com/umijs/dumi/tree/master/packages/theme-default) +- **体验地址:** [dumi 官网](https://d.umijs.org) +- **主题简介:** dumi 的内置主题 + +## `dumi-theme-mobile` + +- **仓库地址:** [dumi/packages/theme-mobile](https://github.com/umijs/dumi/tree/master/packages/theme-mobile) +- **体验地址:**(缺失) +- **主题简介:** 基于 dumi 默认主题扩展的移动端研发主题,特性如下: + 1. sticky 手机模拟容器 + iframe 预览 demo + 2. 基于 [umi-hd](https://github.com/umijs/umi-hd) 为 demo 预览提供 `viewport` 和 root `font-size` 的自动设置 + 3. 提供二维码便于真机预览 + +移动端主题预览效果 + +需要注意的是,如果使用 rem 的响应式方案,在样式源代码中也要采用 rem 单位,建议参考 antd-mobile 的方案,设置 Less 变量[作为基础单位](https://github.com/ant-design/ant-design-mobile/blob/next/packages/antd-mobile-styles/src/base/variables.less#L4),再根据需要[在编译时配置高清变量](https://github.com/ant-design/ant-design-mobile/blob/next/config/config.ts#L96)控制最终渲染值。 + +高清方案可以在 dumi 配置文件中通过 `themeConfig` 配置项切换,配置方式如下: + +```ts +// .umirc.ts +export default { + // ... + themeConfig: { + hd: { + // umi-hd 的 750 高清方案(默认值) + [{ mode: 'vw', options: [100, 750] }], + // 禁用高清方案 + rules: [], + // 根据不同的设备屏幕宽度断点切换高清方案 + rules: [ + { maxWidth: 375, mode: 'vw', options: [100, 750] }, + { minWidth: 376, maxWidth: 750, mode: 'vw', options: [100, 1500] }, + ], + // 更多 rule 配置访问 https://github.com/umijs/dumi/blob/master/packages/theme-mobile/src/typings/config.d.ts#L7 + } + } +} +``` + +## 虚位以待 + +如果你创建了不错的 dumi 主题、想分享给大家使用,请将你的主题信息通过 Pull Request [更新到此文档](https://github.com/umijs/dumi/edit/master/docs/theme/index.zh-CN.md)。 diff --git a/package.json b/package.json index 5ea43d9548..99f2fe8ff8 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ ], "private": true, "scripts": { - "dev": "cross-env BROWSER=none node ./packages/dumi/bin/dumi.js dev", - "dev:mobile": "cross-env BROWSER=none DUMI_THEME=./packages/theme-mobile node ./packages/dumi/bin/dumi.js dev", + "dev": "npm run doc:sync && cross-env BROWSER=none node ./packages/dumi/bin/dumi.js dev", + "dev:mobile": "npm run doc:sync && cross-env BROWSER=none DUMI_THEME=./packages/theme-mobile node ./packages/dumi/bin/dumi.js dev", + "doc:build": "npm run doc:sync && cross-env BROWSER=none node ./packages/dumi/bin/dumi.js build", + "doc:sync": "node scripts/sync-from-umi.js", "watch": "npm run build -- --watch", - "doc:build": "cross-env BROWSER=none node ./packages/dumi/bin/dumi.js build", "build": "father-build", "changelog": "lerna-changelog", "clean": "lerna clean -y", diff --git a/packages/dumi/README.md b/packages/dumi/README.md index a66eac70d1..acb1d2b032 100644 --- a/packages/dumi/README.md +++ b/packages/dumi/README.md @@ -32,7 +32,7 @@ $ yarn dev
@@ -42,8 +42,7 @@ $ yarn dev

@@ -53,8 +52,7 @@ $ yarn dev

@@ -64,19 +62,19 @@ $ yarn dev

react-component
+ +
@@ -86,8 +84,7 @@ $ yarn dev

@@ -97,8 +94,7 @@ $ yarn dev

@@ -108,8 +104,7 @@ $ yarn dev

diff --git a/packages/preset-dumi/src/api-parser/index.test.ts b/packages/preset-dumi/src/api-parser/index.test.ts index 1bbe8cf535..7fe8f1815b 100644 --- a/packages/preset-dumi/src/api-parser/index.test.ts +++ b/packages/preset-dumi/src/api-parser/index.test.ts @@ -9,7 +9,7 @@ const expectPath = path.join(__dirname, 'fixtures', 'expect'); function assertResult(filename) { expect(winEOL(JSON.stringify(parser(path.join(rawPath, filename)), null, 2))).toEqual( winEOL( - fs.readFileSync(path.join(expectPath, `${path.basename(filename, '.tsx')}.json`)).toString(), + fs.readFileSync(path.join(expectPath, `${path.basename(filename, '.tsx')}.json`), 'utf8').toString(), ), ); } diff --git a/packages/preset-dumi/src/index.test.ts b/packages/preset-dumi/src/index.test.ts index 2006c2db54..420d38e43b 100644 --- a/packages/preset-dumi/src/index.test.ts +++ b/packages/preset-dumi/src/index.test.ts @@ -65,7 +65,7 @@ describe('preset-dumi', () => { }, }); - expect(fs.readFileSync(path.join(cwd, 'dist', 'index.html'), 'utf-8')).toContain( + expect(fs.readFileSync(path.join(cwd, 'dist', 'index.html'), 'utf8')).toContain( 'docsearch.js', ); }); @@ -279,7 +279,7 @@ describe('preset-dumi', () => { }); // expect sitemap.xml content correctly - expect(fs.readFileSync(path.join(api.paths.absOutputPath, 'sitemap.xml')).toString()).toEqual( + expect(fs.readFileSync(path.join(api.paths.absOutputPath, 'sitemap.xml'), 'utf8').toString()).toEqual( 'https://d.umijs.org/https://d.umijs.org/test', ); }); diff --git a/packages/preset-dumi/src/loader/index.test.ts b/packages/preset-dumi/src/loader/index.test.ts index 2eded6f527..a00aa0f8b2 100644 --- a/packages/preset-dumi/src/loader/index.test.ts +++ b/packages/preset-dumi/src/loader/index.test.ts @@ -22,7 +22,7 @@ describe('loader', () => { const filePath = path.join(fixture, 'normal.md'); const result = await loader.call( { resource: filePath, resourcePath: filePath }, - fs.readFileSync(filePath).toString(), + fs.readFileSync(filePath, 'utf8').toString(), ); // expect prepend demos @@ -39,7 +39,7 @@ describe('loader', () => { process.env.NODE_ENV = 'production'; const result = await loader.call( { resource: filePath, resourcePath: filePath }, - fs.readFileSync(filePath).toString(), + fs.readFileSync(filePath, 'utf8').toString(), ); process.env.NODE_ENV = oEnv; @@ -51,7 +51,7 @@ describe('loader', () => { const filePath = path.join(fixture, 'katex.md'); const result = await loader.call( { resource: filePath, resourcePath: filePath }, - fs.readFileSync(filePath).toString(), + fs.readFileSync(filePath, 'utf8').toString(), ); // expect import Katex css file @@ -62,11 +62,11 @@ describe('loader', () => { const filePath = path.join(fixture, 'normal.md'); const singleLine = await loader.call( { resource: filePath, resourcePath: filePath, resourceQuery: '?range=L1' }, - fs.readFileSync(filePath).toString(), + fs.readFileSync(filePath, 'utf8').toString(), ); const rangeLines = await loader.call( { resource: filePath, resourcePath: filePath, resourceQuery: '?range=L3-L5' }, - fs.readFileSync(filePath).toString(), + fs.readFileSync(filePath, 'utf8').toString(), ); // expect get correct line diff --git a/packages/preset-dumi/src/plugins/features/demo/index.ts b/packages/preset-dumi/src/plugins/features/demo/index.ts index 17a457b6a1..40d34701db 100644 --- a/packages/preset-dumi/src/plugins/features/demo/index.ts +++ b/packages/preset-dumi/src/plugins/features/demo/index.ts @@ -18,7 +18,7 @@ interface ISingleRoutetDemos { export default (api: IApi) => { const demos: ISingleRoutetDemos = {}; const generateDemosFile = api.utils.lodash.debounce(async () => { - const tpl = fs.readFileSync(path.join(__dirname, 'demos.mst'), 'utf-8'); + const tpl = fs.readFileSync(path.join(__dirname, 'demos.mst'), 'utf8'); const groups: { [key: string]: any[] } = {}; const items = Object.keys(demos).map(uuid => { const { componentName } = demos[uuid].previewerProps; diff --git a/packages/preset-dumi/src/routes/decorator/fallback.ts b/packages/preset-dumi/src/routes/decorator/fallback.ts index 18dd2b33ea..5719ba7734 100644 --- a/packages/preset-dumi/src/routes/decorator/fallback.ts +++ b/packages/preset-dumi/src/routes/decorator/fallback.ts @@ -32,7 +32,7 @@ export default (function fallback(routes) { if (fs.existsSync(readmePath)) { const component = `./README${localeFileAddon}.md`; - const readme = fs.readFileSync(readmePath, 'utf-8'); + const readme = fs.readFileSync(readmePath, 'utf8'); const reg = /(?:^|[\r\n])#+\s+(.+)/; const title = reg.test(readme) ? reg.exec(readme)[1] : 'README'; diff --git a/packages/preset-dumi/src/routes/getFrontMatter.ts b/packages/preset-dumi/src/routes/getFrontMatter.ts index 6026dd54d6..547c12a4b9 100644 --- a/packages/preset-dumi/src/routes/getFrontMatter.ts +++ b/packages/preset-dumi/src/routes/getFrontMatter.ts @@ -7,7 +7,7 @@ import transformer from '../transformer'; */ export default (fileAbsPath: string): { [key: string]: any } => { const { ext } = path.parse(fileAbsPath); - const content = fs.readFileSync(fileAbsPath).toString(); + const content = fs.readFileSync(fileAbsPath, 'utf8').toString(); let meta; switch (ext) { diff --git a/packages/preset-dumi/src/transformer/remark/embed.ts b/packages/preset-dumi/src/transformer/remark/embed.ts index b6140d2646..63338b8f14 100644 --- a/packages/preset-dumi/src/transformer/remark/embed.ts +++ b/packages/preset-dumi/src/transformer/remark/embed.ts @@ -44,7 +44,7 @@ export default function embed(): IDumiUnifiedTransformer { ), [EMBED_SLUGS]: transformer.markdown( getFileRangeLines( - fs.readFileSync(absPath).toString(), + fs.readFileSync(absPath, 'utf8').toString(), parsed.hash?.replace('#', ''), ), absPath, diff --git a/packages/preset-dumi/src/transformer/remark/previewer.ts b/packages/preset-dumi/src/transformer/remark/previewer.ts index 0e8ba2309e..922fec6b74 100644 --- a/packages/preset-dumi/src/transformer/remark/previewer.ts +++ b/packages/preset-dumi/src/transformer/remark/previewer.ts @@ -151,7 +151,7 @@ function generatePreviewerProps( if (isExternalDemo) { const lang = node.properties.filePath.match(/\.(\w+)$/)[1]; const { meta, content } = transformer.code( - fs.readFileSync(node.properties.filePath).toString(), + fs.readFileSync(node.properties.filePath, 'utf8').toString(), ); fileAbsPath = node.properties.filePath; diff --git a/packages/preset-dumi/src/transformer/test/demo-deps.test.ts b/packages/preset-dumi/src/transformer/test/demo-deps.test.ts index 8ccac55e42..71c426943e 100644 --- a/packages/preset-dumi/src/transformer/test/demo-deps.test.ts +++ b/packages/preset-dumi/src/transformer/test/demo-deps.test.ts @@ -12,7 +12,7 @@ describe('demo transformer: dependencies', () => { it('basic analysis', () => { const filePath = path.join(__dirname, '../fixtures/demo-deps/normal/index.tsx'); - const result = analyzeDeps(fs.readFileSync(filePath).toString(), { + const result = analyzeDeps(fs.readFileSync(filePath, 'utf8').toString(), { isTSX: true, fileAbsPath: filePath, }); @@ -23,7 +23,7 @@ describe('demo transformer: dependencies', () => { it('multi level', () => { const filePath = path.join(__dirname, '../fixtures/demo-deps/multi-levels/index.ts'); - const result = analyzeDeps(fs.readFileSync(filePath).toString(), { + const result = analyzeDeps(fs.readFileSync(filePath, 'utf8').toString(), { isTSX: false, fileAbsPath: filePath, }); @@ -36,7 +36,7 @@ describe('demo transformer: dependencies', () => { it('circular reference', () => { const filePath = path.join(__dirname, '../fixtures/demo-deps/circular/index.ts'); - const result = analyzeDeps(fs.readFileSync(filePath).toString(), { + const result = analyzeDeps(fs.readFileSync(filePath, 'utf8').toString(), { isTSX: false, fileAbsPath: filePath, }); @@ -48,7 +48,7 @@ describe('demo transformer: dependencies', () => { it("merge dep's peerDependencies", () => { const filePath = path.join(__dirname, '../fixtures/demo-deps/peer/index.ts'); - const result = analyzeDeps(fs.readFileSync(filePath).toString(), { + const result = analyzeDeps(fs.readFileSync(filePath, 'utf8').toString(), { isTSX: false, fileAbsPath: filePath, }); @@ -71,7 +71,7 @@ describe('demo transformer: dependencies', () => { await service.init(); const filePath = path.join(__dirname, '../fixtures/demo-deps/local-pkgs/test.ts'); - const result = analyzeDeps(fs.readFileSync(filePath).toString(), { + const result = analyzeDeps(fs.readFileSync(filePath, 'utf8').toString(), { isTSX: false, fileAbsPath: filePath, }); diff --git a/packages/preset-dumi/src/transformer/test/demo-missing-react.test.ts b/packages/preset-dumi/src/transformer/test/demo-missing-react.test.ts index 53029fa2d7..9c69b89935 100644 --- a/packages/preset-dumi/src/transformer/test/demo-missing-react.test.ts +++ b/packages/preset-dumi/src/transformer/test/demo-missing-react.test.ts @@ -6,7 +6,7 @@ describe('demo: missing react', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/demo-missing-react.tsx'); it('override react to null for throw error', () => { - const result = demo(fs.readFileSync(FILE_PATH).toString(), { + const result = demo(fs.readFileSync(FILE_PATH, 'utf8').toString(), { isTSX: true, fileAbsPath: FILE_PATH, }); diff --git a/packages/preset-dumi/src/transformer/test/remark-api.test.ts b/packages/preset-dumi/src/transformer/test/remark-api.test.ts index 25d52a3134..21aacc0574 100644 --- a/packages/preset-dumi/src/transformer/test/remark-api.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-api.test.ts @@ -17,7 +17,7 @@ describe('component api example', () => { it('transform api for component md', () => { const filePath = path.join(fixtures, 'Hello', 'index.md'); - const result = transformer.markdown(fs.readFileSync(filePath).toString(), filePath).content; + const result = transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath).content; // compare transform content expect(result).toEqual( @@ -29,7 +29,7 @@ describe('component api example', () => { it('transform api when specific src path', () => { const filePath = path.join(fixtures, 'custom-src.md'); - const result = transformer.markdown(fs.readFileSync(filePath).toString(), filePath).content; + const result = transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath).content; // compare transform content expect(result).toEqual( @@ -41,7 +41,7 @@ describe('component api example', () => { it('transform api and show specific exports', () => { const filePath = path.join(fixtures, 'custom-exports.md'); - const result = transformer.markdown(fs.readFileSync(filePath).toString(), filePath).content; + const result = transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath).content; // compare transform content expect(result).toEqual( @@ -52,7 +52,7 @@ describe('component api example', () => { it('transform api and render correct slugs', () => { const filePath = path.join(fixtures, 'api-slugs.md'); - const result = transformer.markdown(fs.readFileSync(filePath).toString(), filePath); + const result = transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath); // compare transform meta expect(result.meta.slugs).toEqual([ @@ -66,7 +66,7 @@ describe('component api example', () => { it('should guess filename as component name', () => { const filePath = path.join(fixtures, 'guess-name.md'); - const result = transformer.markdown(fs.readFileSync(filePath).toString(), filePath); + const result = transformer.markdown(fs.readFileSync(filePath, 'utf8').toString(), filePath); expect(result.content).toContain('identifier="World"'); }); diff --git a/packages/preset-dumi/src/transformer/test/remark-basic.test.ts b/packages/preset-dumi/src/transformer/test/remark-basic.test.ts index ade2bab16e..3d815d808b 100644 --- a/packages/preset-dumi/src/transformer/test/remark-basic.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-basic.test.ts @@ -7,12 +7,12 @@ describe('basic example', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/remark-basic.md'); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH); + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH); // compare transform content expect(winEOL(result.content)).toEqual( winEOL( - fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-basic.html')).toString(), + fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-basic.html'), 'utf8').toString(), ), ); }); diff --git a/packages/preset-dumi/src/transformer/test/remark-demo.test.ts b/packages/preset-dumi/src/transformer/test/remark-demo.test.ts index fb99ec81db..36f5b4dc64 100644 --- a/packages/preset-dumi/src/transformer/test/remark-demo.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-demo.test.ts @@ -27,13 +27,13 @@ describe('demo example', () => { }); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH).content; + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH).content; // compare transform content expect(clearVersion(winEOL(result))).toEqual( clearVersion( winEOL( - fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-demo.html')).toString(), + fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-demo.html'), 'utf8').toString(), ), ), ); diff --git a/packages/preset-dumi/src/transformer/test/remark-embed.test.ts b/packages/preset-dumi/src/transformer/test/remark-embed.test.ts index 47b601c4b1..b3c1dbf15e 100644 --- a/packages/preset-dumi/src/transformer/test/remark-embed.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-embed.test.ts @@ -14,12 +14,12 @@ describe('embed md example', () => { }); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH).content; + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH).content; // compare transform content expect(winEOL(result).replace(/(require\(')[^]*?(\/packages)/g, '$1$2')).toEqual( winEOL( - fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-embed.html')).toString(), + fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-embed.html'), 'utf8').toString(), ), ); }); diff --git a/packages/preset-dumi/src/transformer/test/remark-header.test.ts b/packages/preset-dumi/src/transformer/test/remark-header.test.ts index aab62ff02f..b7e9e723e5 100644 --- a/packages/preset-dumi/src/transformer/test/remark-header.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-header.test.ts @@ -6,7 +6,7 @@ describe('basic example', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/remark-header.md'); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH); + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH); expect(result.meta.slugs).toEqual([ { depth: 1, value: 'H1', heading: 'h1' }, diff --git a/packages/preset-dumi/src/transformer/test/remark-home.test.ts b/packages/preset-dumi/src/transformer/test/remark-home.test.ts index eb1c54f127..4828a8655a 100644 --- a/packages/preset-dumi/src/transformer/test/remark-home.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-home.test.ts @@ -6,7 +6,7 @@ describe('home example', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/remark-home.md'); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH).meta; + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH).meta; // compare transform content expect(result.hero).not.toBeUndefined(); expect(result.features).not.toBeUndefined(); diff --git a/packages/preset-dumi/src/transformer/test/remark-img.test.ts b/packages/preset-dumi/src/transformer/test/remark-img.test.ts index 9f2763a8b0..576a46108d 100644 --- a/packages/preset-dumi/src/transformer/test/remark-img.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-img.test.ts @@ -7,12 +7,12 @@ describe('img example', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/remark-img.md'); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH).content; + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH).content; // compare transform content expect(winEOL(result)).toEqual( winEOL( - fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-img.html')).toString(), + fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-img.html'), 'utf8').toString(), ), ); }); diff --git a/packages/preset-dumi/src/transformer/test/remark-link.test.ts b/packages/preset-dumi/src/transformer/test/remark-link.test.ts index ae0eabd438..b8aacdbbb0 100644 --- a/packages/preset-dumi/src/transformer/test/remark-link.test.ts +++ b/packages/preset-dumi/src/transformer/test/remark-link.test.ts @@ -7,11 +7,11 @@ describe('link example', () => { const FILE_PATH = path.join(__dirname, '../fixtures/raw/remark-link.md'); it('transform md to jsx', () => { - const result = transformer.markdown(fs.readFileSync(FILE_PATH).toString(), FILE_PATH).content; + const result = transformer.markdown(fs.readFileSync(FILE_PATH, 'utf8').toString(), FILE_PATH).content; // compare transform content expect(winEOL(result)).toEqual( winEOL( - fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-link.html')).toString(), + fs.readFileSync(path.join(__dirname, '../fixtures/expect/remark-link.html'), 'utf8').toString(), ), ); }); diff --git a/packages/preset-dumi/src/utils/moduleResolver.test.ts b/packages/preset-dumi/src/utils/moduleResolver.test.ts index ebf5a30877..63e70ecac7 100644 --- a/packages/preset-dumi/src/utils/moduleResolver.test.ts +++ b/packages/preset-dumi/src/utils/moduleResolver.test.ts @@ -48,7 +48,7 @@ describe('moduleResolver', () => { it('get expected local module content', () => { const content = getModuleResolveContent({ basePath: __dirname, sourcePath: '../context' }); - const expectedContent = fs.readFileSync(path.join(__dirname, '../context.ts')).toString(); + const expectedContent = fs.readFileSync(path.join(__dirname, '../context.ts'), 'utf8').toString(); expect(content).toEqual(expectedContent); }); diff --git a/packages/preset-dumi/src/utils/moduleResolver.ts b/packages/preset-dumi/src/utils/moduleResolver.ts index 103dd3dc27..76ad78ce17 100644 --- a/packages/preset-dumi/src/utils/moduleResolver.ts +++ b/packages/preset-dumi/src/utils/moduleResolver.ts @@ -117,5 +117,5 @@ export const getModuleResolveContent = ({ }: IModuleResolverOpts) => { const resolvePath = getModuleResolvePath({ basePath, sourcePath, extensions }); - return resolvePath ? fs.readFileSync(resolvePath).toString() : ''; + return resolvePath ? fs.readFileSync(resolvePath, 'utf8').toString() : ''; }; diff --git a/packages/preset-dumi/src/utils/watcher.test.ts b/packages/preset-dumi/src/utils/watcher.test.ts index 1cd42b8e0d..1f8dd66b2b 100644 --- a/packages/preset-dumi/src/utils/watcher.test.ts +++ b/packages/preset-dumi/src/utils/watcher.test.ts @@ -5,7 +5,7 @@ import { } from './watcher'; function triggerFileChange(filePath: string) { - fs.writeFileSync(filePath, fs.readFileSync(filePath)); + fs.writeFileSync(filePath, fs.readFileSync(filePath, 'utf8')); } describe('util: watcher', () => { diff --git a/packages/theme-default/src/style/markdown.less b/packages/theme-default/src/style/markdown.less index 9618f470b0..803b7d66d8 100644 --- a/packages/theme-default/src/style/markdown.less +++ b/packages/theme-default/src/style/markdown.less @@ -157,6 +157,12 @@ td:first-child { font-weight: 500; } + + a { + svg { + display: none; + } + } } // links diff --git a/scripts/sync-from-umi.js b/scripts/sync-from-umi.js new file mode 100644 index 0000000000..f394972c03 --- /dev/null +++ b/scripts/sync-from-umi.js @@ -0,0 +1,67 @@ +const fs = require('fs'); +const path = require('path'); +const https = require('https'); + +const UMI_DOC_DIR = path.join(__dirname, '..', 'docs', '.upstream'); +const FILE_LIST = [ + // config docs + { + localname: 'config.md', + upstream: 'https://cdn.jsdelivr.net/gh/umijs/umi@3/docs/config/README.md', + actions: [ + // remove head content + { type: 'slice', value: [13] }, + // replace h2 -> h3 + { type: 'replace', value: [/^\n## /g, '\n### '] }, + // replace jsx to jsx | pure + { type: 'replace', value: [/\n```(jsx|tsx)\s*\n/g, '\n```$1 | pure\n'] }, + // remove badges + { type: 'replace', value: [/\s*[^]+?<\/Badge>/g, ''] }, + // prepend internal link prefix + { type: 'replace', value: [/]\(\//g, '](https://umijs.org/'] }, + // prepend anchor link prefix + { type: 'replace', value: [/]\(#/g, '](https://umijs.org/zh-CN/config#'] }, + // remove unnecessary option + ...['title', 'singular', 'routes', 'mpa', 'mountElementId'].map(option => ({ + type: 'replace', + value: [new RegExp(`(?:^|[\r\n])## ${option}[^]+?([\r\n]#|$)`), '$1'], + })), + ], + }, +]; + +if (!fs.existsSync(UMI_DOC_DIR)) { + fs.mkdirSync(UMI_DOC_DIR); +} + +// process files +FILE_LIST.forEach(file => { + const localPath = path.join(UMI_DOC_DIR, file.localname); + + // get file from upstream + https.get(file.upstream, res => { + let content = ''; + + res.on('data', chunk => { content += chunk }); + res.on('end', () => { + // execute process actions + (file.actions || []).forEach(action => { + switch (action.type) { + case 'slice': + content = content.split(/\n/g).slice(action.value[0], action.value[1]).join('\n'); + break; + + case 'replace': + content = content.replace(action.value[0], action.value[1]); + break; + + default: + } + }); + + // write back to file + fs.writeFileSync(localPath, content); + console.log('sync', file.localname, 'from upstream successfully!'); + }); + }); +});