aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askama_derive/src/parser.rs50
-rw-r--r--testing/templates/literals-escape.html2
-rw-r--r--testing/tests/simple.rs13
3 files changed, 45 insertions, 20 deletions
diff --git a/askama_derive/src/parser.rs b/askama_derive/src/parser.rs
index 91c2d6a..910815a 100644
--- a/askama_derive/src/parser.rs
+++ b/askama_derive/src/parser.rs
@@ -1,6 +1,6 @@
use nom::branch::alt;
-use nom::bytes::complete::{is_not, tag, take_until};
-use nom::character::complete::{char, digit1};
+use nom::bytes::complete::{escaped, is_not, tag, take_until};
+use nom::character::complete::{anychar, char, digit1};
use nom::combinator::{complete, map, opt};
use nom::error::ParseError;
use nom::multi::{many0, many1, separated_list, separated_nonempty_list};
@@ -251,40 +251,50 @@ fn param_num_lit(i: &[u8]) -> IResult<&[u8], MatchParameter> {
map(num_lit, |s| MatchParameter::NumLit(s))(i)
}
+fn str_lit(i: &[u8]) -> IResult<&[u8], &str> {
+ map(
+ delimited(
+ char('\"'),
+ opt(escaped(is_not("\\\""), '\\', anychar)),
+ char('\"'),
+ ),
+ |s| s.map(|s| str::from_utf8(s).unwrap()).unwrap_or(""),
+ )(i)
+}
+
fn expr_str_lit(i: &[u8]) -> IResult<&[u8], Expr> {
- map(delimited(char('"'), take_until("\""), char('"')), |s| {
- Expr::StrLit(str::from_utf8(s).unwrap())
- })(i)
+ map(str_lit, |s| Expr::StrLit(s))(i)
}
fn variant_str_lit(i: &[u8]) -> IResult<&[u8], MatchVariant> {
- map(delimited(char('"'), is_not("\""), char('"')), |s| {
- MatchVariant::StrLit(str::from_utf8(s).unwrap())
- })(i)
+ map(str_lit, |s| MatchVariant::StrLit(s))(i)
}
fn param_str_lit(i: &[u8]) -> IResult<&[u8], MatchParameter> {
- map(delimited(char('"'), is_not("\""), char('"')), |s| {
- MatchParameter::StrLit(str::from_utf8(s).unwrap())
- })(i)
+ map(str_lit, |s| MatchParameter::StrLit(s))(i)
+}
+
+fn char_lit(i: &[u8]) -> IResult<&[u8], &str> {
+ map(
+ delimited(
+ char('\''),
+ opt(escaped(is_not("\\\'"), '\\', anychar)),
+ char('\''),
+ ),
+ |s| s.map(|s| str::from_utf8(s).unwrap()).unwrap_or(""),
+ )(i)
}
fn expr_char_lit(i: &[u8]) -> IResult<&[u8], Expr> {
- map(delimited(char('\''), take_until("'"), char('\'')), |s| {
- Expr::CharLit(str::from_utf8(s).unwrap())
- })(i)
+ map(char_lit, |s| Expr::CharLit(s))(i)
}
fn variant_char_lit(i: &[u8]) -> IResult<&[u8], MatchVariant> {
- map(delimited(char('\''), is_not("'"), char('\'')), |s| {
- MatchVariant::CharLit(str::from_utf8(s).unwrap())
- })(i)
+ map(char_lit, |s| MatchVariant::CharLit(s))(i)
}
fn param_char_lit(i: &[u8]) -> IResult<&[u8], MatchParameter> {
- map(delimited(char('\''), is_not("'"), char('\'')), |s| {
- MatchParameter::CharLit(str::from_utf8(s).unwrap())
- })(i)
+ map(char_lit, |s| MatchParameter::CharLit(s))(i)
}
fn expr_var(i: &[u8]) -> IResult<&[u8], Expr> {
diff --git a/testing/templates/literals-escape.html b/testing/templates/literals-escape.html
new file mode 100644
index 0000000..4886cfb
--- /dev/null
+++ b/testing/templates/literals-escape.html
@@ -0,0 +1,2 @@
+{{ '\x41' }}{{ '\n' }}{{ '\r' }}{{ '\t' }}{{ '\\' }}{{ '\0' }}{{ '\u{2665}' }}{{ '\'' }}{{ '\"' }}{{ '"' }}
+{{ "\x41\n\r\t\\\0\u{2665}\'\"'" }}
diff --git a/testing/tests/simple.rs b/testing/tests/simple.rs
index 53f1122..a075d26 100644
--- a/testing/tests/simple.rs
+++ b/testing/tests/simple.rs
@@ -122,6 +122,19 @@ fn test_literals() {
assert_eq!(s.render().unwrap(), "a\na\ntrue\nfalse");
}
+#[derive(Template)]
+#[template(path = "literals-escape.html")]
+struct LiteralsEscapeTemplate {}
+
+#[test]
+fn test_literals_escape() {
+ let s = LiteralsEscapeTemplate {};
+ assert_eq!(
+ s.render().unwrap(),
+ "A\n\r\t\\\0♥&#x27;&quot;&quot;\nA\n\r\t\\\0♥&#x27;&quot;&#x27;"
+ );
+}
+
struct Holder {
a: usize,
}