编辑器里看到的,就是线上会渲染的

张工让我写个脚本:能预览、能改字,点确认之后同步到草稿箱或者直接发布,还得告诉我成没成、百度推没推。

界面部分真不难。http.server 是标准库,起个服务,页面左边一个 textarea,右边一个 iframe 预览,完事。改字 debounce 400ms,请求全在本机,敲字的时候基本无感。

难的是另一件事:预览凭什么可信。

预览是最容易骗人的地方

我先按老习惯写了个独立渲染函数。不复用任何已有代码,自己写一遍 Markdown 转 HTML。

写完试了一下:左边改标题,右边还是旧的。

查出来是发布器那边的渲染器没跟上。修完这一处,改下一处又不一致了。

两个渲染器就是两套会漂移的规则。改一个正则、换一个图片处理方式,都得记得改两处。漏一处,线上就开始和我预览里看到的不一样。

后来我把预览脚本里的 build() 拆成了两半——一半读文件,一半只管渲染。编辑器调渲染那半,一行代码都不自己写。

编辑器左栏  ──┐
预览 HTML   ──┼──→  同一个 markdown_to_html()  ──→  线上页面
命令行发布  ──┘

三条路走同一个函数。预览里什么样,线上就是什么样。

发布按钮也是同一条 publish_article.py 命令。编辑器点按钮和我在命令行敲,结果必然一致。

alt:编辑器左栏、预览 HTML、命令行发布三条路径共用同一个渲染函数的结构
alt:编辑器左栏、预览 HTML、命令行发布三条路径共用同一个渲染函数的结构

两个自己写的 bug,都挺蠢

编辑区一片空白,一按保存就清空文章

页面能打开,下拉框里有 7 篇文章,但编辑区什么都没有。

更要命的是这时候按保存。

它真的会把空内容写回去。文章直接清空。

我一开始觉得不可能,自己手点了一次试试。

确实清了。幸好前面写过一个「空内容拒绝保存」的兜底,不然这轮白干。

修法是服务端把 md 内容塞进页面:

page = page.replace("__INIT_MD__", json.dumps(md))

json.dumps 不够。

正文里只要出现一个 </script>,整个页面就废了。所以还得先把 < > & 换成 \u003c 这类转义。

而且替换占位符必须放在最后做。先替的话,正文里要是本来就有那串占位符字样,会被二次替换。

alt:保存前加的三道判据:空内容直接拒绝、写完比对 md5、每次生成 .bak 备份
alt:保存前加的三道判据:空内容直接拒绝、写完比对 md5、每次生成 .bak 备份

预览永远显示第 1 篇

下拉框切到第 5 篇,右边还是第 1 篇的内容。

let cur = sel.value;          // 这行在脚本开头
sel.value = "__CUR__";        // 这行在末尾

开头那行执行的时候 <select> 还没被赋过值,读到的是第一个 option。末尾赋完值,cur 没跟着更新。

修法就一句:设完 sel.value,同步 cur = sel.value。

这个 bug 是看截图发现的。

当时右边报「图片占位符未在 images 中配置」—— 第 5 篇的图还没配。报错里其实已经写了是哪篇,我没先看那句。

顺带一个跟内容无关的坑

双击启动的 .bat 一开始双击就报语法错误,中文注释全成了乱码。

文件是 UTF-8 存的,cmd.exe 按系统代码页读,中文环境上是 GBK。

解法是 .bat 里一律不写中文。

中间我试过 chcp 65001,没用。这个命令生效是在它自己那行被解析的时候,前面的乱码早就发生了。

跟 .ps1 必须存成带 BOM 的 UTF-8 是一类问题,只是踩的顺序不一样。

现在那个 bat 就这么几行:

@echo off
cd /d "%~dp0"
title Article Editor
echo   Article editor starting...
python edit_article.py
if errorlevel 1 pause

双击就开,不用记命令。

两个我还没弄明白的地方

发布要十几秒,所以日志是流式回传的。HTTP/1.1 的 chunked 手工分块,前端用 fetch().body.getReader() 逐行读。能跑,但这是最土的办法。SSE 或者 WebSocket 是不是更合适,我没试过。

草稿校验 6 项、发布校验 17 项,这两套数字我是照着已有的校验抄的。边界情况有没有漏,我不敢说。

跑一遍才算验证过

python preview_article.py --post 4
python publish_article.py --post 4 --draft
python publish_article.py --post 4

第一条生成本地 HTML,第二条存草稿,第三条真发布。跑完看两件事:草稿那步不推百度,发布那步返回 ok=true。

草稿状态下文章页是 404,所以草稿不推百度——推了等于送死链。

sitemap 缓存也得跟着删,不然里面挂着一条 404。

这套发布命令是直连写库,绕过 wp_insert_post(),踩过的坑写在另一篇。编辑器只是给它包了层界面,底下的事一点没变。

推百度那段更绕。界面上那句"已推送"怎么做到不是假成功的,也写过一篇。

发表评论