From ffbefaa3b4fa7079db28880d8155b6a6ac1ea1f0 Mon Sep 17 00:00:00 2001 From: PoiScript Date: Fri, 12 Apr 2019 22:29:31 +0800 Subject: [PATCH] chore(export): escape methods --- src/export/html.rs | 121 +++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/src/export/html.rs b/src/export/html.rs index 23dee12..745a6cb 100644 --- a/src/export/html.rs +++ b/src/export/html.rs @@ -6,18 +6,40 @@ use crate::{ objects::{Cookie, Timestamp}, parser::Parser, }; -use jetscii::ascii_chars; +use jetscii::bytes; use std::{ convert::From, - fmt, io::{Error, Write}, marker::PhantomData, }; pub trait HtmlHandler> { + fn escape(&mut self, w: &mut W, text: &str) -> Result<(), E> { + let mut pos = 0; + let bytes = text.as_bytes(); + while let Some(off) = bytes!(b'<', b'>', b'&', b'\'', b'"').find(&bytes[pos..]) { + w.write_all(&bytes[pos..pos + off])?; + + pos += off + 1; + + match text.as_bytes()[pos - 1] { + b'<' => w.write_all(b"<")?, + b'>' => w.write_all(b">")?, + b'&' => w.write_all(b"&")?, + b'\'' => w.write_all(b"'")?, + b'"' => w.write_all(b""")?, + _ => unreachable!(), + } + } + + Ok(w.write_all(&bytes[pos..])?) + } fn headline_beg(&mut self, w: &mut W, hdl: Headline) -> Result<(), E> { let level = if hdl.level <= 6 { hdl.level } else { 6 }; - Ok(write!(w, "{1}", level, Escape(hdl.title))?) + write!(w, "", level)?; + self.escape(w, hdl.title)?; + write!(w, "", level)?; + Ok(()) } fn headline_end(&mut self, w: &mut W) -> Result<(), E> { Ok(()) @@ -62,13 +84,19 @@ pub trait HtmlHandler> { Ok(()) } fn example_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> { - Ok(write!(w, "
{}
", Escape(cont))?) + write!(w, "
")?;
+        self.escape(w, cont)?;
+        write!(w, "
")?; + Ok(()) } fn export_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> { Ok(()) } fn src_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> { - Ok(write!(w, "
{}
", Escape(cont))?) + write!(w, "
")?;
+        self.escape(w, cont)?;
+        write!(w, "
")?; + Ok(()) } fn verse_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> { Ok(()) @@ -111,9 +139,10 @@ pub trait HtmlHandler> { fn fixed_width(&mut self, w: &mut W, cont: &str) -> Result<(), E> { for line in cont.lines() { // remove leading colon - write!(w, "
{}
", Escape(&line[1..]))?; + write!(w, "
")?;
+            self.escape(w, &line[1..])?;
+            write!(w, "
")?; } - Ok(()) } fn table_start(&mut self, w: &mut W) -> Result<(), E> { @@ -153,26 +182,19 @@ pub trait HtmlHandler> { ) -> Result<(), E> { Ok(()) } - fn inline_src( - &mut self, - w: &mut W, - lang: &str, - option: Option<&str>, - body: &str, - ) -> Result<(), E> { - Ok(write!(w, "{}", Escape(body))?) + fn inline_src(&mut self, w: &mut W, _: &str, _: Option<&str>, body: &str) -> Result<(), E> { + write!(w, "")?; + self.escape(w, body)?; + write!(w, "")?; + Ok(()) } fn link(&mut self, w: &mut W, path: &str, desc: Option<&str>) -> Result<(), E> { - if let Some(desc) = desc { - Ok(write!( - w, - r#"{}"#, - Escape(path), - Escape(desc) - )?) - } else { - Ok(write!(w, r#"{0}"#, Escape(path))?) - } + write!(w, r#""#)?; + self.escape(w, desc.unwrap_or(path))?; + write!(w, "")?; + Ok(()) } fn macros(&mut self, w: &mut W, name: &str, args: Option<&str>) -> Result<(), E> { Ok(()) @@ -218,13 +240,20 @@ pub trait HtmlHandler> { Ok(write!(w, "")?) } fn verbatim(&mut self, w: &mut W, cont: &str) -> Result<(), E> { - Ok(write!(w, "{}", Escape(cont))?) + write!(w, "")?; + self.escape(w, cont)?; + write!(w, "")?; + Ok(()) } fn code(&mut self, w: &mut W, cont: &str) -> Result<(), E> { - Ok(write!(w, "{}", Escape(cont))?) + write!(w, "")?; + self.escape(w, cont)?; + write!(w, "")?; + Ok(()) } fn text(&mut self, w: &mut W, cont: &str) -> Result<(), E> { - Ok(write!(w, "{}", Escape(cont))?) + self.escape(w, cont)?; + Ok(()) } fn planning(&mut self, w: &mut W, planning: Planning) -> Result<(), E> { Ok(()) @@ -266,39 +295,3 @@ impl<'a, W: Write, E: From, H: HtmlHandler> HtmlRender<'a, W, E, H> Ok(()) } } - -pub struct Escape<'a>(pub &'a str); - -impl<'a> fmt::Display for Escape<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut pos = 0; - while let Some(off) = ascii_chars!('<', '>', '&', '\'', '"').find(&self.0[pos..]) { - fmt.write_str(&self.0[pos..pos + off])?; - - pos += off + 1; - - match &self.0.as_bytes()[pos - 1] { - b'"' => fmt.write_str(""")?, - b'&' => fmt.write_str("&")?, - b'<' => fmt.write_str("<")?, - b'>' => fmt.write_str(">")?, - b'\'' => fmt.write_str("'")?, - b'\n' => fmt.write_str(" ")?, - _ => unreachable!(), - } - } - - fmt.write_str(&self.0[pos..]) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn escape() { - assert_eq!(format!("{}", Escape("<<<<<<")), "<<<<<<"); - assert_eq!(format!("{}", Escape(" <> <> ")), " <> <> "); - } -}