@@ -775,6 +775,55 @@ pub fn render(w: &mut fmt::Formatter,
775
775
links : & [ ( String , String ) ] ,
776
776
print_toc : bool ,
777
777
html_flags : libc:: c_uint ) -> fmt:: Result {
778
+ // copied from pulldown-cmark (MIT license, Google)
779
+ // https://github.com/google/pulldown-cmark
780
+ // this is temporary till we remove the hoedown renderer
781
+ static HREF_SAFE : [ u8 ; 128 ] = [
782
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
783
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
784
+ 0 , 1 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
785
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 ,
786
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
787
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 ,
788
+ 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
789
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 ,
790
+ ] ;
791
+
792
+ static HEX_CHARS : & ' static [ u8 ] = b"0123456789ABCDEF" ;
793
+
794
+ fn escape_href ( ob : & mut String , s : & str ) {
795
+ let mut mark = 0 ;
796
+ for i in 0 ..s. len ( ) {
797
+ let c = s. as_bytes ( ) [ i] ;
798
+ if c >= 0x80 || HREF_SAFE [ c as usize ] == 0 {
799
+ // character needing escape
800
+
801
+ // write partial substring up to mark
802
+ if mark < i {
803
+ ob. push_str ( & s[ mark..i] ) ;
804
+ }
805
+ match c {
806
+ b'&' => {
807
+ ob. push_str ( "&" ) ;
808
+ } ,
809
+ b'\'' => {
810
+ ob. push_str ( "'" ) ;
811
+ } ,
812
+ _ => {
813
+ let mut buf = [ 0u8 ; 3 ] ;
814
+ buf[ 0 ] = b'%' ;
815
+ buf[ 1 ] = HEX_CHARS [ ( ( c as usize ) >> 4 ) & 0xF ] ;
816
+ buf[ 2 ] = HEX_CHARS [ ( c as usize ) & 0xF ] ;
817
+ ob. push_str ( str:: from_utf8 ( & buf) . unwrap ( ) ) ;
818
+ }
819
+ }
820
+ mark = i + 1 ; // all escaped characters are ASCII
821
+ }
822
+ }
823
+ ob. push_str ( & s[ mark..] ) ;
824
+ }
825
+ // end code copied from pulldown-cmark
826
+
778
827
extern fn hoedown_link (
779
828
ob : * mut hoedown_buffer ,
780
829
content : * const hoedown_buffer ,
@@ -810,6 +859,9 @@ pub fn render(w: &mut fmt::Formatter,
810
859
} )
811
860
} ;
812
861
862
+ let mut link_buf = String :: new ( ) ;
863
+ escape_href ( & mut link_buf, & link) ;
864
+
813
865
let title = unsafe {
814
866
title. as_ref ( ) . map ( |t| {
815
867
let s = t. as_bytes ( ) ;
@@ -818,7 +870,7 @@ pub fn render(w: &mut fmt::Formatter,
818
870
} ;
819
871
820
872
let link_out = format ! ( "<a href=\" {link}\" {title}>{content}</a>" ,
821
- link = link ,
873
+ link = link_buf ,
822
874
title = title. map_or( String :: new( ) ,
823
875
|t| format!( " title=\" {}\" " , t) ) ,
824
876
content = content. unwrap_or( String :: new( ) ) ) ;
0 commit comments