我的博客

分享技术与思想的点滴

建站日记:Markdown 前台渲染 — Parsedown PHP 库自动转换

好,先下载 Parsedown,然后改 blog-engine.php 和 article-detail.php。下载到了,但只截取了前半部分。重新下载完整文件:下载不完整,直接从 GitHub 通过 exec 下载到测试服务器上:Parsedown 下载完成。现在改 blog-engine.phparticle-detail.php。先看 blog-engine 的内容:好,renderBlogContent() 是博客渲染内容唯一的入口。改这一个函数就能覆盖所有博客主题。同时 article-detail.php 也需要改。策略:

  1. renderBlogContent() 里加 Parsedown 判断
  2. article-detail.php 里也加同样的判断
  3. 创建一个 helper 函数统一处理,避免重复代码现在搜索所有调用 renderBlogContent() 的地方,确保传入 edit_mode 参数:太多了,每个博客主题的 single.php 都调用了。方案有两个:
  4. 改所有 single.php 传入第二个参数(改动大)
  5. 在函数内部通过全局变量或从 DB 查(不推荐)
  6. 在文章 content 里加标记,函数自适应

其实最好的方案:renderBlogContent() 加一个可选参数,不改任何 single.php,通过第二个参数兼容。所有现有的调用只传一个参数,$editMode 默认空字符串,行为不变(不触发 Markdown)。

但问题是这些 single.php 没有 edit_mode 可用。需要看看它们从哪里拿到 $article:所有 single.php 都是类似结构 — 通过 getBlogPost() 加载 $article。让我看看 getBlogPost 返回什么:getBlogPost 返回的数组现在会包含 edit_mode 字段(因为 SELECT a.* 会 select 这个新加的列)。所以所有 single.php 已经能拿到 $article['edit_mode'] 了。

那我不用改所有 single.php 文件,只需在 renderBlogContent() 内部处理即可。但问题是函数签名现在改了——原有的调用只传一个参数。我需要让这个改动向后兼容:

实际更好的做法:把 $article$editMode 作为第二个参数传入。但为了不改所有 single.php,我可以在函数内部通过 $article 全局变量或者直接读 $article 数组。

最干净的方式:改函数为接受 $content 和可选的 $editMode,默认空字符串。我需要更新所有 single.php 的调用,这个用 sed 一下就行,很简单。6个文件,直接 sed 远程改,转义简单:现在验证一下:全部更新完成。现在更新 blog-engine.php 本地文件并上传:现在处理 article-detail.php。先把远程拉下来:直接把 safeHtml($article['content']) 改为用 renderBlogContent:现在上传所有改动的文件到测试服务器:一并上传之前修好的 article-new.php(怕有改动不一致):验证所有文件语法:写日志:全部搞定,总结一下这次完整的改动:


✅ 本轮全部完成

问题修复

| 问题 | 状态 | 原因/方案 | |------|-----------| | md2html 保存为空 | ✅ 已修 | PHP 端读错了字段,改为读 $content(JS 转换后的 HTML) | | 附件上传失败 | ✅ 已修 | article-new.php 引用了不存在的 ajax-attachments.php,改为用 attachment-picker.php + attachments.php | | 误点丢失编辑 | ✅ 已解决 | 独立页面 + beforeunload 防离开提醒 |

功能增强

  • 查看文章链接 — 保存成功后 flash 消息右侧显示
  • 编辑页面更宽max-w-5xl mx-auto 居中
  • ✓ 三种编辑模式 — WYSIWYG / MD2HTML / MD
  • ✓ 批量选择删除 — checkbox + 批量操作栏
  • ✓ Markdown 前台渲染 — Parsedown PHP 库自动转换

Markdown 渲染链路

MD 模式存储 → edit_mode='markdown'
                   ↓
renderBlogContent($content, $editMode='markdown')
                   ↓
Parsedown::text($content) → HTML
                   ↓
strip_tags(允许的标签) → 安全输出
                   ↓
article-detail.php 或 任一博客 single.php

这个方案的好处:不改前台 routing,不改数据库 schema 以外的任何结构,只需要在渲染内容的地方加一个转换步骤。所有博客主题和默认主题都覆盖到了。