Skip to content

Latest commit

 

History

History
153 lines (105 loc) · 5.67 KB

CONTRIBUTING.md

File metadata and controls

153 lines (105 loc) · 5.67 KB

Contributing

This Project is currently accepting Contributions. Have a look at the Issues for Inspiration.

Requirements

  • JDK >= 1.8 (see pom.xml)
  • Maven

Project Goals

As stated in the README, the Goal of this Project is to enjoy typesafe, performant HTML generation in Java.

For preventing performance regressions, there are Tests.

Coding Style

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.

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.

Guide to configuring EOL with git

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 j2html-codegen/ directory which contains everything needed to generate the code.

For simplicity (and also to avoid extra dependencies), they do not format the code correctly.

So if you change the Code-Generation Code, you may need to reformat the generated files to fit the Coding Style.

Contribution Workflow

The workflow (most of the time) consists of:

  • Comment (on Issue or PR) to find out what needs Work
  • Get Feedback on your Ideas
  • Fork this repo
  • Open a PR
  • Adjust the PR until it is merged or discarded

Project Architecture

j2html/src/main/java/j2html/TagCreator.java

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(DomContent... dc) {
    return new HtmlTag().with(dc);
}

which can be used in Projects using this dependency as

html(
    head(
        script("https://example.com/my/js/files.js")
    ),
    body(
        div(
            h1("Hello World")
        ).withClasses("container")
    )
)

How are the different HTML Tags implemented?

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 j2html/src/main/java/j2html/tags/specialized 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.

For Reference which Tags support which Attributes, see HTML Attribute Reference.

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.

Dissecting IAccept.java:

public interface IAccept<T extends Tag> extends IInstance<T> {
    default T withAccept(final String accept_) {
        return self().attr("accept", accept_);
    }

    default T withCondAccept(final boolean enable, final String accept_) {
        if (enable) {
            self().attr("accept", accept_);
        }
        return self();
    }
}

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> {
    default T self() {  return (T) this;  }
}

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. 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 j2html-codegen/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)

Other special classes / interfaces in J2HTML

  • 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
  • DomContent.java

How is the Code generation for the Attribute specific Interfaces parameterized?

Attributes differ in their 'type' . Some of them can be set with numbers (which are converted into strings in the html). 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.

j2html/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.