验证富文本表单字段
必填的富文本字段需要一条应用层规则。HTML 可能不为空,而文档中却没有任何文字。请验证编辑器的当前内容,把它复制到要提交的字段中,并在服务器上再次执行同样的规则。
1. 确定什么算作内容
对于工单描述,您可能要求必须有文字。而对于图片配文工具,一张上传的图片本身就可能是有效的文档。仅检查文字的规则必须是有意拒绝只有图片的文档,而不是意外地丢掉一篇有效的内容。
请把必填内容、最小文本长度和最大载荷大小定义为相互独立的规则。HTML 长度计入了标记,并不等于可读字符数。如果使用 getCharCount() 或 getPlainText(),在把其结果作为业务规则之前,请先确认您所安装的版本如何处理空白、列表和换行。
2. 检测空文本,而不是空标记
// Application policy: this field requires text, not an image-only document.
// Browser-side validation helper. This is NOT an HTML sanitizer.
function hasRequiredText(html) {
const template = document.createElement("template");
template.innerHTML = html;
template.content.querySelectorAll("script, style, template")
.forEach(node => node.remove());
return (template.content.textContent || "")
.replace(/[\s\u00a0\u200b\ufeff]/gu, "").length > 0;
}这个示例会拒绝空段落、换行、不换行空格和只有图片的内容。它把内容解析到一个与页面分离的模板中,从不把这些内容插入实际页面。它只是检查是否存在文字,而不是安全过滤器或视觉布局测试:被 CSS 隐藏的文字和应用特有的组件需要各自的策略。
对于最小长度,请决定计算的是代码单元、Unicode 码位还是用户感知的字符。JavaScript 的字符串长度对表情符号的计数可能与可见字符不同。请在请求的两端使用同一策略。
3. 复制当前 HTML 并显示有用的错误提示
// Assumes editor1 is ready and these elements exist on your page.
// Leave the editor's hidden textarea without a native required attribute.
const form = document.querySelector("#ticket");
const field = document.querySelector("#body");
const message = document.querySelector("#body-error"); // e.g. <p role="alert">
form.addEventListener("submit", event => {
const html = editor1.getHTMLCode();
field.value = html; // Include programmatic edits in the submitted value.
if (!hasRequiredText(html)) {
event.preventDefault();
message.textContent = "Please enter a description.";
editor1.focus();
return;
}
message.textContent = "";
// Normal form submission continues to your application's endpoint.
});编辑器的 textarea 被隐藏之后,浏览器原生的 required 验证就无法可靠地充当编辑器的必填规则。普通表单控件可以继续使用常规验证,但编辑器的规则要针对其当前内容实现。不要给隐藏的后备字段加上原生 required 约束,并指望出现一个可获得焦点的错误提示。
在初始化完成之前,请保持 Save 处于禁用状态。验证失败时,保留草稿,在字段附近显示可见的消息,并把焦点移回编辑器。请使用您的集成方式所支持的无障碍钩子,把消息关联到实际的可编辑区域;只在隐藏的 textarea 上设置属性,并不能为编辑区域提供标签。
这段代码只涵盖同步的文本验证。如果有图片正在上传,提交之前请遵循上传完成与保存的顺序。在 React 中,请按照编辑器状态与保存中的说明,在提交时读取当前内容。
4. 在服务器端净化之后再次验证
客户端可以绕过浏览器检查。请对保存操作进行身份验证和授权,强制执行请求和存储限制,使用一个持续维护、基于解析器的策略净化 HTML,然后再判断被接受的文档是否满足您的内容规则。只包含被拒绝标记的文档,不能变成一条被接受的空记录。
返回针对该字段的错误,并让用户的草稿保持可用。绝不要在错误响应中以未转义的形式渲染被拒绝的 HTML。如需接收和存储内容的 C# 或 PHP 示例,请从您所用语言的演示和富文本存储指南开始。
验收清单
- 空编辑器、空白段落和不换行空格会被拒绝。
- 普通文本、带格式的文本以及用户输入的各种语言都能被接受。
- 只有图片的内容遵循明确的策略。
- 以编程方式加载的内容会包含在提交中。
- 验证错误会保留内容,并且可以通过键盘和屏幕阅读器访问。
- 服务器会拒绝无效的直接请求,而不依赖 JavaScript。
可以试试表单提交演示,阅读为什么必填字段会接受空 HTML,或者查看 textarea 安装。