///|
fn html_escape(text : String) -> String {
  let out = StringBuilder()
  for c in text.iter() {
    match c {
      '&' => out.write_string("&")
      '<' => out.write_string("<")
      '>' => out.write_string(">")
      '"' => out.write_string(""")
      '\'' => out.write_string("'")
      '\n' => out.write_string("
\n") '\t' => out.write_string(" ") _ => out.write_char(c) } } out.to_string() } ///| fn css_color(color : Color) -> String { "rgb(\{color.red.max(0).min(255)},\{color.green.max(0).min(255)},\{color.blue.max(0).min(255)})" } ///| fn Document::html_run(self : Document, run : Run) -> String { let out = StringBuilder() let css = StringBuilder() let style = run.style if style.foreground > 0 { if self.colors.get(style.foreground) is Some(color) && !color.automatic { css.write_string("color:\{css_color(color)};") } } if style.background > 0 { if self.colors.get(style.background) is Some(color) && !color.automatic { css.write_string("background-color:\{css_color(color)};") } } if style.size_half_points > 0 && style.size_half_points <= 32767 { let whole = style.size_half_points / 2 let half = if style.size_half_points % 2 == 0 { "" } else { ".5" } css.write_string("font-size:\{whole}\{half}pt;") } let linked = match run.link { Some(target) => safe_link(target) None => false } if linked { out.write_string( "", ) } if !css.is_empty() { out.write_string("") } if style.bold { out.write_string("") } if style.italic { out.write_string("") } if style.underline { out.write_string("") } if style.strike { out.write_string("") } if style.superscript > 0 { out.write_string("") } if style.superscript < 0 { out.write_string("") } out.write_string(html_escape(run.text)) if style.superscript < 0 { out.write_string("") } if style.superscript > 0 { out.write_string("") } if style.strike { out.write_string("") } if style.underline { out.write_string("") } if style.italic { out.write_string("") } if style.bold { out.write_string("") } if !css.is_empty() { out.write_string("") } if linked { out.write_string("") } out.to_string() } ///| fn Document::html_paragraph( self : Document, paragraph : Paragraph, hidden : Bool, ) -> String { let out = StringBuilder() let align = alignment_name(paragraph.style.alignment) out.write_string("

") for run in paragraph.runs { if hidden || !run.style.hidden { out.write_string(self.html_run(run)) } } out.write_string("

") out.to_string() } ///| /// Semantic HTML fragment. No scripts, embedded resources, or raw RTF HTML. pub fn Document::to_html( self : Document, options? : TextOptions = TextOptions::default(), ) -> String { let out = StringBuilder() let mut table = false let mut row : Int? = None let mut cell : Int? = None let mut region : Region? = None for paragraph in self.paragraphs { if !options.accepts(paragraph.region) { continue } if region != Some(paragraph.region) { if table { out.write_string("\n") table = false row = None cell = None } if region is Some(_) { out.write_string("\n") } out.write_string( "
\n", ) region = Some(paragraph.region) } if paragraph.table_row is Some(index) { if !table { out.write_string("
") table = true row = Some(index) cell = paragraph.table_cell } else if row != Some(index) { out.write_string("
") row = Some(index) cell = paragraph.table_cell } else if cell != paragraph.table_cell { out.write_string("") cell = paragraph.table_cell } } else if table { out.write_string("
\n") table = false row = None cell = None } out.write_string(self.html_paragraph(paragraph, options.include_hidden)) out.write_char('\n') } if table { out.write_string("\n") } if region is Some(_) { out.write_string("
\n") } out.to_string() }