@@ -95,6 +95,9 @@ struct TextWriter<'a, I> {
95
95
/// Current list index as a stack of indices.
96
96
list_indices : Vec < Option < u64 > > ,
97
97
98
+ /// A link which will be appended to the current line when the link tag is closed.
99
+ link : Option < CowStr < ' a > > ,
100
+
98
101
needs_newline : bool ,
99
102
}
100
103
@@ -118,6 +121,7 @@ where
118
121
needs_newline : false ,
119
122
#[ cfg( feature = "highlight-code" ) ]
120
123
code_highlighter : None ,
124
+ link : None ,
121
125
}
122
126
}
123
127
@@ -164,7 +168,7 @@ where
164
168
Tag :: Emphasis => self . push_inline_style ( Style :: new ( ) . italic ( ) ) ,
165
169
Tag :: Strong => self . push_inline_style ( Style :: new ( ) . bold ( ) ) ,
166
170
Tag :: Strikethrough => self . push_inline_style ( Style :: new ( ) . crossed_out ( ) ) ,
167
- Tag :: Link { .. } => warn ! ( "Link not yet supported" ) ,
171
+ Tag :: Link { dest_url , .. } => self . push_link ( dest_url ) ,
168
172
Tag :: Image { .. } => warn ! ( "Image not yet supported" ) ,
169
173
Tag :: MetadataBlock ( _) => warn ! ( "Metadata block not yet supported" ) ,
170
174
Tag :: DefinitionList => warn ! ( "Definition list not yet supported" ) ,
@@ -190,7 +194,7 @@ where
190
194
TagEnd :: Emphasis => self . pop_inline_style ( ) ,
191
195
TagEnd :: Strong => self . pop_inline_style ( ) ,
192
196
TagEnd :: Strikethrough => self . pop_inline_style ( ) ,
193
- TagEnd :: Link => { }
197
+ TagEnd :: Link => self . pop_link ( ) ,
194
198
TagEnd :: Image => { }
195
199
TagEnd :: MetadataBlock ( _) => { }
196
200
TagEnd :: DefinitionList => { }
@@ -413,6 +417,22 @@ where
413
417
self . push_line ( Line :: from ( vec ! [ span] ) ) ;
414
418
}
415
419
}
420
+
421
+ /// Store the link to be appended to the link text
422
+ #[ instrument( level = "trace" , skip( self ) ) ]
423
+ fn push_link ( & mut self , dest_url : CowStr < ' a > ) {
424
+ self . link = Some ( dest_url) ;
425
+ }
426
+
427
+ /// Append the link to the current line
428
+ #[ instrument( level = "trace" , skip( self ) ) ]
429
+ fn pop_link ( & mut self ) {
430
+ if let Some ( link) = self . link . take ( ) {
431
+ self . push_span ( " (" . into ( ) ) ;
432
+ self . push_span ( Span :: styled ( link, styles:: LINK ) ) ;
433
+ self . push_span ( ")" . into ( ) ) ;
434
+ }
435
+ }
416
436
}
417
437
418
438
mod styles {
@@ -438,6 +458,9 @@ mod styles {
438
458
. add_modifier ( Modifier :: ITALIC ) ;
439
459
pub const BLOCKQUOTE : Style = Style :: new ( ) . fg ( Color :: Green ) ;
440
460
pub const CODE : Style = Style :: new ( ) . fg ( Color :: White ) . bg ( Color :: Black ) ;
461
+ pub const LINK : Style = Style :: new ( )
462
+ . fg ( Color :: Blue )
463
+ . add_modifier ( Modifier :: UNDERLINED ) ;
441
464
}
442
465
443
466
#[ cfg( test) ]
@@ -763,4 +786,17 @@ mod tests {
763
786
] ) )
764
787
) ;
765
788
}
789
+
790
+ #[ rstest]
791
+ fn link ( with_tracing : DefaultGuard ) {
792
+ assert_eq ! (
793
+ from_str( "[Link](https://example.com)" ) ,
794
+ Text :: from( Line :: from_iter( [
795
+ Span :: from( "Link" ) ,
796
+ Span :: from( " (" ) ,
797
+ Span :: from( "https://example.com" ) . blue( ) . underlined( ) ,
798
+ Span :: from( ")" )
799
+ ] ) )
800
+ ) ;
801
+ }
766
802
}
0 commit comments