ui: Use parsed markdown contents to determine sizing.

This commit is contained in:
Blaž Hrastnik 2021-03-15 17:55:13 +09:00
parent f9b9bc04cc
commit 80eca5c32f

View File

@ -21,10 +21,7 @@ pub fn new(contents: String) -> Self {
Self { contents }
}
}
impl Component for Markdown {
fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
use tui::widgets::{Paragraph, Widget, Wrap};
fn parse(contents: &str) -> tui::text::Text {
use pulldown_cmark::{CodeBlockKind, CowStr, Event, Options, Parser, Tag};
use tui::text::{Span, Spans, Text};
@ -33,7 +30,7 @@ fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
let mut options = Options::empty();
options.insert(Options::ENABLE_STRIKETHROUGH);
let parser = Parser::new_ext(&self.contents, options);
let parser = Parser::new_ext(contents, options);
// TODO: if possible, render links as terminal hyperlinks: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
let mut tags = Vec::new();
@ -43,7 +40,7 @@ fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
fn to_span(text: pulldown_cmark::CowStr) -> Span {
use std::ops::Deref;
Span::raw::<std::borrow::Cow<_>>(match text {
CowStr::Borrowed(s) => s.into(),
CowStr::Borrowed(s) => s.to_string().into(), // could retain borrow
CowStr::Boxed(s) => s.to_string().into(),
CowStr::Inlined(s) => s.deref().to_owned().into(),
})
@ -59,12 +56,12 @@ fn to_span(text: pulldown_cmark::CowStr) -> Span {
Event::End(tag) => {
tags.pop();
match tag {
Tag::Heading(_)
| Tag::Paragraph
| Tag::CodeBlock(CodeBlockKind::Fenced(_)) => {
Tag::Heading(_) | Tag::Paragraph | Tag::CodeBlock(CodeBlockKind::Fenced(_)) => {
// whenever code block or paragraph closes, new line
let spans = std::mem::replace(&mut spans, Vec::new());
if !spans.is_empty() {
lines.push(Spans::from(spans));
}
lines.push(Spans::default());
}
_ => (),
@ -110,9 +107,15 @@ fn to_span(text: pulldown_cmark::CowStr) -> Span {
lines.push(Spans::from(spans));
}
let contents = Text::from(lines);
Text::from(lines)
}
impl Component for Markdown {
fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
use tui::widgets::{Paragraph, Widget, Wrap};
let par = Paragraph::new(contents)
let text = parse(&self.contents);
let par = Paragraph::new(text)
.wrap(Wrap { trim: false })
.scroll((cx.scroll.unwrap_or_default() as u16, 0));
@ -121,7 +124,7 @@ fn to_span(text: pulldown_cmark::CowStr) -> Span {
}
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
let contents = tui::text::Text::from(self.contents.clone());
let contents = parse(&self.contents);
let padding = 2;
let width = std::cmp::min(contents.width() as u16 + padding, viewport.0);
let height = std::cmp::min(contents.height() as u16 + padding, viewport.1);