diff --git a/source/Handlebars.Test/IssueTests.cs b/source/Handlebars.Test/IssueTests.cs index 5e41a2fd..001526db 100644 --- a/source/Handlebars.Test/IssueTests.cs +++ b/source/Handlebars.Test/IssueTests.cs @@ -734,6 +734,23 @@ public void UnrecognisedExpressionThrowsOutOfMemoryException() Assert.Throws(()=> Handlebars.Compile(source)); } + // Issue: https://github.com/Handlebars-Net/Handlebars.Net/issues/519 + [Fact] + public void Issue519_PartialBlockUsableAsBlockAndInIf() + { + var handlebars = Handlebars.Create(); + handlebars.RegisterTemplate("myPartial", + @"Conditional:{{#if @partial-block}} {{> @partial-block}}{{/if}} +Plain: {{> @partial-block}} +Block:{{#> @partial-block }}{{/@partial-block}}"); + + var render = handlebars.Compile("{{#> myPartial}}Block content{{/myPartial}}"); + var actual = render(new { }); + Assert.Contains("Conditional: Block content", actual); + Assert.Contains("Plain: Block content", actual); + Assert.Contains("Block:Block content", actual); + } + // Issue: https://github.com/Handlebars-Net/Handlebars.Net/issues/458 // System.NotImplementedException: byref delegate on Xamarin.iOS / Mono // The Mono runtime does not support delegates with byref (in/ref) parameters. diff --git a/source/Handlebars/BindingContext.cs b/source/Handlebars/BindingContext.cs index 2f1e6c24..19e36731 100644 --- a/source/Handlebars/BindingContext.cs +++ b/source/Handlebars/BindingContext.cs @@ -156,7 +156,20 @@ internal bool TryGetContextVariable(ChainSegment segment, out object value) return BlockParamsObject.TryGetValue(segment, out value) || ContextDataObject.TryGetValue(wellKnownVariable, out value); } - + + // Special handling for @partial-block: return the PartialBlockTemplate delegate + // so that {{#if @partial-block}} is truthy when a block partial is provided. + if (segment.LowerInvariant == "partial-block") + { + if (PartialBlockTemplate != null) + { + value = PartialBlockTemplate; + return true; + } + value = UndefinedBindingResult.Create(segment.TrimmedValue); + return false; + } + return BlockParamsObject.TryGetValue(segment, out value) || ContextDataObject.TryGetValue(segment, out value); } diff --git a/source/Handlebars/Compiler/Lexer/Converter/BlockAccumulators/PartialBlockAccumulatorContext.cs b/source/Handlebars/Compiler/Lexer/Converter/BlockAccumulators/PartialBlockAccumulatorContext.cs index d0f92a3c..e422d7f8 100644 --- a/source/Handlebars/Compiler/Lexer/Converter/BlockAccumulators/PartialBlockAccumulatorContext.cs +++ b/source/Handlebars/Compiler/Lexer/Converter/BlockAccumulators/PartialBlockAccumulatorContext.cs @@ -24,10 +24,16 @@ public override void HandleElement(Expression item) public override Expression GetAccumulatedBlock() { + Expression fallback = _body.Count == 0 + ? null + : _body.Count == 1 + ? _body.First() + : Expression.Block(_body); + return HandlebarsExpression.Partial( _startingNode.PartialName, _startingNode.Argument, - _body.Count > 1 ? Expression.Block(_body) : _body.First()); + fallback); } public override bool IsClosingElement(Expression item)