游记 Markdown 格式化
format_markdown.py 是无第三方依赖、面向本目录游记的幂等格式化脚本。它只调整 Markdown 结构与空白,不改正文措辞、链接地址或 front matter 字段值。
默认规则:
- YAML front matter 与正文之间保留一个空行。
- 标题、正文段落、独立图片等块级元素之间保留一个空行。
- 住宿/餐饮等 emoji 信息行,以及连续的“往期文章”链接,使用两个行末空格表示 CommonMark 硬换行。
- 本目录的写作约定是“一行正文代表一个自然段”,因此连续正文行默认转为独立段落。
- 代码围栏、缩进代码、表格、列表、引用、HTML 块和链接定义不拆散。
- 所有输出统一为 UTF-8、LF 换行,并保留一个文件末尾换行。
先检查单篇文章:
python3 scripts/format_markdown.py --check 'D1:杭州→千岛湖→婺源.md'
查看实际差异:
python3 scripts/format_markdown.py --diff 'D1:杭州→千岛湖→婺源.md'
处理当前目录下全部文章:
python3 scripts/format_markdown.py --write .
--write 默认先把所有将被修改的原文件备份到 .markdown-backups/时间戳/。确认不需要备份时才使用 --no-backup。目录输入默认只处理该目录第一层的 .md 文件,所以不会误处理 scripts/README.md;确实需要遍历子目录时再加 --recursive。
若某批旧文章把连续正文行视为同一段内的强制换行,可显式使用:
python3 scripts/format_markdown.py --prose-mode hard --write PATH
运行回归测试:
python3 scripts/test_format_markdown.py
抖音图片边长处理
prepare_douyin_images.py 会读取文章中的图片真实尺寸,只处理任一边超过 2000 px 的 JPEG/PNG;超限 HEIC 会转换为 JPEG。大批量处理时优先调用 OSS 图片信息接口,不下载合规原图。超限图片会等比例缩小、作为新对象上传至 OSS,再从 OSS 端点回读对象尺寸;全部成功后才替换 Markdown 链接,原 OSS 对象不会删除或覆盖。
只检查单篇文章,不需要 OSS 凭据:
python3 scripts/prepare_douyin_images.py --check 'D1:杭州→千岛湖→婺源.md'
上传并直接更新文章前,临时设置凭据:
export OSS_ACCESS_KEY_ID='...'
export OSS_ACCESS_KEY_SECRET='...'
python3 scripts/prepare_douyin_images.py --write 'D1:杭州→千岛湖→婺源.md'
unset OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET
凭据只从环境变量读取,不应写进脚本、文章或版本库。默认配置为 wmblog、oss-ap-southeast-1.aliyuncs.com、外链前缀 https://img.weimao.me,派生对象写入 douyin/2000px/。--write 默认先备份 Markdown;若想先上传并查看替换映射而不改文章,可改用 --upload-only。
处理大量文章时建议启用可恢复的尺寸缓存:
python3 scripts/prepare_douyin_images.py \
--audit-cache /tmp/douyin-image-audit.json \
--workers 24 \
--upload-workers 6 \
--write PATH
尺寸审计会定期写入缓存;网络中断后重跑同一命令,只补查尚未完成的图片。
如果上传阶段中断,但已有部分派生对象成功写入 OSS,重跑时加上
--recover-existing:脚本会列出派生目录、回读验证可唯一匹配的对象,仅重试缺失图片。
若 OSS 在线图片处理拒绝某个原图,脚本会自动下载原图并在本地等比缩放。
运行图片处理测试:
python3 scripts/test_prepare_douyin_images.py