diff --git a/src/utils/html.rs b/src/utils/html.rs
index cbca198..ef2549f 100644
--- a/src/utils/html.rs
+++ b/src/utils/html.rs
@@ -9,13 +9,30 @@
///
/// 单引号统一为 `'`(HTML5 规范,与原 server 端 `helpers::escape_html` 一致)。
/// 可安全用于文本节点与属性值上下文。
+///
+/// 单遍扫描:旧实现链式调用 5 次 `str::replace`,每次全量扫描 + 分配一个新 String,
+/// 5 个特殊字符意味着 5 次堆分配 + 5 遍扫描。单遍 `match` 只扫描一次、只分配一次。
+/// 该函数被 markdown 渲染管线密集调用(每个标题、每个代码块),属于热点路径。
pub fn escape_html(input: &str) -> String {
- input
- .replace('&', "&")
- .replace('<', "<")
- .replace('>', ">")
- .replace('"', """)
- .replace('\'', "'")
+ // 快速路径:无特殊字符直接 clone(大多纯文本走这里,零额外扫描)。
+ // memchr 风格的逐字节查找比总是分配 + 遍历更省。
+ if !input.as_bytes().iter().any(|&b| {
+ matches!(b, b'&' | b'<' | b'>' | b'"' | b'\'')
+ }) {
+ return input.to_string();
+ }
+ let mut out = String::with_capacity(input.len());
+ for c in input.chars() {
+ match c {
+ '&' => out.push_str("&"),
+ '<' => out.push_str("<"),
+ '>' => out.push_str(">"),
+ '"' => out.push_str("""),
+ '\'' => out.push_str("'"),
+ _ => out.push(c),
+ }
+ }
+ out
}
#[cfg(test)]