Skip to content

Commit 80e099d

Browse files
authored
feat: Add support for links by replacing inner value (#62)
Links are displayed by appending a space and then the link destination in parenthesis. The link is styled blue and underlined.
1 parent 242ffd5 commit 80e099d

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

tui-markdown/src/lib.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ struct TextWriter<'a, I> {
9595
/// Current list index as a stack of indices.
9696
list_indices: Vec<Option<u64>>,
9797

98+
/// A link which will be appended to the current line when the link tag is closed.
99+
link: Option<CowStr<'a>>,
100+
98101
needs_newline: bool,
99102
}
100103

@@ -118,6 +121,7 @@ where
118121
needs_newline: false,
119122
#[cfg(feature = "highlight-code")]
120123
code_highlighter: None,
124+
link: None,
121125
}
122126
}
123127

@@ -164,7 +168,7 @@ where
164168
Tag::Emphasis => self.push_inline_style(Style::new().italic()),
165169
Tag::Strong => self.push_inline_style(Style::new().bold()),
166170
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),
168172
Tag::Image { .. } => warn!("Image not yet supported"),
169173
Tag::MetadataBlock(_) => warn!("Metadata block not yet supported"),
170174
Tag::DefinitionList => warn!("Definition list not yet supported"),
@@ -190,7 +194,7 @@ where
190194
TagEnd::Emphasis => self.pop_inline_style(),
191195
TagEnd::Strong => self.pop_inline_style(),
192196
TagEnd::Strikethrough => self.pop_inline_style(),
193-
TagEnd::Link => {}
197+
TagEnd::Link => self.pop_link(),
194198
TagEnd::Image => {}
195199
TagEnd::MetadataBlock(_) => {}
196200
TagEnd::DefinitionList => {}
@@ -413,6 +417,22 @@ where
413417
self.push_line(Line::from(vec![span]));
414418
}
415419
}
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+
}
416436
}
417437

418438
mod styles {
@@ -438,6 +458,9 @@ mod styles {
438458
.add_modifier(Modifier::ITALIC);
439459
pub const BLOCKQUOTE: Style = Style::new().fg(Color::Green);
440460
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);
441464
}
442465

443466
#[cfg(test)]
@@ -763,4 +786,17 @@ mod tests {
763786
]))
764787
);
765788
}
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+
}
766802
}

0 commit comments

Comments
 (0)