← 中文资源

简体中文版本

转义 HTML 特殊字符

在把不可信值插入 HTML 或属性前转义与号、尖括号、引号和换行,降低 XSS 风险。

阅读英文原文

功能说明

escapeHtml 把与号、小于号、大于号、双引号和单引号替换为实体,escapeHtmlAttribute 在此基础上把换行转换为数字实体,escapeHtmlTemplate 提供带标签模板的便捷写法。它们用于服务端渲染、邮件模板和字符串拼接场景,确保用户输入被当作文本而不是标记解析。输出仍是字符串,不会自动添加引号或包裹元素。

关键代码

替换使用一次性正则与实体映射表,避免多次遍历和链式替换导致的二次转义问题。映射表包含单引号,因为属性常使用单引号包裹;属性函数额外处理 CRLF 与 LF,防止多行值破坏属性结构。标签模板版本对插值逐个转义,静态片段保持原样,适合在代码中书写少量 HTML 片段。

使用注意

手工转义只能处理文本节点和带引号属性,不能替代 HTML 净化。不要把结果再放进未加引号的属性、script、style 或 URL 协议位置,这些上下文需要各自的编码规则。双转义会让 & 显示为字面实体,拼接前应确认值尚未转义。现代框架默认转义插值,只有在明确拼接原始 HTML 时才需要此函数。

验证方式

测试五个特殊字符分别被替换,连续特殊字符不会漏转义。验证属性函数把换行转为 ,并测试 CRLF 与 LF 两种输入。用标签模板拼接用户输入,断言尖括号被转义且静态片段完整。最后测试数字、null、undefined 与对象输入会被 String 转换,并确认没有引入反斜杠或重复转义。

代码示例

const HTML_ENTITIES = {
  "&": "&",
  "<": "&lt;",
  ">": "&gt;",
  '"': "&quot;",
  "'": "&#39;",
};

export function escapeHtml(value) {
  return String(value).replace(/[&<>"']/g, (character) => HTML_ENTITIES[character]);
}

export function escapeHtmlAttribute(value) {
  return escapeHtml(value).replace(/\r?\n/g, "&#10;");
}

export function escapeHtmlTemplate(strings, ...values) {
  return strings.reduce((output, chunk, index) => {
    const value = index < values.length ? escapeHtml(values[index]) : "";
    return output + chunk + value;
  }, "");
}