Skip to content

Instantly share code, notes, and snippets.

@mistivia
Last active January 24, 2026 03:21
Show Gist options
  • Select an option

  • Save mistivia/e5a0890f688225e3b6eb0f98b97cefa4 to your computer and use it in GitHub Desktop.

Select an option

Save mistivia/e5a0890f688225e3b6eb0f98b97cefa4 to your computer and use it in GitHub Desktop.
Convert LaTeX formula to SVG
#!/bin/bash
# Usage: echo '$$E = mc^2$$' | tex2svg > einstein.svg
# 遇到错误立即退出
set -e
# 检查依赖工具
command -v xelatex >/dev/null 2>&1 || { echo >&2 "Error: xelatex not found."; exit 1; }
command -v pdf2svg >/dev/null 2>&1 || { echo >&2 "Error: pdf2svg not found."; exit 1; }
command -v magick >/dev/null 2>&1 || { echo >&2 "Error: magick not found."; exit 1; }
# 创建临时目录,并在脚本结束时自动清理
TMP_DIR=$(mktemp -d)
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
# 1. 从 Stdin 读取 Latex 公式
# 读取所有输入到变量中
INPUT_LATEX=$(cat)
if [ -z "$INPUT_LATEX" ]; then
echo >&2 "Error: No input provided via stdin."
exit 1
fi
# 2. 构造 Latex 文件并调用 xelatex 渲染成 PDF
# 使用 article 类生成整页,这样才有白边可以让我们裁切
cat <<EOF > "$TMP_DIR/formula.tex"
\documentclass[12pt]{article}
\usepackage{amsmath,amssymb,amsfonts}
\usepackage{fontspec}
\usepackage{geometry}
% 设置页边距为0,方便计算,但通常pdf2svg处理整页坐标
\geometry{paper=a4paper, margin=1in}
\pagestyle{empty}
\begin{document}
% 使用 display math 环境
$INPUT_LATEX
\end{document}
EOF
# 编译 PDF (静默模式)
cd "$TMP_DIR"
xelatex -interaction=nonstopmode -output-directory="$TMP_DIR" formula.tex >/dev/null 2>&1
if [ ! -f "formula.pdf" ]; then
echo >&2 "Error: xelatex compilation failed. Check your latex syntax."
exit 1
fi
# 3. 调用 pdf2svg 渲染成 SVG (此时是整页 SVG)
pdf2svg "formula.pdf" "formula.svg"
# 4. 把 SVG 渲染成 PNG
# 关键点:设置 density 72,这样 1 pixel = 1 point (SVG默认单位)
# 这样 magick 计算出的像素坐标可以直接用于 SVG 的 viewBox
magick -density 72 "formula.svg" "formula.png"
# 5. 用 magick 查看切掉白边需要的参数
# -format "%@" 返回类似 "100x50+20+30" (WxH+X+Y) 的字符串,表示非空白区域的边界框
CROP_GEOMETRY=$(magick "formula.png" -format "%@" info:)
# 解析几何参数
# 格式: WIDTHxHEIGHT+X+Y
# 使用 bash 字符串操作解析
rest=${CROP_GEOMETRY#*x}
WIDTH=${CROP_GEOMETRY%%x*}
HEIGHT=${rest%%+*}
rest=${rest#*+}
X=${rest%%+*}
Y=${rest#*+}
# 6. 用这个参数,裁切原来的 svg
# SVG 的 viewBox 属性格式为: viewBox="min-x min-y width height"
# 我们直接修改 SVG 文件的头部
# 为了安全起见,我们添加一点点 padding (例如 2pt),避免边缘笔画被切断
PADDING=2
WIDTH=$(($WIDTH + $PADDING * 2))
HEIGHT=$(($HEIGHT + $PADDING * 2))
X=$(($X - $PADDING))
Y=$(($Y - $PADDING))
# 确保 X, Y 不小于 0
if [ "$X" -lt 0 ]; then X=0; fi
if [ "$Y" -lt 0 ]; then Y=0; fi
# 使用 sed 修改 svg 文件
# 替换 width, height 和 viewBox
# pdf2svg 输出的 svg 头部通常很标准,包含 width="..." height="..." viewBox="..."
sed -i \
-e "s/width=\"[^\"]*\"/width=\"${WIDTH}pt\"/" \
-e "s/height=\"[^\"]*\"/height=\"${HEIGHT}pt\"/" \
-e "s/viewBox=\"[^\"]*\"/viewBox=\"$X $Y $WIDTH $HEIGHT\"/" \
"formula.svg"
# 7. 在 stdout 输出 SVG 结果
cat "formula.svg"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment