summaryrefslogtreecommitdiffstats
path: root/src/utils.rs
diff options
context:
space:
mode:
authorJonas Bushart <jonas@bushart.org>2019-01-20 18:07:20 +0100
committerJonas Bushart <jonas@bushart.org>2019-08-26 00:36:03 +0200
commit917e480a673d1ab03218702d0e9e726131e48799 (patch)
tree560f4308b71c7addc3bdbc85c024482df2d638e2 /src/utils.rs
parent1e06ea72ccf03cd2129d104360e1e07679190a07 (diff)
Implement HTML output for Table and TableSlice
* Add a HTML escaper to the utils class. * Expand TableSlice, Row, and Cell with HTML printing functions. These are implemented from scratch as they share almost nothing with the line based printing used for text, as HTML directly supports multiline cells. * Add tests to Cell and Table which test the new functionality.
Diffstat (limited to 'src/utils.rs')
-rw-r--r--src/utils.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/utils.rs b/src/utils.rs
index f2d89ae..dbd8db1 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -1,4 +1,5 @@
//! Internal only utilities
+use std::fmt;
use std::io::{Error, ErrorKind, Write};
use std::str;
@@ -105,6 +106,43 @@ pub fn display_width(text: &str) -> usize {
width - hidden
}
+/// Wrapper struct which will emit the HTML-escaped version of the contained
+/// string when passed to a format string.
+pub struct HtmlEscape<'a>(pub &'a str);
+
+impl<'a> fmt::Display for HtmlEscape<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ // Because the internet is always right, turns out there's not that many
+ // characters to escape: http://stackoverflow.com/questions/7381974
+ let HtmlEscape(s) = *self;
+ let pile_o_bits = s;
+ let mut last = 0;
+ for (i, ch) in s.bytes().enumerate() {
+ match ch as char {
+ '<' | '>' | '&' | '\'' | '"' => {
+ fmt.write_str(&pile_o_bits[last.. i])?;
+ let s = match ch as char {
+ '>' => "&gt;",
+ '<' => "&lt;",
+ '&' => "&amp;",
+ '\'' => "&#39;",
+ '"' => "&quot;",
+ _ => unreachable!()
+ };
+ fmt.write_str(s)?;
+ last = i + 1;
+ }
+ _ => {}
+ }
+ }
+
+ if last < s.len() {
+ fmt.write_str(&pile_o_bits[last..])?;
+ }
+ Ok(())
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;