add formula support in two pathes
This commit is contained in:
147
src/components/react/MathFlipCard.tsx
Normal file
147
src/components/react/MathFlipCard.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import katex from 'katex';
|
||||
|
||||
interface MathFlipCardProps {
|
||||
latex: string;
|
||||
displayMode?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export default function MathFlipCard({
|
||||
latex,
|
||||
displayMode = true,
|
||||
className = ''
|
||||
}: MathFlipCardProps) {
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
const mathContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (mathContainerRef.current && !isFlipped) {
|
||||
try {
|
||||
katex.render(latex, mathContainerRef.current, {
|
||||
displayMode: displayMode,
|
||||
throwOnError: false,
|
||||
trust: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('KaTeX rendering error:', error);
|
||||
if (mathContainerRef.current) {
|
||||
mathContainerRef.current.textContent = latex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [latex, displayMode, isFlipped]);
|
||||
|
||||
const containerStyle: React.CSSProperties = {
|
||||
perspective: '1000px',
|
||||
width: '100%',
|
||||
minHeight: displayMode ? '120px' : '60px',
|
||||
position: 'relative',
|
||||
};
|
||||
|
||||
const innerStyle: React.CSSProperties = {
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
minHeight: 'inherit',
|
||||
transformStyle: 'preserve-3d',
|
||||
transition: 'transform 0.6s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
};
|
||||
|
||||
const faceStyle = (isFront: boolean): React.CSSProperties => ({
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
minHeight: 'inherit',
|
||||
backfaceVisibility: 'hidden',
|
||||
borderRadius: '0.75rem',
|
||||
padding: displayMode ? '1.5rem' : '0.75rem 1rem',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
background: 'var(--color-muted, #f1f5f9)',
|
||||
border: '1px solid var(--color-border, #e2e8f0)',
|
||||
transform: isFront ? 'rotateY(0deg)' : 'rotateY(180deg)',
|
||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.08)',
|
||||
});
|
||||
|
||||
const codeStyle: React.CSSProperties = {
|
||||
fontFamily: 'var(--font-mono, "JetBrains Mono", monospace)',
|
||||
fontSize: displayMode ? '0.9rem' : '0.85rem',
|
||||
color: 'var(--color-foreground, #1e293b)',
|
||||
background: 'transparent',
|
||||
wordBreak: 'break-word',
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
};
|
||||
|
||||
const buttonStyle: React.CSSProperties = {
|
||||
position: 'absolute',
|
||||
bottom: '0.5rem',
|
||||
right: '0.5rem',
|
||||
padding: '0.25rem 0.75rem',
|
||||
fontSize: '0.75rem',
|
||||
fontWeight: 500,
|
||||
color: 'var(--primary-500, #0ea5e9)',
|
||||
background: 'transparent',
|
||||
border: '1px solid var(--primary-500, #0ea5e9)',
|
||||
borderRadius: '0.375rem',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.2s ease',
|
||||
zIndex: 10,
|
||||
};
|
||||
|
||||
const handleButtonClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setIsFlipped(!isFlipped);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={containerStyle} className={className}>
|
||||
<div style={innerStyle}>
|
||||
<div style={faceStyle(true)}>
|
||||
<div
|
||||
ref={mathContainerRef}
|
||||
style={{
|
||||
color: 'var(--color-foreground, #1e293b)',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
style={buttonStyle}
|
||||
onClick={handleButtonClick}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = 'var(--primary-500, #0ea5e9)';
|
||||
e.currentTarget.style.color = 'white';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'transparent';
|
||||
e.currentTarget.style.color = 'var(--primary-500, #0ea5e9)';
|
||||
}}
|
||||
>
|
||||
显示 LaTeX
|
||||
</button>
|
||||
</div>
|
||||
<div style={faceStyle(false)}>
|
||||
<pre style={codeStyle}>{latex}</pre>
|
||||
<button
|
||||
style={buttonStyle}
|
||||
onClick={handleButtonClick}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = 'var(--primary-500, #0ea5e9)';
|
||||
e.currentTarget.style.color = 'white';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = 'transparent';
|
||||
e.currentTarget.style.color = 'var(--primary-500, #0ea5e9)';
|
||||
}}
|
||||
>
|
||||
显示公式
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
116
src/content/blog/latex-test.mdx
Normal file
116
src/content/blog/latex-test.mdx
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
title: 'LaTeX 公式渲染测试'
|
||||
description: '测试 LaTeX 数学公式渲染功能'
|
||||
pubDate: 2026-03-01
|
||||
author: 'NovaBlog Team'
|
||||
category: '测试'
|
||||
tags: ['测试', 'LaTeX', '数学']
|
||||
---
|
||||
|
||||
import MathFlipCard from '../../components/react/MathFlipCard';
|
||||
|
||||
# LaTeX 公式渲染测试
|
||||
|
||||
## 行内公式
|
||||
|
||||
这是一个行内公式:$E = mc^2$,爱因斯坦的质能方程。
|
||||
|
||||
勾股定理:$a^2 + b^2 = c^2$
|
||||
|
||||
## 块级公式
|
||||
|
||||
高斯积分:
|
||||
|
||||
$$
|
||||
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
|
||||
$$
|
||||
|
||||
## 翻转卡片公式展示
|
||||
|
||||
下面使用翻转卡片展示公式,点击"显示 LaTeX"按钮可以查看源码:
|
||||
|
||||
### 质能方程
|
||||
|
||||
<MathFlipCard latex="E = mc^2" client:load />
|
||||
|
||||
### 麦克斯韦方程组
|
||||
|
||||
<MathFlipCard latex="\nabla \cdot \mathbf{E} = \frac{\rho}{\varepsilon_0}" client:load />
|
||||
|
||||
### 薛定谔方程
|
||||
|
||||
<MathFlipCard latex="i\hbar\frac{\partial}{\partial t}\Psi(\mathbf{r},t) = \left[-\frac{\hbar^2}{2m}\nabla^2 + V(\mathbf{r},t)\right]\Psi(\mathbf{r},t)" client:load />
|
||||
|
||||
### 傅里叶变换
|
||||
|
||||
<MathFlipCard latex="\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x) e^{-2\pi i x \xi} dx" client:load />
|
||||
|
||||
### 矩阵运算
|
||||
|
||||
<MathFlipCard latex="\begin{pmatrix} a & b \\ c & d \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}" client:load />
|
||||
|
||||
## 传统公式展示(对比)
|
||||
|
||||
麦克斯韦方程组:
|
||||
|
||||
$$
|
||||
\nabla \cdot \mathbf{E} = \frac{\rho}{\varepsilon_0}
|
||||
$$
|
||||
|
||||
$$
|
||||
\nabla \cdot \mathbf{B} = 0
|
||||
$$
|
||||
|
||||
$$
|
||||
\nabla \times \mathbf{E} = -\frac{\partial \mathbf{B}}{\partial t}
|
||||
$$
|
||||
|
||||
$$
|
||||
\nabla \times \mathbf{B} = \mu_0 \mathbf{J} + \mu_0 \varepsilon_0 \frac{\partial \mathbf{E}}{\partial t}
|
||||
$$
|
||||
|
||||
## 复杂公式
|
||||
|
||||
薛定谔方程:
|
||||
|
||||
$$
|
||||
i\hbar\frac{\partial}{\partial t}\Psi(\mathbf{r},t) = \left[-\frac{\hbar^2}{2m}\nabla^2 + V(\mathbf{r},t)\right]\Psi(\mathbf{r},t)
|
||||
$$
|
||||
|
||||
傅里叶变换:
|
||||
|
||||
$$
|
||||
\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x) e^{-2\pi i x \xi} dx
|
||||
$$
|
||||
|
||||
矩阵:
|
||||
|
||||
$$
|
||||
\begin{pmatrix}
|
||||
a & b \\
|
||||
c & d
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
x \\
|
||||
y
|
||||
\end{pmatrix}
|
||||
=
|
||||
\begin{pmatrix}
|
||||
ax + by \\
|
||||
cx + dy
|
||||
\end{pmatrix}
|
||||
$$
|
||||
|
||||
求和与积分:
|
||||
|
||||
$$
|
||||
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
|
||||
$$
|
||||
|
||||
$$
|
||||
\prod_{i=1}^{n} i = n!
|
||||
$$
|
||||
|
||||
## 测试完成
|
||||
|
||||
如果你能看到以上公式正确渲染,说明 LaTeX 公式支持已经成功配置!
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: React 动效组件展示
|
||||
description: 展示 NovaBlog 中可用的 React 动效 HTML 组件,包括悬浮卡片、打字机效果、翻转卡片和粒子背景
|
||||
description: 展示 NovaBlog 中可用的 React 动效 HTML 组件,包括悬浮卡片、打字机效果、翻转卡片、粒子背景和数学公式卡片
|
||||
pubDate: 2024-01-20
|
||||
author: NovaBlog
|
||||
tags: [React, 动效, 组件, 教程]
|
||||
@@ -12,6 +12,7 @@ import AnimatedCard from '../../components/react/AnimatedCard';
|
||||
import TypewriterText from '../../components/react/TypewriterText';
|
||||
import FlipCard from '../../components/react/FlipCard';
|
||||
import ParticleBackground from '../../components/react/ParticleBackground';
|
||||
import MathFlipCard from '../../components/react/MathFlipCard';
|
||||
|
||||
# React 动效组件展示
|
||||
|
||||
@@ -134,6 +135,53 @@ NovaBlog 支持在 MDX 中直接使用 React 组件,实现丰富的交互动
|
||||
</div>
|
||||
</ParticleBackground>
|
||||
|
||||
## 📐 数学公式翻转卡片 (MathFlipCard)
|
||||
|
||||
专门用于展示 LaTeX 数学公式的翻转卡片组件。正面显示渲染后的公式,点击"显示 LaTeX"按钮可以查看源码。
|
||||
|
||||
### 质能方程
|
||||
|
||||
<MathFlipCard latex="E = mc^2" client:load />
|
||||
|
||||
### 麦克斯韦方程组
|
||||
|
||||
<MathFlipCard latex="\nabla \cdot \mathbf{E} = \frac{\rho}{\varepsilon_0}" client:load />
|
||||
|
||||
### 薛定谔方程
|
||||
|
||||
<MathFlipCard latex="i\hbar\frac{\partial}{\partial t}\Psi(\mathbf{r},t) = \left[-\frac{\hbar^2}{2m}\nabla^2 + V(\mathbf{r},t)\right]\Psi(\mathbf{r},t)" client:load />
|
||||
|
||||
### 傅里叶变换
|
||||
|
||||
<MathFlipCard latex="\hat{f}(\xi) = \int_{-\infty}^{\infty} f(x) e^{-2\pi i x \xi} dx" client:load />
|
||||
|
||||
### 矩阵运算
|
||||
|
||||
<MathFlipCard latex="\begin{pmatrix} a & b \\ c & d \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}" client:load />
|
||||
|
||||
### 使用方式
|
||||
|
||||
```tsx
|
||||
import MathFlipCard from '../../components/react/MathFlipCard';
|
||||
|
||||
<MathFlipCard
|
||||
latex="E = mc^2"
|
||||
displayMode={true} // 可选,默认为 true
|
||||
client:load
|
||||
/>
|
||||
```
|
||||
|
||||
**属性说明**:
|
||||
- `latex`:LaTeX 公式字符串
|
||||
- `displayMode`:是否为块级公式(可选,默认为 true)
|
||||
- `className`:自定义 CSS 类名(可选)
|
||||
|
||||
**特点**:
|
||||
- 点击"显示 LaTeX"按钮可查看公式源码
|
||||
- 点击"显示公式"按钮返回渲染结果
|
||||
- 支持 KaTeX 的所有语法
|
||||
- 适合教学和技术文档
|
||||
|
||||
## 📝 如何在文章中使用
|
||||
|
||||
### 1. 导入组件
|
||||
@@ -208,5 +256,6 @@ NovaBlog 提供了灵活的组件系统,让你可以在 Markdown 中嵌入丰
|
||||
- ⌨️ **动态文字**:打字机、滚动、闪烁效果
|
||||
- ✨ **背景特效**:粒子、波浪、光效
|
||||
- 🎮 **交互功能**:计数器、表单、游戏
|
||||
- 📐 **数学公式**:翻转卡片展示 LaTeX 公式
|
||||
|
||||
快去尝试创建属于你自己的动效组件吧! 🚀
|
||||
@@ -1,202 +0,0 @@
|
||||
---
|
||||
title: Typst 学术排版展示
|
||||
description: 展示 NovaBlog 中 Typst 的高级排版能力,包括数学公式、矩阵等学术排版
|
||||
pubDate: 2024-01-25
|
||||
author: NovaBlog
|
||||
tags: [Typst, 排版,数学公式,学术写作]
|
||||
category: 教程
|
||||
heroImage: /images/hello-world.jpg
|
||||
---
|
||||
|
||||
# Typst 学术排版展示
|
||||
|
||||
Typst 是一款现代化的排版系统,专为学术写作和技术文档设计。本文将展示 NovaBlog 中 Typst 的数学公式排版能力。
|
||||
|
||||
## 📐 基础数学公式
|
||||
|
||||
### 积分公式
|
||||
|
||||
```
|
||||
$ integral_0^infinity e^(-x^2) dif x = sqrt(pi) / 2 $
|
||||
```
|
||||
|
||||
### 极限与导数
|
||||
|
||||
```
|
||||
$ lim_(x arrow 0) frac(sin x, x) = 1 $
|
||||
```
|
||||
|
||||
```
|
||||
$ frac(dif f, dif x) = lim_(h arrow 0) frac(f(x + h) - f(x), h) $
|
||||
```
|
||||
|
||||
### 微积分基本定理
|
||||
|
||||
```
|
||||
$ integral_a^b f(x) dif x = F(b) - F(a) $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔢 矩阵与线性代数
|
||||
|
||||
### 基础矩阵
|
||||
|
||||
```
|
||||
$ A = mat(1, 2, 3; 4, 5, 6; 7, 8, 9) $
|
||||
```
|
||||
|
||||
### 行列式展开
|
||||
|
||||
```
|
||||
$ det(A) = sum_(i=1)^n a_(1i) dot (-1)^(1+i) dot M_(1i) $
|
||||
```
|
||||
|
||||
### 特征值方程
|
||||
|
||||
```
|
||||
$ det(A - lambda I) = 0 $
|
||||
```
|
||||
|
||||
### 二次型
|
||||
|
||||
```
|
||||
$ Q(x) = x^T A x = sum_(i,j) a_(ij) x_i x_j $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 统计学与概率论
|
||||
|
||||
### 贝叶斯定理
|
||||
|
||||
```
|
||||
$ P(A | B) = frac(P(B | A) dot P(A), P(B)) $
|
||||
```
|
||||
|
||||
### 正态分布
|
||||
|
||||
```
|
||||
$ X tilde N(mu, sigma^2) arrow.f P(x) = frac(1, sigma sqrt(2 pi)) e^(-frac((x-mu)^2, 2 sigma^2)) $
|
||||
```
|
||||
|
||||
### 期望与方差
|
||||
|
||||
```
|
||||
$ E[X] = sum_(i=1)^n x_i p_i quad Var(X) = E[X^2] - (E[X])^2 $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧮 复杂嵌套表达式
|
||||
|
||||
### 巴塞尔问题
|
||||
|
||||
```
|
||||
$ sum_(n=1)^infinity frac(1, n^2) = frac(pi^2, 6) $
|
||||
```
|
||||
|
||||
### 欧拉恒等式
|
||||
|
||||
```
|
||||
$ e^(i pi) + 1 = 0 $
|
||||
```
|
||||
|
||||
### Gamma 函数
|
||||
|
||||
```
|
||||
$ Gamma(z) = integral_0^infinity t^(z-1) e^(-t) dif t $
|
||||
```
|
||||
|
||||
### 斯特林公式
|
||||
|
||||
```
|
||||
$ n! tilde sqrt(2 pi n) (n/e)^n $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚡ 物理学公式
|
||||
|
||||
### 麦克斯韦方程组
|
||||
|
||||
```
|
||||
$ nabla dot E = frac(rho, epsilon_0) $
|
||||
```
|
||||
|
||||
```
|
||||
$ nabla dot B = 0 $
|
||||
```
|
||||
|
||||
```
|
||||
$ nabla times E = -frac(partial B, partial t) $
|
||||
```
|
||||
|
||||
```
|
||||
$ nabla times B = mu_0 J + mu_0 epsilon_0 frac(partial E, partial t) $
|
||||
```
|
||||
|
||||
### 狭义相对论
|
||||
|
||||
```
|
||||
$ E = m c^2 $
|
||||
```
|
||||
|
||||
```
|
||||
$ t' = frac(t, sqrt(1 - v^2/c^2)) = gamma t $
|
||||
```
|
||||
|
||||
```
|
||||
$ gamma = frac(1, sqrt(1 - v^2/c^2)) $
|
||||
```
|
||||
|
||||
### 薛定谔方程
|
||||
|
||||
```
|
||||
$ i hbar frac(partial psi, partial t) = H^ psi $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔬 化学方程式
|
||||
|
||||
```
|
||||
$ 6 CO_2 + 6 H_2 O arrow.r C_6 H_12 O_6 + 6 O_2 $
|
||||
```
|
||||
|
||||
```
|
||||
$ CH_4 + 2 O_2 arrow.r CO_2 + 2 H_2 O $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📐 集合论
|
||||
|
||||
```
|
||||
$ A union B = { x | x in A text( 或 ) x in B } $
|
||||
```
|
||||
|
||||
```
|
||||
$ A intersect B = { x | x in A text( 且 ) x in B } $
|
||||
```
|
||||
|
||||
```
|
||||
$ A setminus B = { x | x in A text( 且 ) x notin B } $
|
||||
```
|
||||
|
||||
```
|
||||
$ P(A) = { S | S subset.eq A } $
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
NovaBlog 曾经通过 TypstBlock 组件支持专业的数学公式排版,适合:
|
||||
|
||||
- 📐 **数学博客**:微积分、线性代数、概率统计
|
||||
- ⚡ **物理笔记**:经典力学、电磁学、量子力学
|
||||
- 🔬 **化学公式**:化学反应方程式
|
||||
- 📊 **学术论文**:复杂的数学推导和证明
|
||||
|
||||
由于技术原因,Typst 支持已暂时移除。
|
||||
@@ -57,6 +57,13 @@ const socialImageURL = image.startsWith('http') ? image : new URL(image, site).h
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- KaTeX CSS for LaTeX Math Rendering -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.16.33/dist/katex.min.css"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
|
||||
<!-- Dark Mode Script (防止闪烁) -->
|
||||
<script is:inline>
|
||||
const theme = (() => {
|
||||
|
||||
Reference in New Issue
Block a user