Skip to content

Commit 03384cc

Browse files
authored
Make liquid tag optional to improve parsing performance (#770)
1 parent a3b3e32 commit 03384cc

7 files changed

Lines changed: 294 additions & 97 deletions

File tree

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
<PackageVersion Include="Microsoft.Extensions.FileProviders.Abstractions" Version="$(MicrosoftExtensionsFileProvidersAbstractionsPackageVersion)" />
1212

1313
<!-- Only used with netstandard2.0 -->
14-
<PackageVersion Include="System.Text.Json" Version="$(SystemTextJsonPackageVersion)" />
14+
<PackageVersion Include="System.Text.Json" Version="9.0.3" />
1515
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
1616
<PackageVersion Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
1717

1818
<!-- Common to all TFMs -->
19-
<PackageVersion Include="Parlot" Version="1.3.3" />
19+
<PackageVersion Include="Parlot" Version="1.3.5" />
2020
<PackageVersion Include="TimeZoneConverter" Version="7.0.0" />
2121

2222
<!-- Benchmarks -->

Fluid.Tests/ParserTests.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,8 @@ public void ShouldParseLiquidTag()
987987
| upcase
988988
%}";
989989

990-
Assert.True(_parser.TryParse(source, out var template, out var errors), errors);
990+
var parser = new FluidParser(new FluidParserOptions { AllowLiquidTag = true });
991+
Assert.True(parser.TryParse(source, out var template, out var errors), errors);
991992
var rendered = template.Render();
992993
Assert.Contains("WELCOME TO THE LIQUID TAG", rendered);
993994
}
@@ -1003,7 +1004,8 @@ public void ShouldParseLiquidTagWithBlocks()
10031004
%}
10041005
";
10051006

1006-
Assert.True(_parser.TryParse(source, out var template, out var errors), errors);
1007+
var parser = new FluidParser(new FluidParserOptions { AllowLiquidTag = true });
1008+
Assert.True(parser.TryParse(source, out var template, out var errors), errors);
10071009
var rendered = template.Render();
10081010
Assert.Contains("WELCOME TO THE LIQUID TAG", rendered);
10091011
}
@@ -1091,11 +1093,11 @@ public void ShouldParseLiquidTagWithDifferentSpaces(string spaces)
10911093
{% liquid
10921094
for c in (1..3)
10931095
echo c
1094-
endforSPACE%}SPACE{{chars}}SPACE
1095-
""".Replace("SPACE", spaces);
1096+
endfor[SPACE]%}[SPACE]{{chars}}[SPACE]
1097+
""".Replace("[SPACE]", spaces);
10961098

1097-
var _parser = new FluidParser();
1098-
Assert.True(_parser.TryParse(source, out var template, out var errors), errors);
1099+
var parser = new FluidParser(new FluidParserOptions { AllowLiquidTag = true });
1100+
Assert.True(parser.TryParse(source, out var template, out var errors), errors);
10991101
var rendered = template.Render();
11001102
Assert.Contains("123", rendered);
11011103
}

Fluid/FluidParser.cs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,25 @@ public class FluidParser
5656
protected readonly Deferred<IReadOnlyList<Statement>> KnownTagsList = Deferred<IReadOnlyList<Statement>>();
5757
protected readonly Deferred<IReadOnlyList<Statement>> AnyTagsList = Deferred<IReadOnlyList<Statement>>();
5858

59-
protected static readonly Parser<TagResult> OutputStart = TagParsers.OutputTagStart();
60-
protected static readonly Parser<TagResult> OutputEnd = TagParsers.OutputTagEnd(true);
61-
protected static readonly Parser<TagResult> TagStart = TagParsers.TagStart();
62-
protected static readonly Parser<TagResult> TagStartSpaced = TagParsers.TagStart(true);
63-
protected static readonly Parser<TagResult> TagEnd = TagParsers.TagEnd(true);
59+
internal const string WhiteSpaceChars = "\t\n\v\f\r \u0085             \u2028\u2029   ";
60+
61+
protected static readonly Parser<TagResult> InlineOutputStart = TagParsers.OutputTagStart();
62+
protected static readonly Parser<TagResult> InlineOutputEnd = TagParsers.OutputTagEnd();
63+
protected static readonly Parser<TagResult> InlineTagStart = TagParsers.TagStart();
64+
protected static readonly Parser<TagResult> InlineTagEnd = TagParsers.TagEnd();
65+
66+
protected static readonly Parser<TagResult> NoInlineOutputStart = NonInlineLiquidTagParsers.OutputTagStart();
67+
protected static readonly Parser<TagResult> NoInlineOutputEnd = Literals.AnyOf(WhiteSpaceChars, minSize: 0).SkipAnd(NonInlineLiquidTagParsers.OutputTagEnd());
68+
protected static readonly Parser<TagResult> NoInlineTagStart = NonInlineLiquidTagParsers.TagStart();
69+
protected static readonly Parser<TagResult> NoInlineTagEnd = Literals.AnyOf(WhiteSpaceChars, minSize: 0).SkipAnd(NonInlineLiquidTagParsers.TagEnd());
70+
71+
protected readonly Parser<TagResult> OutputStart = InlineOutputStart;
72+
protected readonly Parser<TagResult> OutputEnd = InlineOutputEnd;
73+
protected readonly Parser<TagResult> TagStart = InlineTagStart;
74+
protected readonly Parser<TagResult> TagEnd = InlineTagEnd;
75+
76+
protected static readonly Parser<TagResult> RawOutputStart = NonInlineLiquidTagParsers.OutputTagStart();
77+
protected static readonly Parser<TagResult> RawTagStart = NonInlineLiquidTagParsers.TagStart();
6478

6579
protected static readonly LiteralExpression EmptyKeyword = new LiteralExpression(EmptyValue.Instance);
6680
protected static readonly LiteralExpression BlankKeyword = new LiteralExpression(BlankValue.Instance);
@@ -73,6 +87,14 @@ public FluidParser() : this(new())
7387

7488
public FluidParser(FluidParserOptions parserOptions)
7589
{
90+
if (!parserOptions.AllowLiquidTag)
91+
{
92+
OutputStart = NoInlineOutputStart;
93+
OutputEnd = NoInlineOutputEnd;
94+
TagStart = NoInlineTagStart;
95+
TagEnd = NoInlineTagEnd;
96+
}
97+
7698
String.Name = "String";
7799
Number.Name = "Number";
78100

@@ -574,7 +596,7 @@ public FluidParser(FluidParserOptions parserOptions)
574596
Grammar = KnownTagsList;
575597
}
576598

577-
public static Parser<string> CreateTag(string tagName) => TagStart.SkipAnd(Terms.Text(tagName)).AndSkip(TagEnd);
599+
public Parser<string> CreateTag(string tagName) => TagStart.SkipAnd(Terms.Text(tagName)).AndSkip(TagEnd);
578600

579601
public void RegisterIdentifierTag(string tagName, Func<string, TextWriter, TextEncoder, TemplateContext, ValueTask<Completion>> render)
580602
{

Fluid/FluidParserOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,10 @@ public class FluidParserOptions
1414
/// Gets whether parentheses are allowed in templates. Default is <c>false</c>.
1515
/// </summary>
1616
public bool AllowParentheses { get; set; }
17+
18+
/// <summary>
19+
/// Gets whether the inline liquid tag is allowed in templates. Default is <c>false</c>.
20+
/// </summary>
21+
public bool AllowLiquidTag { get; set; }
1722
}
1823
}

0 commit comments

Comments
 (0)