企评社

富文本 / Markdown

左边写 Markdown、右边实时预览;富文本所见即所得可一键转成 Markdown;粘贴 HTML 也能反着转回来

内容只在你的浏览器里处理,不上传、不留存
先说清楚本页的两个取舍。富文本区用的是 contenteditable + document.execCommand:execCommand 已被标准化组织标记为废弃, 但主流浏览器仍支持它。缺点是格式化按钮在部分浏览器上行为不一致(例如在 Firefox 与 Safari 里插入的标签、 换行方式可能不同,粘贴外部内容时也会带进一堆行内样式),所以长文档建议以 Markdown 源码为准, 富文本区更适合"把一段已有内容快速转成 Markdown"。 ② 预览与导出时只做基础净化:本页会移除脚本类标签与事件属性, 但它不是专业级净化器,不要用它渲染来源不可信的内容(详见页面底部说明)。

Markdown 源码 → 实时预览

实时预览(marked 渲染 + 基础净化)
字符数 0 词数 0 行数 0 词数口径:中日韩字符按「每字一词」,其余按空白切分的连续片段计数

导出与复制

导出的内容以 Markdown 源码框为准(富文本「转成 Markdown」与 HTML 转换的结果都会先写回那里); 文件名形如 markdown-20260607120000.md,由浏览器在本地生成并下载,不经服务器。

HTML 导出预览(净化后的正文片段,最多显示前 1200 字符)

        
Markdown 字符数 0 词数 0 行数 0

Markdown、富文本与 HTML:各自适合什么,以及本页做了什么净化

Markdown 语法要点,一屏就能记住。标题用行首的 #(一级一个、二级两个,最多到六级);**粗体***斜体* 用星号包裹;行首 > 是引用;-1. 开头是列表;四个空格或三个反引号包起来是代码;方括号接圆括号是链接(方括号里写文字、圆括号里写网址),感叹号加方括号是图片;一行里用竖线分隔、并在下一行写上 --- 就是表格;三个及以上的连字符或星号独占一行是分隔线。这些符号都是纯 ASCII,任何编辑器、任何系统都能读懂,也不会因为换一个软件就"格式全丢"。本页左侧的工具栏就是往光标处插入这些片段,选中的文字会被自动包进成对标记里。

Markdown 和富文本各自的适用场景。富文本(Word、公众号后台、各类所见即所得编辑器)的优势是所见即所得:加粗就是加粗,字号颜色随点随有,交给完全不懂标记的人也能用,排版精细度高。代价是它把"内容"和"样式"绑在一起存成 HTML,同一段文字在不同软件里可能渲染成两个样子。Markdown 的优势是纯文本:一份 .md 文件用记事本打开也能读,用 Git 能看出一行行改了什么,转换成网页、PDF、公众号排版都只是换一个渲染器。代价是它表达能力有限——字体、颜色、居中、分栏这些它基本不管,需要精细排版时仍要回到富文本或 HTML。一个实用的分工是:存稿、写文档、写技术笔记用 Markdown;最终交付或需要精细排版的成品用富文本。本页把三条路都放在一起,就是为了让你在两者之间随时来回:Markdown 写好了可以直接导出 HTML,从别处复制的富文本或 HTML 也能一键退回 Markdown。

为什么 Markdown 更适合长期存稿。第一,它是纯文本,二十年后任何系统都能打开,不会像老版本的 .doc 那样需要特定软件才能还原;第二,它不依赖样式表,把同一份文件渲染成网页、PDF、电子书只是换渲染器的事;第三,它对版本管理友好,一次修改在 Git 里就是一两行差异,而富文本的一处加粗往往会改掉整段 HTML;第四,它便于程序处理,脚本、静态站点生成器、AI 工具都直接吃 Markdown。需要提醒的是:Markdown 没有统一标准,CommonMark 是最接近共识的规范,表格、删除线、任务列表这些属于 GFM 扩展,不同平台的渲染结果可能略有出入——所以同一份稿件在目标平台上先预览一遍,永远是好习惯。

XSS 是什么,本页做了哪些净化。XSS(跨站脚本)指攻击者把可执行的脚本混进网页内容里,让它在别人的浏览器中运行,从而窃取登录凭据、冒充用户操作。Markdown 本身相对安全,但它允许内嵌原始 HTML,而 Markdown 转出来的是 HTML 字符串——如果直接把这段字符串塞进页面,粘贴进来的 <script>、图片上的 onerror 事件、或者 href="javascript:…" 这类链接就有可能被执行。本页因此在渲染与导出前统一过一遍基础净化:整块移除 scriptiframeobjectembedstyle 等可执行或可嵌入外部内容的元素;移除全部以 on 开头的事件属性;把 javascript:vbscript: 以及非图片的 data: 协议链接从 href/src 里摘掉;其余不在白名单内的标签被剥掉、只保留其中的文字。净化逻辑是一个不依赖浏览器的纯函数,因此它本身可以被逐条断言。但必须说清楚:这是基础净化,不是专业级防护——现实中的攻击面还包括 CSS 注入、SVG 内嵌脚本、畸形标签解析差异等等,专业场景请使用成熟的净化库。所以本页的定位是"处理你自己写的内容",不要用它渲染来源不可信的内容

为什么不上传到服务器,也不做历史记录。Markdown 渲染与 HTML 转 Markdown 都是纯计算:前者是把标记换成标签,后者是把标签换成标记,两步都不需要后端能力,浏览器里几十毫秒就能做完。而这类内容往往正是最私密的那一类——未发布的稿件、内部文档、会议记录、客户材料、产品需求。上传到别人的服务器意味着多一份副本、多一处泄露面,也意味着服务端要为你保存和清理这些文本。所以本页全程在你的设备上完成:渲染、转换、导出、复制全部由页面内的 JavaScript 执行,脚本来自本站自托管(没有 CDN、没有外部请求),你输入的文字不写进网址参数、不写进 localStorage 或 sessionStorage、不写进 cookie,刷新页面就回到空白状态。打开浏览器开发者工具的 Network 面板,整页不会出现任何提交请求——这一点你可以自己验证。

常见问题

这个 Markdown 编辑器的实时预览是怎么实现的?数据会发到服务器吗?

预览是在你的浏览器里用自托管的 marked 把 Markdown 渲染成 HTML,再经过一次基础净化后显示在右侧;转 Markdown 用的是同样自托管的 turndown。两个库都只在第一次需要时才从本站加载(首次约 45KB 与 27KB,之后浏览器会缓存),页面本身没有任何上传接口,也不引用任何 CDN。你输入的文字始终停留在当前页面内,关掉或刷新就什么也不剩。

富文本区的格式化按钮为什么有时候表现不一致?

因为富文本编辑用的是浏览器原生的 contenteditable 与 document.execCommand。execCommand 已经被标准化组织标记为废弃,虽然主流浏览器仍支持,但各家实现细节不同:同样是"加粗",有的插入 b 标签、有的插入带内联样式的 span;粘贴外部内容时也可能带进一堆样式与嵌套结构;列表与引用在不同浏览器里生成的标签也不一样。所以本页把它定位为"把已有内容快速转成 Markdown"的辅助工具,长文档请以 Markdown 源码框为准,转完 Markdown 后也值得再快速扫一眼。

HTML 转 Markdown 会丢东西吗?为什么转换后表格/代码块变了样?

会有损失,而且这是转换本身的限制:Markdown 能表达的只有标题、粗体斜体、链接、图片、列表、引用、代码、分隔线这几类,HTML 里的字号、颜色、居中对齐、多列分栏等都没有对应写法,turndown 会直接丢弃(实测把带颜色与居中的段落转出来只剩纯文字)。另外要特别说明:turndown 的默认规则里没有表格,表格转出来的是"每个单元格文字各占一段"的普通文本,原有的行列结构会丢失,需要表格时请在 Markdown 源码里按竖线语法自己补一遍;跨行跨列的合并单元格同样无法表达。代码块也要看来源:如果源 HTML 里是靠 CSS 空白的普通段落(不少所见即所得编辑器就是这么存的),会被当成普通文本,需要手动补上三个反引号。

预览区做的"基础净化"能防住 XSS 吗?

能挡住最常见的几类:脚本标签、iframe/object/embed 这类可嵌入外部内容的元素、全部以 on 开头的事件属性(如 onerror、onclick)、以及 href/src 里的 javascript:、vbscript: 与 data: 协议(仅放行 data:image/ 开头的图片),其余标签按白名单处理,不在白名单里的标签会被剥掉标签、只留下文字。这已经能覆盖绝大多数"从别处复制一段 Markdown/HTML 过来"的场景。但它不是专业级净化:现实中的攻击面还包括 CSS 注入、SVG 内嵌脚本、浏览器对畸形标签的解析差异等,因此不要用它渲染来源不可信的内容,专业场景请使用成熟的净化库。

统计里的"词数"是怎么算的?中文也算吗?

口径是:中日韩字符(含中文、日文假名、韩文)按"每个字算一个词",其余内容按空白切分的连续片段各算一个词,数字与英文缩写算一个词。这样做是因为中文不用空格分词,若按空格切分会把一整段中文算成 1 个词,明显偏低。字符数按 Unicode 码点统计(emoji 与罕见汉字因为是代理对,不会被算成两个),行数按换行符计数(空文本记为 0 行)。三个统计口径都写成了纯函数,页面与导出用的是同一份实现。

相关工具