Compare commits
8 Commits
j2html-1.2
...
param-name
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92aa3310db | ||
|
|
b42ba41697 | ||
|
|
0c7f75f5b8 | ||
|
|
754003ebf6 | ||
|
|
6968478894 | ||
|
|
0b92a963e9 | ||
|
|
ac92facca7 | ||
|
|
4cf16320ad |
16
README.md
16
README.md
@@ -13,12 +13,12 @@ The project webpage is [j2html.com](http://j2html.com).
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.j2html</groupId>
|
<groupId>com.j2html</groupId>
|
||||||
<artifactId>j2html</artifactId>
|
<artifactId>j2html</artifactId>
|
||||||
<version>1.2.1</version>
|
<version>1.2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
### OR the gradle dependency
|
### Or the gradle dependency
|
||||||
```
|
```
|
||||||
compile 'com.j2html:j2html:1.2.1'
|
compile 'com.j2html:j2html:1.2.2'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Import TagCreator and start building HTML
|
### Import TagCreator and start building HTML
|
||||||
@@ -27,9 +27,9 @@ import static j2html.TagCreator.*;
|
|||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
body().with(
|
body(
|
||||||
h1("Heading!").withClass("example"),
|
h1("Hello, World!"),
|
||||||
img().withSrc("img/hello.png")
|
img().withSrc("/img/hello.png")
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,8 +37,8 @@ public class Main {
|
|||||||
The above Java will result in the following HTML:
|
The above Java will result in the following HTML:
|
||||||
```html
|
```html
|
||||||
<body>
|
<body>
|
||||||
<h1 class="example">Heading!</h1>
|
<h1>Hello, World!</h1>
|
||||||
<img src="img/hello.png">
|
<img src="/img/hello.png">
|
||||||
</body>
|
</body>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
22
pom.xml
22
pom.xml
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<groupId>com.j2html</groupId>
|
<groupId>com.j2html</groupId>
|
||||||
<artifactId>j2html</artifactId>
|
<artifactId>j2html</artifactId>
|
||||||
<version>1.2.2</version>
|
<version>1.2.3-SNAPSHOT</version>
|
||||||
|
|
||||||
<name>j2html</name>
|
<name>j2html</name>
|
||||||
<description>Java to HTML builder with a fluent API</description>
|
<description>Java to HTML builder with a fluent API</description>
|
||||||
@@ -63,7 +63,22 @@
|
|||||||
<artifactId>junit-benchmarks</artifactId>
|
<artifactId>junit-benchmarks</artifactId>
|
||||||
<version>0.7.2</version>
|
<version>0.7.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- performance test dependencies -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.velocity</groupId>
|
||||||
|
<artifactId>velocity</artifactId>
|
||||||
|
<version>1.7</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.16.18</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
@@ -78,6 +93,9 @@
|
|||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
<target>1.8</target>
|
<target>1.8</target>
|
||||||
<optimize>true</optimize>
|
<optimize>true</optimize>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<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,8 +2,10 @@ package j2html.tags;
|
|||||||
|
|
||||||
import j2html.attributes.Attr;
|
import j2html.attributes.Attr;
|
||||||
import j2html.attributes.Attribute;
|
import j2html.attributes.Attribute;
|
||||||
|
import j2html.attributes.LambdaAttribute;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
public abstract class Tag<T extends Tag<T>> extends DomContent {
|
public abstract class Tag<T extends Tag<T>> extends DomContent {
|
||||||
protected String tagName;
|
protected String tagName;
|
||||||
@@ -79,6 +81,28 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
|||||||
return (T) this;
|
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.
|
||||||
|
*
|
||||||
|
* @param attribute the attribute
|
||||||
|
* @return itself for easy chaining
|
||||||
|
*/
|
||||||
|
public T attr(Attribute attribute) {
|
||||||
|
Iterator<Attribute> iterator = attributes.iterator();
|
||||||
|
String name = attribute.getName();
|
||||||
|
if (name != null) {
|
||||||
|
// name == null is allowed, but those Attributes are not rendered. So we add them anyway.
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Attribute existingAttribute = iterator.next();
|
||||||
|
if (existingAttribute.getName().equals(name)) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributes.add(attribute);
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a custom attribute without value
|
* Sets a custom attribute without value
|
||||||
*
|
*
|
||||||
@@ -111,11 +135,6 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
|||||||
return ((Tag) obj).render().equals(this.render());
|
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) {
|
public T withClasses(String... classes) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (String s : classes) {
|
for (String s : classes) {
|
||||||
@@ -124,6 +143,19 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
|
|||||||
return attr(Attr.CLASS, sb.toString().trim());
|
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() {
|
public T isAutoComplete() {
|
||||||
return attr(Attr.AUTOCOMPLETE, null);
|
return attr(Attr.AUTOCOMPLETE, null);
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/test/java/j2html/comparison/ComparisonData.java
Normal file
17
src/test/java/j2html/comparison/ComparisonData.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package j2html.comparison;
|
||||||
|
|
||||||
|
import j2html.comparison.model.Employee;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class ComparisonData {
|
||||||
|
|
||||||
|
public static List<Employee> fiveHundredEmployees() {
|
||||||
|
return IntStream.range(0, 500).mapToObj(i -> new Employee(i, "Some name", "Some title")).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> tableNumbers = IntStream.range(1, 51).boxed().collect(Collectors.toList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package j2html.comparison;
|
||||||
|
|
||||||
|
import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
|
||||||
|
import com.carrotsearch.junitbenchmarks.BenchmarkRule;
|
||||||
|
import com.carrotsearch.junitbenchmarks.Clock;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TestRule;
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
@BenchmarkOptions(callgc = false, benchmarkRounds = 20_000, warmupRounds = 200, concurrency = 2, clock = Clock.NANO_TIME)
|
||||||
|
public class RenderPerformanceComparisonTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TestRule benchmarkRun = new BenchmarkRule();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void j2htmlPerformance() throws Exception {
|
||||||
|
TestJ2html.helloWorld();
|
||||||
|
TestJ2html.fiveHundredEmployees();
|
||||||
|
TestJ2html.macros();
|
||||||
|
TestJ2html.multiplicationTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void velocityPerformance() throws Exception {
|
||||||
|
TestVelocity.helloWorld();
|
||||||
|
TestVelocity.fiveHundredEmployees();
|
||||||
|
TestVelocity.macros();
|
||||||
|
TestVelocity.multiplicationTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
30
src/test/java/j2html/comparison/TestJ2html.java
Normal file
30
src/test/java/j2html/comparison/TestJ2html.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package j2html.comparison;
|
||||||
|
|
||||||
|
import j2html.comparison.j2html.FiveHundredEmployees;
|
||||||
|
import j2html.comparison.j2html.HelloWorld;
|
||||||
|
import j2html.comparison.j2html.Macros;
|
||||||
|
import j2html.comparison.j2html.MultiplicationTable;
|
||||||
|
|
||||||
|
public class TestJ2html {
|
||||||
|
|
||||||
|
public static String helloWorld() {
|
||||||
|
return HelloWorld.tag.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fiveHundredEmployees() {
|
||||||
|
return FiveHundredEmployees.tag.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String macros() {
|
||||||
|
return Macros.tag.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String multiplicationTable() {
|
||||||
|
return MultiplicationTable.tag.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(MultiplicationTable.tag.renderFormatted());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
52
src/test/java/j2html/comparison/TestVelocity.java
Normal file
52
src/test/java/j2html/comparison/TestVelocity.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package j2html.comparison;
|
||||||
|
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.velocity.VelocityContext;
|
||||||
|
import org.apache.velocity.app.VelocityEngine;
|
||||||
|
|
||||||
|
public class TestVelocity {
|
||||||
|
|
||||||
|
private static VelocityEngine velocityEngine;
|
||||||
|
|
||||||
|
static {
|
||||||
|
velocityEngine = new VelocityEngine();
|
||||||
|
velocityEngine.setProperty("resource.loader", "class");
|
||||||
|
velocityEngine.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String render(String templatePath, Map<String, Object> model) {
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
velocityEngine.getTemplate(templatePath, StandardCharsets.UTF_8.name()).merge(
|
||||||
|
new VelocityContext(model), stringWriter
|
||||||
|
);
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String helloWorld() {
|
||||||
|
return render("/comparison/velocity/helloWorld.vm", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fiveHundredEmployees() {
|
||||||
|
Map<String, Object> model = new HashMap<>();
|
||||||
|
model.put("employees", ComparisonData.fiveHundredEmployees());
|
||||||
|
return render("/comparison/velocity/fiveHundredEmployees.vm", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String macros() {
|
||||||
|
return render("/comparison/velocity/macros.vm", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String multiplicationTable() {
|
||||||
|
Map<String, Object> model = new HashMap<>();
|
||||||
|
model.put("tableNumbers", ComparisonData.tableNumbers);
|
||||||
|
return render("/comparison/velocity/multiplicationTable.vm", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(multiplicationTable());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package j2html.comparison.j2html;
|
||||||
|
|
||||||
|
import j2html.comparison.ComparisonData;
|
||||||
|
import j2html.tags.ContainerTag;
|
||||||
|
import static j2html.TagCreator.each;
|
||||||
|
import static j2html.TagCreator.li;
|
||||||
|
import static j2html.TagCreator.ul;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.join;
|
||||||
|
|
||||||
|
public class FiveHundredEmployees {
|
||||||
|
|
||||||
|
public static ContainerTag tag = ul(
|
||||||
|
each(ComparisonData.fiveHundredEmployees(), employee ->
|
||||||
|
li(join(employee.getId(), employee.getName(), employee.getTitle()))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
27
src/test/java/j2html/comparison/j2html/HelloWorld.java
Normal file
27
src/test/java/j2html/comparison/j2html/HelloWorld.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package j2html.comparison.j2html;
|
||||||
|
|
||||||
|
import j2html.tags.ContainerTag;
|
||||||
|
import static j2html.TagCreator.attrs;
|
||||||
|
import static j2html.TagCreator.body;
|
||||||
|
import static j2html.TagCreator.h1;
|
||||||
|
import static j2html.TagCreator.head;
|
||||||
|
import static j2html.TagCreator.html;
|
||||||
|
import static j2html.TagCreator.link;
|
||||||
|
import static j2html.TagCreator.main;
|
||||||
|
import static j2html.TagCreator.title;
|
||||||
|
|
||||||
|
public class HelloWorld {
|
||||||
|
|
||||||
|
public static ContainerTag tag = html(
|
||||||
|
head(
|
||||||
|
title("Title"),
|
||||||
|
link().withRel("stylesheet").withHref("/css/main.css")
|
||||||
|
),
|
||||||
|
body(
|
||||||
|
main(attrs("#main.content"),
|
||||||
|
h1("Heading!")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
46
src/test/java/j2html/comparison/j2html/Macros.java
Normal file
46
src/test/java/j2html/comparison/j2html/Macros.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package j2html.comparison.j2html;
|
||||||
|
|
||||||
|
import j2html.tags.ContainerTag;
|
||||||
|
import j2html.tags.DomContent;
|
||||||
|
import static j2html.TagCreator.attrs;
|
||||||
|
import static j2html.TagCreator.body;
|
||||||
|
import static j2html.TagCreator.div;
|
||||||
|
import static j2html.TagCreator.h1;
|
||||||
|
import static j2html.TagCreator.head;
|
||||||
|
import static j2html.TagCreator.html;
|
||||||
|
import static j2html.TagCreator.link;
|
||||||
|
import static j2html.TagCreator.main;
|
||||||
|
import static j2html.TagCreator.title;
|
||||||
|
|
||||||
|
public class Macros {
|
||||||
|
|
||||||
|
public static ContainerTag tag = mainLayout(
|
||||||
|
div(
|
||||||
|
h1("Example content"),
|
||||||
|
someMacro(1),
|
||||||
|
someMacro(2),
|
||||||
|
someMacro(3)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
private static ContainerTag mainLayout(DomContent content) {
|
||||||
|
return html(
|
||||||
|
head(
|
||||||
|
title("Title"),
|
||||||
|
link().withRel("stylesheet").withHref("/css/main.css")
|
||||||
|
),
|
||||||
|
body(
|
||||||
|
main(attrs("#main.content"),
|
||||||
|
content
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ContainerTag someMacro(int i) {
|
||||||
|
return div(
|
||||||
|
"Macro call " + i
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package j2html.comparison.j2html;
|
||||||
|
|
||||||
|
import j2html.comparison.ComparisonData;
|
||||||
|
import j2html.tags.ContainerTag;
|
||||||
|
import static j2html.TagCreator.*;
|
||||||
|
|
||||||
|
public class MultiplicationTable {
|
||||||
|
|
||||||
|
public static ContainerTag tag = table(
|
||||||
|
tbody(
|
||||||
|
each(ComparisonData.tableNumbers, i -> tr(
|
||||||
|
each(ComparisonData.tableNumbers, j -> td(
|
||||||
|
String.valueOf(i * j)
|
||||||
|
))
|
||||||
|
))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
10
src/test/java/j2html/comparison/model/Employee.java
Normal file
10
src/test/java/j2html/comparison/model/Employee.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package j2html.comparison.model;
|
||||||
|
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
public class Employee {
|
||||||
|
int id;
|
||||||
|
String name;
|
||||||
|
String title;
|
||||||
|
}
|
||||||
24
src/test/java/j2html/model/DynamicHrefAttribute.java
Normal file
24
src/test/java/j2html/model/DynamicHrefAttribute.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package j2html.model;
|
||||||
|
|
||||||
|
import j2html.attributes.Attribute;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DynamicHrefAttribute extends Attribute {
|
||||||
|
|
||||||
|
public DynamicHrefAttribute() {
|
||||||
|
super("href");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderModel(Appendable writer, Object model) throws IOException {
|
||||||
|
writer.append(" ");
|
||||||
|
writer.append(getName());
|
||||||
|
writer.append("=\"");
|
||||||
|
writer.append(getUrl(model));
|
||||||
|
writer.append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl(Object model) {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
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,10 +1,13 @@
|
|||||||
package j2html.tags;
|
package j2html.tags;
|
||||||
|
|
||||||
import j2html.Config;
|
import j2html.Config;
|
||||||
|
import j2html.model.DynamicHrefAttribute;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import static j2html.TagCreator.a;
|
||||||
import static j2html.TagCreator.body;
|
import static j2html.TagCreator.body;
|
||||||
import static j2html.TagCreator.div;
|
import static j2html.TagCreator.div;
|
||||||
import static j2html.TagCreator.footer;
|
import static j2html.TagCreator.footer;
|
||||||
|
import static j2html.TagCreator.form;
|
||||||
import static j2html.TagCreator.header;
|
import static j2html.TagCreator.header;
|
||||||
import static j2html.TagCreator.html;
|
import static j2html.TagCreator.html;
|
||||||
import static j2html.TagCreator.iff;
|
import static j2html.TagCreator.iff;
|
||||||
@@ -92,5 +95,29 @@ public class TagTest {
|
|||||||
assertThat(testTagAttrWithoutAttr.render(), is("<a attribute></a>"));
|
assertThat(testTagAttrWithoutAttr.render(), is("<a attribute></a>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDynamicAttribute() throws Exception {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#* @vtlvariable name="employees" type="java.util.List<j2html.comparison.ComparisonData.Employee>" *#
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
#foreach($employee in $employees)
|
||||||
|
<li>$employee.id $employee.name $employee.title</li>
|
||||||
|
#end
|
||||||
|
</ul>
|
||||||
11
src/test/resources/comparison/velocity/helloWorld.vm
Normal file
11
src/test/resources/comparison/velocity/helloWorld.vm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Title</title>
|
||||||
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main id="main" class="content">
|
||||||
|
<h1>Heading!</h1>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
28
src/test/resources/comparison/velocity/macros.vm
Normal file
28
src/test/resources/comparison/velocity/macros.vm
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#macro(mainLayout)
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Title</title>
|
||||||
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main id="main" class="content">
|
||||||
|
$!bodyContent
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
#end
|
||||||
|
|
||||||
|
#@mainLayout()
|
||||||
|
<div>
|
||||||
|
<h1>Example content</h1>
|
||||||
|
#someMacro(1)
|
||||||
|
#someMacro(2)
|
||||||
|
#someMacro(3)
|
||||||
|
</div>
|
||||||
|
#end
|
||||||
|
|
||||||
|
#macro(someMacro $callNumber)
|
||||||
|
<div>
|
||||||
|
Macro call $callNumber
|
||||||
|
</div>
|
||||||
|
#end
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
#foreach($i in $tableNumbers)
|
||||||
|
<tr>
|
||||||
|
#foreach($j in $tableNumbers)
|
||||||
|
#set($product = $i * $j)
|
||||||
|
<td>$product</td>
|
||||||
|
#end
|
||||||
|
</tr>
|
||||||
|
#end
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
Reference in New Issue
Block a user