@@ -133,11 +133,37 @@ macro_rules! event_loop_break {
133
133
} }
134
134
}
135
135
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
+
136
162
pub fn render ( w : & mut fmt:: Formatter ,
137
163
s : & str ,
138
164
print_toc : bool ,
139
165
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 ) {
141
167
let mut origtext = String :: new ( ) ;
142
168
while let Some ( event) = parser. next ( ) {
143
169
match event {
@@ -215,8 +241,8 @@ pub fn render(w: &mut fmt::Formatter,
215
241
} ) ;
216
242
}
217
243
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 ) {
220
246
let mut ret = String :: new ( ) ;
221
247
let mut id = String :: new ( ) ;
222
248
event_loop_break ! ( parser, toc_builder, shorter, ret, true , & mut Some ( & mut id) ,
@@ -249,32 +275,48 @@ pub fn render(w: &mut fmt::Formatter,
249
275
ret, lvl = level, id = id, sec = sec) ) ;
250
276
}
251
277
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 > ) {
254
281
let mut content = String :: new ( ) ;
255
282
event_loop_break ! ( parser, toc_builder, shorter, content, false , id, Event :: End ( Tag :: Code ) ) ;
256
283
buffer. push_str ( & format ! ( "<code>{}</code>" ,
257
284
Escape ( & collapse_whitespace( content. trim_right( ) ) ) ) ) ;
258
285
}
259
286
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 > ,
261
302
shorter : MarkdownOutputStyle , url : & str , mut title : String ,
262
303
id : & mut Option < & mut String > ) {
263
304
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) ) ;
266
307
}
267
308
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 > ) {
270
312
let mut content = String :: new ( ) ;
271
313
event_loop_break ! ( parser, toc_builder, shorter, content, true , id,
272
314
Event :: End ( Tag :: Paragraph ) ) ;
273
315
buffer. push_str ( & format ! ( "<p>{}</p>" , content. trim_right( ) ) ) ;
274
316
}
275
317
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 ) {
278
320
let mut content = String :: new ( ) ;
279
321
event_loop_break ! ( parser, toc_builder, shorter, content, true , & mut None ,
280
322
Event :: End ( Tag :: TableHead ) |
@@ -284,8 +326,8 @@ pub fn render(w: &mut fmt::Formatter,
284
326
buffer. push_str ( & format ! ( "<td>{}</td>" , content. trim( ) ) ) ;
285
327
}
286
328
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 ) {
289
331
let mut content = String :: new ( ) ;
290
332
while let Some ( event) = parser. next ( ) {
291
333
match event {
@@ -303,8 +345,8 @@ pub fn render(w: &mut fmt::Formatter,
303
345
buffer. push_str ( & format ! ( "<tr>{}</tr>" , content) ) ;
304
346
}
305
347
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 ) {
308
350
let mut content = String :: new ( ) ;
309
351
while let Some ( event) = parser. next ( ) {
310
352
match event {
@@ -322,7 +364,7 @@ pub fn render(w: &mut fmt::Formatter,
322
364
}
323
365
}
324
366
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 > ,
326
368
shorter : MarkdownOutputStyle ) {
327
369
let mut content = String :: new ( ) ;
328
370
let mut rows = String :: new ( ) ;
@@ -347,16 +389,16 @@ pub fn render(w: &mut fmt::Formatter,
347
389
} ) ) ;
348
390
}
349
391
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 ) {
352
394
let mut content = String :: new ( ) ;
353
395
event_loop_break ! ( parser, toc_builder, shorter, content, true , & mut None ,
354
396
Event :: End ( Tag :: BlockQuote ) ) ;
355
397
buffer. push_str ( & format ! ( "<blockquote>{}</blockquote>" , content. trim_right( ) ) ) ;
356
398
}
357
399
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 ) {
360
402
let mut content = String :: new ( ) ;
361
403
while let Some ( event) = parser. next ( ) {
362
404
match event {
@@ -372,7 +414,7 @@ pub fn render(w: &mut fmt::Formatter,
372
414
buffer. push_str ( & format ! ( "<li>{}</li>" , content) ) ;
373
415
}
374
416
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 > ,
376
418
shorter : MarkdownOutputStyle ) {
377
419
let mut content = String :: new ( ) ;
378
420
while let Some ( event) = parser. next ( ) {
@@ -389,23 +431,40 @@ pub fn render(w: &mut fmt::Formatter,
389
431
buffer. push_str ( & format ! ( "<ul>{}</ul>" , content) ) ;
390
432
}
391
433
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 > ) {
394
437
let mut content = String :: new ( ) ;
395
438
event_loop_break ! ( parser, toc_builder, shorter, content, false , id,
396
439
Event :: End ( Tag :: Emphasis ) ) ;
397
440
buffer. push_str ( & format ! ( "<em>{}</em>" , content) ) ;
398
441
}
399
442
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 > ,
401
444
shorter : MarkdownOutputStyle , id : & mut Option < & mut String > ) {
402
445
let mut content = String :: new ( ) ;
403
446
event_loop_break ! ( parser, toc_builder, shorter, content, false , id,
404
447
Event :: End ( Tag :: Strong ) ) ;
405
448
buffer. push_str ( & format ! ( "<strong>{}</strong>" , content) ) ;
406
449
}
407
450
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 > > ,
409
468
toc_builder : & mut Option < TocBuilder > , shorter : MarkdownOutputStyle ,
410
469
id : & mut Option < & mut String > ) -> bool {
411
470
if let Some ( event) = next_event {
@@ -423,7 +482,10 @@ pub fn render(w: &mut fmt::Formatter,
423
482
paragraph ( parser, buffer, toc_builder, shorter, id) ;
424
483
}
425
484
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) ;
427
489
}
428
490
Event :: Start ( Tag :: Table ( _) ) => {
429
491
table ( parser, buffer, toc_builder, shorter) ;
@@ -440,6 +502,23 @@ pub fn render(w: &mut fmt::Formatter,
440
502
Event :: Start ( Tag :: Strong ) => {
441
503
strong ( parser, buffer, toc_builder, shorter, id) ;
442
504
}
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
+ }
443
522
Event :: Html ( h) | Event :: InlineHtml ( h) => {
444
523
buffer. push_str ( & * h) ;
445
524
}
@@ -457,13 +536,17 @@ pub fn render(w: &mut fmt::Formatter,
457
536
None
458
537
} ;
459
538
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 ) ;
461
540
loop {
462
541
let next_event = parser. next ( ) ;
463
542
if !looper ( & mut parser, & mut buffer, next_event, & mut toc_builder, shorter, & mut None ) {
464
543
break
465
544
}
466
545
}
546
+ if !parser. footnotes . is_empty ( ) {
547
+ buffer. push_str ( & format ! ( "<div class=\" footnotes\" ><hr><ol>{}</ol></div>" ,
548
+ parser. footnotes. join( "" ) ) ) ;
549
+ }
467
550
let mut ret = toc_builder. map_or ( Ok ( ( ) ) , |builder| {
468
551
write ! ( w, "<nav id=\" TOC\" >{}</nav>" , builder. into_toc( ) )
469
552
} ) ;
0 commit comments