Skip to content

Commit

Permalink
Fix characters to be escaped (axuno#251)
Browse files Browse the repository at this point in the history
Fix: Table of characters, that must be escaped with a backslash
* Removed ' and " => no escaping
* Added { and } => must always be escaped
* Chars to be escaped in Options: only ( and )
  • Loading branch information
axunonb authored Feb 28, 2022
1 parent 799bff2 commit bb37ebc
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 25 deletions.
18 changes: 9 additions & 9 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,20 @@ SmartFormat v3.0-alpha.5
Note: `PoolingDisabled` is just for showing the advantage of object pooling, which was added in `v3.0-alpha.5`.

### 2. Exact control of whitespace text output
This was an issue in v2 and was going back to combining `string.Format` compatibility with *Smart.Format* features. This is resolved by setting the desired mode with `SmartSettings.StringFormatCompatibility` (defaults to `false`). ([#172](https://github.com/axuno/SmartFormat/pull/172))
This was an issue in v2 and was going back to combining `string.Format` compatibility with *SmartFormat* features. This is resolved by setting the desired mode with `SmartSettings.StringFormatCompatibility` (defaults to `false`). ([#172](https://github.com/axuno/SmartFormat/pull/172))

### 3. Literals may contain any Unicode characters ([#166](https://github.com/axuno/SmartFormat/pull/166))
Add unicode escape characters like `"\u1234"`. Thanks to [@karljj1](https://github.com/karljj1).

### 4. Separate modes for "*Smart.Format* features" and "`string.Format` compatibility"
### 4. Separate modes for "*SmartFormat* features" and "`string.Format` compatibility"

The mode can be set with `SmartSettings.StringFormatCompatibility`. By default, `SmartSettings.StringFormatCompatibility` is `false`. ([#173](https://github.com/axuno/SmartFormat/pull/173), [#175](https://github.com/axuno/SmartFormat/pull/175))

Reasoning: The distinction was necessary because of syntax conflicts between SmartFormat extensions and `string.Format`. It brings a more concise and clear set of formatting rules and full `string.Format` compatibility even in "edge cases".

**a) *Smart.Format* features mode**
* Brings the full set of features implemented in *Smart.Format*
* Curly braces are escaped the *Smart.Format* way with `\{` and `\}`.
**a) *SmartFormat* features mode**
* Brings the full set of features implemented in *SmartFormat*
* Curly braces are escaped the *SmartFormat* way with `\{` and `\}`.
* As long as special characters `(){}:\` are escaped with `\`, any character is allowed anywhere. Note: This applies also for the colon.

**b) `string.Format` compatibility mode**
Expand Down Expand Up @@ -208,7 +208,7 @@ Smart.Format("{0.ToLower.TrimStart.TrimEnd.ToBase64}", " ABCDE ");

C# like `nullable` notation allows to display `Nullable<T>` types.

The *Smart.Format* notation is `"{SomeNullable?.Property}"`. If `SomeNullable` is null, the expression is evaluated as `string.Empty`.
The *SmartFormat* notation is `"{SomeNullable?.Property}"`. If `SomeNullable` is null, the expression is evaluated as `string.Empty`.

The nullable operator can also be used for evaluating a list index. E.g.: `Smart.Format("{TheList?[1]}")` will output `string.Empty`, if the list variable is null.

Expand Down Expand Up @@ -296,7 +296,7 @@ The default is `false`.

If `true`, the`Parser` will parse all content inside &lt;script&gt; and &lt;style&gt; tags as `LiteralText`. All other places may still contain `Placeholder`s.

This is because &lt;script&gt; and &lt;style&gt; tags may contain curly or square braces, that interfere with the SmartFormat {`Placeholder`}.
This is because &lt;script&gt; and &lt;style&gt; tags may contain curly or square braces, that interfere with the *SmartFormat* {`Placeholder`}.

Best results can only be expected with clean HTML: balanced opening and closing tags, single and double quotes. Also, do not use angle brackets, single and double quotes in script or style comments.

Expand Down Expand Up @@ -346,11 +346,11 @@ SmartFormat is not a fully-fledged HTML parser. If this is required, use [AngleS
CommonLanguagesTimeTextInfo.AddLanguage(language, custom)
```
* **Changed:**
a) This notation - using formats as formatter options - was allowed in *Smart.Format v2.x*, but is now depreciated. It is still detected and working, as long as the format part is left empty
a) This notation - using formats as formatter options - was allowed in *SmartFormat* *v2.x*, but is now depreciated. It is still detected and working, as long as the format part is left empty
```CSharp
var formatDepreciated = "{0:time(abbr hours noless)}";
```
b) This format string is recommended for *Smart.Format v3* and later. It allows for including the language as an option to the `TimeFormatter`:
b) This format string is recommended for *SmartFormat* *v3* and later. It allows for including the language as an option to the `TimeFormatter`:
```CSharp
// Without language option:
var formatRecommended = "{0:time:abbr hours noless:}";
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@

[![Paypal-Donations](https://img.shields.io/badge/Donate-PayPal-important.svg?style=flat-square)](https://www.paypal.com/donate?hosted_button_id=KSC3LRAR26AHN)

**SmartFormat** is a **string composition** library written in C# which can be a drop-in replacement for `string.Format`. More than that **Smart.Format** can format data with named placeholders, lists, localization, pluralization and other smart extensions.
**SmartFormat** is a is a **lightweight text templating** library written in C# which can be a drop-in replacement for `string.Format`. More than that **SmartFormat** can format data with named placeholders, lists, localization, pluralization and other smart extensions.

* High performance with low memory footprint
* Minimal, intuitive syntax
* Formatting takes place exclusively at runtime
* Exact control of whitespace text output
* `string.Format` compatibility mode and `Smart.Format` enhanced mode
* Minimal, intuitive syntax
* Many built-in extensions, custom extensions are easy to integrate
* Most common data sources work out-of-the-box
* Many built-in formatting extensions
* Custom formatting and source extensions are easy to integrate

### Supported Frameworks
* .Net Framework 4.6.1 and later
Expand Down
5 changes: 3 additions & 2 deletions src/SmartFormat.Tests/Core/EscapedLiteralTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void TryGetChar_FormatterOption_Test(char testChar, char testCharResult)
else Assert.That(found, Is.False);
}

[TestCase(@"\\ \' abc\\", @"\ ' abc\", false)] // included in look-up table
[TestCase(@"\\ \{ \} abc\\", @"\ { } abc\", false)] // included in look-up table
[TestCase(@"\zabc\", @"\z", true)] // not included in look-up table
public void UnEscapeCharLiterals_General_Test(string input, string expected, bool shouldThrow)
{
Expand Down Expand Up @@ -75,7 +75,8 @@ public void UnEscapeCharLiterals_FormatterOption_Test(string input, string expec
}

[TestCase(@"abc", @"abc")] // not to escape
[TestCase("\'\"\\\n", @"\'\""\\\n")] // to escape
//[TestCase("\'\"\\\n", @"\'\""\\\n")] // to escape
[TestCase("{}\\\n", @"\{\}\\\n")] // to escape
public void EscapeCharLiterals_General_Test(string input, string expected)
{
var result = new string(EscapedLiteral.EscapeCharLiterals('\\', input, 0, input.Length, false).ToArray());
Expand Down
4 changes: 2 additions & 2 deletions src/SmartFormat.Tests/Core/LiteralTextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public void FormatCharacterLiteralsAsString()
[Test]
public void AllSupportedCharacterLiteralsAsUnicode()
{
const string formatWithFileBehavior = @"All supported literal characters: \' \"" \\ \a \b \f \n \r \t \v \0 \u2022!";
const string formatWithCodeBehavior = "All supported literal characters: \' \" \\ \a \b \f \n \r \t \v \0 \u2022!";
const string formatWithFileBehavior = @"All supported literal characters: \\ \a \b \f \n \r \t \v \0 \u2022!";
const string formatWithCodeBehavior = "All supported literal characters: \\ \a \b \f \n \r \t \v \0 \u2022!";

var formatter = Smart.CreateDefaultSmartFormat(new SmartSettings {Parser = new ParserSettings {ConvertCharacterStringLiterals = true}});

Expand Down
4 changes: 4 additions & 0 deletions src/SmartFormat.Tests/Extensions/IsMatchFormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public void Currency_Symbol(string currency, string expected)
[TestCase("+", @"\+", @"\\+")]
[TestCase("*", @"\*", @"\\*")]
[TestCase("^", @"\^", @"\\^")]
[TestCase("$", @"\$", @"\\$")]
[TestCase(".", @"\.", @"\\.")]
[TestCase("[", @"\[", @"\\[")]
[TestCase("]", @"\]", @"\\]")]
Expand All @@ -137,7 +138,10 @@ public void Escaped_Option_And_RegEx_Chars(string search, string regExEscaped, s
var smart = GetFormatter();
// To be escaped with backslash for PCRE RegEx: ".^$*+?()[]{}\|"
var regEx = new Regex(regExEscaped);

Assert.That(EscapedLiteral.EscapeCharLiterals('\\', regExEscaped, 0, regExEscaped.Length, true), Is.EqualTo(optionsEscaped));
Assert.IsTrue(regEx.Match(search).Success);

var result = smart.Format("{0:ismatch(" + optionsEscaped + "):found {}|}", search);
Assert.That(result, Is.EqualTo("found " + search));
}
Expand Down
4 changes: 0 additions & 4 deletions src/SmartFormat.Tests/SmartFormat.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,4 @@
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Folder Include="Extensions.Pluralization\" />
</ItemGroup>

</Project>
8 changes: 3 additions & 5 deletions src/SmartFormat/Core/Parsing/EscapedLiteral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public static class EscapedLiteral
{
private static readonly Dictionary<char, char> GeneralLookupTable = new() {
// General
{'\'', '\''},
{'\"', '\"'},
{'\\', '\\'},
{'{', '{'},
{'}', '}'},
{'0', '\0'},
{'a', '\a'},
{'b', '\b'},
Expand All @@ -33,9 +33,7 @@ public static class EscapedLiteral
private static readonly Dictionary<char, char> FormatterOptionsLookupTable = new() {
// Smart.Format characters used in formatter options
{'(', '('},
{')', ')'},
{'{', '{'},
{'}', '}'}
{')', ')'}
};

/// <summary>
Expand Down

0 comments on commit bb37ebc

Please sign in to comment.