Skip to content

Commit d1998b8

Browse files
committed
Attributes per tag PoC
1 parent 764b5d7 commit d1998b8

File tree

8 files changed

+104
-52
lines changed

8 files changed

+104
-52
lines changed

src/main/java/j2html/TagCreator.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package j2html;
22

3+
import j2html.attributes.AAttribute;
4+
import j2html.attributes.AreaAttribute;
35
import j2html.attributes.Attr;
46
import j2html.tags.ContainerTag;
57
import j2html.tags.DomContent;
@@ -8,6 +10,7 @@
810
import j2html.tags.InlineStaticResource;
911
import j2html.tags.Text;
1012
import j2html.tags.UnescapedText;
13+
1114
import java.util.Collection;
1215
import java.util.List;
1316
import java.util.Map;
@@ -198,12 +201,12 @@ public static DomContent document() {
198201
}
199202

200203
// EmptyTags, generated in class j2html.tags.TagCreatorCodeGenerator
201-
public static EmptyTag area() {
202-
return new EmptyTag("area");
204+
public static EmptyTag<AreaAttribute> area() {
205+
return new EmptyTag<>("area");
203206
}
204207

205-
public static EmptyTag area(Attr.ShortForm shortAttr) {
206-
return Attr.addTo(new EmptyTag("area"), shortAttr);
208+
public static EmptyTag<AreaAttribute> area(Attr.ShortForm shortAttr) {
209+
return Attr.addTo(new EmptyTag<AreaAttribute>("area"), shortAttr);
207210
}
208211

209212
public static EmptyTag base() {
@@ -319,28 +322,28 @@ public static EmptyTag wbr(Attr.ShortForm shortAttr) {
319322
}
320323

321324
// ContainerTags, generated in class j2html.tags.TagCreatorCodeGenerator
322-
public static ContainerTag a() {
323-
return new ContainerTag("a");
325+
public static ContainerTag<AAttribute> a() {
326+
return new ContainerTag<>("a");
324327
}
325328

326-
public static ContainerTag a(String text) {
327-
return new ContainerTag("a").withText(text);
329+
public static ContainerTag<AAttribute> a(String text) {
330+
return new ContainerTag<AAttribute>("a").withText(text);
328331
}
329332

330-
public static ContainerTag a(DomContent... dc) {
331-
return new ContainerTag("a").with(dc);
333+
public static ContainerTag<AAttribute> a(DomContent... dc) {
334+
return new ContainerTag<AAttribute>("a").with(dc);
332335
}
333336

334-
public static ContainerTag a(Attr.ShortForm shortAttr) {
335-
return Attr.addTo(new ContainerTag("a"), shortAttr);
337+
public static ContainerTag<AAttribute> a(Attr.ShortForm shortAttr) {
338+
return Attr.addTo(new ContainerTag<AAttribute>("a"), shortAttr);
336339
}
337340

338-
public static ContainerTag a(Attr.ShortForm shortAttr, String text) {
339-
return Attr.addTo(new ContainerTag("a").withText(text), shortAttr);
341+
public static ContainerTag<AAttribute> a(Attr.ShortForm shortAttr, String text) {
342+
return Attr.addTo(new ContainerTag<AAttribute>("a").withText(text), shortAttr);
340343
}
341344

342-
public static ContainerTag a(Attr.ShortForm shortAttr, DomContent... dc) {
343-
return Attr.addTo(new ContainerTag("a").with(dc), shortAttr);
345+
public static ContainerTag<AAttribute> a(Attr.ShortForm shortAttr, DomContent... dc) {
346+
return Attr.addTo(new ContainerTag<AAttribute>("a").with(dc), shortAttr);
344347
}
345348

346349
public static ContainerTag abbr() {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package j2html.attributes;
2+
3+
public enum AAttribute {
4+
5+
CHARSET,
6+
COORDS,
7+
DOWNLOAD,
8+
HREF,
9+
HREFLANG,
10+
MEDIA,
11+
NAME,
12+
PING,
13+
REL,
14+
REV,
15+
SHAPE,
16+
TARGET,
17+
TYPE
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package j2html.attributes;
2+
3+
public enum AreaAttribute {
4+
5+
ALT,
6+
COORDS,
7+
DOWNLOAD,
8+
HREF,
9+
HREFLANG,
10+
MEDIA,
11+
NOHREF,
12+
REL,
13+
SHAPE,
14+
TARGET,
15+
TYPE
16+
}

src/main/java/j2html/attributes/Attr.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
public class Attr {
66

77
public static class ShortForm {
8+
89
String id;
910
String classes;
1011

@@ -44,7 +45,7 @@ public static ShortForm shortFormFromAttrsString(String attrs) {
4445
return new ShortForm(id.trim(), classes.toString().trim());
4546
}
4647

47-
public static <T extends Tag<T>> T addTo(T tag, ShortForm shortForm) {
48+
public static <T extends Tag<T, A>, A extends Enum<A>> T addTo(T tag, ShortForm shortForm) {
4849
if (shortForm.hasId() && shortForm.hasClasses()) {
4950
return tag.withId(shortForm.id).withClass(shortForm.classes);
5051
}
@@ -57,6 +58,10 @@ public static <T extends Tag<T>> T addTo(T tag, ShortForm shortForm) {
5758
return tag;
5859
}
5960

61+
public static String getName(Enum<?> attribute) {
62+
return attribute.name().replaceAll("_", "-").toLowerCase();
63+
}
64+
6065
private Attr() {
6166
}
6267

@@ -170,5 +175,4 @@ private Attr() {
170175
public static final String VALUE = "value";
171176
public static final String WIDTH = "width";
172177
public static final String WRAP = "wrap";
173-
174178
}

src/main/java/j2html/tags/ContainerTag.java

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package j2html.tags;
22

33
import j2html.Config;
4+
45
import java.io.IOException;
56
import java.util.ArrayList;
67
import java.util.List;
78

8-
public class ContainerTag extends Tag<ContainerTag> {
9+
public class ContainerTag<A extends Enum<A>> extends Tag<ContainerTag<A>, A> {
910

1011
private List<DomContent> children;
1112

@@ -14,14 +15,13 @@ public ContainerTag(String tagName) {
1415
this.children = new ArrayList<>();
1516
}
1617

17-
1818
/**
1919
* Appends a DomContent-object to the end of this element
2020
*
2121
* @param child DomContent-object to be appended
2222
* @return itself for easy chaining
2323
*/
24-
public ContainerTag with(DomContent child) {
24+
public ContainerTag<A> with(DomContent child) {
2525
if (this == child) {
2626
throw new RuntimeException("Cannot append a tag to itself.");
2727
}
@@ -32,7 +32,6 @@ public ContainerTag with(DomContent child) {
3232
return this;
3333
}
3434

35-
3635
/**
3736
* Call with-method based on condition
3837
* {@link #with(DomContent child)}
@@ -41,18 +40,17 @@ public ContainerTag with(DomContent child) {
4140
* @param child DomContent-object to be appended if condition met
4241
* @return itself for easy chaining
4342
*/
44-
public ContainerTag condWith(boolean condition, DomContent child) {
43+
public ContainerTag<A> condWith(boolean condition, DomContent child) {
4544
return condition ? this.with(child) : this;
4645
}
4746

48-
4947
/**
5048
* Appends a list of DomContent-objects to the end of this element
5149
*
5250
* @param children DomContent-objects to be appended
5351
* @return itself for easy chaining
5452
*/
55-
public ContainerTag with(Iterable<? extends DomContent> children) {
53+
public ContainerTag<A> with(Iterable<? extends DomContent> children) {
5654
if (children != null) {
5755
for (DomContent child : children) {
5856
this.with(child);
@@ -61,7 +59,6 @@ public ContainerTag with(Iterable<? extends DomContent> children) {
6159
return this;
6260
}
6361

64-
6562
/**
6663
* Call with-method based on condition
6764
* {@link #with(java.lang.Iterable)}
@@ -70,25 +67,23 @@ public ContainerTag with(Iterable<? extends DomContent> children) {
7067
* @param children DomContent-objects to be appended if condition met
7168
* @return itself for easy chaining
7269
*/
73-
public ContainerTag condWith(boolean condition, Iterable<? extends DomContent> children) {
70+
public ContainerTag<A> condWith(boolean condition, Iterable<? extends DomContent> children) {
7471
return condition ? this.with(children) : this;
7572
}
7673

77-
7874
/**
7975
* Appends the DomContent-objects to the end of this element
8076
*
8177
* @param children DomContent-objects to be appended
8278
* @return itself for easy chaining
8379
*/
84-
public ContainerTag with(DomContent... children) {
80+
public ContainerTag<A> with(DomContent... children) {
8581
for (DomContent child : children) {
8682
with(child);
8783
}
8884
return this;
8985
}
9086

91-
9287
/**
9388
* Call with-method based on condition
9489
* {@link #with(DomContent... children)}
@@ -97,18 +92,17 @@ public ContainerTag with(DomContent... children) {
9792
* @param children DomContent-objects to be appended if condition met
9893
* @return itself for easy chaining
9994
*/
100-
public ContainerTag condWith(boolean condition, DomContent... children) {
95+
public ContainerTag<A> condWith(boolean condition, DomContent... children) {
10196
return condition ? this.with(children) : this;
10297
}
10398

104-
10599
/**
106100
* Appends a Text-object to this element
107101
*
108102
* @param text the text to be appended
109103
* @return itself for easy chaining
110104
*/
111-
public ContainerTag withText(String text) {
105+
public ContainerTag<A> withText(String text) {
112106
return with(new Text(text));
113107
}
114108

@@ -181,5 +175,4 @@ public void renderModel(Appendable writer, Object model) throws IOException {
181175
}
182176
renderCloseTag(writer);
183177
}
184-
185178
}

src/main/java/j2html/tags/EmptyTag.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import j2html.attributes.Attribute;
55
import java.io.IOException;
66

7-
public class EmptyTag extends Tag<EmptyTag> {
7+
public class EmptyTag<A extends Enum<A>> extends Tag<EmptyTag<A>, A> {
88

99
public EmptyTag(String tagName) {
1010
super(tagName);

src/main/java/j2html/tags/Tag.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import j2html.attributes.Attr;
44
import j2html.attributes.Attribute;
5+
56
import java.io.IOException;
67
import java.util.ArrayList;
78
import java.util.Iterator;
89

9-
public abstract class Tag<T extends Tag<T>> extends DomContent {
10+
public abstract class Tag<T extends Tag<T, A>, A extends Enum<A>> extends DomContent {
11+
1012
protected String tagName;
1113
private ArrayList<Attribute> attributes;
1214

@@ -90,6 +92,10 @@ public T attr(String attribute, Object value) {
9092
return (T) this;
9193
}
9294

95+
public T attr(A attribute, Object value) {
96+
return attr(Attr.getName(attribute), value);
97+
}
98+
9399
/**
94100
* Adds the specified attribute. If the Tag previously contained an attribute with the same name, the old attribute is replaced by the specified attribute.
95101
*
@@ -123,6 +129,10 @@ public T attr(String attribute) {
123129
return attr(attribute, null);
124130
}
125131

132+
public T attr(A attribute) {
133+
return attr(attribute, null);
134+
}
135+
126136
/**
127137
* Call attr-method based on condition
128138
* {@link #attr(String attribute, Object value)}
@@ -136,6 +146,10 @@ public T condAttr(boolean condition, String attribute, String value) {
136146
return (condition ? attr(attribute, value) : (T) this);
137147
}
138148

149+
public T condAttr(boolean condition, A attribute, String value) {
150+
return (condition ? attr(attribute, value) : (T) this);
151+
}
152+
139153
@Override
140154
public boolean equals(Object obj) {
141155
if (obj == null || !(obj instanceof Tag)) {

src/main/java/j2html/tags/TagCreatorCodeGenerator.java

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,40 @@
33
import java.util.Arrays;
44
import java.util.List;
55

6+
import static org.apache.commons.lang3.StringUtils.capitalize;
7+
68
class TagCreatorCodeGenerator {
79

810
public static void main(String[] args) {
911
System.out.println("// EmptyTags, generated in " + TagCreatorCodeGenerator.class);
1012
for (String tag : emptyTags()) {
11-
String emptyA1 = "public static EmptyTag " + tag + "()";
12-
String emptyA2 = "{ return new EmptyTag(\"" + tag + "\"); }";
13+
String attribute = capitalize(tag) + "Attribute";
14+
String emptyA1 = "public static EmptyTag<" + attribute + "> " + tag + "()";
15+
String emptyA2 = "{ return new EmptyTag<>(\"" + tag + "\"); }";
1316
// Attr shorthands
14-
String emptyB1 = "public static EmptyTag " + tag + "(Attr.ShortForm shortAttr)";
15-
String emptyB2 = "{ return Attr.addTo(new EmptyTag(\"" + tag + "\"), shortAttr); }";
17+
String emptyB1 = "public static EmptyTag<" + attribute + "> " + tag + "(Attr.ShortForm shortAttr)";
18+
String emptyB2 = "{ return Attr.addTo(new EmptyTag<" + attribute + ">(\"" + tag + "\"), shortAttr); }";
1619
// Print
1720
System.out.println(String.format("%-80s%1s", emptyA1, emptyA2));
1821
System.out.println(String.format("%-80s%1s", emptyB1, emptyB2));
1922
System.out.println("");
2023
}
2124
System.out.println("// ContainerTags, generated in " + TagCreatorCodeGenerator.class);
2225
for (String tag : containerTags()) {
23-
String containerA1 = "public static ContainerTag " + tag + "()";
24-
String containerA2 = "{ return new ContainerTag(\"" + tag + "\"); }";
25-
String containerB1 = "public static ContainerTag " + tag + "(String text)";
26-
String containerB2 = "{ return new ContainerTag(\"" + tag + "\").withText(text); }";
27-
String containerC1 = "public static ContainerTag " + tag + "(DomContent... dc)";
28-
String containerC2 = "{ return new ContainerTag(\"" + tag + "\").with(dc); }";
26+
String attribute = capitalize(tag) + "Attribute";
27+
String containerA1 = "public static ContainerTag<" + attribute + "> " + tag + "()";
28+
String containerA2 = "{ return new ContainerTag<>(\"" + tag + "\"); }";
29+
String containerB1 = "public static ContainerTag<" + attribute + "> " + tag + "(String text)";
30+
String containerB2 = "{ return new ContainerTag<" + attribute + ">(\"" + tag + "\").withText(text); }";
31+
String containerC1 = "public static ContainerTag<" + attribute + "> " + tag + "(DomContent... dc)";
32+
String containerC2 = "{ return new ContainerTag<" + attribute + ">(\"" + tag + "\").with(dc); }";
2933
// Attr shorthands
30-
String containerD1 = "public static ContainerTag " + tag + "(Attr.ShortForm shortAttr)";
31-
String containerD2 = "{ return Attr.addTo(new ContainerTag(\"" + tag + "\"), shortAttr); }";
32-
String containerE1 = "public static ContainerTag " + tag + "(Attr.ShortForm shortAttr, String text)";
33-
String containerE2 = "{ return Attr.addTo(new ContainerTag(\"" + tag + "\").withText(text), shortAttr); }";
34-
String containerF1 = "public static ContainerTag " + tag + "(Attr.ShortForm shortAttr, DomContent... dc)";
35-
String containerF2 = "{ return Attr.addTo(new ContainerTag(\"" + tag + "\").with(dc), shortAttr); }";
34+
String containerD1 = "public static ContainerTag<" + attribute + "> " + tag + "(Attr.ShortForm shortAttr)";
35+
String containerD2 = "{ return Attr.addTo(new ContainerTag<" + attribute + ">(\"" + tag + "\"), shortAttr); }";
36+
String containerE1 = "public static ContainerTag<" + attribute + "> " + tag + "(Attr.ShortForm shortAttr, String text)";
37+
String containerE2 = "{ return Attr.addTo(new ContainerTag<" + attribute + ">(\"" + tag + "\").withText(text), shortAttr); }";
38+
String containerF1 = "public static ContainerTag<" + attribute + "> " + tag + "(Attr.ShortForm shortAttr, DomContent... dc)";
39+
String containerF2 = "{ return Attr.addTo(new <" + attribute + ">ContainerTag(\"" + tag + "\").with(dc), shortAttr); }";
3640
// Print
3741
System.out.println(String.format("%-80s%1s", containerA1, containerA2));
3842
System.out.println(String.format("%-80s%1s", containerB1, containerB2));

0 commit comments

Comments
 (0)