核心是嵌入专业Markdown编辑器(如EasyMDE)并适配Bootstrap布局,而非仅用textarea;需禁用默认toolbar、手动同步滚动、用marked+DOMPurify安全渲染预览,并校验Markdown语法有效性。

用 Bootstrap 4/5 搭后台 Markdown 编辑器,核心不是“美化”,而是“不破坏编辑体验”
Bootstrap 本身不提供 Markdown 解析或编辑能力,它只负责布局和样式。直接套用 form-control 包裹 textarea 写 Markdown,会丢失实时预览、语法高亮、快捷键等关键功能——这不是“做了”,是“没做对”。真正可行的路径是:用专业 Markdown 编辑器(如 EasyMDE 或 simplemde)嵌入 Bootstrap 布局,并手动对齐样式与响应行为。
选对编辑器:优先用 EasyMDE,别碰已停更的 simplemde
simplemde 自 2018 年起停止维护,其依赖的 codemirror 版本过旧,与 Bootstrap 5 的 flex 容器、resize: none 冲突明显,常见报错 Cannot read property 'focus' of null。而 EasyMDE 是其活跃分支,支持现代 CSS、修复了高度自适应问题,且 API 兼容性好。
- 通过 CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/easymde@2.19.1/dist/js/easymde.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde@2.19.1/dist/easymde.min.css">
- 初始化时禁用默认 toolbar(避免与 Bootstrap 按钮样式打架):
const easyMDE = new EasyMDE({ element: document.getElementById("markdown-editor"), toolbar: false, // 关键:交由 Bootstrap 控制按钮区 autosave: false, spellChecker: false }); - 把
EasyMDE实例挂载到 Bootstrap 的.col内,而非直接塞进.form-group—— 否则响应式断点下高度塌陷
让预览区和编辑区共存且同步滚动,别用 iframe
很多方案用 iframe 渲染预览,导致跨域、样式隔离、滚动不同步。正确做法是用 marked + DOMPurify 在同一页面解析并插入到相邻 div 中:
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
- 引入解析库:
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.5/dist/purify.min.js"></script>
- 监听
easyMDE.codemirror.on("change", ...),每次变更后调用:const html = DOMPurify.sanitize(marked.parse(easyMDE.value())); previewEl.innerHTML = html;
- 为预览区加
class="bg-light p-3 border rounded",与 Bootstrap 表单区域视觉统一;设置max-height: 60vh; overflow-y: auto;防止撑满屏幕 - 滚动同步需手动绑定:监听编辑区
scroll事件,按比例映射到预览区scrollTop(注意防抖,否则卡顿)
提交前校验 Markdown 有效性,而不是只校验空值
后台写作页面常忽略一个事实:用户可能输入大量空格、非法链接、未闭合的代码块,导致服务端解析失败或 XSS。前端需轻量拦截:
- 检查是否含未闭合的反引号:
if ((easyMDE.value().match(/`/g) || []).length % 2 !== 0) { alert("存在未闭合的行内代码块"); return false; } - 检测常见危险 HTML 标签(即使 marked 默认不渲染):
if (/<(script|iframe|object|embed)/i.test(easyMDE.value())) { alert("禁止使用 HTML 标签"); return false; } - 提交时取
easyMDE.value()而非textarea.value—— 后者在EasyMDE初始化后已失效
样式兼容性比功能更难缠:Bootstrap 的 $enable-responsive-font-sizes: true 可能让 CodeMirror 字体在小屏上缩得太小,此时要显式重置 .CodeMirror { font-size: 1rem !important; }。

















