如何实现带行号折叠功能的React源码展示组件以适配Solidity代码
基于React17 + MUI4实现可折叠Solidity源码查看面板方案
1. 基础源码展示组件实现
不需要自行编写Solidity代码解析逻辑,直接使用成熟的第三方语法高亮库react-syntax-highlighter即可,该库内置Solidity语法支持,可直接完成代码高亮、行号展示等基础能力,和你当前的技术栈完全兼容。
实现步骤:
- 安装兼容版本依赖:
npm install react-syntax-highlighter@15.4.5 # 若需要TS类型支持可以额外装 @types/react-syntax-highlighter
- 基础组件示例代码:
import React from 'react'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { atomOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'; import { solidity } from 'react-syntax-highlighter/dist/esm/languages/prism'; import { Card, CardContent, Typography } from '@material-ui/core'; // 注册Solidity语言 SyntaxHighlighter.registerLanguage('solidity', solidity); const SolidityCodeViewer = ({ code, contractName }) => { return ( <Card variant="outlined"> <CardContent> <Typography variant="h6" gutterBottom> {contractName} 源码 </Typography> <SyntaxHighlighter language="solidity" style={atomOneDark} showLineNumbers customStyle={{ margin: 0, borderRadius: '4px', maxHeight: '800px', }} > {code} </SyntaxHighlighter> </CardContent> </Card> ); }; export default SolidityCodeViewer;
你可以根据项目的MUI主题调整customStyle里的样式参数,和整体设计保持统一。
2. 代码折叠功能实现
分两种实现程度,你可以根据需求选择:
方案1:行级手动折叠(轻量实现,无需额外解析)
利用MUI自带的Collapse组件 + 自定义行渲染能力,实现指定行范围的折叠,适合只需要简单折叠整段代码的场景:
import React, { useState } from 'react'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { atomOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'; import { solidity } from 'react-syntax-highlighter/dist/esm/languages/prism'; import { Card, CardContent, Typography, IconButton } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import ExpandLessIcon from '@material-ui/icons/ExpandLess'; SyntaxHighlighter.registerLanguage('solidity', solidity); const SolidityCodeViewer = ({ code, contractName }) => { // 示例:控制第10-25行的折叠状态,实际场景可以动态绑定多个折叠区间 const [isBlockCollapsed, setIsBlockCollapsed] = useState(false); const codeLines = code.split('\n'); const visibleLines = [ ...codeLines.slice(0, 9), ...(isBlockCollapsed ? [] : codeLines.slice(9, 25)), ...codeLines.slice(25) ]; return ( <Card variant="outlined"> <CardContent> <Typography variant="h6" gutterBottom> {contractName} 源码 </Typography> <IconButton size="small" onClick={() => setIsBlockCollapsed(!isBlockCollapsed)} style={{ position: 'absolute', left: '20px', top: '80px' }} > {isBlockCollapsed ? <ExpandMoreIcon /> : <ExpandLessIcon />} </IconButton> <SyntaxHighlighter language="solidity" style={atomOneDark} showLineNumbers customStyle={{ margin: 0, borderRadius: '4px', maxHeight: '800px', paddingLeft: '50px' }} > {visibleLines.join('\n')} </SyntaxHighlighter> </CardContent> </Card> ); }; export default SolidityCodeViewer;
方案2:按语法块自动折叠(和ftmscan效果一致)
如果需要实现点击函数、合约定义旁的箭头自动折叠整个语法块,只需要额外引入solidity-parser-antlr库解析Solidity源码的AST,自动提取每个合约、函数、结构体的行起止范围,动态生成折叠控制点即可,不需要自行写语法解析逻辑。
- 安装依赖:
npm install solidity-parser-antlr@0.4.11 - 解析逻辑核心:调用
parse方法传入源码,遍历AST节点拿到每个可折叠块的loc.start.line和loc.end.line属性,和上面的折叠状态绑定即可。
内容的提问来源于stack exchange,提问作者kimiro
相关产品推荐
相关产品推荐

