diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b921acc..eacb2b1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ New features Enhancements ------------ +* Two double quotes (`""`) in a string literal now maps to `"`; two back-ticks (``` `` ```) in a literal string now maps to `` ` ``. * Added `Engine::register_type_with_name_raw` to register a custom type based on a fully-qualified type path. * Added `into_array` and `into_typed_array` for `Dynamic`. * Added `FnPtr::call` and `FnPtr::call_within_context` to simplify calling a function pointer. diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 8bdcc508..79018371 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1175,6 +1175,15 @@ pub fn parse_string_literal( result.push(next_char) } + // Double wrapper + _ if termination_char == next_char + && escape.is_empty() + && stream.peek_next().map_or(false, |c| c == termination_char) => + { + eat_next(stream, pos); + result.push(termination_char) + } + // Close wrapper _ if termination_char == next_char && escape.is_empty() => { state.is_within_text_terminated_by = None; diff --git a/tests/string.rs b/tests/string.rs index 62f00b86..ac7991f3 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -8,6 +8,10 @@ fn test_string() -> Result<(), Box> { engine.eval::(r#""Test string: \u2764""#)?, "Test string: ❤" ); + assert_eq!( + engine.eval::(r#""Test string: ""\u2764""""#)?, + r#"Test string: "❤""# + ); assert_eq!( engine.eval::("\"Test\rstring: \\u2764\"")?, "Test\rstring: ❤" @@ -24,6 +28,10 @@ fn test_string() -> Result<(), Box> { engine.eval::(" `Test string: \\u2764\nhello,\\nworld!`")?, "Test string: \\u2764\nhello,\\nworld!" ); + assert_eq!( + engine.eval::(r#" `Test string: \\u2764\n``hello``,\\n"world"!`"#)?, + r#"Test string: \\u2764\n`hello`,\\n"world"!"# + ); assert_eq!( engine.eval::(" `\nTest string: \\u2764\nhello,\\nworld!`")?, "Test string: \\u2764\nhello,\\nworld!"