问题现象

博客在手机端打开 Day 5 这类文章时,中文文字出现了逐字分行的问题:

创 建 N A T 网 关

明明一行能显示的文字,被拆成了一个个单字,视觉上完全无法阅读。

第一反应:CSS 问题

以为是 word-breakwhite-space 的锅。用 MobaXterm 连上服务器,先把 CSS 文件拉下来看:

scp root@***.uuworld.cn:/var/www/blog/static/css/tech.css .

找到好几处 word-break: break-word,这个属性在手机端会让浏览器在任意字符之间断行——而中文没有空格,浏览器就把每个字都当成了合法断点,自然就逐字分行显示。

修改方案:把涉及中文内容的 word-break: break-word 全部改成 word-break: normal,让中文按自然语意换行。

同步回服务器,重建 Hugo:

scp tech.css root@***.uuworld.cn:/var/www/blog/static/css/tech.css
ssh root@***.uuworld.cn "cd /var/www/blog && hugo"

验证 CSS 是否更新:

curl https://***.uuworld.cn/css/tech.css | grep 'word-break'

结果:CSS 已生效。但刷新手机端,问题依旧。

深入:HTML 里藏了什么

CSS 修改了但没效果,怀疑 HTML 本身就有问题。用 curl 抓页面看:

curl http://***.uuworld.cn/acp/acp-day-05-acp-day-5-vpc-nat/ | grep -A5 '典型实验流程'

输出里发现了这个:

<div class="goat svg-container ">
  <svg xmlns="http://www.w3.org/2000/svg" font-family="Menlo,Lucida Console,monospace" viewBox="0 0 192 201">
    <g transform='translate(8,16)'>
      <text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>系</text>
      <text text-anchor='middle' x='0' y='20' fill='currentColor' style='font-size:1em'>├</text>
      <text text-anchor='middle' x='0' y='36' fill='currentColor' style='font-size:1em'>├</text>

问题找到了!Hugo 生成的 HTML 里,代码块被转成了 SVG 图形,每个字符都是独立的 <text> 元素。手机端 SVG 无法正确缩放,浏览器就把每个字符当成独立行来渲染。

根因定位:Hugo 内置 goat 库

Hugo 二进制文件里内置了 goat 库:

strings /usr/local/bin/hugo | grep -i 'goat'
Goat *goat.SVG github.com/bep/goat

Hugo v0.146.0 extended 版本的代码块渲染逻辑里,藏着一个内置模板 embedded/templates/_markup/render-codeblock-goat.html。这个模板会自动检测代码块里的树形图字符(├── └─ ),然后把它们转成 SVG 图形。

Day 5 文章里有这段代码块:

系统路由表 ├── 创建VPC后自动生成 ├── 不可删除、不可手动创建 └── 可添加自定义路由条目

Hugo 检测到 ├──└── 字符,触发 goat 转换,生成了 SVG 而不是普通代码块。

解决方案:覆盖 Hugo 内置模板

Hugo 的 render hook 机制支持自定义覆盖。只需在项目 layouts 目录下创建同名模板:

mkdir -p /var/www/blog/layouts/_default/_markup
cat > /var/www/blog/layouts/_default/_markup/render-codeblock-goat.html << 'EOF'
{{- .Inner -}}
EOF

这个空模板只输出原始文本内容,覆盖了 Hugo 内置的 SVG 生成逻辑。

同时,把 markdown 里的树形图字符也替换成普通列表格式,彻底消除触发条件:

系统路由表 - 创建VPC后自动生成 - 不可删除、不可手动创建 - 可添加自定义路由条目

重建验证:

cd /var/www/blog && hugo
curl http://***.uuworld.cn/acp/acp-day-05-acp-day-5-vpc-nat/ | grep -c 'svg-container'
# 输出: 0

经验总结

阶段 动作 结果
第一反应 修改 CSS word-break CSS 生效但问题依旧
深入排查 curl 查看 HTML 发现 SVG 标签
根因定位 strings 检查 Hugo binary 发现内置 goat 库
解决方案 创建 render-codeblock-goat.html 覆盖 0 个 SVG,问题解决

Hugo extended 版本内置了很多额外功能(SCSS/SASS 渲染、goat SVG 等),这些功能在配置文件里完全看不到,但会影响页面输出。遇到类似"改了 CSS 没效果"的问题,记得直接查 HTML 源码,很可能是生成阶段就已经出错了。

相关文件

  • /var/www/blog/layouts/_default/_markup/render-codeblock-goat.html — 空模板,覆盖内置 goat 转换
  • /var/www/blog/static/css/tech.css — 手机端 CSS 优化(word-break: normal)