关于本文
本文是通过利用生成式 AI 的自动生成工作流创建的。我们将使用虚拟数据和浏览器操作来学习 Marked 和 DOMPurify 的用途、机制以及失败时的观察要点。不会访问实际的服务或个人信息。验证状态:于 2026-10-30 核对了官方文档和 GitHub 固定提交中的 HTML/JavaScript。未执行实际浏览器操作、CDN 获取及渲染/音频输出,文中的结果为代码的预期值。
| 项目 | 内容 |
|---|---|
| 对象 | Chrome/Edge/Firefox 等现代浏览器(未确认实机兼容性) |
| 使用库 | Marked 和 DOMPurify(教程内版本:Marked 16.3.0 / DOMPurify 3.4.17) |
| 费用 | 演示源码本身无需付费 API。通信费用和使用条件取决于具体环境 |
| 数据 | 页面内的虚拟数据。无需认证信息、位置信息、企业数据 |
| 学习操作 | 输入 Markdown 时显示经过安全处理的 HTML 预览 |
为什么要尝试这项技术
在写博客时,如果能预览 Markdown,就能更容易地确认标题和列表的排版格式。然而,从 Markdown 生成 HTML 的处理本身并不意味着能直接生成安全的 HTML。Marked 的作用是将 Markdown 解析为 HTML,而 DOMPurify 的作用是从 HTML 中移除危险的元素和属性。将两者结合起来,就可以通过一个小型的演示来学习便利性与安全性之间的边界。它并不能替代实际发布用的 CMS 的认证或保存功能。
在制作动态示例时,不能止步于“界面动了”这一表象,而需要区分“哪个输入改变了哪个变量、哪段处理更新了绘制”。在本节教程中,我们会在屏幕上明确显示这种变化。当将其引入实际服务时,请另外设计认证和保存的处理。
首先尝试:在线演示与预期结果
首先显示“星空备忘录”的标题以及粗体、斜体的 Markdown,然后点击更新按钮。请确认标题和列表是否作为 HTML 结构体现出来了。接着将其改写为虚构的字符串,观察预览是否发生了改变。在观察动作时,请将转换 Markdown 之前的字符串与反映到 DOM 的结果分开思考。画面下方的 SUCCESS 意味着处理无异常地结束,并不保证对所有攻击的安全性。
操作前需确认的事项
确认您的电脑可以运行 JavaScript。不需要管理员权限。
打开浏览器的开发者工具,准备检查 Console 中是否有错误、Network 中是否有 CDN 获取失败的情况。
如果演示未实际发布,请将 Daily Code 侧的
index.html与app.js保存到同一个文件夹中,并在本地 HTTP 服务器中打开。当使用 module 时,不保证通过 file:// 直接运行的有效性。对比操作前后的结果。如果与预期值不同,请先记录“什么没有显示出来”。
原理总图
flowchart LR
A["入力やクリック"] --> B["イベントを受ける"]
B --> C["MarkedとDOMPurify のAPI"]
C --> D["状態と描画を更新"]
D --> E["見た目と文字で確認"]
此图为学习用概念图,并未表示浏览器内部实现或网络通信的细节。无论是什么库,“追踪操作触及哪个变量”这一点都是相通的。
无法使用公开演示时的本地确认方法
通过 GitHub 的 Raw 视图,将固定提交的HTML 主体和JavaScript 主体分别index.html与app.js保存在同一个新建文件夹中。仅靠 README 无法运行。在 Windows 上,在该文件夹中打开 PowerShellpy -3 -m http.server 8000 --bind 127.0.0.1,在 Linux/macOS 上运行python3 -m http.server 8000 --bind 127.0.0.1,然后打开同一台电脑上的http://127.0.0.1:8000/。若要退出,请在终端中按Ctrl+C。由于浏览器会从外部 CDN 获取库本身,若无法连接,请检查 Console 和 Network 中的错误。此步骤为复现指南,并非本文章的浏览器实测报告。
它是如何运作的:解读 API
Marked 的 parse 会从 Markdown 文本生成 HTML 字符串。由于 Markdown 本身可以包含 HTML,因此解析结果中可能会混入 onerror 等事件属性。Marked 不会对该 HTML 进行无害化处理。在将生成结果传递给浏览器中的 innerHTML 之前,请使用 DOMPurify.sanitize 将其限制为安全的元素。在本次演示中,将进一步禁止图片、iframe、style 和 script,并且外部链接也将无法点击。这是教学用的限制,根据具体用途,必须明确设计允许的元素。
如何阅读最简代码
// Marked単体のHTMLをinnerHTMLへ直渡ししない const unsafeHtml = marked.parse(markdownText); const safeHtml = DOMPurify.sanitize(unsafeHtml); preview.innerHTML = safeHtml;
以上是提取了 API 要点的摘录。它并非可复制并独立运行的完整文件。用于运行的 HTML 和实现代码大全请在 Daily Code 侧的 README / 演示文件中确认。跟踪哪个函数选择了 HTML 元素、哪一行更新了数值,并使用已知的虚构值进行尝试。
只更改一个条件并进行比较
如果在输入中添加普通的粗体,它将被转换为 strong 元素。另一方面,即使输入包含图片的 Markdown,演示中也不会显示图片。这是因为故意禁止了外部图片的加载。如果将其集成到公共 CMS 中,则只允许必需的标签,同时还要检查 URL 的协议和链接的属性。能够分别修改 Markdown 语法和 HTML 允许规则这一点非常重要。
比较的步骤是:记录初始值,只更改一个地方,并确认结果是否出现在预期位置。如果同时更改多个输入,就会分不清是什么产生了影响。请将包含恢复到修改前状态的操作也纳入验证范围。
发生故障时应该检查哪里
仅仅因为通过了 Markdown 转换库就判断为“安全”是错误的。在加工了 HTML 字符串之后又再次拼接不安全的 HTML,就会失去无害化的意义。在实际业务中,HTML Sanitizer 的更新、CSP、Trusted Types 等也是考虑对象。如果直接公开用户输入,不仅在浏览器端,在服务器端也需要进行适当的验证。本次示例是一个简单的浏览器显示实验,不能代替安全性保证或渗透测试。
| 观察到的状态 | 区分点 | 应对示例 |
|---|---|---|
| 画面从初始状态起没有变化 | 脚本获取、初始化、事件注册 | 检查 控制台 / 网络 / script 标签 |
| 显示发生了变化但含义不正确 | 输入值、数组、单位、更新目标 | 固定数值,逐个条件进行检查 |
| 无法按动按钮 | 选择器与 DOM 生成顺序 | 检查 HTML 以确认 id 是否一致 |
| 仅在部分终端上无法运行 | 浏览器功能、权限、CDN、性能 | 记录终端与版本、复现操作 |
浏览器内的错误与公共 Web 服务器的故障是不同的。前者应通过开发者工具中的错误内容来调查,后者则通过 HTTP 响应或资产分发条件来调查。绝不把未知的失败表述为成功,这能提升技术备忘录的可靠性。
业务与学习中的应用
可应用于技术文档预览、记事本、轻量级 CMS、内部 Wiki 原型制作等。实际的编辑权限、修订历史、发布流程、回滚、防止恶意文件上传等则是不同的业务需求。仅仅选择预览库并不能完善整个发布基础设施的安全性。
引入前需要决定的事项
向读者发布时,需决定显示的数据来自何处、谁可以修改、保留在屏幕上的信息种类以及库更新时的确认事项。本次演示既没有登录也没有服务器保存。因此,在添加运营功能之前,建议首先区分“按预期显示的最小部分”与“实际业务中需要可靠性、权限和备份的部分”。由于第三方 CDN 涉及外部通信,因此必须提前确认企业网络是否允许。
与其它方式进行比较
| 方式 | 适用场景 | 注意点 |
|---|---|---|
| Marked 和 DOMPurify | 适用于输入 Markdown 并显示安全处理后的 HTML 预览等场景 | 需要更新依赖库并管理使用条件 |
| 浏览器标准 API | 自行编写小型功能 | 自行确认规范和兼容性 |
| 静态图像和表格 | 不需要交互的说明 | 无法即时体验状态的变化 |
库是按需选择的工具。请将你想达成目标的需求与学习成本进行综合权衡。在小型页面中,不把“引入库”作为唯一目的,往往会更容易维护。
GitHub 示例
博客正文负责背景和思路,Daily Code 则负责提供可执行和修改的代码,两者的角色各有分工。其中不包含用于向外部服务发布或保存数据的 API。
官方信息与一手资料
资料查阅范围:截至2026-10-27编辑时,请参考官方文档。这并不保证链接未来的更改或所有CDN资产的响应。
验证范围的补充说明
我们已将存储在GitHub上的固定源代码与官方API说明进行了比对。浏览器操作、CDN加载以及在各个操作系统上的运行结果尚未经验证。在进行实际动作确认时,请检查控制台(Console)和网络(Network),切勿仅凭屏幕上的SUCCESS显示就断定所有条件都已成功。
