@@ -775,6 +775,55 @@ pub fn render(w: &mut fmt::Formatter,
775775 links : & [ ( String , String ) ] ,
776776 print_toc : bool ,
777777 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+
778827 extern fn hoedown_link (
779828 ob : * mut hoedown_buffer ,
780829 content : * const hoedown_buffer ,
@@ -810,6 +859,9 @@ pub fn render(w: &mut fmt::Formatter,
810859 } )
811860 } ;
812861
862+ let mut link_buf = String :: new ( ) ;
863+ escape_href ( & mut link_buf, & link) ;
864+
813865 let title = unsafe {
814866 title. as_ref ( ) . map ( |t| {
815867 let s = t. as_bytes ( ) ;
@@ -818,7 +870,7 @@ pub fn render(w: &mut fmt::Formatter,
818870 } ;
819871
820872 let link_out = format ! ( "<a href=\" {link}\" {title}>{content}</a>" ,
821- link = link ,
873+ link = link_buf ,
822874 title = title. map_or( String :: new( ) ,
823875 |t| format!( " title=\" {}\" " , t) ) ,
824876 content = content. unwrap_or( String :: new( ) ) ) ;
0 commit comments