Code blocks get rendered without line breaks (#122)

This commit is contained in:
Ulyssa 2023-07-07 21:42:14 -07:00
parent 6e8e12b579
commit b1ccec6732
No known key found for this signature in database
GPG key ID: F2873CA2997B83C5
4 changed files with 148 additions and 3 deletions

23
Cargo.lock generated
View file

@ -873,6 +873,12 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1bba4f227a4a53d12b653f50ca7bf10c9119ae2aba56aff9e0338b5c98f36a" checksum = "8c1bba4f227a4a53d12b653f50ca7bf10c9119ae2aba56aff9e0338b5c98f36a"
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.9.0" version = "0.9.0"
@ -1535,6 +1541,7 @@ dependencies = [
"mime_guess", "mime_guess",
"modalkit", "modalkit",
"open", "open",
"pretty_assertions",
"regex", "regex",
"rpassword", "rpassword",
"serde", "serde",
@ -2578,6 +2585,16 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "pretty_assertions"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
"diff",
"yansi",
]
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "1.3.1" version = "1.3.1"
@ -4519,6 +4536,12 @@ dependencies = [
"linked-hash-map", "linked-hash-map",
] ]
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.3.0" version = "1.3.0"

View file

@ -66,6 +66,7 @@ features = ["macros", "net", "rt-multi-thread", "sync", "time"]
[dev-dependencies] [dev-dependencies]
lazy_static = "1.4.0" lazy_static = "1.4.0"
pretty_assertions = "1.4.0"
[profile.release] [profile.release]
lto = true lto = true

View file

@ -237,6 +237,7 @@ pub enum StyleTreeNode {
Image(Option<String>), Image(Option<String>),
List(StyleTreeChildren, ListStyle), List(StyleTreeChildren, ListStyle),
Paragraph(Box<StyleTreeNode>), Paragraph(Box<StyleTreeNode>),
Pre(Box<StyleTreeNode>),
Reply(Box<StyleTreeNode>), Reply(Box<StyleTreeNode>),
Ruler, Ruler,
Style(Box<StyleTreeNode>, Style), Style(Box<StyleTreeNode>, Style),
@ -311,6 +312,39 @@ impl StyleTreeNode {
child.print(printer, style); child.print(printer, style);
printer.commit(); printer.commit();
}, },
StyleTreeNode::Pre(child) => {
let mut subp = printer.sub(2).literal(true);
let subw = subp.width();
child.print(&mut subp, style);
printer.commit();
printer.push_line(
vec![
Span::styled(line::TOP_LEFT, style),
Span::styled(line::HORIZONTAL.repeat(subw), style),
Span::styled(line::TOP_RIGHT, style),
]
.into(),
);
for mut line in subp.finish() {
line.0.insert(0, Span::styled(line::VERTICAL, style));
line.0.push(Span::styled(line::VERTICAL, style));
printer.push_line(line);
}
printer.push_line(
vec![
Span::styled(line::BOTTOM_LEFT, style),
Span::styled(line::HORIZONTAL.repeat(subw), style),
Span::styled(line::BOTTOM_RIGHT, style),
]
.into(),
);
printer.commit();
},
StyleTreeNode::Reply(child) => { StyleTreeNode::Reply(child) => {
if printer.hide_reply() { if printer.hide_reply() {
return; return;
@ -585,6 +619,7 @@ fn h2t(hdl: &Handle) -> StyleTreeChildren {
// Other text blocks. // Other text blocks.
"blockquote" => StyleTreeNode::Blockquote(c2t(&node.children.borrow())), "blockquote" => StyleTreeNode::Blockquote(c2t(&node.children.borrow())),
"div" | "p" => StyleTreeNode::Paragraph(c2t(&node.children.borrow())), "div" | "p" => StyleTreeNode::Paragraph(c2t(&node.children.borrow())),
"pre" => StyleTreeNode::Pre(c2t(&node.children.borrow())),
// No children. // No children.
"hr" => StyleTreeNode::Ruler, "hr" => StyleTreeNode::Ruler,
@ -593,7 +628,7 @@ fn h2t(hdl: &Handle) -> StyleTreeChildren {
"img" => StyleTreeNode::Image(attrs_to_alt(&attrs.borrow())), "img" => StyleTreeNode::Image(attrs_to_alt(&attrs.borrow())),
// These don't render in any special way. // These don't render in any special way.
"a" | "details" | "html" | "pre" | "summary" | "sub" | "sup" => { "a" | "details" | "html" | "summary" | "sub" | "sup" => {
*c2t(&node.children.borrow()) *c2t(&node.children.borrow())
}, },
@ -630,6 +665,7 @@ pub fn parse_matrix_html(s: &str) -> StyleTree {
pub mod tests { pub mod tests {
use super::*; use super::*;
use crate::util::space_span; use crate::util::space_span;
use pretty_assertions::assert_eq;
#[test] #[test]
fn test_header() { fn test_header() {
@ -1173,4 +1209,76 @@ pub mod tests {
]) ])
); );
} }
#[test]
fn test_pre_tag() {
let s = concat!(
"<pre><code class=\"language-rust\">",
"fn hello() -&gt; usize {\n",
" return 5;\n",
"}\n",
"</code></pre>\n"
);
let tree = parse_matrix_html(s);
let text = tree.to_text(25, Style::default(), true);
assert_eq!(text.lines.len(), 5);
assert_eq!(
text.lines[0],
Spans(vec![
Span::raw(line::TOP_LEFT),
Span::raw(line::HORIZONTAL.repeat(23)),
Span::raw(line::TOP_RIGHT)
])
);
assert_eq!(
text.lines[1],
Spans(vec![
Span::raw(line::VERTICAL),
Span::raw("fn"),
Span::raw(" "),
Span::raw("hello"),
Span::raw("("),
Span::raw(")"),
Span::raw(" "),
Span::raw("-"),
Span::raw(">"),
Span::raw(" "),
Span::raw("usize"),
Span::raw(" "),
Span::raw("{"),
Span::raw(" "),
Span::raw(line::VERTICAL)
])
);
assert_eq!(
text.lines[2],
Spans(vec![
Span::raw(line::VERTICAL),
Span::raw(" "),
Span::raw("return"),
Span::raw(" "),
Span::raw("5"),
Span::raw(";"),
Span::raw(" "),
Span::raw(line::VERTICAL)
])
);
assert_eq!(
text.lines[3],
Spans(vec![
Span::raw(line::VERTICAL),
Span::raw("}"),
Span::raw(" ".repeat(22)),
Span::raw(line::VERTICAL)
])
);
assert_eq!(
text.lines[4],
Spans(vec![
Span::raw(line::BOTTOM_LEFT),
Span::raw(line::HORIZONTAL.repeat(23)),
Span::raw(line::BOTTOM_RIGHT)
])
);
}
} }

View file

@ -17,6 +17,7 @@ pub struct TextPrinter<'a> {
alignment: Alignment, alignment: Alignment,
curr_spans: Vec<Span<'a>>, curr_spans: Vec<Span<'a>>,
curr_width: usize, curr_width: usize,
literal: bool,
} }
impl<'a> TextPrinter<'a> { impl<'a> TextPrinter<'a> {
@ -30,6 +31,7 @@ impl<'a> TextPrinter<'a> {
alignment: Alignment::Left, alignment: Alignment::Left,
curr_spans: vec![], curr_spans: vec![],
curr_width: 0, curr_width: 0,
literal: false,
} }
} }
@ -38,6 +40,11 @@ impl<'a> TextPrinter<'a> {
self self
} }
pub fn literal(mut self, literal: bool) -> Self {
self.literal = literal;
self
}
pub fn hide_reply(&self) -> bool { pub fn hide_reply(&self) -> bool {
self.hide_reply self.hide_reply
} }
@ -56,6 +63,7 @@ impl<'a> TextPrinter<'a> {
alignment: self.alignment, alignment: self.alignment,
curr_spans: vec![], curr_spans: vec![],
curr_width: 0, curr_width: 0,
literal: self.literal,
} }
} }
@ -162,11 +170,16 @@ impl<'a> TextPrinter<'a> {
for mut word in UnicodeSegmentation::split_word_bounds(s) { for mut word in UnicodeSegmentation::split_word_bounds(s) {
if let "\n" | "\r\n" = word { if let "\n" | "\r\n" = word {
if self.literal {
self.commit();
continue;
}
// Render embedded newlines as spaces. // Render embedded newlines as spaces.
word = " "; word = " ";
} }
if self.curr_width == 0 && word.chars().all(char::is_whitespace) { if !self.literal && self.curr_width == 0 && word.chars().all(char::is_whitespace) {
// Drop leading whitespace. // Drop leading whitespace.
continue; continue;
} }
@ -182,7 +195,7 @@ impl<'a> TextPrinter<'a> {
// Word doesn't fit on this line, so start a new one. // Word doesn't fit on this line, so start a new one.
self.commit(); self.commit();
if word.chars().all(char::is_whitespace) { if !self.literal && word.chars().all(char::is_whitespace) {
// Drop leading whitespace. // Drop leading whitespace.
continue; continue;
} }