at main 102 lines 3.6 kB view raw
1use super::{FacetFeature, FacetOutput}; 2use std::fmt::Write; 3 4pub struct HtmlFacetOutput<W: Write> { 5 writer: W, 6} 7 8impl<W: Write> HtmlFacetOutput<W> { 9 pub fn new(writer: W) -> Self { 10 Self { writer } 11 } 12 13 pub fn into_inner(self) -> W { 14 self.writer 15 } 16} 17 18impl<W: Write> FacetOutput for HtmlFacetOutput<W> { 19 type Error = std::fmt::Error; 20 21 fn write_text(&mut self, text: &str) -> Result<(), Self::Error> { 22 for c in text.chars() { 23 match c { 24 '&' => self.writer.write_str("&amp;")?, 25 '<' => self.writer.write_str("&lt;")?, 26 '>' => self.writer.write_str("&gt;")?, 27 _ => self.writer.write_char(c)?, 28 } 29 } 30 Ok(()) 31 } 32 33 fn start_feature(&mut self, feature: &FacetFeature<'_>) -> Result<(), Self::Error> { 34 match feature { 35 FacetFeature::Bold => write!(self.writer, "<strong>"), 36 FacetFeature::Italic => write!(self.writer, "<em>"), 37 FacetFeature::Code => write!(self.writer, "<code>"), 38 FacetFeature::Underline => write!(self.writer, "<u>"), 39 FacetFeature::Strikethrough => write!(self.writer, "<s>"), 40 FacetFeature::Highlight => write!(self.writer, "<mark>"), 41 FacetFeature::Link { uri } => { 42 write!(self.writer, "<a href=\"")?; 43 for c in uri.chars() { 44 match c { 45 '"' => self.writer.write_str("%22")?, 46 _ => self.writer.write_char(c)?, 47 } 48 } 49 write!(self.writer, "\">") 50 } 51 FacetFeature::DidMention { did } => { 52 write!( 53 self.writer, 54 "<a class=\"mention\" href=\"https://bsky.app/profile/{}\">", 55 did 56 ) 57 } 58 FacetFeature::AtMention { at_uri } => { 59 write!(self.writer, "<a class=\"at-mention\" href=\"{}\">", at_uri) 60 } 61 FacetFeature::Tag { tag } => { 62 write!( 63 self.writer, 64 "<a class=\"hashtag\" href=\"https://bsky.app/hashtag/{}\">", 65 tag 66 ) 67 } 68 FacetFeature::Id { id } => { 69 if let Some(id) = id { 70 write!(self.writer, "<span id=\"{}\">", id) 71 } else { 72 write!(self.writer, "<span>") 73 } 74 } 75 } 76 } 77 78 fn end_feature(&mut self, feature: &FacetFeature<'_>) -> Result<(), Self::Error> { 79 match feature { 80 FacetFeature::Bold => write!(self.writer, "</strong>"), 81 FacetFeature::Italic => write!(self.writer, "</em>"), 82 FacetFeature::Code => write!(self.writer, "</code>"), 83 FacetFeature::Underline => write!(self.writer, "</u>"), 84 FacetFeature::Strikethrough => write!(self.writer, "</s>"), 85 FacetFeature::Highlight => write!(self.writer, "</mark>"), 86 FacetFeature::Link { .. } 87 | FacetFeature::DidMention { .. } 88 | FacetFeature::AtMention { .. } 89 | FacetFeature::Tag { .. } => write!(self.writer, "</a>"), 90 FacetFeature::Id { .. } => write!(self.writer, "</span>"), 91 } 92 } 93} 94 95pub fn render_faceted_html( 96 text: &str, 97 facets: &[super::NormalizedFacet<'_>], 98) -> Result<String, std::fmt::Error> { 99 let mut output = HtmlFacetOutput::new(String::new()); 100 super::process_faceted_text(text, facets, &mut output)?; 101 Ok(output.into_inner()) 102}