@@ -340,29 +340,86 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
340
340
/// Make headings links with anchor IDs and build up TOC.
341
341
struct LinkReplacer < ' a , ' b , I : Iterator < Item = Event < ' a > > > {
342
342
inner : I ,
343
- links : & ' b [ RenderedLink ] ,
343
+ links : & ' a [ RenderedLink ] ,
344
+ shortcut_link : Option < & ' b RenderedLink > ,
344
345
}
345
346
346
- impl < ' a , ' b , I : Iterator < Item = Event < ' a > > > LinkReplacer < ' a , ' b , I > {
347
- fn new ( iter : I , links : & ' b [ RenderedLink ] ) -> Self {
348
- LinkReplacer { inner : iter, links }
347
+ impl < ' a , I : Iterator < Item = Event < ' a > > > LinkReplacer < ' a , ' _ , I > {
348
+ fn new ( iter : I , links : & ' a [ RenderedLink ] ) -> Self {
349
+ LinkReplacer { inner : iter, links, shortcut_link : None }
349
350
}
350
351
}
351
352
352
- impl < ' a , ' b , I : Iterator < Item = Event < ' a > > > Iterator for LinkReplacer < ' a , ' b , I > {
353
+ impl < ' a : ' b , ' b , I : Iterator < Item = Event < ' a > > > Iterator for LinkReplacer < ' a , ' b , I > {
353
354
type Item = Event < ' a > ;
354
355
355
356
fn next ( & mut self ) -> Option < Self :: Item > {
356
- let event = self . inner . next ( ) ;
357
- if let Some ( Event :: Start ( Tag :: Link ( kind, dest, text) ) ) = event {
358
- if let Some ( link) = self . links . iter ( ) . find ( |link| link. original_text == * dest) {
359
- Some ( Event :: Start ( Tag :: Link ( kind, link. href . clone ( ) . into ( ) , text) ) )
360
- } else {
361
- Some ( Event :: Start ( Tag :: Link ( kind, dest, text) ) )
357
+ let mut event = self . inner . next ( ) ;
358
+
359
+ // Remove disambiguators from shortcut links (`[fn@f]`)
360
+ match & mut event {
361
+ Some ( Event :: Start ( Tag :: Link (
362
+ pulldown_cmark:: LinkType :: ShortcutUnknown ,
363
+ dest,
364
+ title,
365
+ ) ) ) => {
366
+ debug ! ( "saw start of shortcut link to {} with title {}" , dest, title) ;
367
+ let link = if let Some ( link) =
368
+ self . links . iter ( ) . find ( |& link| * link. original_text == * * dest)
369
+ {
370
+ // Not sure why this is necessary - maybe the broken_link_callback doesn't always work?
371
+ * dest = CowStr :: Borrowed ( link. href . as_ref ( ) ) ;
372
+ Some ( link)
373
+ } else {
374
+ self . links . iter ( ) . find ( |& link| * link. href == * * dest)
375
+ } ;
376
+ if let Some ( link) = link {
377
+ trace ! ( "it matched" ) ;
378
+ assert ! ( self . shortcut_link. is_none( ) , "shortcut links cannot be nested" ) ;
379
+ self . shortcut_link = Some ( link) ;
380
+ }
362
381
}
363
- } else {
364
- event
382
+ Some ( Event :: End ( Tag :: Link ( pulldown_cmark:: LinkType :: ShortcutUnknown , dest, _) ) ) => {
383
+ debug ! ( "saw end of shortcut link to {}" , dest) ;
384
+ if let Some ( _link) = self . links . iter ( ) . find ( |& link| * link. href == * * dest) {
385
+ assert ! ( self . shortcut_link. is_some( ) , "saw closing link without opening tag" ) ;
386
+ self . shortcut_link = None ;
387
+ }
388
+ }
389
+ // Handle backticks in inline code blocks
390
+ Some ( Event :: Code ( text) ) => {
391
+ trace ! ( "saw code {}" , text) ;
392
+ if let Some ( link) = self . shortcut_link {
393
+ trace ! ( "original text was {}" , link. original_text) ;
394
+ if * * text == link. original_text [ 1 ..link. original_text . len ( ) - 1 ] {
395
+ debug ! ( "replacing {} with {}" , text, link. new_text) ;
396
+ * text = link. new_text . clone ( ) . into ( ) ;
397
+ }
398
+ }
399
+ }
400
+ // Replace plain text in links
401
+ Some ( Event :: Text ( text) ) => {
402
+ trace ! ( "saw text {}" , text) ;
403
+ if let Some ( link) = self . shortcut_link {
404
+ trace ! ( "original text was {}" , link. original_text) ;
405
+ if * * text == * link. original_text {
406
+ debug ! ( "replacing {} with {}" , text, link. new_text) ;
407
+ * text = link. new_text . clone ( ) . into ( ) ;
408
+ }
409
+ }
410
+ }
411
+ Some ( Event :: Start ( Tag :: Link ( _, dest, _) ) ) => {
412
+ if let Some ( link) = self . links . iter ( ) . find ( |& link| * link. original_text == * * dest) {
413
+ // Not sure why this is necessary - maybe the broken_link_callback doesn't always work?
414
+ * dest = CowStr :: Borrowed ( link. href . as_ref ( ) ) ;
415
+ }
416
+ }
417
+ // Anything else couldn't have been a valid Rust path
418
+ _ => { }
365
419
}
420
+
421
+ // Yield the modified event
422
+ event
366
423
}
367
424
}
368
425
@@ -857,7 +914,7 @@ impl Markdown<'_> {
857
914
}
858
915
let replacer = |_: & str , s : & str | {
859
916
if let Some ( link) = links. iter ( ) . find ( |link| & * link. original_text == s) {
860
- Some ( ( link. original_text . clone ( ) , link. href . clone ( ) ) )
917
+ Some ( ( link. href . clone ( ) , link. new_text . clone ( ) ) )
861
918
} else {
862
919
None
863
920
}
@@ -934,8 +991,8 @@ impl MarkdownSummaryLine<'_> {
934
991
}
935
992
936
993
let replacer = |_: & str , s : & str | {
937
- if let Some ( rendered_link ) = links. iter ( ) . find ( |link| & * link. original_text == s) {
938
- Some ( ( rendered_link . original_text . clone ( ) , rendered_link . href . clone ( ) ) )
994
+ if let Some ( link ) = links. iter ( ) . find ( |link| & * link. original_text == s) {
995
+ Some ( ( link . href . clone ( ) , link . new_text . clone ( ) ) )
939
996
} else {
940
997
None
941
998
}
0 commit comments