为代码块添加行号样式,优化代码渲染逻辑,支持按行显示代码内容。

This commit is contained in:
神秘人
2025-07-08 13:14:55 +08:00
parent c0038359ab
commit b2b4bcf14c
2 changed files with 61 additions and 10 deletions

View File

@@ -267,3 +267,37 @@
margin: 10px 0;
}
}
// 代码块带行号样式
.mac-style.with-line-number {
position: relative;
.hljs {
display: block;
padding: 0;
background: none;
}
.code-line {
display: flex;
align-items: flex-start;
min-height: 1.6em;
font-size: 1em;
line-height: 1.6;
white-space: pre;
}
.line-number {
display: inline-block;
width: 2.5em;
text-align: right;
color: #888;
user-select: none;
opacity: 0.6;
margin-right: 1em;
font-size: 0.95em;
font-family: inherit;
}
.line-content {
flex: 1;
word-break: break-all;
white-space: pre;
}
}

View File

@@ -92,15 +92,23 @@ const ContentMD = ({ data }: Props) => {
const [expanded, setExpanded] = useState(false);
const isLong = value.split("\n").length > 10;
const highlighted = useMemo(() => {
// 新增:将代码按行分割
const codeLines = useMemo(() => value.split("\n"), [value]);
const highlightedLines = useMemo(() => {
try {
if (hljs.getLanguage(language)) {
return hljs.highlight(value, { language }).value;
return hljs.highlight(value, { language }).value.split("\n");
}
} catch { }
return hljs.highlightAuto(value).value;
return hljs.highlightAuto(value).value.split("\n");
}, [value, language]);
const linesToRender = highlightedLines;
if (linesToRender.length > 1 && linesToRender[linesToRender.length - 1] === "") {
linesToRender.pop();
}
const handleCopy = () => {
navigator.clipboard.writeText(value).then(
() => toast.success("代码已复制 🎉"),
@@ -110,8 +118,7 @@ const ContentMD = ({ data }: Props) => {
return (
<pre
className={`mac-style ${isLong ? (expanded ? "expanded" : "collapsed") : ""
}`}
className={`mac-style with-line-number ${isLong ? (expanded ? "expanded" : "collapsed") : ""}`}
onClick={() => {
if (isLong && !expanded) setExpanded(true);
}}
@@ -130,10 +137,19 @@ const ContentMD = ({ data }: Props) => {
<BiCopy size={16} />
</button>
<code
className={`hljs language-${language}`}
dangerouslySetInnerHTML={{ __html: highlighted }}
/>
{/* 新增:带行号的代码渲染 */}
<code className={`hljs language-${language}`}>
{linesToRender.map((line, idx) => (
<div key={idx} className="code-line">
<span className="line-number">{idx + 1}</span>
<span
className="line-content"
dangerouslySetInnerHTML={{ __html: line || "\u200B" }}
/>
</div>
))}
</code>
{isLong && (
<button
className="toggle-btn"
@@ -145,7 +161,7 @@ const ContentMD = ({ data }: Props) => {
>
{expanded
? "收起代码"
: `展开代码 (${value.split("\n").length} 行)`}
: `展开代码 (${value.split("\n").length - 1} 行)`}
</button>
)}
</pre>
@@ -231,6 +247,7 @@ const ContentMD = ({ data }: Props) => {
autoClose={1000}
hideProgressBar
/>
<PhotoProvider>
<div className="content markdown-body">
<ReactMarkdown