Move escaping routines into a shared maud_htmlescape crate
This commit is contained in:
parent
37419d9781
commit
2213c0dc32
9 changed files with 94 additions and 73 deletions
|
@ -12,6 +12,8 @@ script:
|
||||||
printf 'Checking for tabs in %s\n' "$TRAVIS_COMMIT_RANGE"
|
printf 'Checking for tabs in %s\n' "$TRAVIS_COMMIT_RANGE"
|
||||||
! git diff --name-only --diff-filter=ACMR "$TRAVIS_COMMIT_RANGE" | xargs grep $'\t'
|
! git diff --name-only --diff-filter=ACMR "$TRAVIS_COMMIT_RANGE" | xargs grep $'\t'
|
||||||
fi
|
fi
|
||||||
|
- ( cd maud_htmlescape && cargo test --all-features )
|
||||||
|
- if command -v cargo-clippy > /dev/null; then ( cd maud_htmlescape && cargo clippy -- -D warnings ); fi
|
||||||
- ( cd maud && cargo test --all-features )
|
- ( cd maud && cargo test --all-features )
|
||||||
- if command -v cargo-clippy > /dev/null; then ( cd maud && cargo clippy -- -D warnings ); fi
|
- if command -v cargo-clippy > /dev/null; then ( cd maud && cargo clippy -- -D warnings ); fi
|
||||||
- ( cd maud_macros && cargo test --all-features )
|
- ( cd maud_macros && cargo test --all-features )
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"maud",
|
"maud_htmlescape",
|
||||||
"maud_macros",
|
"maud_macros",
|
||||||
|
"maud",
|
||||||
"maud_extras",
|
"maud_extras",
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,6 +13,7 @@ description = "Compile-time HTML templates."
|
||||||
categories = ["template-engine"]
|
categories = ["template-engine"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
maud_htmlescape = { version = "0.17.0", path = "../maud_htmlescape" }
|
||||||
maud_macros = { version = "0.16.3", path = "../maud_macros" }
|
maud_macros = { version = "0.16.3", path = "../maud_macros" }
|
||||||
iron = { version = "0.5.1", optional = true }
|
iron = { version = "0.5.1", optional = true }
|
||||||
rocket = { version = "0.3", optional = true }
|
rocket = { version = "0.3", optional = true }
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#[cfg(feature = "iron")] extern crate iron;
|
#[cfg(feature = "iron")] extern crate iron;
|
||||||
#[cfg(feature = "rocket")] extern crate rocket;
|
#[cfg(feature = "rocket")] extern crate rocket;
|
||||||
|
|
||||||
|
extern crate maud_htmlescape;
|
||||||
extern crate maud_macros;
|
extern crate maud_macros;
|
||||||
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -121,52 +122,7 @@ impl<T: AsRef<str> + Into<String>> Into<String> for PreEscaped<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An adapter that escapes HTML special characters.
|
pub use maud_htmlescape::Escaper;
|
||||||
///
|
|
||||||
/// The following characters are escaped:
|
|
||||||
///
|
|
||||||
/// * `&` is escaped as `&`
|
|
||||||
/// * `<` is escaped as `<`
|
|
||||||
/// * `>` is escaped as `>`
|
|
||||||
/// * `"` is escaped as `"`
|
|
||||||
///
|
|
||||||
/// All other characters are passed through unchanged.
|
|
||||||
///
|
|
||||||
/// **Note:** In versions prior to 0.13, the single quote (`'`) was
|
|
||||||
/// escaped as well.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use maud::Escaper;
|
|
||||||
/// use std::fmt::Write;
|
|
||||||
/// let mut s = String::new();
|
|
||||||
/// write!(Escaper::new(&mut s), "<script>launchMissiles()</script>").unwrap();
|
|
||||||
/// assert_eq!(s, "<script>launchMissiles()</script>");
|
|
||||||
/// ```
|
|
||||||
pub struct Escaper<'a>(&'a mut String);
|
|
||||||
|
|
||||||
impl<'a> Escaper<'a> {
|
|
||||||
/// Creates an `Escaper` from a `String`.
|
|
||||||
pub fn new(buffer: &'a mut String) -> Escaper<'a> {
|
|
||||||
Escaper(buffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> fmt::Write for Escaper<'a> {
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
for b in s.bytes() {
|
|
||||||
match b {
|
|
||||||
b'&' => self.0.push_str("&"),
|
|
||||||
b'<' => self.0.push_str("<"),
|
|
||||||
b'>' => self.0.push_str(">"),
|
|
||||||
b'"' => self.0.push_str("""),
|
|
||||||
_ => unsafe { self.0.as_mut_vec().push(b) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The literal string `<!DOCTYPE html>`.
|
/// The literal string `<!DOCTYPE html>`.
|
||||||
///
|
///
|
||||||
|
|
15
maud_htmlescape/Cargo.toml
Normal file
15
maud_htmlescape/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
|
||||||
|
name = "maud_htmlescape"
|
||||||
|
# When releasing a new version, please update html_root_url in lib.rs
|
||||||
|
version = "0.17.0"
|
||||||
|
authors = ["Chris Wong <lambda.fairy@gmail.com>"]
|
||||||
|
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
documentation = "https://docs.rs/maud_htmlescape/"
|
||||||
|
homepage = "https://maud.lambda.xyz/"
|
||||||
|
repository = "https://github.com/lfairy/maud"
|
||||||
|
description = "Internal support code used by Maud."
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
68
maud_htmlescape/lib.rs
Normal file
68
maud_htmlescape/lib.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
//! Internal support code used by the [Maud] template engine.
|
||||||
|
//!
|
||||||
|
//! You should not need to depend on this crate directly.
|
||||||
|
//!
|
||||||
|
//! [Maud]: https://maud.lambda.xyz
|
||||||
|
|
||||||
|
#![doc(html_root_url = "https://docs.rs/maud_htmlescape/0.17.0")]
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// An adapter that escapes HTML special characters.
|
||||||
|
///
|
||||||
|
/// The following characters are escaped:
|
||||||
|
///
|
||||||
|
/// * `&` is escaped as `&`
|
||||||
|
/// * `<` is escaped as `<`
|
||||||
|
/// * `>` is escaped as `>`
|
||||||
|
/// * `"` is escaped as `"`
|
||||||
|
///
|
||||||
|
/// All other characters are passed through unchanged.
|
||||||
|
///
|
||||||
|
/// **Note:** In versions prior to 0.13, the single quote (`'`) was
|
||||||
|
/// escaped as well.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// use std::fmt::Write;
|
||||||
|
/// let mut s = String::new();
|
||||||
|
/// write!(Escaper::new(&mut s), "<script>launchMissiles()</script>").unwrap();
|
||||||
|
/// assert_eq!(s, "<script>launchMissiles()</script>");
|
||||||
|
/// ```
|
||||||
|
pub struct Escaper<'a>(&'a mut String);
|
||||||
|
|
||||||
|
impl<'a> Escaper<'a> {
|
||||||
|
/// Creates an `Escaper` from a `String`.
|
||||||
|
pub fn new(buffer: &'a mut String) -> Escaper<'a> {
|
||||||
|
Escaper(buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> fmt::Write for Escaper<'a> {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for b in s.bytes() {
|
||||||
|
match b {
|
||||||
|
b'&' => self.0.push_str("&"),
|
||||||
|
b'<' => self.0.push_str("<"),
|
||||||
|
b'>' => self.0.push_str(">"),
|
||||||
|
b'"' => self.0.push_str("""),
|
||||||
|
_ => unsafe { self.0.as_mut_vec().push(b) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::fmt::Write;
|
||||||
|
use Escaper;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let mut s = String::new();
|
||||||
|
write!(Escaper::new(&mut s), "<script>launchMissiles()</script>").unwrap();
|
||||||
|
assert_eq!(s, "<script>launchMissiles()</script>");
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ description = "Compile-time HTML templates."
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
literalext = { version = "0.1", default-features = false, features = ["proc-macro"] }
|
literalext = { version = "0.1", default-features = false, features = ["proc-macro"] }
|
||||||
|
maud_htmlescape = { version = "0.17.0", path = "../maud_htmlescape" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "maud_macros"
|
name = "maud_macros"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![doc(html_root_url = "https://docs.rs/maud_macros/0.16.3")]
|
#![doc(html_root_url = "https://docs.rs/maud_macros/0.16.3")]
|
||||||
|
|
||||||
extern crate literalext;
|
extern crate literalext;
|
||||||
|
extern crate maud_htmlescape;
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
// TODO move lints into their own `maud_lints` crate
|
// TODO move lints into their own `maud_lints` crate
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use proc_macro::{Literal, Term, TokenNode, TokenStream};
|
use proc_macro::{Literal, Term, TokenNode, TokenStream};
|
||||||
use proc_macro::quote;
|
use proc_macro::quote;
|
||||||
use std::fmt;
|
|
||||||
|
use maud_htmlescape::Escaper;
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
output: TokenNode,
|
output: TokenNode,
|
||||||
|
@ -166,28 +167,3 @@ fn html_escape(s: &str) -> String {
|
||||||
Escaper::new(&mut buffer).write_str(s).unwrap();
|
Escaper::new(&mut buffer).write_str(s).unwrap();
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move this into a common `maud_htmlescape` crate
|
|
||||||
struct Escaper<'a>(&'a mut String);
|
|
||||||
|
|
||||||
impl<'a> Escaper<'a> {
|
|
||||||
/// Creates an `Escaper` from a `String`.
|
|
||||||
pub fn new(buffer: &'a mut String) -> Escaper<'a> {
|
|
||||||
Escaper(buffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> fmt::Write for Escaper<'a> {
|
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
||||||
for b in s.bytes() {
|
|
||||||
match b {
|
|
||||||
b'&' => self.0.push_str("&"),
|
|
||||||
b'<' => self.0.push_str("<"),
|
|
||||||
b'>' => self.0.push_str(">"),
|
|
||||||
b'"' => self.0.push_str("""),
|
|
||||||
_ => unsafe { self.0.as_mut_vec().push(b) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue