From 8939c89dab970e79cebff4c6901a2b3c0ea8644e Mon Sep 17 00:00:00 2001 From: c0dedance <2627702283@qq.com> Date: Sun, 22 Oct 2023 16:48:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A1=B5=E9=9D=A2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=B5=81=E6=89=93=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin-routes/RouteService.test.ts | 6 ++-- src/node/plugin-routes/RouteService.ts | 2 +- src/node/plugin-routes/index.ts | 3 +- src/runtime/App.tsx | 23 ++++++++++++++ src/runtime/client-entry.tsx | 17 +++++++--- src/runtime/hooks.ts | 9 ++++++ src/runtime/index.ts | 2 ++ src/runtime/theme-default/Layout/index.tsx | 25 +++++++++------ src/shared/types/index.ts | 31 +++++++++++++++++++ src/shared/types/types.d.ts | 4 +-- 10 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 src/runtime/hooks.ts create mode 100644 src/runtime/index.ts diff --git a/src/node/__test__/plugin-routes/RouteService.test.ts b/src/node/__test__/plugin-routes/RouteService.test.ts index 66c68fb..78b47fd 100644 --- a/src/node/__test__/plugin-routes/RouteService.test.ts +++ b/src/node/__test__/plugin-routes/RouteService.test.ts @@ -37,9 +37,9 @@ describe('RouteService', async () => { import Route1 from 'TEST_DIR/guide/a.tsx'; import Route2 from 'TEST_DIR/guide/index.tsx'; export const routes = [ - { \\"path\\": '/b', \\"element\\": React.createElement(Route0)}, - { \\"path\\": '/guide/a', \\"element\\": React.createElement(Route1)}, - { \\"path\\": '/guide/', \\"element\\": React.createElement(Route2)}, + { \\"path\\": '/b', \\"element\\": React.createElement(Route0), \\"preload\\": () => import('TEST_DIR/b.tsx')}, + { \\"path\\": '/guide/a', \\"element\\": React.createElement(Route1), \\"preload\\": () => import('TEST_DIR/guide/a.tsx')}, + { \\"path\\": '/guide/', \\"element\\": React.createElement(Route2), \\"preload\\": () => import('TEST_DIR/guide/index.tsx')}, ] " `) diff --git a/src/node/plugin-routes/RouteService.ts b/src/node/plugin-routes/RouteService.ts index 372db51..b8c8ef4 100644 --- a/src/node/plugin-routes/RouteService.ts +++ b/src/node/plugin-routes/RouteService.ts @@ -46,7 +46,7 @@ export const routes = [ ${this.#routeMeta .map( (item, index) => - `{ "path": '${item.routePath}', "element": React.createElement(Route${index})},` + `{ "path": '${item.routePath}', "element": React.createElement(Route${index}), "preload": () => import('${item.absolutePath}')},` ) .join('\n')} ] diff --git a/src/node/plugin-routes/index.ts b/src/node/plugin-routes/index.ts index dd8e79e..d57dd12 100644 --- a/src/node/plugin-routes/index.ts +++ b/src/node/plugin-routes/index.ts @@ -1,6 +1,6 @@ -import React from 'react' import { Plugin } from 'vite' import { RouteService } from './RouteService' +import type { PageModule } from 'shared/types' interface PluginOptions { root: string @@ -10,6 +10,7 @@ export interface Route { path: string element: React.ReactElement filePath: string + preload: () => Promise } const CONVENTIONAL_ROUTE_ID = 'rpress:routes' diff --git a/src/runtime/App.tsx b/src/runtime/App.tsx index 391ad93..2b831ae 100644 --- a/src/runtime/App.tsx +++ b/src/runtime/App.tsx @@ -1,4 +1,8 @@ +import { matchRoutes } from 'react-router-dom' import { Layout } from './theme-default' +import siteData from 'rpress:site-data' +import { routes } from 'rpress:routes' +import type { PageData } from 'shared/types' export default function App() { return ( @@ -7,3 +11,22 @@ export default function App() { ) } + +export async function initPageData(routePath: string): Promise { + const matched = matchRoutes(routes, routePath) + if (!matched) { + return { + siteData, + pagePath: routePath, + frontmatter: {}, + pageType: '404', + } + } + const moduleInfo = await matched[0].route.preload() + return { + siteData, + pagePath: routePath, + frontmatter: moduleInfo.frontmatter, + pageType: 'doc', + } +} diff --git a/src/runtime/client-entry.tsx b/src/runtime/client-entry.tsx index 7a9dc8c..003a521 100644 --- a/src/runtime/client-entry.tsx +++ b/src/runtime/client-entry.tsx @@ -1,16 +1,23 @@ import { createRoot } from 'react-dom/client' import { BrowserRouter } from 'react-router-dom' -import App from './App' +import App, { initPageData } from './App' +import { DataContext } from './hooks' -function renderInBrowser() { +async function renderInBrowser() { const containerEl = document.getElementById('root') if (!containerEl) { throw new Error('#root element not found') } + // 初始化 PageData + const pageData = await initPageData(location.pathname) + console.log(pageData, 'pageData') + createRoot(containerEl).render( - - - + + + + + ) } diff --git a/src/runtime/hooks.ts b/src/runtime/hooks.ts new file mode 100644 index 0000000..72d8b6e --- /dev/null +++ b/src/runtime/hooks.ts @@ -0,0 +1,9 @@ +import { createContext, useContext } from 'react' +import type { PageData } from 'shared/types' + +export const DataContext = createContext({} as PageData) + +/* 提供数据供前端组件消费 */ +export const usePageData = () => { + return useContext(DataContext) +} diff --git a/src/runtime/index.ts b/src/runtime/index.ts new file mode 100644 index 0000000..3affcc1 --- /dev/null +++ b/src/runtime/index.ts @@ -0,0 +1,2 @@ +export { Content } from './Content' +export * from './hooks' diff --git a/src/runtime/theme-default/Layout/index.tsx b/src/runtime/theme-default/Layout/index.tsx index c952130..e0379a3 100644 --- a/src/runtime/theme-default/Layout/index.tsx +++ b/src/runtime/theme-default/Layout/index.tsx @@ -1,14 +1,19 @@ -import { Content } from '../../Content' +import { usePageData } from '../../' import 'uno.css' export function Layout() { - return ( -
-

nav

- - -
- ) + const pageData = usePageData() + // 获取 pageType + const { pageType } = pageData + // 根据 pageType 分发不同的页面内容 + const getContent = () => { + if (pageType === 'home') { + return
Home 页面
+ } else if (pageType === 'doc') { + return
正文页面
+ } else { + return
404 页面
+ } + } + return
{getContent()}
} diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index 986fb52..46bc0b8 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -1,4 +1,11 @@ import type { UserConfig as ViteUserConfig } from 'vite' +import type { ComponentType } from 'react' + +export interface PageModule { + default: ComponentType + frontmatter?: FrontMatter + [key: string]: unknown +} // 用户配置的超集 export interface SiteConfig { @@ -41,3 +48,27 @@ type SidebarItem = { text: string link: string } +/* page */ +export type PageType = 'home' | 'doc' | 'custom' | '404' + +export interface Header { + id: string + text: string + depth: number +} +// 页面元信息 +export interface FrontMatter { + title?: string + description?: string + pageType?: PageType + sidebar?: boolean + outline?: boolean +} + +export interface PageData { + siteData: UserConfig + pagePath: string + frontmatter: FrontMatter + pageType: PageType + toc?: Header[] +} diff --git a/src/shared/types/types.d.ts b/src/shared/types/types.d.ts index 10cbba3..12f63d0 100644 --- a/src/shared/types/types.d.ts +++ b/src/shared/types/types.d.ts @@ -4,7 +4,7 @@ declare module 'rpress:site-data' { export default siteData } declare module 'rpress:routes' { - import type { RouteObject } from 'react-router-dom' - const routes: RouteObject[] + import type { Route } from 'node/plugin-routes' + const routes: Route[] export { routes } }