@@ -133,11 +133,37 @@ macro_rules! event_loop_break {
133133 } }
134134}
135135
136+ struct ParserWrapper < ' a > {
137+ parser : Parser < ' a > ,
138+ footnotes : Vec < String > ,
139+ current_footnote_id : u16 ,
140+ }
141+
142+ impl < ' a > ParserWrapper < ' a > {
143+ pub fn new ( s : & ' a str ) -> ParserWrapper < ' a > {
144+ ParserWrapper {
145+ parser : Parser :: new_ext ( s, pulldown_cmark:: OPTION_ENABLE_TABLES |
146+ pulldown_cmark:: OPTION_ENABLE_FOOTNOTES ) ,
147+ footnotes : Vec :: new ( ) ,
148+ current_footnote_id : 1 ,
149+ }
150+ }
151+ pub fn next ( & mut self ) -> Option < Event < ' a > > {
152+ self . parser . next ( )
153+ }
154+
155+ pub fn get_next_footnote_id ( & mut self ) -> u16 {
156+ let tmp = self . current_footnote_id ;
157+ self . current_footnote_id += 1 ;
158+ tmp
159+ }
160+ }
161+
136162pub fn render ( w : & mut fmt:: Formatter ,
137163 s : & str ,
138164 print_toc : bool ,
139165 shorter : MarkdownOutputStyle ) -> fmt:: Result {
140- fn code_block ( parser : & mut Parser , buffer : & mut String , lang : & str ) {
166+ fn code_block ( parser : & mut ParserWrapper , buffer : & mut String , lang : & str ) {
141167 let mut origtext = String :: new ( ) ;
142168 while let Some ( event) = parser. next ( ) {
143169 match event {
@@ -215,8 +241,8 @@ pub fn render(w: &mut fmt::Formatter,
215241 } ) ;
216242 }
217243
218- fn heading ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
219- shorter : MarkdownOutputStyle , level : i32 ) {
244+ fn heading ( parser : & mut ParserWrapper , buffer : & mut String ,
245+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle , level : i32 ) {
220246 let mut ret = String :: new ( ) ;
221247 let mut id = String :: new ( ) ;
222248 event_loop_break ! ( parser, toc_builder, shorter, ret, true , & mut Some ( & mut id) ,
@@ -249,32 +275,48 @@ pub fn render(w: &mut fmt::Formatter,
249275 ret, lvl = level, id = id, sec = sec) ) ;
250276 }
251277
252- fn inline_code ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
253- shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
278+ fn inline_code ( parser : & mut ParserWrapper , buffer : & mut String ,
279+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
280+ id : & mut Option < & mut String > ) {
254281 let mut content = String :: new ( ) ;
255282 event_loop_break ! ( parser, toc_builder, shorter, content, false , id, Event :: End ( Tag :: Code ) ) ;
256283 buffer. push_str ( & format ! ( "<code>{}</code>" ,
257284 Escape ( & collapse_whitespace( content. trim_right( ) ) ) ) ) ;
258285 }
259286
260- fn link ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
287+ fn link ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
288+ shorter : MarkdownOutputStyle , url : & str , title : & str ,
289+ id : & mut Option < & mut String > ) {
290+ let mut content = String :: new ( ) ;
291+ event_loop_break ! ( parser, toc_builder, shorter, content, true , id,
292+ Event :: End ( Tag :: Link ( _, _) ) ) ;
293+ if title. is_empty ( ) {
294+ buffer. push_str ( & format ! ( "<a href=\" {}\" >{}</a>" , url, content) ) ;
295+ } else {
296+ buffer. push_str ( & format ! ( "<a href=\" {}\" title=\" {}\" >{}</a>" ,
297+ url, Escape ( title) , content) ) ;
298+ }
299+ }
300+
301+ fn image ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
261302 shorter : MarkdownOutputStyle , url : & str , mut title : String ,
262303 id : & mut Option < & mut String > ) {
263304 event_loop_break ! ( parser, toc_builder, shorter, title, true , id,
264- Event :: End ( Tag :: Link ( _, _) ) ) ;
265- buffer. push_str ( & format ! ( "<a href =\" {}\" >{}</a >" , url, title) ) ;
305+ Event :: End ( Tag :: Image ( _, _) ) ) ;
306+ buffer. push_str ( & format ! ( "<img src =\" {}\" alt= \" {} \" >" , url, title) ) ;
266307 }
267308
268- fn paragraph ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
269- shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
309+ fn paragraph ( parser : & mut ParserWrapper , buffer : & mut String ,
310+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
311+ id : & mut Option < & mut String > ) {
270312 let mut content = String :: new ( ) ;
271313 event_loop_break ! ( parser, toc_builder, shorter, content, true , id,
272314 Event :: End ( Tag :: Paragraph ) ) ;
273315 buffer. push_str ( & format ! ( "<p>{}</p>" , content. trim_right( ) ) ) ;
274316 }
275317
276- fn table_cell ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
277- shorter : MarkdownOutputStyle ) {
318+ fn table_cell ( parser : & mut ParserWrapper , buffer : & mut String ,
319+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ) {
278320 let mut content = String :: new ( ) ;
279321 event_loop_break ! ( parser, toc_builder, shorter, content, true , & mut None ,
280322 Event :: End ( Tag :: TableHead ) |
@@ -284,8 +326,8 @@ pub fn render(w: &mut fmt::Formatter,
284326 buffer. push_str ( & format ! ( "<td>{}</td>" , content. trim( ) ) ) ;
285327 }
286328
287- fn table_row ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
288- shorter : MarkdownOutputStyle ) {
329+ fn table_row ( parser : & mut ParserWrapper , buffer : & mut String ,
330+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ) {
289331 let mut content = String :: new ( ) ;
290332 while let Some ( event) = parser. next ( ) {
291333 match event {
@@ -303,8 +345,8 @@ pub fn render(w: &mut fmt::Formatter,
303345 buffer. push_str ( & format ! ( "<tr>{}</tr>" , content) ) ;
304346 }
305347
306- fn table_head ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
307- shorter : MarkdownOutputStyle ) {
348+ fn table_head ( parser : & mut ParserWrapper , buffer : & mut String ,
349+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ) {
308350 let mut content = String :: new ( ) ;
309351 while let Some ( event) = parser. next ( ) {
310352 match event {
@@ -322,7 +364,7 @@ pub fn render(w: &mut fmt::Formatter,
322364 }
323365 }
324366
325- fn table ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
367+ fn table ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
326368 shorter : MarkdownOutputStyle ) {
327369 let mut content = String :: new ( ) ;
328370 let mut rows = String :: new ( ) ;
@@ -347,16 +389,16 @@ pub fn render(w: &mut fmt::Formatter,
347389 } ) ) ;
348390 }
349391
350- fn blockquote ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
351- shorter : MarkdownOutputStyle ) {
392+ fn blockquote ( parser : & mut ParserWrapper , buffer : & mut String ,
393+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ) {
352394 let mut content = String :: new ( ) ;
353395 event_loop_break ! ( parser, toc_builder, shorter, content, true , & mut None ,
354396 Event :: End ( Tag :: BlockQuote ) ) ;
355397 buffer. push_str ( & format ! ( "<blockquote>{}</blockquote>" , content. trim_right( ) ) ) ;
356398 }
357399
358- fn list_item ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
359- shorter : MarkdownOutputStyle ) {
400+ fn list_item ( parser : & mut ParserWrapper , buffer : & mut String ,
401+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ) {
360402 let mut content = String :: new ( ) ;
361403 while let Some ( event) = parser. next ( ) {
362404 match event {
@@ -372,7 +414,7 @@ pub fn render(w: &mut fmt::Formatter,
372414 buffer. push_str ( & format ! ( "<li>{}</li>" , content) ) ;
373415 }
374416
375- fn list ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
417+ fn list ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
376418 shorter : MarkdownOutputStyle ) {
377419 let mut content = String :: new ( ) ;
378420 while let Some ( event) = parser. next ( ) {
@@ -389,23 +431,40 @@ pub fn render(w: &mut fmt::Formatter,
389431 buffer. push_str ( & format ! ( "<ul>{}</ul>" , content) ) ;
390432 }
391433
392- fn emphasis ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
393- shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
434+ fn emphasis ( parser : & mut ParserWrapper , buffer : & mut String ,
435+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
436+ id : & mut Option < & mut String > ) {
394437 let mut content = String :: new ( ) ;
395438 event_loop_break ! ( parser, toc_builder, shorter, content, false , id,
396439 Event :: End ( Tag :: Emphasis ) ) ;
397440 buffer. push_str ( & format ! ( "<em>{}</em>" , content) ) ;
398441 }
399442
400- fn strong ( parser : & mut Parser , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
443+ fn strong ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
401444 shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
402445 let mut content = String :: new ( ) ;
403446 event_loop_break ! ( parser, toc_builder, shorter, content, false , id,
404447 Event :: End ( Tag :: Strong ) ) ;
405448 buffer. push_str ( & format ! ( "<strong>{}</strong>" , content) ) ;
406449 }
407450
408- fn looper < ' a > ( parser : & ' a mut Parser , buffer : & mut String , next_event : Option < Event < ' a > > ,
451+ fn footnote ( parser : & mut ParserWrapper , buffer : & mut String ,
452+ toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
453+ mut definition : String , id : & mut Option < & mut String > ) {
454+ event_loop_break ! ( parser, toc_builder, shorter, definition, true , id,
455+ Event :: End ( Tag :: FootnoteDefinition ( _) ) ) ;
456+ buffer. push_str ( & definition) ;
457+ }
458+
459+ fn rule ( parser : & mut ParserWrapper , buffer : & mut String , toc_builder : & mut Option < TocBuilder > ,
460+ shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
461+ let mut content = String :: new ( ) ;
462+ event_loop_break ! ( parser, toc_builder, shorter, content, true , id,
463+ Event :: End ( Tag :: Rule ) ) ;
464+ buffer. push_str ( "<hr>" ) ;
465+ }
466+
467+ fn looper < ' a > ( parser : & ' a mut ParserWrapper , buffer : & mut String , next_event : Option < Event < ' a > > ,
409468 toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
410469 id : & mut Option < & mut String > ) -> bool {
411470 if let Some ( event) = next_event {
@@ -423,7 +482,10 @@ pub fn render(w: &mut fmt::Formatter,
423482 paragraph ( parser, buffer, toc_builder, shorter, id) ;
424483 }
425484 Event :: Start ( Tag :: Link ( ref url, ref t) ) => {
426- link ( parser, buffer, toc_builder, shorter, url, t. as_ref ( ) . to_owned ( ) , id) ;
485+ link ( parser, buffer, toc_builder, shorter, url, t. as_ref ( ) , id) ;
486+ }
487+ Event :: Start ( Tag :: Image ( ref url, ref t) ) => {
488+ image ( parser, buffer, toc_builder, shorter, url, t. as_ref ( ) . to_owned ( ) , id) ;
427489 }
428490 Event :: Start ( Tag :: Table ( _) ) => {
429491 table ( parser, buffer, toc_builder, shorter) ;
@@ -440,6 +502,23 @@ pub fn render(w: &mut fmt::Formatter,
440502 Event :: Start ( Tag :: Strong ) => {
441503 strong ( parser, buffer, toc_builder, shorter, id) ;
442504 }
505+ Event :: Start ( Tag :: Rule ) => {
506+ rule ( parser, buffer, toc_builder, shorter, id) ;
507+ }
508+ Event :: Start ( Tag :: FootnoteDefinition ( ref def) ) => {
509+ let mut content = String :: new ( ) ;
510+ footnote ( parser, & mut content, toc_builder, shorter, def. as_ref ( ) . to_owned ( ) ,
511+ id) ;
512+ let cur_len = parser. footnotes . len ( ) + 1 ;
513+ parser. footnotes . push ( format ! ( "<li id=\" ref{}\" >{}<a href=\" #supref{0}\" \
514+ rev=\" footnote\" >↩</a></li>",
515+ cur_len, content) ) ;
516+ }
517+ Event :: FootnoteReference ( _) => {
518+ buffer. push_str ( & format ! ( "<sup id=\" supref{0}\" ><a href=\" #ref{0}\" >{0}</a>\
519+ </sup>",
520+ parser. get_next_footnote_id( ) ) ) ;
521+ }
443522 Event :: Html ( h) | Event :: InlineHtml ( h) => {
444523 buffer. push_str ( & * h) ;
445524 }
@@ -457,13 +536,17 @@ pub fn render(w: &mut fmt::Formatter,
457536 None
458537 } ;
459538 let mut buffer = String :: new ( ) ;
460- let mut parser = Parser :: new_ext ( s , pulldown_cmark :: OPTION_ENABLE_TABLES ) ;
539+ let mut parser = ParserWrapper :: new ( s ) ;
461540 loop {
462541 let next_event = parser. next ( ) ;
463542 if !looper ( & mut parser, & mut buffer, next_event, & mut toc_builder, shorter, & mut None ) {
464543 break
465544 }
466545 }
546+ if !parser. footnotes . is_empty ( ) {
547+ buffer. push_str ( & format ! ( "<div class=\" footnotes\" ><hr><ol>{}</ol></div>" ,
548+ parser. footnotes. join( "" ) ) ) ;
549+ }
467550 let mut ret = toc_builder. map_or ( Ok ( ( ) ) , |builder| {
468551 write ! ( w, "<nav id=\" TOC\" >{}</nav>" , builder. into_toc( ) )
469552 } ) ;
0 commit comments