Compare commits
1 Commits
master
...
param-name
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92aa3310db |
3
pom.xml
3
pom.xml
@@ -93,6 +93,9 @@
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<optimize>true</optimize>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
24
src/main/java/j2html/attributes/LambdaAttribute.java
Normal file
24
src/main/java/j2html/attributes/LambdaAttribute.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package j2html.attributes;
|
||||
|
||||
import j2html.reflection.MethodFinder;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface LambdaAttribute extends MethodFinder, Function<String, Object> {
|
||||
|
||||
default String name() {
|
||||
checkParametersEnabled();
|
||||
return parameter(0).getName();
|
||||
}
|
||||
|
||||
default String value() {
|
||||
checkParametersEnabled();
|
||||
return String.valueOf(this.apply(name()));
|
||||
}
|
||||
|
||||
default void checkParametersEnabled() {
|
||||
if ("arg0".equals(parameter(0).getName())) {
|
||||
throw new IllegalStateException("You need java 8u60 or newer for parameter reflection to work");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/j2html/reflection/MethodFinder.java
Normal file
48
src/main/java/j2html/reflection/MethodFinder.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package j2html.reflection;
|
||||
|
||||
// Written by Benjamin Weber (http://benjiweber.co.uk/blog/author/benji/)
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.invoke.SerializedLambda;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public interface MethodFinder extends Serializable {
|
||||
|
||||
default SerializedLambda serialized() {
|
||||
try {
|
||||
Method replaceMethod = getClass().getDeclaredMethod("writeReplace");
|
||||
replaceMethod.setAccessible(true);
|
||||
return (SerializedLambda) replaceMethod.invoke(this);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
default Class<?> getContainingClass() {
|
||||
try {
|
||||
String className = serialized().getImplClass().replaceAll("/", ".");
|
||||
return Class.forName(className);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
default Method method() {
|
||||
SerializedLambda lambda = serialized();
|
||||
Class<?> containingClass = getContainingClass();
|
||||
return Arrays.stream(containingClass.getDeclaredMethods())
|
||||
.filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName()))
|
||||
.findFirst()
|
||||
.orElseThrow(UnableToGuessMethodException::new);
|
||||
}
|
||||
|
||||
default Parameter parameter(int n) {
|
||||
return method().getParameters()[n];
|
||||
}
|
||||
|
||||
class UnableToGuessMethodException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package j2html.tags;
|
||||
|
||||
import j2html.attributes.Attr;
|
||||
import j2html.attributes.Attribute;
|
||||
import j2html.attributes.LambdaAttribute;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -79,7 +80,7 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
||||
setAttribute(attribute, value == null ? null : String.valueOf(value));
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the specified attribute. If the Tag previously contained an attribute with the same name, the old attribute is replaced by the specified attribute.
|
||||
*
|
||||
@@ -134,11 +135,6 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
||||
return ((Tag) obj).render().equals(this.render());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience methods that call attr with predefined attributes
|
||||
*
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public T withClasses(String... classes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : classes) {
|
||||
@@ -147,6 +143,19 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
||||
return attr(Attr.CLASS, sb.toString().trim());
|
||||
}
|
||||
|
||||
public T withAttrs(LambdaAttribute... lambdaAttributes) {
|
||||
for (LambdaAttribute attr : lambdaAttributes) {
|
||||
attr(attr.name(), attr.value());
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience methods that call attr with predefined attributes
|
||||
*
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
|
||||
public T isAutoComplete() {
|
||||
return attr(Attr.AUTOCOMPLETE, null);
|
||||
}
|
||||
|
||||
17
src/test/java/j2html/reflection/NamedValueTest.java
Normal file
17
src/test/java/j2html/reflection/NamedValueTest.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package j2html.reflection;
|
||||
|
||||
import j2html.attributes.LambdaAttribute;
|
||||
import org.junit.Test;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class NamedValueTest {
|
||||
|
||||
@Test
|
||||
public void testNamedValueWorks() {
|
||||
LambdaAttribute pair = five -> 5;
|
||||
assertThat("five", is(pair.name()));
|
||||
assertThat("5", is(pair.value()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
package j2html.tags;
|
||||
|
||||
import j2html.Config;
|
||||
import j2html.model.DynamicHrefAttribute;
|
||||
import org.junit.Test;
|
||||
import static j2html.TagCreator.a;
|
||||
import static j2html.TagCreator.body;
|
||||
import static j2html.TagCreator.div;
|
||||
import static j2html.TagCreator.footer;
|
||||
import static j2html.TagCreator.form;
|
||||
import static j2html.TagCreator.header;
|
||||
import static j2html.TagCreator.html;
|
||||
import static j2html.TagCreator.iff;
|
||||
@@ -13,9 +18,6 @@ import static j2html.TagCreator.p;
|
||||
import static j2html.TagCreator.tag;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import j2html.Config;
|
||||
import j2html.model.DynamicHrefAttribute;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TagTest {
|
||||
|
||||
@@ -98,11 +100,24 @@ public class TagTest {
|
||||
ContainerTag testTagWithAttrValueNull = new ContainerTag("a").attr(new DynamicHrefAttribute());
|
||||
assertThat(testTagWithAttrValueNull.render(), is("<a href=\"/\"></a>"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDynamicAttributeReplacement() throws Exception {
|
||||
ContainerTag testTagWithAttrValueNull = new ContainerTag("a").attr("href", "/link").attr(new DynamicHrefAttribute());
|
||||
assertThat(testTagWithAttrValueNull.render(), is("<a href=\"/\"></a>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterNameReflectionAttributes() throws Exception {
|
||||
String expectedAnchor = "<a href=\"http://example.com\">example.com</a>";
|
||||
String actualAnchor = a("example.com").withAttrs(href -> "http://example.com").render();
|
||||
assertThat(actualAnchor, is(expectedAnchor));
|
||||
String expectedForm = "<form method=\"post\" action=\"/form-path\"><input name=\"email\" type=\"email\"><input name=\"password\" type=\"password\"></form>";
|
||||
String actualForm = form().withAttrs(method -> "post", action -> "/form-path").with(
|
||||
input().withAttrs(name -> "email", type -> "email"),
|
||||
input().withAttrs(name -> "password", type -> "password")
|
||||
).render();
|
||||
assertThat(actualForm, is(expectedForm));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user