createAppFile 方法
实现思路:
根据
components-page/src/pages/index.jsx
文件,提取所有导出的组件名和组件页面,并以此生成页面布局和路由。左侧为
menu
组件,右侧为 路由控制的页面内容。其中新增了一个首页,首页内容为一个个卡片,卡片内容由组件缩略图和组件名组成
实现代码
点击 展开/收起 jsx 代码
import fs from 'fs';
import path from 'path';
function getComponentDescription(componentName) {
const pageDir = path.join(
process.cwd(),
'components-page',
'src',
'pages',
componentName,
);
const fileExtensions = ['.jsx'];
const indexFilePath = fileExtensions
.map((ext) => path.join(pageDir, `index${ext}`))
.find((filePath) => fs.existsSync(filePath));
// 读取 index 文件内容
const indexContent = fs.readFileSync(indexFilePath, 'utf-8');
// 提取 @des-url 后面的内容作为 description
const urlMatch = indexContent.match(/@des-url\s+(.*)/);
const iconurl = urlMatch ? urlMatch[1] : '';
// 提取 @des 后面的内容作为 description
const desMatch = indexContent.match(/@des\s+(.*)/);
const des = desMatch ? desMatch[1] : '';
console.log('des', des);
return {
iconurl,
des,
};
}
function createAppFile() {
const appFilePath = path.join(
process.cwd(),
'components-page',
'src',
'App.jsx',
);
const pagesIndexPath = path.join(
process.cwd(),
'components-page',
'src',
'pages',
'index.js',
);
let menuItems = [];
let routes = [];
if (fs.existsSync(pagesIndexPath)) {
const indexContent = fs.readFileSync(pagesIndexPath, 'utf-8');
const exportMatches = indexContent.match(
/export\s\{[^\}]+\}\sfrom\s'\.\/([^/]+)\/demoPage\.jsx';/g,
);
if (exportMatches) {
exportMatches.forEach((match) => {
const componentName = match.match(
/from\s'\.\/([^/]+)\/demoPage\.jsx';/,
)[1];
const routePath = `/${componentName}`;
const { iconurl, des } = getComponentDescription(componentName);
menuItems.push({
key: componentName,
label: componentName,
iconurl,
des,
});
routes.push(`
<Route path="${routePath}" element={<${componentName} />} />
`);
});
}
}
const appContent = `
import React from 'react';
import { Layout, Menu } from 'antd';
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom';
import {
${menuItems.map((item) => `${item.key}`).join(',\n ')}
} from './pages';
const { Header, Sider, Content } = Layout;
const TotalPage = ({ menus }) => {
return (
<div className="total-page">
{menus.map((item) => {
const { key, label, iconurl, des } = item;
return (
<div key={key} className="total-page-item">
<div className="total-page-item-title">
<div className="total-page-item-title-label">{label}</div>
<div className="total-page-item-title-des">{des}</div>
</div>
<div className="total-page-item-content">
{iconurl ? (
<img
src={iconurl}
width="100%"
height="100%"
/>
) : (
<div>暂无图标</div>
)}
</div>
</div>
)
})}
</div>
)
}
export default function App() {
const items = [
${menuItems
.map(
(item) => `
{
key: '${item.key}',
label: <Link to="/${item.key}">${item.label}</Link>,
iconurl: '${item.iconurl}',
des: '${item.des}',
}`,
)
.join(',\n ')}
];
return (
<Router>
<Layout style={{ minHeight: '100vh' }}>
<Sider width={200} className="site-layout-background">
<Menu
mode="inline"
defaultSelectedKeys={['1']}
style={{ height: '100%', borderRight: 0 }}
items={[
{
key: 'home',
label: <Link to="/">首页</Link>,
},
...items,
]}
/>
</Sider>
<Layout className="main-layout-background">
<Content style={{ margin: '24px 16px 0', overflow: 'initial' }}>
<Routes>
${routes.join('\n ')}
<Route
path="/"
element={<TotalPage menus={items} />}
/>
</Routes>
</Content>
</Layout>
</Layout>
</Router>
);
}
`;
if (!fs.existsSync(path.dirname(appFilePath))) {
fs.mkdirSync(path.dirname(appFilePath), { recursive: true });
}
fs.writeFileSync(appFilePath, appContent.trim());
console.log('------------------------------------------------------------');
console.log(`App.jsx 和 路由 已创建,请查看:${appFilePath}`);
}
export default createAppFile;