diff --git a/docs/src/main/asciidoc/qute-reference.adoc b/docs/src/main/asciidoc/qute-reference.adoc index 042bd403989e9..6f0f1787cf274 100644 --- a/docs/src/main/asciidoc/qute-reference.adoc +++ b/docs/src/main/asciidoc/qute-reference.adoc @@ -348,7 +348,7 @@ NOTE: The current context can be accessed via the implicit binding `this`. |Elvis Operator |Outputs the default value if the previous part cannot be resolved or resolves to `null`. -|`{person.name ?: 'John'}`, `{person.name or 'John'}` +|`{person.name ?: 'John'}`, `{person.name or 'John'}`, `{person.name.or('John')}` |orEmpty |Outputs an empty list if the previous part cannot be resolved or resolves to `null`. @@ -370,7 +370,7 @@ NOTE: The current context can be accessed via the implicit binding `this`. TIP: The condition in a ternary operator evaluates to `true` if the value is not considered `falsy` as described in the <>. -NOTE: In fact, the operators are implemented as "virtual methods" that consume one parameter and can be used with infix notation, i.e. `{person.name or 'John'}` is translated to `{person.name.or('John')}`. +NOTE: In fact, the operators are implemented as "virtual methods" that consume one parameter and can be used with infix notation. For example `{person.name or 'John'}` is translated to `{person.name.or('John')}` and `{item.isActive ? item.name : 'Inactive item'}` is translated to `{item.isActive.ifTruthy(item.name).or('Inactive item')}` ==== Arrays @@ -780,10 +780,13 @@ This section might also come in handy when we'd like to avoid multiple expensive This section allows you to define named local variables: [source,html] ---- -{#let myParent=order.item.parent} +{#let myParent=order.item.parent isActive=false age=10} <1>

{myParent.name}

+ Is active: {isActive} + Age: {age} {/let} ---- +<1> The local variable is initialized with an expression that can also represent a <>. The section tag is also registered under the `set` alias: diff --git a/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java index 1b642f5e56063..6e45aadcc309e 100644 --- a/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java +++ b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java @@ -1100,7 +1100,7 @@ TemplateVariantsBuildItem collectTemplateVariants(List te @BuildStep void excludeTypeChecks(QuteConfig config, BuildProducer excludes) { // Exclude all checks that involve built-in value resolvers - List skipOperators = Arrays.asList("?:", "or", ":", "?", "&&", "||"); + List skipOperators = Arrays.asList("?:", "or", ":", "?", "ifTruthy", "&&", "||"); excludes.produce(new TypeCheckExcludeBuildItem(new Predicate() { @Override public boolean test(TypeCheck check) { diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/ValueResolvers.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/ValueResolvers.java index dc8c643c83164..fefd93a678e6f 100644 --- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/ValueResolvers.java +++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/ValueResolvers.java @@ -79,7 +79,7 @@ public CompletionStage resolve(EvalContext context) { } /** - * Returns the default value if the base object is null or {@link Result#NOT_FOUND}. + * Returns the default value if the base object is null or {@link Result#NOT_FOUND} and the base object otherwise. * * {@code foo.or(bar)}, {@code foo or true}, {@code name ?: 'elvis'} */ @@ -133,6 +133,8 @@ public CompletionStage resolve(EvalContext context) { } /** + * Returns {@link Result#NOT_FOUND} if the base object is falsy and the base object otherwise. + *

* Can be used together with {@link #orResolver()} to form a ternary operator. * * {@code person.isElvis ? 'elvis' : notElvis} @@ -141,8 +143,16 @@ public static ValueResolver trueResolver() { return new ValueResolver() { public boolean appliesTo(EvalContext context) { - return context.getParams().size() == 1 - && ("?".equals(context.getName())); + if (context.getParams().size() != 1) { + return false; + } + switch (context.getName()) { + case "?": + case "ifTruthy": + return true; + default: + return false; + } } @Override diff --git a/independent-projects/qute/core/src/test/java/io/quarkus/qute/SetSectionTest.java b/independent-projects/qute/core/src/test/java/io/quarkus/qute/SetSectionTest.java index 24f6519ee8d1d..960b061f9088d 100644 --- a/independent-projects/qute/core/src/test/java/io/quarkus/qute/SetSectionTest.java +++ b/independent-projects/qute/core/src/test/java/io/quarkus/qute/SetSectionTest.java @@ -20,4 +20,15 @@ public void testLet() { engine.parse("{foo}:{baz} - {#let foo=true bar='mix'}{foo}:{bar}:{baz}{/}").data("baz", "what?!").render()); } + @Test + public void testLiterals() { + Engine engine = Engine.builder().addDefaults().addValueResolver(new ReflectionValueResolver()).build(); + assertEquals("1::4::Andy::false", + engine.parse( + "{#let foo=1 bar='qute' baz=name.or('Andy') alpha=name.ifTruthy('true').or('false')}" + + "{#for i in foo}{count}{/for}::{bar.length}::{baz}::{alpha}" + + "{/let}") + .render()); + } + }