构建支持本地草稿和下载的 Markdown 写作应用

构建一个浏览器应用,让用户以可视化方式写作,将 Markdown 草稿保存到本地,并下载 .md 文件。此工作流适用于文档草稿、README 文件或个人笔记。
要体验完整的在线示例,请打开 RichMarkdown。它使用 RichTextEditor,并提供本地笔记、研究资料剪藏和多种导出选项。该产品可免费使用;在自己的应用中使用编辑器时,仍需单独考虑编辑器的授权。
先准备好可用的编辑器
下载编辑器,并通过网站提供其 richtexteditor 文件夹。通过本地 Web 服务器运行页面,不要直接打开 file: URL。创建实例前,先加载核心和插件。快速入门介绍了各框架的具体配置方法。
添加草稿保存和下载操作
下面的完整页面会创建名为 editor 的编辑器、带有 id="download" 的按钮,以及带有 id="save-status" 的状态元素。为每个文档使用不同且固定的键。
<link rel="stylesheet" href="/richtexteditor/rte_theme_default.css">
<script src="/richtexteditor/rte.js"></script>
<script src="/richtexteditor/plugins/all_plugins.js"></script>
<div id="editor"></div>
<button id="download" type="button">Download .md</button>
<p id="save-status" role="status"></p>
<script>
const editor = new RichTextEditor("#editor");
const status = document.getElementById("save-status");
const key = "my-markdown-draft";
let saved = "";
try { saved = localStorage.getItem(key) || ""; }
catch { status.textContent = "Browser storage is unavailable. Download a copy."; }
editor.fromMarkdown(saved || "# Untitled\n\nStart writing.");
function saveDraft() {
try {
localStorage.setItem(key, editor.toMarkdown());
status.textContent = "Saved in this browser.";
} catch {
status.textContent = "Draft could not be saved. Download a copy.";
}
}
let timer;
editor.attachEvent("change", function () {
clearTimeout(timer);
timer = setTimeout(saveDraft, 300);
});
window.addEventListener("pagehide", saveDraft);
document.getElementById("download").addEventListener("click", function () {
const blob = new Blob([editor.toMarkdown()], {
type: "text/markdown;charset=utf-8"
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "document.md";
document.body.appendChild(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
});
</script>
确定 Markdown 必须保留的内容
在决定仅使用 Markdown 保存文档之前,先用实际文档进行测试。标题、列表、链接、引用和围栏代码块都有对应的 Markdown 表示方式。合并的表格单元格、批注和任意字体样式则无法准确转换为普通 Markdown。如果这些细节很重要,还应保留 HTML 或结构化 JSON。
代码块的语言标记用于描述其内容,不会执行、编译或验证代码。JavaScript、TypeScript、PHP 和 C# 示例应作为文本保留在文档中。
本地草稿只是便捷功能
localStorage中的数据属于当前浏览器和源。它不是备份、加密存储或跨设备同步机制。- 清除网站数据会删除草稿。请提供下载操作,并在编辑器附近说明这一点。
- 处理多个文档时,使用独立的键和文档列表。文档数量较多时,可能需要 IndexedDB。
- 团队使用时,应采用需要身份验证的服务器存储,并处理编辑冲突。共用一个本地键并不能实现协作。
处理客户文档前的准备
对服务器端的每次读写都进行授权检查。将提交的 Markdown 视为不可信输入。如果服务器将其转换为 HTML,应根据 HTML 的展示位置,选择适当的 Markdown 渲染器和 HTML 净化策略。浏览器预览不能替代服务器端验证。
将图片文件单独保存,并存储稳定的 URL。Markdown 文件不会自动包含其引用的图片。请参阅保存包含图片的富文本。
检查工作流
- 输入标题和列表,然后等待保存成功的提示。
- 重新加载页面,确认草稿已恢复。
- 添加代码块,下载文件,并在 Markdown 阅读器中打开。
- 检查语言标记、缩进、链接和图片。
- 禁用浏览器存储,确认仍可下载文件。
接下来可参阅将 Word 和 Google Docs 文档转换为 Markdown、交互式 Markdown 演示和必填内容验证。