diff --git a/Fluid.Tests/ParserTests.cs b/Fluid.Tests/ParserTests.cs index 14fce83c..92da3372 100644 --- a/Fluid.Tests/ParserTests.cs +++ b/Fluid.Tests/ParserTests.cs @@ -165,6 +165,26 @@ public void ShouldParseRawWithBlocks() Assert.Equal(" {%if true%} {%endif%} ", (statements.ElementAt(0) as RawStatement).Text.ToString()); } + [Fact] + public void ShouldParseEmptyRawTags() + { + var statements = Parse(@"{% raw %}{% endraw %}"); + + Assert.Single(statements); + Assert.IsType(statements.ElementAt(0)); + Assert.Equal("", (statements.ElementAt(0) as RawStatement).Text.ToString()); + } + + [Fact] + public void ShouldParseEmptyCommentTags() + { + var statements = Parse(@"{% comment %}{% endcomment %}"); + + Assert.Single(statements); + Assert.IsType(statements.ElementAt(0)); + Assert.Equal("", (statements.ElementAt(0) as CommentStatement).Text.ToString()); + } + [Fact] public void ShouldParseComment() { diff --git a/Fluid/FluidParser.cs b/Fluid/FluidParser.cs index be6d56d0..11f57ea5 100644 --- a/Fluid/FluidParser.cs +++ b/Fluid/FluidParser.cs @@ -250,20 +250,20 @@ public FluidParser(FluidParserOptions parserOptions) var BreakTag = TagEnd.Then(x => new BreakStatement()).ElseError("Invalid 'break' tag"); var ContinueTag = TagEnd.Then(x => new ContinueStatement()).ElseError("Invalid 'continue' tag"); var CommentTag = TagEnd - .SkipAnd(AnyCharBefore(CreateTag("endcomment"))) + .SkipAnd(AnyCharBefore(CreateTag("endcomment"), canBeEmpty: true)) .AndSkip(CreateTag("endcomment").ElseError($"'{{% endcomment %}}' was expected")) .Then(x => new CommentStatement(x)) .ElseError("Invalid 'comment' tag") ; - var CaptureTag = Identifier + var CaptureTag = Identifier.ElseError(string.Format(ErrorMessages.IdentifierAfterTag, "capture")) .AndSkip(TagEnd) .And(AnyTagsList) .AndSkip(CreateTag("endcapture").ElseError($"'{{% endcapture %}}' was expected")) .Then(x => new CaptureStatement(x.Item1, x.Item2)) .ElseError("Invalid 'capture' tag") ; - var MacroTag = Identifier.ElseError(ErrorMessages.IdentifierAfterMacro) - .AndSkip(LParen).ElseError(ErrorMessages.IdentifierAfterMacro) + var MacroTag = Identifier.ElseError(string.Format(ErrorMessages.IdentifierAfterTag, "macro")) + .AndSkip(LParen).ElseError(string.Format(ErrorMessages.IdentifierAfterTag, "macro")) .And(FunctionDefinitionArgumentsList) .AndSkip(RParen) .AndSkip(TagEnd) @@ -309,7 +309,7 @@ public FluidParser(FluidParserOptions parserOptions) .ElseError("Invalid 'render' tag") ; - var RawTag = TagEnd.SkipAnd(AnyCharBefore(CreateTag("endraw"), consumeDelimiter: true, failOnEof: true).Then(x => new RawStatement(x))).ElseError("Not end tag found for {% raw %}"); + var RawTag = TagEnd.SkipAnd(AnyCharBefore(CreateTag("endraw"), canBeEmpty: true, consumeDelimiter: true, failOnEof: true).Then(x => new RawStatement(x))).ElseError("Not end tag found for {% raw %}"); var AssignTag = Identifier.Then(x => x).ElseError(ErrorMessages.IdentifierAfterAssign).AndSkip(Equal.ElseError(ErrorMessages.EqualAfterAssignIdentifier)).And(FilterExpression).AndSkip(TagEnd.ElseError(ErrorMessages.ExpectedTagEnd)).Then(x => new AssignStatement(x.Item1, x.Item2)); var IfTag = LogicalExpression .AndSkip(TagEnd) diff --git a/Fluid/Parser/ErrorMessages.cs b/Fluid/Parser/ErrorMessages.cs index 52a0ebc2..597f37d9 100644 --- a/Fluid/Parser/ErrorMessages.cs +++ b/Fluid/Parser/ErrorMessages.cs @@ -1,4 +1,6 @@ -namespace Fluid.Parser +using System; + +namespace Fluid.Parser { public static class ErrorMessages { @@ -11,7 +13,8 @@ public static class ErrorMessages public const string ExpectedOutputEnd = "End of tag '}}' was expected"; public const string ExpectedStringRender = "A quoted string value is required for the render tag"; public const string FunctionsNotAllowed = "Functions are not allowed"; - public const string IdentifierAfterMacro = "An identifier was expected after the 'macro' tag"; + [Obsolete] public const string IdentifierAfterMacro = "An identifier was expected after the 'macro' tag"; + public const string IdentifierAfterTag = "An identifier was expected after the '{0}' tag"; public const string ParentesesAfterFunctionName = "Start of arguments '(' is expected after a function name"; } }