Merge pull request #187 from obecker/htmltag
Remove manual tags, use only generated tags
This commit is contained in:
@@ -16,15 +16,15 @@ For preventing performance regressions, there are Tests.
|
||||
|
||||
## Coding Style
|
||||
|
||||
There is a ```.editorconfig``` and a ```eclipse_formatting_profile.xml```
|
||||
There is a `.editorconfig` and a `eclipse_formatting_profile.xml`
|
||||
|
||||
What sticks out is that end of line is CRLF ```'\r\n'``` for this Project.
|
||||
What sticks out is that end of line is CRLF `'\r\n'` for this Project.
|
||||
|
||||
This means that if you're on Linux ```'\n'```, you have to configure git to handle this
|
||||
This means that if you're on Linux `'\n'`, you have to configure git to handle this
|
||||
correctly so that you have the correct EOL in your working directory,
|
||||
and the EOL is also correct in the repository itself.
|
||||
|
||||
For this purpose, j2html has a ```.gitattributes``` file.
|
||||
For this purpose, j2html has a `.gitattributes` file.
|
||||
|
||||
[Guide to configuring EOL with git](https://docs.github.com/en/github/using-git/configuring-git-to-handle-line-endings)
|
||||
|
||||
@@ -33,7 +33,7 @@ If you are on Windows, there should be no Problems.
|
||||
### Reformatting of generated Java Code
|
||||
|
||||
As this Projects makes use of Code-Generation techniques in order to generate a more typesafe API without too much manual Work,
|
||||
there is the ```code_gen/``` directory which contains everything needed to generate the code.
|
||||
there is the `code_gen/` directory which contains everything needed to generate the code.
|
||||
|
||||
For simplicity (and also to avoid extra dependencies), they do not format the code correctly.
|
||||
|
||||
@@ -57,8 +57,8 @@ This is **the** central class in J2HTML. It provides the methods
|
||||
for users of J2HTML to generate all HTML Tags.
|
||||
It contains methods like
|
||||
```
|
||||
public static HtmlTag html(HeadTag head, BodyTag body){
|
||||
return new HtmlTag(head, body);
|
||||
public static HtmlTag html(DomContent... dc) {
|
||||
return new HtmlTag().with(dc);
|
||||
}
|
||||
```
|
||||
which can be used in Projects using this dependency as
|
||||
@@ -80,20 +80,20 @@ html(
|
||||
Each HTML Tag has it's own class, which makes it possible for each Tag to have
|
||||
the correct Attributes and Methods to set those Attributes.
|
||||
|
||||
The classes are located in ```library/src/main/java/j2html/tags/specialized/``` and follow the naming convention ```tag_name + 'Tag.java'```, e.g. ```BodyTag.java```.
|
||||
The classes are located in `library/src/main/java/j2html/tags/specialized/generated` and follow the naming convention `tag_name + 'Tag.java'`, e.g. `BodyTag.java`.
|
||||
Notice that the first letter of the Tag is in uppercase.
|
||||
|
||||
Each Tag-specific class ```implements``` interfaces which correspond to the Attributes that can be set on these Tags.
|
||||
Each Tag-specific class `implements` interfaces which correspond to the Attributes that can be set on these Tags.
|
||||
|
||||
For Reference which Tags support which Attributes, see [HTML Attribute Reference](https://www.w3schools.com/tags/ref_attributes.asp).
|
||||
|
||||
For Example, ```ButtonTag``` might implement ```IType<ButtonTag>``` which says it can have an Attribute ```type```, which may later show up like ```<button type="submit"></button>```.
|
||||
For Example, `ButtonTag` might implement `IType<ButtonTag>` which says it can have an Attribute `type`, which may later show up like `<button type="submit"></button>`.
|
||||
|
||||
### How are the Attributes of HTML Tags implemented?
|
||||
|
||||
Each Attribute has it's own interface in ```src/main/java/j2html/tags/attributes/``` and follows the naming convention ```"I" + attribute_name + '.java'```, e.g. ```IAccept.java```. Notice that the first letter of the Attribute is in uppercase.
|
||||
Each Attribute has it's own interface in `src/main/java/j2html/tags/attributes/` and follows the naming convention `"I" + attribute_name + '.java'`, e.g. `IAccept.java`. Notice that the first letter of the Attribute is in uppercase.
|
||||
|
||||
Dissecting ```IAccept.java```:
|
||||
Dissecting `IAccept.java`:
|
||||
|
||||
```
|
||||
public interface IAccept<T extends Tag> extends IInstance<T> {
|
||||
@@ -110,8 +110,8 @@ public interface IAccept<T extends Tag> extends IInstance<T> {
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, **IAccept** extends ```IInstance<T>``` which provides only the ```self()``` Method to access an instance of type ```T```.
|
||||
All attribute-specific interfaces extend ```IInstance<T>```.
|
||||
As you can see, **IAccept** extends `IInstance<T>` which provides only the `self()` Method to access an instance of type `T`.
|
||||
All attribute-specific interfaces extend `IInstance<T>`.
|
||||
|
||||
```
|
||||
public interface IInstance<T> {
|
||||
@@ -119,26 +119,23 @@ public interface IInstance<T> {
|
||||
}
|
||||
```
|
||||
|
||||
```IInstance<T>``` is cheating the type system because ```self()``` returns an instance of type ```T```, but the implementing class
|
||||
`IInstance<T>` is cheating the type system because `self()` returns an instance of type `T`, but the implementing class
|
||||
technically does not have to supply it's own type as the type argument. But by convention, in this Project, the implementing class
|
||||
always supplies it's own type as the type argument.
|
||||
|
||||
But in ```default``` methods in interfaces there is AFAIK no way to obtain the type of the class that is implementing the interface.
|
||||
But in `default` methods in interfaces there is AFAIK no way to obtain the type of the class that is implementing the interface.
|
||||
If you find a way, that would be a great PR.
|
||||
|
||||
### Special classes/interfaces besides TagCreator.java
|
||||
|
||||
There are 3 classes which contain code-generating methods in ```code_gen/src/main/java/j2html_codegen/generators/```:
|
||||
There are 3 classes which contain code-generating methods in `code_gen/src/main/java/j2html_codegen/generators/`:
|
||||
|
||||
- AttributeInterfaceCodeGenerator.java (generating the interfaces for the attributes)
|
||||
- SpecializedTagClassCodeGenerator.java (generating the classes for the tags)
|
||||
- TagCreatorCodeGenerator.java (generating some contents of TagCreator.java)
|
||||
- `AttributeInterfaceCodeGenerator.java` (generating the interfaces for the attributes)
|
||||
- `SpecializedTagClassCodeGenerator.java` (generating the classes for the tags)
|
||||
- `TagCreatorCodeGenerator.java` (generating some contents of `TagCreator.java`)
|
||||
|
||||
### Other special classes / interfaces in J2HTML
|
||||
|
||||
- HtmlTag, BodyTag, HeadTag are special because they are handwritten and have special semantics in HTML: they can only be used once.
|
||||
This is not modeled fully in J2HTML though.
|
||||
|
||||
- **Tag.java** is the base class for every tag and extends DomContent
|
||||
- **EmptyTag.java** is the base class for all Tags which have no contents
|
||||
- **ContainerTag.java** is the base class for all Tags which can contain other tags
|
||||
@@ -150,7 +147,7 @@ Attributes differ in their 'type' . Some of them can be set with numbers (which
|
||||
Others can only be set or not set, others still have 3 states: set, unset, and not present.
|
||||
To model these propertise, a single Attribute can be described by an instance of **AttrD.java**.
|
||||
|
||||
```library/src/main/java/j2html/tags/generators/AttributesList.java``` contains the different Attributes, their properties,
|
||||
`library/src/main/java/j2html/tags/generators/AttributesList.java` contains the different Attributes, their properties,
|
||||
and the Tags they can be set on. It is the starting point for adding new Attributes and customizing their properties.
|
||||
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public final class TagCreatorCodeGenerator {
|
||||
"bdi",
|
||||
"bdo",
|
||||
"blockquote",
|
||||
//"body" BodyTag is managed manually,
|
||||
"body",
|
||||
"button",
|
||||
"canvas",
|
||||
"caption",
|
||||
@@ -124,9 +124,9 @@ public final class TagCreatorCodeGenerator {
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
//"head", HeadTag is managed manually
|
||||
"head",
|
||||
"header",
|
||||
//"html" HtmlTag is managed manually
|
||||
"html",
|
||||
"i",
|
||||
"iframe",
|
||||
"ins",
|
||||
|
||||
@@ -9,7 +9,6 @@ import j2html.tags.InlineStaticResource;
|
||||
import j2html.tags.Tag;
|
||||
import j2html.tags.Text;
|
||||
import j2html.tags.UnescapedText;
|
||||
import j2html.tags.specialized.manual.*;
|
||||
import j2html.tags.specialized.generated.*;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -220,44 +219,27 @@ public class TagCreator {
|
||||
public static DomContent document() {
|
||||
return rawHtml("<!DOCTYPE html>");
|
||||
}
|
||||
// -- start of manually managed tags --
|
||||
|
||||
// EmptyTags
|
||||
|
||||
//ContainerTags
|
||||
public static HtmlTag html() {
|
||||
return new HtmlTag();
|
||||
}
|
||||
|
||||
public static HtmlTag html(String text) { return html().withText(text); }
|
||||
|
||||
public static HtmlTag html(DomContent... dc) { return html().with(dc); }
|
||||
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr) {
|
||||
return Attr.addTo(new HtmlTag(), shortAttr);
|
||||
return Attr.addTo(html(), shortAttr);
|
||||
}
|
||||
|
||||
public static HtmlTag html(HeadTag head){
|
||||
return new HtmlTag(head);
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr, String text) {
|
||||
return Attr.addTo(html(text), shortAttr);
|
||||
}
|
||||
|
||||
public static HtmlTag html(BodyTag body){
|
||||
return new HtmlTag(body);
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr, DomContent... dc) {
|
||||
return Attr.addTo(html(dc), shortAttr);
|
||||
}
|
||||
|
||||
public static HtmlTag html(HeadTag head, BodyTag body){
|
||||
return new HtmlTag(head, body);
|
||||
}
|
||||
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr, HeadTag head){
|
||||
return Attr.addTo(new HtmlTag(head), shortAttr);
|
||||
}
|
||||
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr, BodyTag body){
|
||||
return Attr.addTo(new HtmlTag(body), shortAttr);
|
||||
}
|
||||
|
||||
public static HtmlTag html(Attr.ShortForm shortAttr, HeadTag head, BodyTag body){
|
||||
return Attr.addTo(new HtmlTag(head, body), shortAttr);
|
||||
}
|
||||
|
||||
|
||||
public static BodyTag body() {
|
||||
return new BodyTag();
|
||||
}
|
||||
@@ -306,14 +288,6 @@ public class TagCreator {
|
||||
return Attr.addTo(new HeadTag().with(dc), shortAttr);
|
||||
}
|
||||
|
||||
// -- end of manually managed tags --
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// EmptyTags, generated in class j2html.tags.generators.TagCreatorCodeGenerator
|
||||
public static AreaTag area () { return new AreaTag(); }
|
||||
public static AreaTag area (Attr.ShortForm shortAttr) { return Attr.addTo( new AreaTag(), shortAttr); }
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package j2html.tags.specialized.generated;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
import j2html.tags.attributes.*;
|
||||
|
||||
public final class BodyTag extends ContainerTag<BodyTag>
|
||||
implements
|
||||
IOnafterprint<BodyTag>,
|
||||
IOnbeforeprint<BodyTag>,
|
||||
IOnbeforeunload<BodyTag>,
|
||||
IOnerror<BodyTag>,
|
||||
IOnhashchange<BodyTag>,
|
||||
IOnload<BodyTag>,
|
||||
IOnoffline<BodyTag>,
|
||||
IOnonline<BodyTag>,
|
||||
IOnpagehide<BodyTag>,
|
||||
IOnpageshow<BodyTag>,
|
||||
IOnpopstate<BodyTag>,
|
||||
IOnresize<BodyTag>,
|
||||
IOnstorage<BodyTag>,
|
||||
IOnunload<BodyTag> {
|
||||
|
||||
public BodyTag() {
|
||||
super("body");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package j2html.tags.specialized.manual;
|
||||
package j2html.tags.specialized.generated;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package j2html.tags.specialized.generated;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
|
||||
public final class HtmlTag extends ContainerTag<HtmlTag> {
|
||||
|
||||
public HtmlTag() {
|
||||
super("html");
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package j2html.tags.specialized.manual;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
|
||||
public final class BodyTag extends ContainerTag<BodyTag> {
|
||||
|
||||
public BodyTag() {
|
||||
super("body");
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package j2html.tags.specialized.manual;
|
||||
|
||||
import j2html.Config;
|
||||
import j2html.attributes.Attribute;
|
||||
import j2html.rendering.TagBuilder;
|
||||
import j2html.rendering.FlatHtml;
|
||||
import j2html.rendering.HtmlBuilder;
|
||||
import j2html.rendering.IndentedHtml;
|
||||
import j2html.tags.Tag;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class HtmlTag extends Tag<HtmlTag> {
|
||||
|
||||
private final Optional<HeadTag> head;
|
||||
private final Optional<BodyTag> body;
|
||||
|
||||
public HtmlTag() {
|
||||
super("html");
|
||||
|
||||
head = Optional.empty();
|
||||
body = Optional.empty();
|
||||
}
|
||||
|
||||
public HtmlTag(HeadTag head) {
|
||||
super("html");
|
||||
this.head = Optional.of(head);
|
||||
this.body = Optional.empty();
|
||||
}
|
||||
|
||||
public HtmlTag(BodyTag body) {
|
||||
super("html");
|
||||
this.head = Optional.empty();
|
||||
this.body = Optional.of(body);
|
||||
}
|
||||
|
||||
public HtmlTag(HeadTag head, BodyTag body) {
|
||||
super("html");
|
||||
this.head = Optional.of(head);
|
||||
this.body = Optional.of(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) throws IOException {
|
||||
TagBuilder tagBuilder = builder.appendStartTag("html");
|
||||
for(Attribute attribute : getAttributes()){
|
||||
attribute.render(tagBuilder, model);
|
||||
}
|
||||
tagBuilder.completeTag();
|
||||
|
||||
if(head.isPresent()){
|
||||
head.get().render(builder, model);
|
||||
}
|
||||
|
||||
if(body.isPresent()){
|
||||
body.get().render(builder, model);
|
||||
}
|
||||
|
||||
builder.appendEndTag("html");
|
||||
|
||||
return builder.output();
|
||||
}
|
||||
|
||||
public String renderFormatted() {
|
||||
try {
|
||||
return render(IndentedHtml.into(new StringBuilder(), Config.global())).toString();
|
||||
}catch (IOException e){
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void renderModel(Appendable writer, Object model) throws IOException {
|
||||
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
|
||||
? (HtmlBuilder<?>) writer
|
||||
: FlatHtml.into(writer, Config.global());
|
||||
|
||||
render(builder, model);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package j2html.comparison.j2html;
|
||||
|
||||
import j2html.tags.specialized.manual.HtmlTag;
|
||||
import j2html.tags.specialized.generated.HtmlTag;
|
||||
|
||||
import static j2html.TagCreator.attrs;
|
||||
import static j2html.TagCreator.body;
|
||||
|
||||
@@ -2,7 +2,7 @@ package j2html.comparison.j2html;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
import j2html.tags.DomContent;
|
||||
import j2html.tags.specialized.manual.HtmlTag;
|
||||
import j2html.tags.specialized.generated.HtmlTag;
|
||||
|
||||
import static j2html.TagCreator.attrs;
|
||||
import static j2html.TagCreator.body;
|
||||
|
||||
@@ -3,13 +3,13 @@ package j2html.tags;
|
||||
import j2html.Config;
|
||||
import j2html.attributes.Attribute;
|
||||
import j2html.model.DynamicHrefAttribute;
|
||||
import j2html.tags.specialized.generated.HtmlTag;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import j2html.tags.specialized.manual.HtmlTag;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.body;
|
||||
import static j2html.TagCreator.div;
|
||||
import static j2html.TagCreator.footer;
|
||||
|
||||
Reference in New Issue
Block a user