From 8d2728a7677218901795518613497d5bbb3fb5e5 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 23 May 2020 18:40:09 -0400 Subject: [PATCH] Implement javascript string escaping. --- js/test_cases/filters/input1.json | 2 +- js/test_cases/filters/main.dust | 6 ++++++ src/bin.rs | 25 ++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/js/test_cases/filters/input1.json b/js/test_cases/filters/input1.json index c0bb598..0dfba3a 100644 --- a/js/test_cases/filters/input1.json +++ b/js/test_cases/filters/input1.json @@ -11,5 +11,5 @@ "object": { "foo": "bar" }, - "special_characters": "<>&\"'" + "special_characters": "<>xx\b&\"'\t\f\n\r\\" } diff --git a/js/test_cases/filters/main.dust b/js/test_cases/filters/main.dust index df5b2d4..f18a342 100644 --- a/js/test_cases/filters/main.dust +++ b/js/test_cases/filters/main.dust @@ -20,3 +20,9 @@ Object html escaping disabled: {object|s}{~n} Object stringified: {object|js}{~n} Object stringified and parsed: {object|js|jp}{~n} Object stringified, html escaping disabled, parsed, stringified, and html escaped: {object|js|s|jp|js|h}{~n} + +Special characters: {special_characters}{~n} +Special characters html escaping disabled and javascript escaped: {special_characters|s|j}{~n} +Special characters javascript escaped and html escaping disabled: {special_characters|j|s}{~n} +Special characters javascript escaped once: {special_characters|j}{~n} +Special characters javascript escaped twice: {special_characters|j|j}{~n} diff --git a/src/bin.rs b/src/bin.rs index 102d53d..668d527 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -88,6 +88,23 @@ fn html_escape(inp: &str) -> String { output } +fn javascript_escape(inp: &str) -> String { + // Adding 10% space from the original to avoid re-allocations by + // leaving room for escaped sequences. + let mut output = String::with_capacity(((inp.len() as f64) * 1.1) as usize); + inp.chars().for_each(|c| match c { + '"' => output.push_str(r#"\""#), + '\'' => output.push_str(r#"\'"#), + '\t' => output.push_str(r#"\t"#), + '\x0C' => output.push_str(r#"\f"#), + '\n' => output.push_str(r#"\n"#), + '\r' => output.push_str(r#"\r"#), + '\\' => output.push_str(r#"\\"#), + _ => output.push(c), + }); + output +} + fn apply_filter( json_value: &serde_json::Value, filter: &Filter, @@ -114,7 +131,13 @@ fn apply_filter( (_, Filter::JsonStringify) => { Ok(serde_json::Value::String(json_value.to_string())) } - // TODO: javascript string escape + // Javascript escape filter + (serde_json::Value::String(string), Filter::JavascriptStringEncode) => { + Ok(serde_json::Value::String(javascript_escape(string))) + } + (_, Filter::JavascriptStringEncode) => Ok(serde_json::Value::String(javascript_escape( + &json_value.render(&Vec::new())?, + ))), // TODO: EncodeUri // TODO: EncodeUriComponent _ => panic!("Unimplemented"),