about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYotam Ofek <yotam.ofek@gmail.com>2025-02-19 18:13:02 +0000
committerYotam Ofek <yotam.ofek@gmail.com>2025-02-19 18:42:02 +0000
commit489f5c19d4c54df381f5b7b7d6c1f24094f028b6 (patch)
tree786402dd77df2b7859f1192f8c8f69819a38e2a7
parented49386d3aa3a445a9889707fd405df01723eced (diff)
downloadrust-489f5c19d4c54df381f5b7b7d6c1f24094f028b6.tar.gz
rust-489f5c19d4c54df381f5b7b7d6c1f24094f028b6.zip
librustdoc: Use `pulldown-cmark-escape` for HTML escaping
-rw-r--r--Cargo.lock1
-rw-r--r--src/librustdoc/Cargo.toml1
-rw-r--r--src/librustdoc/html/escape.rs51
3 files changed, 5 insertions, 48 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 22a349b2d32..74407be1444 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4577,6 +4577,7 @@ dependencies = [
  "itertools",
  "minifier",
  "pulldown-cmark 0.9.6",
+ "pulldown-cmark-escape",
  "regex",
  "rinja",
  "rustdoc-json-types",
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index c07cc4dc347..91cc4088788 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -15,6 +15,7 @@ itertools = "0.12"
 indexmap = "2"
 minifier = { version = "0.3.5", default-features = false }
 pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false }
+pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 serde_json = "1.0"
diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs
index 88654ed32da..ac9e2f42cc6 100644
--- a/src/librustdoc/html/escape.rs
+++ b/src/librustdoc/html/escape.rs
@@ -5,6 +5,7 @@
 
 use std::fmt;
 
+use pulldown_cmark_escape::FmtWriter;
 use unicode_segmentation::UnicodeSegmentation;
 
 /// Wrapper struct which will emit the HTML-escaped version of the contained
@@ -13,31 +14,7 @@ pub(crate) struct Escape<'a>(pub &'a str);
 
 impl fmt::Display for Escape<'_> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Because the internet is always right, turns out there's not that many
-        // characters to escape: http://stackoverflow.com/questions/7381974
-        let Escape(s) = *self;
-        let pile_o_bits = s;
-        let mut last = 0;
-        for (i, ch) in s.char_indices() {
-            let s = match ch {
-                '>' => "&gt;",
-                '<' => "&lt;",
-                '&' => "&amp;",
-                '\'' => "&#39;",
-                '"' => "&quot;",
-                _ => continue,
-            };
-            fmt.write_str(&pile_o_bits[last..i])?;
-            fmt.write_str(s)?;
-            // NOTE: we only expect single byte characters here - which is fine as long as we
-            // only match single byte characters
-            last = i + 1;
-        }
-
-        if last < s.len() {
-            fmt.write_str(&pile_o_bits[last..])?;
-        }
-        Ok(())
+        pulldown_cmark_escape::escape_html(FmtWriter(fmt), self.0)
     }
 }
 
@@ -51,29 +28,7 @@ pub(crate) struct EscapeBodyText<'a>(pub &'a str);
 
 impl fmt::Display for EscapeBodyText<'_> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Because the internet is always right, turns out there's not that many
-        // characters to escape: http://stackoverflow.com/questions/7381974
-        let EscapeBodyText(s) = *self;
-        let pile_o_bits = s;
-        let mut last = 0;
-        for (i, ch) in s.char_indices() {
-            let s = match ch {
-                '>' => "&gt;",
-                '<' => "&lt;",
-                '&' => "&amp;",
-                _ => continue,
-            };
-            fmt.write_str(&pile_o_bits[last..i])?;
-            fmt.write_str(s)?;
-            // NOTE: we only expect single byte characters here - which is fine as long as we
-            // only match single byte characters
-            last = i + 1;
-        }
-
-        if last < s.len() {
-            fmt.write_str(&pile_o_bits[last..])?;
-        }
-        Ok(())
+        pulldown_cmark_escape::escape_html_body_text(FmtWriter(fmt), self.0)
     }
 }