@@ -340,29 +340,86 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
340340/// Make headings links with anchor IDs and build up TOC.
341341struct LinkReplacer < ' a , ' b , I : Iterator < Item = Event < ' a > > > {
342342 inner : I ,
343- links : & ' b [ RenderedLink ] ,
343+ links : & ' a [ RenderedLink ] ,
344+ shortcut_link : Option < & ' b RenderedLink > ,
344345}
345346
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 }
349350 }
350351}
351352
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 > {
353354 type Item = Event < ' a > ;
354355
355356 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+ }
362381 }
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+ _ => { }
365419 }
420+
421+ // Yield the modified event
422+ event
366423 }
367424}
368425
@@ -857,7 +914,7 @@ impl Markdown<'_> {
857914 }
858915 let replacer = |_: & str , s : & str | {
859916 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 ( ) ) )
861918 } else {
862919 None
863920 }
@@ -934,8 +991,8 @@ impl MarkdownSummaryLine<'_> {
934991 }
935992
936993 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 ( ) ) )
939996 } else {
940997 None
941998 }
0 commit comments