about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2018-01-22 22:23:08 +0530
committerManish Goregaokar <manishsmail@gmail.com>2018-01-22 22:23:08 +0530
commitcfc9f5a9d8adaf02a19fffa46b0d24792a64ed2b (patch)
tree4e1e8cb02459c95904ce88fbd0dbba624dd1b524
parentfe93adad2c4f7a9709e44f157d97f2fe623c0236 (diff)
downloadrust-cfc9f5a9d8adaf02a19fffa46b0d24792a64ed2b.tar.gz
rust-cfc9f5a9d8adaf02a19fffa46b0d24792a64ed2b.zip
Temporary fix missing escape_href in hoedown_link by copying pulldown's code
-rw-r--r--src/librustdoc/html/markdown.rs54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index c8de48ea42b..b0cfd12c27a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -775,6 +775,55 @@ pub fn render(w: &mut fmt::Formatter,
               links: &[(String, String)],
               print_toc: bool,
               html_flags: libc::c_uint) -> fmt::Result {
+    // copied from pulldown-cmark (MIT license, Google)
+    // https://github.com/google/pulldown-cmark
+    // this is temporary till we remove the hoedown renderer
+    static HREF_SAFE: [u8; 128] = [
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+            0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+        ];
+
+    static HEX_CHARS: &'static [u8] = b"0123456789ABCDEF";
+
+    fn escape_href(ob: &mut String, s: &str) {
+        let mut mark = 0;
+        for i in 0..s.len() {
+            let c = s.as_bytes()[i];
+            if c >= 0x80 || HREF_SAFE[c as usize] == 0 {
+                // character needing escape
+
+                // write partial substring up to mark
+                if mark < i {
+                    ob.push_str(&s[mark..i]);
+                }
+                match c {
+                    b'&' => {
+                        ob.push_str("&amp;");
+                    },
+                    b'\'' => {
+                        ob.push_str("&#x27;");
+                    },
+                    _ => {
+                        let mut buf = [0u8; 3];
+                        buf[0] = b'%';
+                        buf[1] = HEX_CHARS[((c as usize) >> 4) & 0xF];
+                        buf[2] = HEX_CHARS[(c as usize) & 0xF];
+                        ob.push_str(str::from_utf8(&buf).unwrap());
+                    }
+                }
+                mark = i + 1;  // all escaped characters are ASCII
+            }
+        }
+        ob.push_str(&s[mark..]);
+    }
+    // end code copied from pulldown-cmark
+
     extern fn hoedown_link(
         ob: *mut hoedown_buffer,
         content: *const hoedown_buffer,
@@ -810,6 +859,9 @@ pub fn render(w: &mut fmt::Formatter,
             })
         };
 
+        let mut link_buf = String::new();
+        escape_href(&mut link_buf, &link);
+
         let title = unsafe {
             title.as_ref().map(|t| {
                 let s = t.as_bytes();
@@ -818,7 +870,7 @@ pub fn render(w: &mut fmt::Formatter,
         };
 
         let link_out = format!("<a href=\"{link}\"{title}>{content}</a>",
-                               link = link,
+                               link = link_buf,
                                title = title.map_or(String::new(),
                                                     |t| format!(" title=\"{}\"", t)),
                                content = content.unwrap_or(String::new()));