Skip to content

Commit

Permalink
refactor: useRouteMeta & useTabMeta with getRouteMetaById (#1888)
Browse files Browse the repository at this point in the history
* refactor: useRouteMeta & useTabMeta

* fix: route meta

* refactor: fix sidebar

* chore: code clean
  • Loading branch information
MadCcc committed Sep 12, 2023
1 parent 7b47630 commit baec225
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 7 deletions.
24 changes: 22 additions & 2 deletions src/client/theme-api/useRouteMeta.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
import { matchRoutes, useAppData, useLocation, useRouteData } from 'dumi';
import {
getRouteMetaById,
matchRoutes,
useAppData,
useLocation,
useRouteData,
} from 'dumi';
import { useCallback, useState } from 'react';
import use from './context/use';
import type { IRouteMeta } from './types';
import { useIsomorphicLayoutEffect } from './utils';

const cache = new Map<string, ReturnType<getRouteMetaById>>();

const useAsyncRouteMeta = (id: string) => {
if (!cache.has(id)) {
cache.set(id, getRouteMetaById(id));
}

return use<ReturnType<getRouteMetaById>>(cache.get(id));
};

/**
* hook for get matched route meta
*/
export const useRouteMeta = () => {
const { route } = useRouteData();
const { pathname } = useLocation();
const { clientRoutes } = useAppData();

const routeMeta = useAsyncRouteMeta(route.id);

const getter = useCallback((): IRouteMeta => {
let ret: IRouteMeta;

if (route.path === pathname && !('isLayout' in route)) {
// use `useRouteData` result if matched, for performance
ret = (route as any).meta;
ret = routeMeta;
} else {
// match manually for dynamic route & layout component
const matched = matchRoutes(clientRoutes, pathname)?.pop();
Expand Down
1 change: 0 additions & 1 deletion src/client/theme-default/slots/ContentTabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const ContentTabs: FC<IContentTabsProps> = ({
const intl = useIntl();

// TODO: tab.Extra & tab.Action render

return Boolean(tabs?.length) ? (
<ul className="dumi-default-content-tabs">
<li onClick={() => onChange()} data-active={!key || undefined}>
Expand Down
3 changes: 2 additions & 1 deletion src/features/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export default (api: IApi) => {
noPluginDir: true,
path: 'dumi/exports.ts',
content: `export * from '../exports';
export * from '${winPath(require.resolve('../client/theme-api'))}';`,
export * from '${winPath(require.resolve('../client/theme-api'))}';
export { getRouteMetaById } from './meta/route-meta';`,
});
});
};
17 changes: 14 additions & 3 deletions src/features/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,25 @@ export default (api: IApi) => {
});

// generate meta lazy entry
const mdFiles = parsedMetaFiles.filter((metaFile) =>
metaFile.file.endsWith('.md'),
);

api.writeTmpFile({
noPluginDir: true,
path: 'dumi/meta/demos.ts',
tplPath: winPath(join(TEMPLATES_DIR, 'meta-demos.ts.tpl')),
context: {
metaFiles: parsedMetaFiles.filter((metaFile) =>
metaFile.file.endsWith('.md'),
),
metaFiles: mdFiles,
},
});

api.writeTmpFile({
noPluginDir: true,
path: 'dumi/meta/route-meta.ts',
tplPath: winPath(join(TEMPLATES_DIR, 'meta-route.ts.tpl')),
context: {
metaFiles: mdFiles,
},
});

Expand Down
43 changes: 43 additions & 0 deletions src/templates/meta-route.ts.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { tabs } from './tabs';

const files = {
{{#metaFiles}}
'{{{id}}}': {
frontmatterGetter: () => import('{{{file}}}?type=frontmatter'),
textGetter: () => import('{{{file}}}?type=text'),
{{#tabs}}
tabs: {{{tabs}}},
{{/tabs}}
},
{{/metaFiles}}
};

export const getRouteMetaById = async (id: string) => {
const file = files[id];
if (!file) {
return null;
}

const text = await file.textGetter();
const frontmatter = await file.frontmatterGetter();

const tabsMeta = file.tabs && await Promise.all(file.tabs.map(async (tab) => {
const meta = await getRouteMetaById(tab) ?? {
frontmatter: { title: tabs[tab].title },
toc: [],
texts: [],
};
return {
...tabs[tab],
meta,
}
}));

return {
texts: text?.texts,
toc: text?.toc,
frontmatter: frontmatter?.frontmatter,
tabs: tabsMeta,
};
}

0 comments on commit baec225

Please sign in to comment.