Working on IntrinsicHtml and nested render closures.
This commit is contained in:
parent
6ee903bde0
commit
5b1a1bcdec
4
web-views/sketching/echoElement.wvc
Normal file
4
web-views/sketching/echoElement.wvc
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
import groowt.view.web.lib.Echo
|
||||
---
|
||||
<Echo greeting="Hello!"><p>${context}</p></Echo>
|
@ -56,24 +56,23 @@ class IntrinsicHtml extends DelegatingWebViewComponent implements WithHtml {
|
||||
if (this.isVoidElement && this.hasChildren()) {
|
||||
throw new ComponentRenderException('A void html element cannot have children.')
|
||||
}
|
||||
return {
|
||||
it << '<'
|
||||
it << this.name
|
||||
return { writer ->
|
||||
writer << '<'
|
||||
writer << this.name
|
||||
if (!this.attr.isEmpty()) {
|
||||
it << ' '
|
||||
this.formatAttr(it)
|
||||
writer << ' '
|
||||
this.formatAttr(writer)
|
||||
}
|
||||
it << '>'
|
||||
writer << '>'
|
||||
if (this.hasChildren()) {
|
||||
this.children.each {
|
||||
def renderer = it.getRenderer(this)
|
||||
renderer.call(it.child)
|
||||
it.renderTo(writer, this)
|
||||
}
|
||||
}
|
||||
if (!this.isVoidElement) {
|
||||
it << '</'
|
||||
it << this.name
|
||||
it << '>'
|
||||
writer << '</'
|
||||
writer << this.name
|
||||
writer << '>'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,21 +4,28 @@ import groovy.lang.Closure;
|
||||
import groowt.view.component.ComponentTemplate;
|
||||
import groowt.view.component.ViewComponent;
|
||||
import groowt.view.component.runtime.ComponentWriter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import groowt.view.component.runtime.DefaultComponentWriter;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.io.Writer;
|
||||
|
||||
public class WebViewComponentChild {
|
||||
|
||||
private static final class ChildRenderClosure extends Closure<Void> {
|
||||
|
||||
private final ViewComponent parent;
|
||||
private final @Nullable Object child;
|
||||
private final Object child;
|
||||
private final ComponentWriter writer;
|
||||
|
||||
public ChildRenderClosure(ComponentTemplate template, ViewComponent parent, @Nullable Object child) {
|
||||
public ChildRenderClosure(
|
||||
ComponentTemplate template,
|
||||
ViewComponent parent,
|
||||
ComponentWriter writer,
|
||||
Object child
|
||||
) {
|
||||
super(template, template);
|
||||
this.parent = parent;
|
||||
this.child = child;
|
||||
this.writer = writer;
|
||||
this.setDelegate(this.parent);
|
||||
this.setResolveStrategy(Closure.DELEGATE_FIRST);
|
||||
}
|
||||
@ -27,23 +34,19 @@ public class WebViewComponentChild {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
public void doCall(ComponentWriter writer) {
|
||||
writer.append(Objects.requireNonNull(this.child));
|
||||
}
|
||||
|
||||
public void doCall(ComponentWriter writer, Object givenChild) {
|
||||
writer.append(givenChild);
|
||||
public void doCall() {
|
||||
this.writer.append(this.child);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final ComponentTemplate template;
|
||||
private final ComponentWriter out;
|
||||
private final ComponentWriter componentWriter;
|
||||
private final Object child;
|
||||
|
||||
public WebViewComponentChild(ComponentTemplate template, ComponentWriter out, Object child) {
|
||||
public WebViewComponentChild(ComponentTemplate template, ComponentWriter componentWriter, Object child) {
|
||||
this.template = template;
|
||||
this.out = out;
|
||||
this.componentWriter = componentWriter;
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
@ -52,13 +55,14 @@ public class WebViewComponentChild {
|
||||
}
|
||||
|
||||
public void render(ViewComponent parent) {
|
||||
final var cl = this.getRenderer(parent);
|
||||
cl.call(this.child);
|
||||
new ChildRenderClosure(this.template, parent, this.componentWriter, this.child).call();
|
||||
}
|
||||
|
||||
public Closure<Void> getRenderer(ViewComponent parent) {
|
||||
final var cl = new ChildRenderClosure(this.template, parent, null);
|
||||
return cl.curry(this.out);
|
||||
public Writer renderTo(Writer out, ViewComponent parent) {
|
||||
final var componentWriter = new DefaultComponentWriter(out);
|
||||
final var childRenderClosure = new ChildRenderClosure(this.template, parent, componentWriter, this.child);
|
||||
childRenderClosure.call();
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package groowt.view.web.transpile.resolve;
|
||||
|
||||
import groowt.view.web.WebViewComponentBugError;
|
||||
import groowt.view.web.compiler.WebViewComponentTemplateCompileUnit;
|
||||
import groowt.view.web.util.Either;
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
@ -30,10 +29,12 @@ public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassN
|
||||
|
||||
// try pre-pending package and asking for fqn
|
||||
final var packageName = this.moduleNode.getPackageName();
|
||||
final String fqn;
|
||||
if (packageName.endsWith(".")) {
|
||||
throw new WebViewComponentBugError(new IllegalStateException("Package name illegally ends with '.'"));
|
||||
fqn = this.moduleNode + nameWithoutPackage;
|
||||
} else {
|
||||
fqn = this.moduleNode.getPackageName() + "." + nameWithoutPackage;
|
||||
}
|
||||
final var fqn = this.moduleNode.getPackageName() + "." + nameWithoutPackage;
|
||||
final var withPackage = this.getClassForFqn(fqn);
|
||||
if (withPackage.isRight()) {
|
||||
return withPackage;
|
||||
|
@ -22,8 +22,8 @@ class IntrinsicHtmlTests extends AbstractWebViewComponentTests {
|
||||
|
||||
@Test
|
||||
@Disabled('Until we figure out nested closure delegates')
|
||||
void canUseEchoAttrProperty() {
|
||||
this.doTest('<Echo greeting="Hello!"><p>$greeting</p></Echo>', '<p>Hello!</p>')
|
||||
void canUseEchoAttrPropertyViaContext() {
|
||||
this.doTest('<Echo greeting="Hello!"><p>${context}</p></Echo>', '<p>Hello!</p>')
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user