@@ -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
@@ -459,6 +468,18 @@ public void Escaping_TheEscapingCharacter_ShouldWork()
459468 Assert . That ( result , Is . EqualTo ( @"\\aaa\{}bbb ccc\x{}ddd\\" ) ) ;
460469 }
461470
471+ [ Test ]
472+ public void Parsing_Selector_With_CharFromBlocklist_ShouldThrow ( )
473+ {
474+ var settings = new SmartSettings { Parser = new ParserSettings { SelectorCharFilter = FilterType . Blocklist } } ;
475+ var parser = GetRegularParser ( settings ) ;
476+
477+ // The newline character is in the default blocklist of disallowed characters
478+ Assert . That ( ( ) => parser . ParseFormat ( "{A\n B}" ) ,
479+ Throws . Exception . InstanceOf < ParsingErrors > ( ) . And . Message
480+ . Contains ( new Parser . ParsingErrorText ( ) [ Parser . ParsingError . InvalidCharactersInSelector ] ) ) ;
481+ }
482+
462483 [ Test ]
463484 public void StringFormat_Escaping_In_Literal ( )
464485 {
@@ -536,8 +557,10 @@ public void Parse_Unicode(string formatString, string unicodeLiteral, int itemIn
536557 [ TestCase ( "{%C}" , '%' ) ]
537558 public void Selector_With_Custom_Selector_Character ( string formatString , char customChar )
538559 {
560+ // settings must be set before parser instantiation
539561 var settings = new SmartSettings ( ) ;
540- settings . Parser . AddCustomSelectorChars ( new [ ] { customChar } ) ;
562+ settings . Parser . AddCustomSelectorChars ( [ customChar ] ) ;
563+ var x = settings . Parser . GetSelectorChars ( ) ;
541564 var parser = GetRegularParser ( settings ) ;
542565 var result = parser . ParseFormat ( formatString ) ;
543566
@@ -546,7 +569,7 @@ public void Selector_With_Custom_Selector_Character(string formatString, char cu
546569 Assert . That ( placeholder ! . Selectors , Has . Count . EqualTo ( 1 ) ) ;
547570 Assert . Multiple ( ( ) =>
548571 {
549- Assert . That ( placeholder ! . Selectors , Has . Count . EqualTo ( placeholder ! . GetSelectors ( ) . Count ) ) ;
572+ Assert . That ( placeholder . Selectors , Has . Count . EqualTo ( placeholder . GetSelectors ( ) . Count ) ) ;
550573 Assert . That ( placeholder . Selectors [ 0 ] . ToString ( ) , Is . EqualTo ( formatString . Substring ( 1 , 2 ) ) ) ;
551574 } ) ;
552575 }
@@ -555,8 +578,10 @@ public void Selector_With_Custom_Selector_Character(string formatString, char cu
555578 [ TestCase ( "{a°b}" , '°' ) ]
556579 public void Selectors_With_Custom_Operator_Character ( string formatString , char customChar )
557580 {
558- var parser = GetRegularParser ( ) ;
559- parser . Settings . Parser . AddCustomOperatorChars ( new [ ] { customChar } ) ;
581+ // settings must be set before parser instantiation
582+ var settings = new SmartSettings ( ) ;
583+ settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
584+ var parser = GetRegularParser ( settings ) ;
560585 var result = parser . ParseFormat ( formatString ) ;
561586
562587 var placeholder = result . Items [ 0 ] as Placeholder ;
@@ -583,10 +608,12 @@ public void Selector_WorksWithAllUnicodeChars(string selector)
583608 {
584609 // See https://github.com/axuno/SmartFormat/issues/454
585610
611+ // settings must be set before parser instantiation
612+ var settings = new SmartSettings { Parser = { SelectorCharFilter = FilterType . Blocklist } } ;
586613 const string expected = "The Value" ;
587614 // The default formatter with default settings should be able to handle any
588615 // Unicode characters in selectors except the "magic" disallowed ones
589- var formatter = Smart . CreateDefaultSmartFormat ( ) ;
616+ var formatter = Smart . CreateDefaultSmartFormat ( settings ) ;
590617 // Use the Unicode string as a selector of the placeholder
591618 var template = $ "{{{selector}}}";
592619 var result = formatter . Format ( template , new Dictionary < string , string > { { selector , expected } } ) ;
@@ -647,10 +674,11 @@ public void Selector_With_Nullable_Operator_Character(string formatString)
647674 public void Selector_With_Other_Contiguous_Operator_Characters ( string formatString , char customChar )
648675 {
649676 // contiguous operator characters are parsed as "ONE operator string"
650-
651- var parser = GetRegularParser ( ) ;
677+ var settings = new SmartSettings ( ) ;
678+ settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
679+ var parser = GetRegularParser ( settings ) ;
652680 // adding '.' is ignored, as it's a standard operator
653- parser . Settings . Parser . AddCustomOperatorChars ( new [ ] { customChar } ) ;
681+ parser . Settings . Parser . AddCustomOperatorChars ( [ customChar ] ) ;
654682 var result = parser . ParseFormat ( formatString ) ;
655683
656684 var placeholder = result . Items [ 0 ] as Placeholder ;
@@ -706,6 +734,12 @@ public void ParseInputAsHtml(string input)
706734 Assert . That ( literalText ! . RawText , Is . EqualTo ( input ) ) ;
707735 }
708736
737+ #region * Parse HTML input without ParserSetting 'IsHtml'
738+
739+ /// <summary>
740+ /// <see cref="ParserSettings.SelectorCharFilter"/> is <see cref="FilterType.Blocklist"/>:
741+ /// all characters are allowed in selectors
742+ /// </summary>
709743 [ TestCase ( "<script>{Placeholder}</script>" , "{Placeholder}" ) ]
710744 [ TestCase ( "<style>{Placeholder}</style>" , "{Placeholder}" ) ]
711745 [ TestCase ( "Something <style>h1 { color : #000; }</style>! nice" , "{ color : #000; }" ) ]
@@ -715,7 +749,12 @@ public void ParseHtmlInput_Without_ParserSetting_IsHtml(string input, string sel
715749 var parser = GetRegularParser ( new SmartSettings
716750 {
717751 StringFormatCompatibility = false ,
718- Parser = new ParserSettings { ErrorAction = ParseErrorAction . ThrowError , ParseInputAsHtml = false }
752+ Parser = new ParserSettings
753+ {
754+ SelectorCharFilter = FilterType . Blocklist ,
755+ ErrorAction = ParseErrorAction . ThrowError ,
756+ ParseInputAsHtml = false
757+ }
719758 } ) ;
720759
721760 var result = parser . ParseFormat ( input ) ;
@@ -724,9 +763,45 @@ public void ParseHtmlInput_Without_ParserSetting_IsHtml(string input, string sel
724763 Assert . That ( result . Items , Has . Count . EqualTo ( 3 ) ) ;
725764 Assert . That ( ( ( Placeholder ) result . Items [ 1 ] ) . RawText , Is . EqualTo ( selector ) ) ;
726765 } ) ;
766+ }
727767
768+ /// <summary>
769+ /// <see cref="ParserSettings.SelectorCharFilter"/> is <see cref="FilterType.Allowlist"/>:
770+ /// Predefined set of allowed characters in selectors
771+ /// </summary>
772+ [ TestCase ( "<script>{Placeholder}</script>" , false ) ] // should parse a placeholder
773+ [ TestCase ( "<style>{Placeholder}</style>" , false ) ] // should parse a placeholder
774+ [ TestCase ( "Something <style>h1 { color : #000; }</style>! nice" , true ) ] // illegal selector chars
775+ [ TestCase ( "Something <script>{const a = '</script>';}</script>! nice" , true ) ] // illegal selector chars
776+ public void ParseHtmlInput_Without_ParserSetting_IsHtml ( string input , bool shouldThrow )
777+ {
778+ var parser = GetRegularParser ( new SmartSettings
779+ {
780+ StringFormatCompatibility = false ,
781+ Parser = new ParserSettings
782+ {
783+ SelectorCharFilter = FilterType . Allowlist ,
784+ ErrorAction = ParseErrorAction . ThrowError ,
785+ ParseInputAsHtml = false
786+ }
787+ } ) ;
788+
789+ switch ( shouldThrow )
790+ {
791+ case true :
792+ Assert . That ( ( ) => _ = parser . ParseFormat ( input ) , Throws . TypeOf < ParsingErrors > ( ) ) ;
793+ break ;
794+ case false :
795+ {
796+ var result = parser . ParseFormat ( input ) ;
797+ Assert . That ( result . Items , Has . Count . EqualTo ( 3 ) ) ;
798+ break ;
799+ }
800+ }
728801 }
729802
803+ #endregion
804+
730805 /// <summary>
731806 /// SmartFormat is able to parse script tags, if <see cref="ParserSettings.ParseInputAsHtml"/> is <see langword="true"/>
732807 /// </summary>
0 commit comments