@@ -155,6 +155,7 @@ public void Parser_Error_Action_Ignore()
155155 // | Literal | Erroneous | | Okay |
156156 var invalidTemplate = "Hello, I'm {Name from {City} {Street}" ;
157157
158+ // settings must be set before parser instantiation
158159 var parser = GetRegularParser ( new SmartSettings { Parser = new ParserSettings { ErrorAction = ParseErrorAction . Ignore } } ) ;
159160 using var parsed = parser . ParseFormat ( invalidTemplate ) ;
160161
@@ -177,6 +178,7 @@ public void Parser_Error_Action_Ignore()
177178 [ TestCase ( "Hello, I'm {Name from {City} {Street" , false ) ]
178179 public void Parser_Error_Action_MaintainTokens ( string invalidTemplate , bool lastItemIsPlaceholder )
179180 {
181+ // settings must be set before parser instantiation
180182 var parser = GetRegularParser ( new SmartSettings { Parser = new ParserSettings { ErrorAction = ParseErrorAction . MaintainTokens } } ) ;
181183 using var parsed = parser . ParseFormat ( invalidTemplate ) ;
182184
@@ -203,14 +205,21 @@ public void Parser_Error_Action_MaintainTokens(string invalidTemplate, bool last
203205 public void Parser_Error_Action_OutputErrorInResult ( )
204206 {
205207 // | Literal | Erroneous |
206- // ▼ Selector must not contain {
207208 var invalidTemplate = "Hello, I'm {Name from {City}" ;
208-
209- var parser = GetRegularParser ( new SmartSettings { Parser = new ParserSettings { ErrorAction = ParseErrorAction . OutputErrorInResult } } ) ;
209+
210+ var parser = GetRegularParser ( new SmartSettings
211+ {
212+ Parser = new ParserSettings
213+ {
214+ SelectorCharFilter = FilterType . Allowlist , // default
215+ ErrorAction = ParseErrorAction . OutputErrorInResult
216+ }
217+ } ) ;
218+
210219 using var parsed = parser . ParseFormat ( invalidTemplate ) ;
211220
212221 Assert . That ( parsed . Items , Has . Count . EqualTo ( 1 ) ) ;
213- Assert . That ( parsed . Items [ 0 ] . RawText , Does . StartWith ( "The format string has 1 issue " ) ) ;
222+ Assert . That ( parsed . Items [ 0 ] . RawText , Does . StartWith ( "The format string has 3 issues " ) ) ;
214223 }
215224
216225 [ Test ]
@@ -414,11 +423,11 @@ public void Parser_NotifyParsingError()
414423 } ) ;
415424
416425 formatter . Parser . OnParsingFailure += ( o , args ) => parsingError = args . Errors ;
417- var res = formatter . Format ( "{NoName {Other} {Same" , default ( object ) ! ) ;
426+ var res = formatter . Format ( "{NoName {Other} {Same" ) ;
418427 Assert . Multiple ( ( ) =>
419428 {
420- Assert . That ( parsingError ! . Issues , Has . Count . EqualTo ( 2 ) ) ;
421- Assert . That ( parsingError . Issues [ 1 ] . Issue , Is . EqualTo ( new Parser . ParsingErrorText ( ) [ SmartFormat . Core . Parsing . Parser . ParsingError . MissingClosingBrace ] ) ) ;
429+ Assert . That ( parsingError ! . Issues , Has . Count . EqualTo ( 3 ) ) ;
430+ Assert . That ( parsingError . Issues [ 2 ] . Issue , Is . EqualTo ( new Parser . ParsingErrorText ( ) [ Parser . ParsingError . MissingClosingBrace ] ) ) ;
422431 } ) ;
423432 }
424433
@@ -536,8 +545,10 @@ public void Parse_Unicode(string formatString, string unicodeLiteral, int itemIn
536545 [ TestCase ( "{%C}" , '%' ) ]
537546 public void Selector_With_Custom_Selector_Character ( string formatString , char customChar )
538547 {
548+ // settings must be set before parser instantiation
539549 var settings = new SmartSettings ( ) ;
540- settings . Parser . AddCustomSelectorChars ( new [ ] { customChar } ) ;
550+ settings . Parser . AddCustomSelectorChars ( [ customChar ] ) ;
551+ var x = settings . Parser . GetSelectorChars ( ) ;
541552 var parser = GetRegularParser ( settings ) ;
542553 var result = parser . ParseFormat ( formatString ) ;
543554
@@ -546,7 +557,7 @@ public void Selector_With_Custom_Selector_Character(string formatString, char cu
546557 Assert . That ( placeholder ! . Selectors , Has . Count . EqualTo ( 1 ) ) ;
547558 Assert . Multiple ( ( ) =>
548559 {
549- Assert . That ( placeholder ! . Selectors , Has . Count . EqualTo ( placeholder ! . GetSelectors ( ) . Count ) ) ;
560+ Assert . That ( placeholder . Selectors , Has . Count . EqualTo ( placeholder . GetSelectors ( ) . Count ) ) ;
550561 Assert . That ( placeholder . Selectors [ 0 ] . ToString ( ) , Is . EqualTo ( formatString . Substring ( 1 , 2 ) ) ) ;
551562 } ) ;
552563 }
@@ -555,8 +566,10 @@ public void Selector_With_Custom_Selector_Character(string formatString, char cu
555566 [ TestCase ( "{a°b}" , '°' ) ]
556567 public void Selectors_With_Custom_Operator_Character ( string formatString , char customChar )
557568 {
558- var parser = GetRegularParser ( ) ;
559- parser . Settings . Parser . AddCustomOperatorChars ( new [ ] { customChar } ) ;
569+ // settings must be set before parser instantiation
570+ var settings = new SmartSettings ( ) ;
571+ settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
572+ var parser = GetRegularParser ( settings ) ;
560573 var result = parser . ParseFormat ( formatString ) ;
561574
562575 var placeholder = result . Items [ 0 ] as Placeholder ;
@@ -583,10 +596,12 @@ public void Selector_WorksWithAllUnicodeChars(string selector)
583596 {
584597 // See https://github.com/axuno/SmartFormat/issues/454
585598
599+ // settings must be set before parser instantiation
600+ var settings = new SmartSettings { Parser = { SelectorCharFilter = FilterType . Blocklist } } ;
586601 const string expected = "The Value" ;
587602 // The default formatter with default settings should be able to handle any
588603 // Unicode characters in selectors except the "magic" disallowed ones
589- var formatter = Smart . CreateDefaultSmartFormat ( ) ;
604+ var formatter = Smart . CreateDefaultSmartFormat ( settings ) ;
590605 // Use the Unicode string as a selector of the placeholder
591606 var template = $ "{{{selector}}}";
592607 var result = formatter . Format ( template , new Dictionary < string , string > { { selector , expected } } ) ;
@@ -647,10 +662,11 @@ public void Selector_With_Nullable_Operator_Character(string formatString)
647662 public void Selector_With_Other_Contiguous_Operator_Characters ( string formatString , char customChar )
648663 {
649664 // contiguous operator characters are parsed as "ONE operator string"
650-
651- var parser = GetRegularParser ( ) ;
665+ var settings = new SmartSettings ( ) ;
666+ settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
667+ var parser = GetRegularParser ( settings ) ;
652668 // adding '.' is ignored, as it's a standard operator
653- parser . Settings . Parser . AddCustomOperatorChars ( new [ ] { customChar } ) ;
669+ parser . Settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
654670 var result = parser . ParseFormat ( formatString ) ;
655671
656672 var placeholder = result . Items [ 0 ] as Placeholder ;
@@ -706,6 +722,12 @@ public void ParseInputAsHtml(string input)
706722 Assert . That ( literalText ! . RawText , Is . EqualTo ( input ) ) ;
707723 }
708724
725+ #region * Parse HTML input without ParserSetting 'IsHtml'
726+
727+ /// <summary>
728+ /// <see cref="ParserSettings.SelectorCharFilter"/> is <see cref="FilterType.Blocklist"/>:
729+ /// all characters are allowed in selectors
730+ /// </summary>
709731 [ TestCase ( "<script>{Placeholder}</script>" , "{Placeholder}" ) ]
710732 [ TestCase ( "<style>{Placeholder}</style>" , "{Placeholder}" ) ]
711733 [ TestCase ( "Something <style>h1 { color : #000; }</style>! nice" , "{ color : #000; }" ) ]
@@ -715,7 +737,12 @@ public void ParseHtmlInput_Without_ParserSetting_IsHtml(string input, string sel
715737 var parser = GetRegularParser ( new SmartSettings
716738 {
717739 StringFormatCompatibility = false ,
718- Parser = new ParserSettings { ErrorAction = ParseErrorAction . ThrowError , ParseInputAsHtml = false }
740+ Parser = new ParserSettings
741+ {
742+ SelectorCharFilter = FilterType . Blocklist ,
743+ ErrorAction = ParseErrorAction . ThrowError ,
744+ ParseInputAsHtml = false
745+ }
719746 } ) ;
720747
721748 var result = parser . ParseFormat ( input ) ;
@@ -724,9 +751,45 @@ public void ParseHtmlInput_Without_ParserSetting_IsHtml(string input, string sel
724751 Assert . That ( result . Items , Has . Count . EqualTo ( 3 ) ) ;
725752 Assert . That ( ( ( Placeholder ) result . Items [ 1 ] ) . RawText , Is . EqualTo ( selector ) ) ;
726753 } ) ;
754+ }
755+
756+ /// <summary>
757+ /// <see cref="ParserSettings.SelectorCharFilter"/> is <see cref="FilterType.Allowlist"/>:
758+ /// Predefined set of allowed characters in selectors
759+ /// </summary>
760+ [ TestCase ( "<script>{Placeholder}</script>" , false ) ] // should parse a placeholder
761+ [ TestCase ( "<style>{Placeholder}</style>" , false ) ] // should parse a placeholder
762+ [ TestCase ( "Something <style>h1 { color : #000; }</style>! nice" , true ) ] // illegal selector chars
763+ [ TestCase ( "Something <script>{const a = '</script>';}</script>! nice" , true ) ] // illegal selector chars
764+ public void ParseHtmlInput_Without_ParserSetting_IsHtml ( string input , bool shouldThrow )
765+ {
766+ var parser = GetRegularParser ( new SmartSettings
767+ {
768+ StringFormatCompatibility = false ,
769+ Parser = new ParserSettings
770+ {
771+ SelectorCharFilter = FilterType . Allowlist ,
772+ ErrorAction = ParseErrorAction . ThrowError ,
773+ ParseInputAsHtml = false
774+ }
775+ } ) ;
727776
777+ switch ( shouldThrow )
778+ {
779+ case true :
780+ Assert . That ( ( ) => _ = parser . ParseFormat ( input ) , Throws . TypeOf < ParsingErrors > ( ) ) ;
781+ break ;
782+ case false :
783+ {
784+ var result = parser . ParseFormat ( input ) ;
785+ Assert . That ( result . Items , Has . Count . EqualTo ( 3 ) ) ;
786+ break ;
787+ }
788+ }
728789 }
729790
791+ #endregion
792+
730793 /// <summary>
731794 /// SmartFormat is able to parse script tags, if <see cref="ParserSettings.ParseInputAsHtml"/> is <see langword="true"/>
732795 /// </summary>
0 commit comments