-
-
Notifications
You must be signed in to change notification settings - Fork 388
Render blocks in the parent context and assure a block is passed to templates that use @partial-block #620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7fe1f93
0b057c3
e41b907
91da4d3
cff998b
50e7eb8
0155376
90d11bf
94f37c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| import java.io.FileNotFoundException; | ||
| import java.io.IOException; | ||
| import java.io.Writer; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.LinkedList; | ||
|
|
@@ -120,10 +121,31 @@ protected void merge(final Context context, final Writer writer) | |
| /** Inline partial? */ | ||
| LinkedList<Map<String, Template>> partials = context.data(Context.INLINE_PARTIALS); | ||
| Map<String, Template> inlineTemplates = partials.getLast(); | ||
| Template callee = context.data(Context.CALLEE); | ||
|
|
||
| final boolean pathIsPartialBlock = "@partial-block".equals(path); | ||
| final Template lastPartialBlock = inlineTemplates.get("@partial-block"); | ||
| final boolean parentIsNotLastPartialBlock = !isCalleeOf(callee, lastPartialBlock); | ||
|
|
||
| if (pathIsPartialBlock && parentIsNotLastPartialBlock) { | ||
| throw new IllegalArgumentException( | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already merged it, but I'm struggling to figure out why we do fail here, can you explain? Here is a test case that fails today bc of this check: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi and thanks for the merge! We'll get back to you about this asap. |
||
| callee + " does not provide a @partial-block for " + this | ||
| ); | ||
| } | ||
|
|
||
| if (this.partial != null) { | ||
| this.partial.apply(context); | ||
| inlineTemplates.put("@partial-block", this.partial); | ||
| if (!handlebars.lazyPartialBlockEvaluation()) { | ||
| this.partial.apply(context); | ||
| } | ||
|
|
||
| inlineTemplates.put("@partial-block", | ||
| new PartialBlockForwardingTemplate(this, | ||
| this.partial, | ||
| inlineTemplates.get("@partial-block"), | ||
| callee, | ||
| handlebars | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| Template template = inlineTemplates.get(path); | ||
|
|
@@ -171,8 +193,10 @@ protected void merge(final Context context, final Writer writer) | |
| } | ||
|
|
||
| } | ||
| context.data(Context.CALLEE, this); | ||
| Context ctx = Context.newPartialContext(context, this.scontext, hash(context)); | ||
| template.apply(ctx, writer); | ||
| context.data(Context.CALLEE, callee); | ||
| } catch (IOException ex) { | ||
| String reason = String.format("The partial '%s' at '%s' could not be found", | ||
| loader.resolve(path.text()), ex.getMessage()); | ||
|
|
@@ -183,6 +207,23 @@ protected void merge(final Context context, final Writer writer) | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * @param callee parent template of the currently traversed template | ||
| * @param partialBlock partial block candidate | ||
| * @return returns if callee and partialBlock are the same | ||
| */ | ||
| private boolean isCalleeOf(final Template callee, final Template partialBlock) { | ||
| if (callee == null || partialBlock == null) { | ||
| return false; | ||
| } | ||
|
|
||
| if (!callee.filename().equalsIgnoreCase(partialBlock.filename())) { | ||
| return false; | ||
| } | ||
|
|
||
| return Arrays.equals(callee.position(), partialBlock.position()); | ||
| } | ||
|
|
||
| /** | ||
| * True, if the file was already processed. | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| /** | ||
| * Copyright (c) 2012-2015 Edgar Espina | ||
| * | ||
| * This file is part of Handlebars.java. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package com.github.jknack.handlebars.internal; | ||
|
|
||
| import com.github.jknack.handlebars.Context; | ||
| import com.github.jknack.handlebars.Handlebars; | ||
| import com.github.jknack.handlebars.Template; | ||
|
|
||
| import java.io.IOException; | ||
| import java.io.Writer; | ||
| import java.util.LinkedList; | ||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * | ||
| */ | ||
| public class PartialBlockForwardingTemplate extends BaseTemplate { | ||
| /** | ||
| * The block to be passed as partial-block. | ||
| */ | ||
| private final Template block; | ||
|
|
||
| /** | ||
| * The previous partial-block definition of the template which contains this partial. | ||
| */ | ||
| private final Template parentPartialBlock; | ||
|
|
||
| /** | ||
| * The callee of the parent partial. | ||
| */ | ||
| private final Template callee; | ||
|
|
||
| /** | ||
| * Constructs a PartialBlockForwardingTemplate. | ||
| * | ||
| * @param parent the parent partial | ||
| * @param block the block to be passed as partial-block. | ||
| * @param parentPartialBlock the previous partial-block definition of | ||
| * the template which contains this partial. | ||
| * @param callee the template that renders the parent | ||
| * @param handlebars handlebars | ||
| */ | ||
| public PartialBlockForwardingTemplate( | ||
| final Template parent, | ||
| final Template block, | ||
| final Template parentPartialBlock, | ||
| final Template callee, | ||
| final Handlebars handlebars | ||
| ) { | ||
| super(handlebars); | ||
| this.block = block; | ||
| this.parentPartialBlock = parentPartialBlock; | ||
| this.callee = callee; | ||
| this.filename(block.filename()); | ||
| this.position(parent.position()[0], parent.position()[1]); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| protected void merge(final Context context, final Writer writer) throws IOException { | ||
| LinkedList<Map<String, Template>> partials = context.data(Context.INLINE_PARTIALS); | ||
| Map<String, Template> inlineTemplates = partials.getLast(); | ||
| Template oldPartialBlock = inlineTemplates.get("@partial-block"); | ||
| Template oldCallee = context.data(Context.CALLEE); | ||
|
|
||
| context.data(Context.CALLEE, callee); | ||
| inlineTemplates.put("@partial-block", parentPartialBlock); | ||
| block.apply(context, writer); | ||
| inlineTemplates.put("@partial-block", oldPartialBlock); | ||
| context.data(Context.CALLEE, oldCallee); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public String text() { | ||
| return block.text(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.github.jknack.handlebars; | ||
|
|
||
| import org.junit.Test; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| import static junit.framework.TestCase.assertEquals; | ||
|
|
||
| public class LazyPartialBlockEvaluationTest extends AbstractTest { | ||
| @Override | ||
| protected void configure(Handlebars handlebars) { | ||
| handlebars.setLazyPartialBlockEvaluation(true); | ||
| } | ||
|
|
||
| @Test | ||
| public void shouldSupportMultipleLevelsOfNestedPartialBlocks() throws IOException { | ||
| String myMoreNestedPartial = "I{{> @partial-block}}I"; | ||
| String myNestedPartial = "A{{#> myMoreNestedPartial}}{{> @partial-block}}{{/myMoreNestedPartial}}B"; | ||
| String myPartial = "{{#> myNestedPartial}}{{> @partial-block}}{{/myNestedPartial}}"; | ||
| Template t = compile("C{{#> myPartial}}hello{{/myPartial}}D", new Hash(), $("myPartial", myPartial, "myNestedPartial", myNestedPartial,"myMoreNestedPartial", myMoreNestedPartial)); | ||
| String result = t.apply(null); | ||
| assertEquals("'CAIhelloIBD' should === '" + result + "': ", "CAIhelloIBD", result); | ||
| } | ||
|
|
||
| @Test(expected = HandlebarsException.class) | ||
| public void shouldNotDefineInlinePartialsInPartialBlockCall() throws IOException { | ||
| // myPartial should not be defined and thus throw a handlebars exception | ||
| shouldCompileToWithPartials( | ||
| "{{#> dude}}{{#*inline \"myPartial\"}}success{{/inline}}{{/dude}}", | ||
| $, $("dude", "{{> myPartial }}"), ""); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add two examples when this flag is on/off
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey I added two tests that deal with this pull request's changes. Is everything okay now?