@@ -72,6 +72,9 @@ type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
72
72
type headerfn = extern "C" fn ( * mut hoedown_buffer , * const hoedown_buffer ,
73
73
libc:: c_int , * mut libc:: c_void ) ;
74
74
75
+ type codespanfn = extern "C" fn ( * mut hoedown_buffer , * const hoedown_buffer ,
76
+ * mut libc:: c_void ) ;
77
+
75
78
type linkfn = extern "C" fn ( * mut hoedown_buffer , * const hoedown_buffer ,
76
79
* const hoedown_buffer , * const hoedown_buffer ,
77
80
* mut libc:: c_void ) -> libc:: c_int ;
@@ -89,11 +92,12 @@ struct hoedown_renderer {
89
92
blockhtml : Option < extern "C" fn ( * mut hoedown_buffer , * const hoedown_buffer ,
90
93
* mut libc:: c_void ) > ,
91
94
header : Option < headerfn > ,
92
-
93
95
other_block_level_callbacks : [ libc:: size_t ; 9 ] ,
94
96
95
97
/* span level callbacks - NULL or return 0 prints the span verbatim */
96
- other_span_level_callbacks_1 : [ libc:: size_t ; 9 ] ,
98
+ autolink : libc:: size_t , // unused
99
+ codespan : Option < codespanfn > ,
100
+ other_span_level_callbacks_1 : [ libc:: size_t ; 7 ] ,
97
101
link : Option < linkfn > ,
98
102
other_span_level_callbacks_2 : [ libc:: size_t ; 5 ] ,
99
103
// hoedown will add `math` callback here, but we use an old version of it.
@@ -185,6 +189,30 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
185
189
}
186
190
}
187
191
192
+ /// Returns a new string with all consecutive whitespace collapsed into
193
+ /// single spaces.
194
+ ///
195
+ /// The input is assumed to be already trimmed.
196
+ fn collapse_whitespace ( s : & str ) -> String {
197
+ let mut buffer = String :: with_capacity ( s. len ( ) ) ;
198
+ let mut previous_char_is_whitespace = false ;
199
+
200
+ for c in s. chars ( ) {
201
+ if c. is_whitespace ( ) {
202
+ if !previous_char_is_whitespace {
203
+ buffer. push ( ' ' ) ;
204
+ }
205
+
206
+ previous_char_is_whitespace = true ;
207
+ } else {
208
+ buffer. push ( c) ;
209
+ previous_char_is_whitespace = false ;
210
+ }
211
+ }
212
+
213
+ buffer
214
+ }
215
+
188
216
thread_local ! ( static USED_HEADER_MAP : RefCell <HashMap <String , usize >> = {
189
217
RefCell :: new( HashMap :: new( ) )
190
218
} ) ;
@@ -299,6 +327,20 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
299
327
300
328
reset_headers ( ) ;
301
329
330
+ extern fn codespan ( ob : * mut hoedown_buffer , text : * const hoedown_buffer , _: * mut libc:: c_void ) {
331
+ let content = if text. is_null ( ) {
332
+ "" . to_string ( )
333
+ } else {
334
+ let bytes = unsafe { ( * text) . as_bytes ( ) } ;
335
+ let s = str:: from_utf8 ( bytes) . unwrap ( ) ;
336
+ collapse_whitespace ( s)
337
+ } ;
338
+
339
+ let content = format ! ( "<code>{}</code>" , Escape ( & content) ) ;
340
+ let element = CString :: new ( content) . unwrap ( ) ;
341
+ unsafe { hoedown_buffer_puts ( ob, element. as_ptr ( ) ) ; }
342
+ }
343
+
302
344
unsafe {
303
345
let ob = hoedown_buffer_new ( DEF_OUNIT ) ;
304
346
let renderer = hoedown_html_renderer_new ( 0 , 0 ) ;
@@ -310,6 +352,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
310
352
= & mut opaque as * mut _ as * mut libc:: c_void ;
311
353
( * renderer) . blockcode = Some ( block) ;
312
354
( * renderer) . header = Some ( header) ;
355
+ ( * renderer) . codespan = Some ( codespan) ;
313
356
314
357
let document = hoedown_document_new ( renderer, HOEDOWN_EXTENSIONS , 16 ) ;
315
358
hoedown_document_render ( document, ob, s. as_ptr ( ) ,
@@ -523,7 +566,7 @@ pub fn plain_summary_line(md: &str) -> String {
523
566
#[ cfg( test) ]
524
567
mod tests {
525
568
use super :: { LangString , Markdown } ;
526
- use super :: plain_summary_line;
569
+ use super :: { collapse_whitespace , plain_summary_line} ;
527
570
528
571
#[ test]
529
572
fn test_lang_string_parse ( ) {
@@ -571,4 +614,17 @@ mod tests {
571
614
t ( "# top header" , "top header" ) ;
572
615
t ( "## header" , "header" ) ;
573
616
}
617
+
618
+ #[ test]
619
+ fn test_collapse_whitespace ( ) {
620
+ fn t ( input : & str , expected : & str ) {
621
+ let actual = collapse_whitespace ( input) ;
622
+ assert_eq ! ( actual, expected) ;
623
+ }
624
+
625
+ t ( "foo" , "foo" ) ;
626
+ t ( "foo bar" , "foo bar" ) ;
627
+ t ( "foo bar\n baz" , "foo bar baz" ) ;
628
+ t ( "foo bar \n baz\t \t qux" , "foo bar baz qux" ) ;
629
+ }
574
630
}
0 commit comments