diff --git a/src/book.rs b/src/book.rs index 613419c..3fe33ee 100644 --- a/src/book.rs +++ b/src/book.rs @@ -46,6 +46,7 @@ fn tag_name_from(tag_content: &str) -> &str { pub fn strip_html(input: &str) -> String { let mut out = String::with_capacity(input.len()); let mut pos = 0; + let mut heading_level: Option = None; while pos < input.len() { // Find next '<' @@ -63,7 +64,14 @@ pub fn strip_html(input: &str) -> String { // Emit text before the tag if tag_start > pos { - out.push_str(&decode_entities(&input[pos..tag_start])); + let text = decode_entities(&input[pos..tag_start]); + if heading_level.is_some() { + out.push_str("\x01"); + out.push_str(&text); + out.push_str("\x02"); + } else { + out.push_str(&text); + } } // Find '>' to close the tag @@ -115,10 +123,24 @@ pub fn strip_html(input: &str) -> String { "/li" | "/dd" | "/dt" | "/ol" | "/ul" => { pos = tag_end + 1; } - "p" | "div" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "blockquote" => { + "h1" => { heading_level = Some(1); pos = tag_end + 1; } + "h2" => { heading_level = Some(2); pos = tag_end + 1; } + "h3" => { heading_level = Some(3); pos = tag_end + 1; } + "h4" => { heading_level = Some(4); pos = tag_end + 1; } + "h5" => { heading_level = Some(5); pos = tag_end + 1; } + "h6" => { heading_level = Some(6); pos = tag_end + 1; } + "p" | "div" | "blockquote" => { pos = tag_end + 1; } - "/p" | "/div" | "/blockquote" | "/h1" | "/h2" | "/h3" | "/h4" | "/h5" | "/h6" => { + "/p" | "/div" | "/blockquote" => { + if !out.is_empty() && !out.ends_with('\n') { + out.push('\n'); + } + out.push('\n'); + pos = tag_end + 1; + } + "/h1" | "/h2" | "/h3" | "/h4" | "/h5" | "/h6" => { + heading_level = None; if !out.is_empty() && !out.ends_with('\n') { out.push('\n'); } diff --git a/src/reader.rs b/src/reader.rs index 9c6b3ad..76836ac 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -239,13 +239,38 @@ egui::ComboBox::from_id_salt("bg_type_selector") ui.with_layout( egui::Layout::top_down(align).with_main_justify(false), |ui| { - ui.add( - egui::Label::new( - egui::RichText::new(&indented) + let mut is_heading = false; + let mut remaining = indented.as_str(); + while !remaining.is_empty() { + if let Some(pos) = remaining.find(['\x01', '\x02']) { + if pos > 0 { + let text = &remaining[..pos]; + let mut rt = egui::RichText::new(text) + .size(style.font_size) + .color(colors.text); + if is_heading { + rt = rt.strong(); + } + ui.add(egui::Label::new(rt).wrap()); + } + let marker = remaining.chars().nth(pos).unwrap(); + if marker == '\x01' { + is_heading = true; + } else { + is_heading = false; + } + remaining = &remaining[pos + 1..]; + } else { + let mut rt = egui::RichText::new(remaining) .size(style.font_size) - .color(colors.text) - ).wrap() - ); + .color(colors.text); + if is_heading { + rt = rt.strong(); + } + ui.add(egui::Label::new(rt).wrap()); + break; + } + } }, ); });