Skip to content

Commit

Permalink
refactor: improve 2-level nav forward compatibility (#1679)
Browse files Browse the repository at this point in the history
* refactor: improve 2-level nav forward compatibility

* refactor: bump dumi version for theme-mobile

* docs: describe 2-level nav compatibility

* refactor: 2-level nav compatible with local example

* refactor: improve 2-level nav style

* refactor: use nav.second instead nav.parent

* docs: update docs

* docs: improve 2-level nav warning
  • Loading branch information
PeachScript authored May 21, 2023
1 parent 0d8f860 commit f6a51c1
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 41 deletions.
16 changes: 13 additions & 3 deletions docs/config/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,19 @@ title: 配置页面标题

## nav

- 类型:`string | { title: string; order: number; parent: { title: string; order: string } }`
- 类型:`string | { title: string; order: number; second: string | { title: string; order: string } }`
- 默认值:`undefined`

<!-- 2-level nav warning start -->

:::warning
二级导航为 dumi v2.2 的新增特性,由于二级导航特性会影响主题 API 的行为,为了保证对存量项目及主题包的向前兼容,dumi 仅在项目 `devDependencies` 中声明的 dumi 版本号大于等于 `2.2.0`(例如 `^2.2.0`)时才会启用该特性

如果你的项目使用了三方主题包,能否使用二级导航则取决于主题包是否适配该特性,dumi 会依据主题包 `peerDependencies` 中声明的 dumi 版本作为判断依据
:::

<!-- 2-level nav warning end -->

配置当前页所属的一级导航及二级导航,同一导航类目下仅需配置任意一个 Markdown 文件即可全局生效,未配置时将会使用[默认规则](../guide/conventional-routing.md#导航归类及生成)

例如:
Expand All @@ -100,9 +110,9 @@ nav:
title: 名称
order: 1
# 单独配置二级导航名称
parent: 父级名称
second: 父级名称
# 同时配置二级导航名称和顺序,order 越小越靠前,默认为 0
parent:
second:
title: 父级名称
order: 1
---
Expand Down
6 changes: 4 additions & 2 deletions docs/guide/conventional-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ nav:

### 约定式二级导航 <Badge>2.2.0+</Badge>

<embed src="../config/markdown.md#RE-/<!-- 2-level nav warning[^]+ 2-level nav warning end -->/"></embed>

同时,为了便于组织文档,dumi 还支持生成二级导航,使用起来也非常简单,以如下目录结构为例:

```bash
Expand All @@ -77,9 +79,9 @@ docs
---
nav:
# 单独设置二级导航名称
parent: 移动端
second: 移动端
# 同时设置二级导航名称和顺序,order 越小越靠前,默认为 0
parent:
second:
title: 移动端
order: 1
---
Expand Down
16 changes: 9 additions & 7 deletions docs/theme/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import { useFullSidebarData } from 'dumi';
const Example = () => {
const sidebar = useFullSidebarData();
// 返回值:Record<string, ISidebarGroup[]>
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L140
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L171

// 其他逻辑
};
Expand All @@ -86,7 +86,7 @@ import { useLocale } from 'dumi';
const Example = () => {
const locale = useLocale();
// 返回值:{ id: string; name: string; base: string } | { id: string; name: string; suffix: string }
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L121
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L152

// 其他逻辑
};
Expand All @@ -98,15 +98,17 @@ const Example = () => {
- 场景:定制导航栏时需要用到
- 用法:

> 注意,由于后续会支持二级导航,该 hook 的返回数据结构可能会有些许调整
:::info
如果你是 dumi v2.2 发布之前的主题包开发者,建议更新导航栏组件对[二级导航数据](https://github.com/umijs/dumi/discussions/1618)的支持,并将主题包 `peerDependencies` 中的 dumi 版本设置为 `^2.2.0`,以便主题包用户使用[约定式二级导航](../guide/conventional-routing.md#约定式二级导航)特性
:::

```ts
import { useNavData } from 'dumi';

const Example = () => {
const nav = useNavData();
// 返回值:INavItem[]
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L126
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L157

// 其他逻辑
};
Expand Down Expand Up @@ -175,7 +177,7 @@ const Example = () => {
tabs,
} = useRouteMeta();
// 返回值:IRouteMeta
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L48
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L56

// 其他逻辑
};
Expand Down Expand Up @@ -224,7 +226,7 @@ import { useSidebarData } from 'dumi';
const Example = () => {
const sidebar = useSidebarData();
// 返回值:ISidebarGroup[]
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L140
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L171

// 其他逻辑
};
Expand Down Expand Up @@ -275,7 +277,7 @@ const Example = () => {
texts,
} = useTabMeta();
// 返回值:IRouteTabMeta
// 类型定义:https://github.com/umijs/dumi/tree/master/src/client/theme-api/types.ts#L108
// 类型定义:https://github.com/umijs/dumi/blob/master/src/client/theme-api/types.ts#L135

// 其他逻辑
};
Expand Down
5 changes: 5 additions & 0 deletions src/client/theme-api/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ interface ISiteContext {
themeConfig: IThemeConfig;
loading: boolean;
setLoading: (status: boolean) => void;
/**
* private field, do not use it in your code
*/
_2_level_nav_available: boolean;
}

export const SiteContext = createContext<ISiteContext>({
Expand All @@ -32,6 +36,7 @@ export const SiteContext = createContext<ISiteContext>({
themeConfig: {} as IThemeConfig,
loading: false,
setLoading: () => {},
_2_level_nav_available: true,
});

export const useSiteData = () => {
Expand Down
6 changes: 3 additions & 3 deletions src/client/theme-api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export interface IRouteMeta {
| {
title?: string;
order?: number;
parent?: Omit<IRouteMeta['frontmatter']['nav'], 'parent'>;
second?: Omit<IRouteMeta['frontmatter']['nav'], 'second'>;
};
group?: string | { title?: string; order?: number };
order?: number;
Expand Down Expand Up @@ -105,7 +105,7 @@ export interface IRouteMeta {
depth: number;
title: string;
/**
* private field, will be removed in the future
* private field, do not use it in your code
*/
_debug_demo?: boolean;
}[];
Expand Down Expand Up @@ -143,7 +143,7 @@ export interface IRouteMeta {
};
}[];
/**
* private field, will be removed in the future
* private field, do not use it in your code
*/
_atom_route?: boolean;
}
Expand Down
22 changes: 11 additions & 11 deletions src/client/theme-api/useNavData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function genNavItem(
export const useNavData = () => {
const locale = useLocale();
const routes = useLocaleDocRoutes();
const { themeConfig } = useSiteData();
const { themeConfig, _2_level_nav_available: is2LevelNav } = useSiteData();
const sidebar = useFullSidebarData();
const sidebarDataComparer = useRouteDataComparer<INavItems[0]>();
const [nav] = useState<INavItems>(() => {
Expand Down Expand Up @@ -65,8 +65,8 @@ export const useNavData = () => {
// convert sidebar data to nav data
.reduce<Record<string, INavItems[0]>>((ret, [link, groups]) => {
const [, parentPath, restPath] = link.match(/^(\/[^/]+)([^]+)?$/)!;
const isNestedNav = Boolean(restPath);
const [rootMeta, parentMeta] = Object.values(routes).reduce<
const isNestedNav = Boolean(restPath) && is2LevelNav;
const [firstMeta, secondMeta] = Object.values(routes).reduce<
{
title?: string;
order?: number;
Expand All @@ -80,7 +80,7 @@ export const useNavData = () => {
if (isNestedNav)
pickRouteSortMeta(
ret[1],
'nav.parent',
'nav.second',
route.meta!.frontmatter,
);
}
Expand All @@ -90,26 +90,26 @@ export const useNavData = () => {
);

if (isNestedNav) {
// fallback to use parent path as title
parentMeta.title ??= parentPath
// fallback to use parent path as 1-level nav title
firstMeta.title ??= parentPath
.slice(1)
.replace(/^[a-z]/, (s) => s.toUpperCase());

// handle nested nav item as parent children
const parent = (ret[parentPath] ??= genNavItem(
parentMeta,
const second = (ret[parentPath] ??= genNavItem(
firstMeta,
groups,
parentPath,
));

parent.children ??= [];
second.children ??= [];
ret[parentPath].children!.push(
genNavItem(rootMeta, groups, link, groups[0].children[0].link),
genNavItem(secondMeta, groups, link, groups[0].children[0].link),
);
} else {
// handle root nav item
ret[link] = genNavItem(
rootMeta,
firstMeta,
groups,
link,
groups[0].children[0].link,
Expand Down
22 changes: 15 additions & 7 deletions src/client/theme-api/useSidebarData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ const getLocaleClearPath = (routePath: string, locale: ILocalesConfig[0]) => {
/**
* get parent path from route path
*/
function getRouteParentPath(path: string, meta: IRouteMeta) {
function getRouteParentPath(
path: string,
{ meta, is2LevelNav }: { meta: IRouteMeta; is2LevelNav: boolean },
) {
const isIndexDocRoute =
meta.frontmatter.filename?.endsWith('index.md') && !meta._atom_route;
meta.frontmatter.filename?.endsWith('index.md') &&
!meta._atom_route &&
is2LevelNav;
const paths = path
.split('/')
// strip end slash
Expand All @@ -38,8 +43,8 @@ function getRouteParentPath(path: string, meta: IRouteMeta) {
// least 1-level
1,
),
// up to 2-level
2,
// up to 2-level when use conventional 2-level nav
is2LevelNav ? 2 : Infinity,
);

return paths.slice(0, sliceEnd).join('/');
Expand All @@ -51,7 +56,7 @@ function getRouteParentPath(path: string, meta: IRouteMeta) {
export const useFullSidebarData = () => {
const locale = useLocale();
const routes = useLocaleDocRoutes();
const { themeConfig } = useSiteData();
const { themeConfig, _2_level_nav_available: is2LevelNav } = useSiteData();
const sidebarDataComparer = useRouteDataComparer<
ISidebarGroup | ISidebarItem
>();
Expand All @@ -74,7 +79,7 @@ export const useFullSidebarData = () => {
// a/b => /a/b (if route file is a/b/index.md)
// a/b/c => /a/b
const parentPath = `/${route.path!.replace(clearPath, (s) =>
getRouteParentPath(s, route.meta!),
getRouteParentPath(s, { is2LevelNav, meta: route.meta! }),
)}`;
const { title, order } = pickRouteSortMeta(
{ order: 0 },
Expand Down Expand Up @@ -204,6 +209,7 @@ export const useTreeSidebarData = () => {
export const useSidebarData = () => {
const locale = useLocale();
const sidebar = useFullSidebarData();
const { _2_level_nav_available: is2LevelNav } = useSiteData();
const { pathname } = useLocation();
const meta = useRouteMeta();
const clearPath = getLocaleClearPath(pathname.slice(1), locale);
Expand All @@ -214,7 +220,9 @@ export const useSidebarData = () => {
// /en-US/a/b => /en-US/a
// /en-US/a/b/ => /en-US/a (also strip trailing /)
const parentPath = clearPath
? pathname.replace(clearPath, (s) => getRouteParentPath(s, meta))
? pathname.replace(clearPath, (s) =>
getRouteParentPath(s, { is2LevelNav, meta }),
)
: pathname;

return parentPath ? sidebar[parentPath] : [];
Expand Down
6 changes: 3 additions & 3 deletions src/client/theme-api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ export const useRouteDataComparer = <
*/
export const pickRouteSortMeta = (
original: Partial<Pick<INavItem, 'order' | 'title'>>,
field: 'nav' | 'nav.parent' | 'group',
field: 'nav' | 'nav.second' | 'group',
fm: IRouteMeta['frontmatter'],
) => {
const sub: IRouteMeta['frontmatter']['group'] =
field === 'nav.parent'
field === 'nav.second'
? typeof fm.nav === 'object'
? fm.nav.parent
? fm.nav.second
: {}
: fm[field];

Expand Down
8 changes: 5 additions & 3 deletions src/client/theme-default/slots/Navbar/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@
}
}

&[data-collapsed] > svg {
transform: rotate(180deg);
@media @mobile {
&[data-collapsed] > svg {
transform: rotate(180deg);
}
}

@media @desktop {
Expand Down Expand Up @@ -122,7 +124,7 @@
padding: 0 18px;
color: @c-text-secondary;
font-size: 15px;
line-height: 1.5;
line-height: 1.6;
text-align: left;

@media @mobile {
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ export const PICKED_PKG_FIELDS = {
};

export const USELESS_TMP_FILES = ['tsconfig.json', 'typings.d.ts'];

export const VERSION_2_LEVEL_NAV = '^2.2.0';
Loading

0 comments on commit f6a51c1

Please sign in to comment.