From 37b11eea8354da3549fc595e5e331c210b48d471 Mon Sep 17 00:00:00 2001 From: wang <1509326266@qq.com> Date: Sat, 24 Aug 2024 20:12:01 +0800 Subject: [PATCH] feat(projects): can create routing information in a routing file & assign layout manually & custom error boundary path --- src/route-core/const.ts | 74 +++++++++++++++++++++++++++++++------ src/route-core/options.ts | 3 ++ src/route-core/transform.ts | 2 +- src/types/index.ts | 3 ++ 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/route-core/const.ts b/src/route-core/const.ts index c22afc9..a646f0c 100644 --- a/src/route-core/const.ts +++ b/src/route-core/const.ts @@ -9,6 +9,7 @@ import { formatCode } from '../shared/prettier'; import { FIRST_LEVEL_ROUTE_COMPONENT_SPLIT, LAYOUT_PREFIX, VIEW_PREFIX } from '../constants'; import type { ElegantConstRoute, ElegantReactRouterOption, RouteConstExport } from '../types'; import { createPrefixCommentOfGenFile } from './comment'; +import { log } from './log'; export async function genConstFile(tree: ElegantRouterTree[], options: ElegantReactRouterOption) { const { cwd, constDir } = options; @@ -17,6 +18,7 @@ export async function genConstFile(tree: ElegantRouterTree[], options: ElegantRe const code = await getConstCode(tree, options); + await writeFile(routesFilePath, code, 'utf8'); } @@ -31,19 +33,27 @@ async function getConstCode(trees: ElegantRouterTree[], options: ElegantReactRou await writeFile(routeFilePath, code, 'utf-8'); } + const md = await loadFile(routeFilePath, { parser: { parse } }); + const autoRoutes = trees.map(item => transformRouteTreeToElegantConstRoute(item, options)); const oldRoutes = JSON.parse(JSON.stringify(md.exports.generatedRoutes)) as ElegantConstRoute[]; - const updated = getUpdatedRouteConst(oldRoutes, autoRoutes, options); + + + const updated =await getUpdatedRouteConst(oldRoutes, autoRoutes, options); md.exports.generatedRoutes = updated as any; + let { code } = generateCode(md); + + code = transformComponent(code); + const formattedCode = await formatCode(code); const removedEmptyLineCode = formattedCode.replace(/,\n\n/g, `,\n`); @@ -65,27 +75,55 @@ export const generatedRoutes: GeneratedRoute[] = []; return code; } -function getUpdatedRouteConst( + async function getUpdatedRouteConst( oldConst: ElegantConstRoute[], newConst: ElegantConstRoute[], options: ElegantReactRouterOption ) { const oldRouteMap = getElegantConstRouteMap(oldConst); - const updated = newConst.map(item => { + + + const updated =await Promise.all(newConst.map(async (item)=> { const oldRoute = oldRouteMap.get(item.name); + let config={} as ElegantConstRoute + if (options.routeInfoByFile) { + const configFile=item.name.split("_").join('/')+'/'+options.routeInfoFileName + + const {cwd,pageDir}=options + const routeFilePath = path.posix.join(cwd, pageDir,configFile); + + try { + const md = await loadFile(routeFilePath, { parser: { parse } }); + config = JSON.parse(JSON.stringify(md.exports)) as ElegantConstRoute; + + } catch (error:any) { + + log('Note that no file related to routing information is created in this file:'+' '+error.path, 'info', options.log); + } + } + if (!oldRoute) { + if (options.routeInfoByFile) { + Object.assign(item,config) + } return item; } + const { name, path: routePath, component, children, meta, ...rest } = item; + const updatedRoute = { ...oldRoute, path: routePath }; const isFirstLevel = !name.includes(PAGE_DEGREE_SPLITTER) && !children?.length; - if (oldRoute.component && component) { + + + if (config.layout||oldRoute.layout) { + updatedRoute.component = 'layout.'+ config.layout||oldRoute.layout; + }else if (oldRoute.component && component) { if (isFirstLevel) { const { layoutName: oldLayoutName } = resolveFirstLevelRouteComponent(oldRoute.component); const { layoutName: newLayoutName } = resolveFirstLevelRouteComponent(component); @@ -101,31 +139,41 @@ function getUpdatedRouteConst( const layoutName = oldRoute.component.replace(LAYOUT_PREFIX, ''); const hasLayout = Boolean(options.layouts[layoutName]); - if (isView || (isLayout && !hasLayout)) { + + + if (isView || (isLayout && !hasLayout)) { updatedRoute.component = component; } + } } + mergeObject(updatedRoute, rest); - if (!updatedRoute.meta && meta) { updatedRoute.meta = meta; } - if (updatedRoute.meta && meta) { mergeObject(updatedRoute.meta, meta); } + if (options.routeInfoByFile) { + Object.assign(updatedRoute,config) + } + if (children?.length) { - updatedRoute.children = getUpdatedRouteConst(oldRoute?.children || [], children, options); + updatedRoute.children = + await getUpdatedRouteConst(oldRoute?.children || [], children, options); } return updatedRoute; - }); + })); return updated; -} + } + + + function mergeObject>(target: T, source: T) { const keys = Object.keys(source) as (keyof T)[]; @@ -140,6 +188,7 @@ function mergeObject>(target: T, source: T) { function getElegantConstRouteMap(constRoutes: ElegantConstRoute[]) { const routeMap = new Map(); + function recursiveGetElegantConstRoute(routes: ElegantConstRoute[]) { routes.forEach(item => { const { name, children } = item; @@ -164,9 +213,12 @@ function getElegantConstRouteMap(constRoutes: ElegantConstRoute[]) { * @param options the plugin options */ function transformRouteTreeToElegantConstRoute(tree: ElegantRouterTree, options: ElegantReactRouterOption) { + + const { defaultLayout, onRouteMetaGen } = options; const { routeName, routePath, children = [] } = tree; + const layoutComponent = `${LAYOUT_PREFIX}${defaultLayout}`; const firstLevelRouteComponent = getFirstLevelRouteComponent(routeName, defaultLayout); @@ -233,8 +285,8 @@ function resolveFirstLevelRouteComponent(component: string) { } function transformComponent(routeJson: string) { - const COMPONENT_REG = /"component":\s*"(.*?)"/g; + const COMPONENT_REG = /"component":\s*"(.*?)"/g; const result = routeJson.replace(COMPONENT_REG, match => { const [component, viewOrLayout] = match.split(':'); diff --git a/src/route-core/options.ts b/src/route-core/options.ts index 9e31992..96b6f64 100644 --- a/src/route-core/options.ts +++ b/src/route-core/options.ts @@ -10,6 +10,7 @@ export function createPluginOptions(erOptions: ElegantRouterOption, options?: Pa const DTS_DIR = 'src/types/elegant-router.d.ts'; const IMPORT_DIR = 'src/router/elegant/imports.ts'; const CONST_DIR = 'src/router/elegant/routes.ts'; + const ROUTE_INFO_FILENAME = 'config.ts'; const TRANSFORM_DIR = 'src/router/elegant/transform.ts'; const CUSTOM_ROUTES_MAP: Record = { root: '/', @@ -29,6 +30,8 @@ export function createPluginOptions(erOptions: ElegantRouterOption, options?: Pa map: {}, names: [] }, + routeInfoByFile: true, + routeInfoFileName:ROUTE_INFO_FILENAME, layouts: DEFAULT_LAYOUTS, defaultLayout: Object.keys(DEFAULT_LAYOUTS)[0], layoutLazyImport: _name => true, diff --git a/src/route-core/transform.ts b/src/route-core/transform.ts index 71c663c..7a07b20 100644 --- a/src/route-core/transform.ts +++ b/src/route-core/transform.ts @@ -35,7 +35,7 @@ import type { FunctionComponent } from "react"; import type { ElegantConstRoute } from '@ohh-889/react-auto-route'; import type { RouteMap, RouteKey, RoutePath } from '@elegant-router/types'; import { redirect } from 'react-router-dom' -import ErrorBoundary from '../../../ErrorBoundary.tsx' +import ErrorBoundary from "${options.errorBoundaryPath||'../../../ErrorBoundary.tsx'}" type CustomRouteObject = Omit & { diff --git a/src/types/index.ts b/src/types/index.ts index 5f2211a..17ebf78 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -118,6 +118,9 @@ export interface ElegantReactRouterOption extends ElegantRouterOption { * @param routeName the route name */ onRouteMetaGen(routeName: string): Record; + errorBoundaryPath?: string + routeInfoByFile?: boolean, + routeInfoFileName?:string } export type CustomRouteConfig = {