chore(export): escape methods
This commit is contained in:
parent
0101612029
commit
ffbefaa3b4
|
@ -6,18 +6,40 @@ use crate::{
|
||||||
objects::{Cookie, Timestamp},
|
objects::{Cookie, Timestamp},
|
||||||
parser::Parser,
|
parser::Parser,
|
||||||
};
|
};
|
||||||
use jetscii::ascii_chars;
|
use jetscii::bytes;
|
||||||
use std::{
|
use std::{
|
||||||
convert::From,
|
convert::From,
|
||||||
fmt,
|
|
||||||
io::{Error, Write},
|
io::{Error, Write},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait HtmlHandler<W: Write, E: From<Error>> {
|
pub trait HtmlHandler<W: Write, E: From<Error>> {
|
||||||
|
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> {
|
fn headline_beg(&mut self, w: &mut W, hdl: Headline) -> Result<(), E> {
|
||||||
let level = if hdl.level <= 6 { hdl.level } else { 6 };
|
let level = if hdl.level <= 6 { hdl.level } else { 6 };
|
||||||
Ok(write!(w, "<h{0}>{1}</h{0}>", level, Escape(hdl.title))?)
|
write!(w, "<h{}>", level)?;
|
||||||
|
self.escape(w, hdl.title)?;
|
||||||
|
write!(w, "</h{}>", level)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn headline_end(&mut self, w: &mut W) -> Result<(), E> {
|
fn headline_end(&mut self, w: &mut W) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -62,13 +84,19 @@ pub trait HtmlHandler<W: Write, E: From<Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn example_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
fn example_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
||||||
Ok(write!(w, "<pre><code>{}</code></pre>", Escape(cont))?)
|
write!(w, "<pre><code>")?;
|
||||||
|
self.escape(w, cont)?;
|
||||||
|
write!(w, "</pre></code>")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn export_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
fn export_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn src_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
fn src_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
||||||
Ok(write!(w, "<pre><code>{}</code></pre>", Escape(cont))?)
|
write!(w, "<pre><code>")?;
|
||||||
|
self.escape(w, cont)?;
|
||||||
|
write!(w, "</pre></code>")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn verse_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
fn verse_block(&mut self, w: &mut W, cont: &str, args: Option<&str>) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -111,9 +139,10 @@ pub trait HtmlHandler<W: Write, E: From<Error>> {
|
||||||
fn fixed_width(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
fn fixed_width(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
||||||
for line in cont.lines() {
|
for line in cont.lines() {
|
||||||
// remove leading colon
|
// remove leading colon
|
||||||
write!(w, "<pre>{}</pre>", Escape(&line[1..]))?;
|
write!(w, "<pre>")?;
|
||||||
|
self.escape(w, &line[1..])?;
|
||||||
|
write!(w, "</pre>")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn table_start(&mut self, w: &mut W) -> Result<(), E> {
|
fn table_start(&mut self, w: &mut W) -> Result<(), E> {
|
||||||
|
@ -153,26 +182,19 @@ pub trait HtmlHandler<W: Write, E: From<Error>> {
|
||||||
) -> Result<(), E> {
|
) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn inline_src(
|
fn inline_src(&mut self, w: &mut W, _: &str, _: Option<&str>, body: &str) -> Result<(), E> {
|
||||||
&mut self,
|
write!(w, "<code>")?;
|
||||||
w: &mut W,
|
self.escape(w, body)?;
|
||||||
lang: &str,
|
write!(w, "</code>")?;
|
||||||
option: Option<&str>,
|
Ok(())
|
||||||
body: &str,
|
|
||||||
) -> Result<(), E> {
|
|
||||||
Ok(write!(w, "<code>{}</code>", Escape(body))?)
|
|
||||||
}
|
}
|
||||||
fn link(&mut self, w: &mut W, path: &str, desc: Option<&str>) -> Result<(), E> {
|
fn link(&mut self, w: &mut W, path: &str, desc: Option<&str>) -> Result<(), E> {
|
||||||
if let Some(desc) = desc {
|
write!(w, r#"<a href=""#)?;
|
||||||
Ok(write!(
|
self.escape(w, path)?;
|
||||||
w,
|
write!(w, r#"">"#)?;
|
||||||
r#"<a href="{}">{}</a>"#,
|
self.escape(w, desc.unwrap_or(path))?;
|
||||||
Escape(path),
|
write!(w, "</a>")?;
|
||||||
Escape(desc)
|
Ok(())
|
||||||
)?)
|
|
||||||
} else {
|
|
||||||
Ok(write!(w, r#"<a href="{0}">{0}</a>"#, Escape(path))?)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fn macros(&mut self, w: &mut W, name: &str, args: Option<&str>) -> Result<(), E> {
|
fn macros(&mut self, w: &mut W, name: &str, args: Option<&str>) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -218,13 +240,20 @@ pub trait HtmlHandler<W: Write, E: From<Error>> {
|
||||||
Ok(write!(w, "</u>")?)
|
Ok(write!(w, "</u>")?)
|
||||||
}
|
}
|
||||||
fn verbatim(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
fn verbatim(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
||||||
Ok(write!(w, "<code>{}</code>", Escape(cont))?)
|
write!(w, "<code>")?;
|
||||||
|
self.escape(w, cont)?;
|
||||||
|
write!(w, "</code>")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn code(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
fn code(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
||||||
Ok(write!(w, "<code>{}</code>", Escape(cont))?)
|
write!(w, "<code>")?;
|
||||||
|
self.escape(w, cont)?;
|
||||||
|
write!(w, "</code>")?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
fn text(&mut self, w: &mut W, cont: &str) -> Result<(), E> {
|
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> {
|
fn planning(&mut self, w: &mut W, planning: Planning) -> Result<(), E> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -266,39 +295,3 @@ impl<'a, W: Write, E: From<Error>, H: HtmlHandler<W, E>> HtmlRender<'a, W, E, H>
|
||||||
Ok(())
|
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(" <> <> ")), " <> <> ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue