之前一直没有太注意有个博客有个很严重的格式问题, 就是所有的代码片段(高亮)部分, 只要开头出现了
tab键, 就会出现严重的显示/渲染问题. 之前主要都是本地 Typora 在查看, 没太注意, 深表歉意…. 还希望小伙伴看到任何问题及时反馈/提醒, 不胜感谢这种 Tab 和空格之间的转换问题我想也是经典历史遗留问题之一了, 借此机会正好来单独说说.
0x00. 前言
A. 问题描述
简单说下问题, 就是只要我在 markdown 的 code 标记内, 或者是其他地方, 连续使用了1个或多个tab 符号, 或者是从其他的网页, 文本编辑器(VSCode)中复制过来, 都会导致 markdown 文件在渲染为 HTML 时出现类似下图的问题: (导致阅读体验受到严重影响)
如果多个 tab 不是出现在代码部分, 那也可能导致那行的排版出现意料外的紊乱, 而因为 Typora 自身对各种渲染做的很好, 所以并不会察觉, 但由于各种 Hexo 主题实现不一, 就可能出现各种奇怪的现象. 所以我们希望把所有 md 文件中的 tab 都转为空格代替. 避免出现类似兼容/渲染问题
那你可能会说, 我平常不用 Tab 或者其他编辑器里自动转空格不就好了. 别说, 还真不行:)
比如还有个很蛋疼的地方来自于VSCode, 经过我各种尝试, 发现它都不能禁止 Tab 的使用, 它有个选项是当你使用Tab, 或程序自动使用Tab, 实际最后自动转换为空格, 也就是说看起来是Tab, 实际是空格. 但是因为 typora 的复制功能默认是带有样式的, 这样就导致所有从 VSCode 复制来的代码段, 默认就出现了大量 Tab, 平常也注意不到, 导致积累成了大坑.
B. 解决方案
那你可能会说, 就算 vscode 或者其他编辑器有tab, 不就一个 tab 替换空格的事么? 一行 sed 搞定多简单.. 唔, 但是你可能要想一下这两个问题:
- sed这样过于粗暴的全文递归替换….你真的放心么? 如果行中间有
tab,你是否需要保留? 如果需要来回转换呢? - 历史文件, 一次性转换一次, 新加的文件, 你要每次都去人工检查一下是否有
tab存在么..
针对这两个问题, 我们就请出了居然是内置在Unix中的 expand/unexpand 命令, 用更简单可靠的方式来操作 Tab 和空格的转换.
0x01. 实战
关于expand兄弟的介绍, 直接看这篇就好, 唯一不太方便的就是它没有提供一个就地置换 (sed -i)的选项, 所以转换后还需要临时文件来存储才能覆盖当前文件.
A. 替换历史文件
这个脚本是我基于git-hook版改编而来, 你可以直接下载, 也可以自己复制代码命名为 tab2space.sh , 使用前修改一下 path 就好. 以下特性:
- 修改
temp命令生成的文件后缀, 避免被各种杀毒软件/机制误杀, 加后缀你可以把*.md加白名单 - 异常退出机制, 避免无意义耗时 & 执行后续代码的风险 (Win这里Bash无法识别
(echo "xx" && exit1)的语法, 调半天还是没法. 醉了..) - 增加文件计数, 方便最后对比确认
- 提供备份, 你可以注释20行, 这样不会生成备份文件 (避免任何转换意外导致源文件损坏或日期改变, 请手动删除备份文件)
- 默认不带
expand -i参数, 它的含义是不替换中间的tab字符, 想了下似乎没必要保留. (需要自己补上) - 仅转换带有
tab的文章, 避免每次扫描时间过长 - 应使用多线程并行转换, 单线程效率低. (TODO)
1 |
|
然后你可能说, 我还是不放心你的脚本和expand 命令, 我想看看具体的变动情况, 哪些文件的哪些行被替换了, 这里建议使用git的版本控制来查看, 比如使用hexo b 备份后用 github 查看就很直观.
B. 提交时自动替换 (*)
这个基本引用自前辈的版本, 只稍加一点调整/优化, 文件直接放到 Hexo/.git/hook/pre-commit 下即可. 钩子会在 hexo b 备份时执行. (backup插件需安装). 如果你放 .deploy_git/.git 下我想似乎不能起到作用, 因为它记录的是转为 html 的文件变化了. 变化点有三:
- 修改
temp文件后缀, 避免被各种杀毒软件/机制误杀 - 添加
exit 1机制, 避免连续却不退出的无意义耗时. 以及执行后续代码的风险 - 文件匹配改为
.md
1 |
|
特别注意: 这个钩子并不能(不适合)在Windows上直接运行, 原因是Windows git会把路径中国中文相关字符进行编码, 然后这个编码你直接 ls xxx 访问是不存在的, 导致转换失败, 并且会每次执行钩子都报错… 这个问题目前没想到简单的好办法, 除非新文件 path 中没有任何中文字符, 但是这样文件多了找起来不直观. 所以还是尽早告别Win吧….
0x02. 感想
虽然这次是个小问题, 但是说实话把它好好想清楚, 给出周全的解决方案, 执行完却是很费了一点功夫… (主要是Win蛋疼的环境/中文编码问题)
让我不由得想起了以前看的 <<硅谷>> 剧里的经典台词: One tab saves you eight spaces…..
今天才明白, Tab虽然好用, 但除了会丢掉爱情:) 还真有一些隐蔽的导致天坑的地方, 正确的食用方式应该是:
- 设置 Tab 直转为空格 (按下Tab, 显示 & 实际都是空格, 例如IDEA, 而非VSCode目前做法)
- 设置 IDE 自动缩进, 减少不必要的手动 Tab 缩进
- 其他需要的地方, 再愉快使用Tab..
然后还想到一个问题, 就是平常文档格式的规范问题, 代码规范现在有很多类似lint/goformat 类工具自动帮你检查/格式化规范, 但是比如中文文档里, 经常容易出现的标点错误, 中英标点混用, 以及不恰当和应该有空格的等问题还没看到很好的解决方案, 也许以后也可以关注一下 ~
参考资料:

