Expose Escaper
type
This commit is contained in:
parent
6030eed9f7
commit
c68f98d3a7
3 changed files with 61 additions and 38 deletions
|
@ -2,4 +2,5 @@ language: rust
|
|||
rust: nightly
|
||||
sudo: false
|
||||
script:
|
||||
- ( cd maud && cargo test --verbose )
|
||||
- ( cd maud_macros && cargo test --verbose )
|
||||
|
|
|
@ -8,6 +8,51 @@
|
|||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
/// An adapter that escapes HTML special characters.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use maud::Escaper;
|
||||
/// use std::fmt::Write;
|
||||
/// let mut result = String::new();
|
||||
/// write!(Escaper::new(&mut result), "<script>launchMissiles()</script>").unwrap();
|
||||
/// assert_eq!(result, "<script>launchMissiles()</script>");
|
||||
/// ```
|
||||
pub struct Escaper<'a> {
|
||||
// FIXME: store the writer directly instead of borrowing it
|
||||
// see <https://github.com/rust-lang/rust/pull/28368>
|
||||
inner: &'a mut fmt::Write,
|
||||
}
|
||||
|
||||
impl<'a> Escaper<'a> {
|
||||
/// Creates an `Escaper` from a `std::fmt::Write`.
|
||||
pub fn new(inner: &'a mut fmt::Write) -> Escaper<'a> {
|
||||
Escaper { inner: inner }
|
||||
}
|
||||
|
||||
/// Extracts the inner writer.
|
||||
pub fn into_inner(self) -> &'a mut fmt::Write {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for Escaper<'a> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
try!(match c {
|
||||
'&' => self.inner.write_str("&"),
|
||||
'<' => self.inner.write_str("<"),
|
||||
'>' => self.inner.write_str(">"),
|
||||
'"' => self.inner.write_str("""),
|
||||
'\'' => self.inner.write_str("'"),
|
||||
_ => self.inner.write_char(c),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps a `std::io::Write` in a `std::fmt::Write`.
|
||||
///
|
||||
/// Most I/O libraries work with binary data (`[u8]`), but Maud outputs
|
||||
|
@ -37,11 +82,15 @@ impl<W: io::Write> Utf8Writer<W> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Extracts the inner writer, along with any errors encountered
|
||||
/// along the way.
|
||||
pub fn into_inner(self) -> (W, io::Result<()>) {
|
||||
let Utf8Writer { inner, result } = self;
|
||||
(inner, result)
|
||||
}
|
||||
|
||||
/// Drops the inner writer, returning any errors encountered
|
||||
/// along the way.
|
||||
pub fn into_result(self) -> io::Result<()> {
|
||||
self.result
|
||||
}
|
||||
|
@ -68,38 +117,3 @@ impl<W: io::Write> fmt::Write for Utf8Writer<W> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Escapes an HTML value.
|
||||
pub fn escape(s: &str) -> String {
|
||||
use std::fmt::Write;
|
||||
let mut buf = String::new();
|
||||
rt::Escaper { inner: &mut buf }.write_str(s).unwrap();
|
||||
buf
|
||||
}
|
||||
|
||||
/// Internal functions used by the `maud_macros` package. You should
|
||||
/// never need to call these directly.
|
||||
#[doc(hidden)]
|
||||
pub mod rt {
|
||||
use std::fmt;
|
||||
|
||||
pub struct Escaper<'a, 'b: 'a> {
|
||||
pub inner: &'a mut (fmt::Write + 'b),
|
||||
}
|
||||
|
||||
impl<'a, 'b> fmt::Write for Escaper<'a, 'b> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for c in s.chars() {
|
||||
try!(match c {
|
||||
'&' => self.inner.write_str("&"),
|
||||
'<' => self.inner.write_str("<"),
|
||||
'>' => self.inner.write_str(">"),
|
||||
'"' => self.inner.write_str("""),
|
||||
'\'' => self.inner.write_str("'"),
|
||||
_ => write!(self.inner, "{}", c),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::fmt::Write;
|
||||
use syntax::ast::{Expr, Ident, Pat, Stmt, TokenTree, TtToken};
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
|
||||
use maud;
|
||||
use maud::Escaper;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Escape {
|
||||
|
@ -119,7 +120,7 @@ impl<'cx> Renderer<'cx> {
|
|||
let escaped;
|
||||
let s = match escape {
|
||||
Escape::PassThru => s,
|
||||
Escape::Escape => { escaped = maud::escape(s); &*escaped },
|
||||
Escape::Escape => { escaped = html_escape(s); &*escaped },
|
||||
};
|
||||
self.push_str(s);
|
||||
}
|
||||
|
@ -133,7 +134,7 @@ impl<'cx> Renderer<'cx> {
|
|||
Escape::Escape =>
|
||||
quote_expr!(self.cx,
|
||||
write!(
|
||||
::maud::rt::Escaper { inner: $w },
|
||||
::maud::Escaper::new($w),
|
||||
"{}",
|
||||
$expr)),
|
||||
};
|
||||
|
@ -190,3 +191,10 @@ impl<'cx> Renderer<'cx> {
|
|||
self.push(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
fn html_escape(s: &str) -> String {
|
||||
use std::fmt::Write;
|
||||
let mut out = String::new();
|
||||
Escaper::new(&mut out).write_str(s).unwrap();
|
||||
out
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue