@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
5050use crate :: html:: toc:: TocBuilder ;
5151
5252use pulldown_cmark:: {
53- html, BrokenLink , CodeBlockKind , CowStr , Event , LinkType , Options , Parser , Tag ,
53+ html, BrokenLink , CodeBlockKind , CowStr , Event , LinkType , OffsetIter , Options , Parser , Tag ,
5454} ;
5555
5656#[ cfg( test) ]
@@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
12401240pub ( crate ) struct MarkdownLink {
12411241 pub kind : LinkType ,
12421242 pub link : String ,
1243+ pub display_text : Option < String > ,
12431244 pub range : MarkdownLinkRange ,
12441245}
12451246
@@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
12631264 }
12641265}
12651266
1266- pub ( crate ) fn markdown_links < R > (
1267- md : & str ,
1267+ pub ( crate ) fn markdown_links < ' md , R > (
1268+ md : & ' md str ,
12681269 preprocess_link : impl Fn ( MarkdownLink ) -> Option < R > ,
12691270) -> Vec < R > {
12701271 if md. is_empty ( ) {
@@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>(
13751376 MarkdownLinkRange :: Destination ( range. clone ( ) )
13761377 } ;
13771378
1378- Parser :: new_with_broken_link_callback (
1379+ let mut broken_link_callback = |link : BrokenLink < ' md > | Some ( ( link. reference , "" . into ( ) ) ) ;
1380+ let mut event_iter = Parser :: new_with_broken_link_callback (
13791381 md,
13801382 main_body_opts ( ) ,
1381- Some ( & mut | link : BrokenLink < ' _ > | Some ( ( link . reference , "" . into ( ) ) ) ) ,
1383+ Some ( & mut broken_link_callback ) ,
13821384 )
1383- . into_offset_iter ( )
1384- . filter_map ( |( event, span) | match event {
1385- Event :: Start ( Tag :: Link ( link_type, dest, _) ) if may_be_doc_link ( link_type) => {
1386- let range = match link_type {
1387- // Link is pulled from the link itself.
1388- LinkType :: ReferenceUnknown | LinkType :: ShortcutUnknown => {
1389- span_for_offset_backward ( span, b'[' , b']' )
1390- }
1391- LinkType :: CollapsedUnknown => span_for_offset_forward ( span, b'[' , b']' ) ,
1392- LinkType :: Inline => span_for_offset_backward ( span, b'(' , b')' ) ,
1393- // Link is pulled from elsewhere in the document.
1394- LinkType :: Reference | LinkType :: Collapsed | LinkType :: Shortcut => {
1395- span_for_link ( & dest, span)
1385+ . into_offset_iter ( ) ;
1386+ let mut links = Vec :: new ( ) ;
1387+
1388+ while let Some ( ( event, span) ) = event_iter. next ( ) {
1389+ match event {
1390+ Event :: Start ( Tag :: Link ( link_type, dest, _) ) if may_be_doc_link ( link_type) => {
1391+ let range = match link_type {
1392+ // Link is pulled from the link itself.
1393+ LinkType :: ReferenceUnknown | LinkType :: ShortcutUnknown => {
1394+ span_for_offset_backward ( span, b'[' , b']' )
1395+ }
1396+ LinkType :: CollapsedUnknown => span_for_offset_forward ( span, b'[' , b']' ) ,
1397+ LinkType :: Inline => span_for_offset_backward ( span, b'(' , b')' ) ,
1398+ // Link is pulled from elsewhere in the document.
1399+ LinkType :: Reference | LinkType :: Collapsed | LinkType :: Shortcut => {
1400+ span_for_link ( & dest, span)
1401+ }
1402+ LinkType :: Autolink | LinkType :: Email => unreachable ! ( ) ,
1403+ } ;
1404+
1405+ let display_text = if matches ! (
1406+ link_type,
1407+ LinkType :: Inline
1408+ | LinkType :: ReferenceUnknown
1409+ | LinkType :: Reference
1410+ | LinkType :: Shortcut
1411+ | LinkType :: ShortcutUnknown
1412+ ) {
1413+ collect_link_data ( & mut event_iter)
1414+ } else {
1415+ None
1416+ } ;
1417+
1418+ if let Some ( link) = preprocess_link ( MarkdownLink {
1419+ kind : link_type,
1420+ link : dest. into_string ( ) ,
1421+ display_text,
1422+ range,
1423+ } ) {
1424+ links. push ( link) ;
13961425 }
1397- LinkType :: Autolink | LinkType :: Email => unreachable ! ( ) ,
1398- } ;
1399- preprocess_link ( MarkdownLink { kind : link_type, range, link : dest. into_string ( ) } )
1426+ }
1427+ _ => { }
14001428 }
1401- _ => None ,
1402- } )
1403- . collect ( )
1429+ }
1430+
1431+ links
1432+ }
1433+
1434+ /// Collects additional data of link.
1435+ fn collect_link_data < ' input , ' callback > (
1436+ event_iter : & mut OffsetIter < ' input , ' callback > ,
1437+ ) -> Option < String > {
1438+ let mut display_text: Option < String > = None ;
1439+ let mut append_text = |text : CowStr < ' _ > | {
1440+ if let Some ( display_text) = & mut display_text {
1441+ display_text. push_str ( & text) ;
1442+ } else {
1443+ display_text = Some ( text. to_string ( ) ) ;
1444+ }
1445+ } ;
1446+
1447+ while let Some ( ( event, _span) ) = event_iter. next ( ) {
1448+ match event {
1449+ Event :: Text ( text) => {
1450+ append_text ( text) ;
1451+ }
1452+ Event :: Code ( code) => {
1453+ append_text ( code) ;
1454+ }
1455+ Event :: End ( _) => {
1456+ break ;
1457+ }
1458+ _ => { }
1459+ }
1460+ }
1461+
1462+ display_text
14041463}
14051464
14061465#[ derive( Debug ) ]
0 commit comments