Skip to content

Introduce DefaultHtmlBuilder #196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions library/src/main/java/j2html/Config.java
Original file line number Diff line number Diff line change
@@ -7,14 +7,14 @@
import j2html.utils.Minifier;
import j2html.utils.TextEscaper;

import java.util.Collections;

public class Config {

/**
* Change this to configure text-escaping
* For example, to disable escaping, do <code>{@code Config.textEscaper = text -> text;}</code>
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withTextEscaper(TextEscaper)}
*/
@Deprecated
public static TextEscaper textEscaper = EscapeUtil::escape;
/**
* Change this to configure css-minification.
@@ -29,14 +29,18 @@ public class Config {
/**
* Change this to configure enable/disable closing empty tags
* The default is to NOT close them
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withEmptyTagsClosed(boolean)}
*/
@Deprecated
public static boolean closeEmptyTags = false;
private static String FOUR_SPACES = " ";

/**
* Change this to configure indentation when rendering formatted html
* The default is four spaces
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withIndenter(Indenter)}
*/
public static Indenter indenter = (level, text) -> String.join("", Collections.nCopies(level, FOUR_SPACES)) + text;
@Deprecated
public static Indenter indenter = Indenter.defaults();


private TextEscaper _textEscaper;
@@ -93,6 +97,10 @@ public Indenter indenter() {
return _indenter;
}

/**
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withTextEscaper(TextEscaper)}
*/
@Deprecated
public Config withTextEscaper(TextEscaper textEscaper){
Config copy = new Config(this);
copy._textEscaper = textEscaper;
@@ -111,12 +119,20 @@ public Config withJsMinifier(Minifier jsMinifier){
return copy;
}

/**
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withEmptyTagsClosed(boolean)}
*/
@Deprecated
public Config withEmptyTagsClosed(boolean closeEmptyTags){
Config copy = new Config(this);
copy._closeEmptyTags = closeEmptyTags;
return copy;
}

/**
* @deprecated in favor of {@link j2html.rendering.DefaultHtmlBuilder#withIndenter(Indenter)}
*/
@Deprecated
public Config withIndenter(Indenter indenter){
Config copy = new Config(this);
copy._indenter = indenter;
@@ -128,7 +144,7 @@ public Config withIndenter(Indenter indenter){
CSSMin::compressCss,
JSMin::compressJs,
false,
(level, text) -> String.join("", Collections.nCopies(level, FOUR_SPACES)) + text
Indenter.defaults()
);

public static final Config defaults() {
125 changes: 125 additions & 0 deletions library/src/main/java/j2html/rendering/DefaultHtmlBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package j2html.rendering;

import j2html.Config;
import j2html.utils.Indenter;
import j2html.utils.TextEscaper;

/**
* Default entry point for constructing an {@link HtmlBuilder} instance.
* Examples:
*
* <pre>
* HtmlTag html = ...
* Appendable out = ...
* html.render(DefaultHtmlBuilder.into(out));
* </pre>
*
* will write the HTML into {@code out} without any line breaks or indentation
* using the default settings of {@link Config#defaults()}.
* <p>
*
* <pre>
* html.render(DefaultHtmlBuilder.indented(true).into(out));
* </pre>
*
* will write the HTML into {@code out} with line breaks and indentation using
* the default settings and the indenter {@link Indenter#defaults()}.
* <p>
*
* <pre>
* html.render(DefaultHtmlBuilder.indented(true).withIndenter(Indenter.with("\t")).into(out));
* </pre>
*
* will use the tab character {@code \t} for indentation.
* <p>
* A different {@link TextEscaper} can be provided using
* {@link #withTextEscaper(TextEscaper)}, a different setting for the closing of
* empty tags can be applied with {@link #withEmptyTagsClosed(boolean)}.
* <p>
* There is also a convenience method {@link #inMemory()} for rendering the HTML
* into a String:
*
* <pre>
* String text = html.render(DefaultHtmlBuilder.with...().inMemory()).toString();
* </pre>
*/
public class DefaultHtmlBuilder {

public static <A extends Appendable> HtmlBuilder<A> into(A out) {
return new Configurer().into(out);
}

public static HtmlBuilder<StringBuilder> inMemory() {
return into(new StringBuilder());
}

public static Configurer indented(boolean indented) {
return new Configurer().indented(indented);
}

public static Configurer withEmptyTagsClosed(boolean closeTags) {
return new Configurer().withEmptyTagsClosed(closeTags);
}

public static Configurer withTextEscaper(TextEscaper textEscaper) {
return new Configurer().withTextEscaper(textEscaper);
}

public static Configurer withIndenter(Indenter indenter) {
return new Configurer().withIndenter(indenter);
}

/**
* @deprecated will be removed in a future version
*/
@Deprecated
public static Configurer withConfig(Config config) {
return new Configurer(config);
}

public static class Configurer {
private boolean indented;
private Config config;

private Configurer() {
this(Config.defaults());
}

private Configurer(Config config) {
this.config = config;
this.indented = false;
}

@SuppressWarnings("deprecation")
public <A extends Appendable> HtmlBuilder<A> into(A out) {
return this.indented ? IndentedHtml.into(out, this.config) : FlatHtml.into(out, this.config);
}

public HtmlBuilder<StringBuilder> inMemory() {
return into(new StringBuilder());
}

public Configurer indented(boolean indented) {
this.indented = indented;
return this;
}

@SuppressWarnings("deprecation")
public Configurer withEmptyTagsClosed(boolean closeTags) {
this.config = this.config.withEmptyTagsClosed(closeTags);
return this;
}

@SuppressWarnings("deprecation")
public Configurer withTextEscaper(TextEscaper textEscaper) {
this.config = this.config.withTextEscaper(textEscaper);
return this;
}

@SuppressWarnings("deprecation")
public Configurer withIndenter(Indenter indenter) {
this.config = this.config.withIndenter(indenter);
return this;
}
}
}
6 changes: 6 additions & 0 deletions library/src/main/java/j2html/rendering/FlatHtml.java
Original file line number Diff line number Diff line change
@@ -9,7 +9,10 @@
* Composes HTML without any extra line breaks or indentation.
*
* @param <T> The type of the Appendable to which HTML will be appended.
*
* @deprecated in favor of {@link DefaultHtmlBuilder}
*/
// should be made package private in 2.0
public class FlatHtml<T extends Appendable> implements HtmlBuilder<T> {

/**
@@ -20,6 +23,7 @@ public class FlatHtml<T extends Appendable> implements HtmlBuilder<T> {
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for flat HTML.
*/
@Deprecated
public static final <T extends Appendable> FlatHtml<T> into(T out) {
return new FlatHtml<>(out, Config.defaults());
}
@@ -43,6 +47,7 @@ public static final <T extends Appendable> FlatHtml<T> into(T out, Config config
*
* @return An HtmlBuilder for flat HTML.
*/
@Deprecated
public static final FlatHtml<StringBuilder> inMemory() {
return into(new StringBuilder());
}
@@ -53,6 +58,7 @@ public static final FlatHtml<StringBuilder> inMemory() {
* @param config The Config which will specify text escapement, tag closing, etc.
* @return An HtmlBuilder for flat HTML.
*/
@Deprecated
public static final FlatHtml<StringBuilder> inMemory(Config config) {
return into(new StringBuilder(), config);
}
3 changes: 3 additions & 0 deletions library/src/main/java/j2html/rendering/HtmlBuilder.java
Original file line number Diff line number Diff line change
@@ -7,6 +7,9 @@
* Appendable, and support appending HTML-specific character
* sequences to that Appendable.
* <p>
* This library provides configurable implementations for flat and
* indented HTML, which can be obtained from the {@link DefaultHtmlBuilder}.
* <p>
* Note: HtmlBuilder extends Appendable for compatibility with
* previous version of this library. This extension will probably be
* removed in the future, so avoid relying on the deprecated methods
6 changes: 6 additions & 0 deletions library/src/main/java/j2html/rendering/IndentedHtml.java
Original file line number Diff line number Diff line change
@@ -12,7 +12,10 @@
* Composes HTML with lines breaks and indentation between tags and text.
*
* @param <T> The type of the Appendable to which HTML will be appended.
*
* @deprecated in favor of {@link DefaultHtmlBuilder}
*/
// should be made package private in 2.0
public class IndentedHtml<T extends Appendable> implements HtmlBuilder<T> {

/**
@@ -23,6 +26,7 @@ public class IndentedHtml<T extends Appendable> implements HtmlBuilder<T> {
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for indented HTML.
*/
@Deprecated
public static final <T extends Appendable> IndentedHtml<T> into(T out) {
return new IndentedHtml<>(out, Config.defaults());
}
@@ -46,6 +50,7 @@ public static final <T extends Appendable> IndentedHtml<T> into(T out, Config co
*
* @return An HtmlBuilder for indented HTML.
*/
@Deprecated
public static final IndentedHtml<StringBuilder> inMemory() {
return into(new StringBuilder());
}
@@ -57,6 +62,7 @@ public static final IndentedHtml<StringBuilder> inMemory() {
* @param config The Config which will specify indentation, text escapement, tag closing, etc.
* @return An HtmlBuilder for indented HTML.
*/
@Deprecated
public static final IndentedHtml<StringBuilder> inMemory(Config config) {
return into(new StringBuilder(), config);
}
11 changes: 5 additions & 6 deletions library/src/main/java/j2html/tags/ContainerTag.java
Original file line number Diff line number Diff line change
@@ -2,11 +2,9 @@

import j2html.Config;
import j2html.attributes.Attribute;
import j2html.rendering.TagBuilder;
import j2html.rendering.FlatHtml;
import j2html.rendering.DefaultHtmlBuilder;
import j2html.rendering.HtmlBuilder;
import j2html.rendering.IndentedHtml;

import j2html.rendering.TagBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -145,9 +143,10 @@ public int getNumChildren() {
*
* @return the rendered and formatted string
*/
@SuppressWarnings("deprecation")
public String renderFormatted() {
try {
return render(IndentedHtml.into(new StringBuilder(), Config.global())).toString();
return render(DefaultHtmlBuilder.withConfig(Config.global()).indented(true).inMemory()).toString();
}catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
@@ -179,7 +178,7 @@ public <A extends Appendable> A render(HtmlBuilder<A> builder, Object model) thr
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
: DefaultHtmlBuilder.withConfig(Config.global()).into(writer);

render(builder, model);
}
7 changes: 3 additions & 4 deletions library/src/main/java/j2html/tags/EmptyTag.java
Original file line number Diff line number Diff line change
@@ -2,10 +2,9 @@

import j2html.Config;
import j2html.attributes.Attribute;
import j2html.rendering.TagBuilder;
import j2html.rendering.FlatHtml;
import j2html.rendering.DefaultHtmlBuilder;
import j2html.rendering.HtmlBuilder;

import j2html.rendering.TagBuilder;
import java.io.IOException;

public class EmptyTag<T extends EmptyTag<T>> extends Tag<T> {
@@ -35,7 +34,7 @@ public <A extends Appendable> A render(HtmlBuilder<A> builder, Object model) thr
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
: DefaultHtmlBuilder.withConfig(Config.global()).into(writer);

render(builder, model);
}
8 changes: 4 additions & 4 deletions library/src/main/java/j2html/tags/Renderable.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package j2html.tags;

import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.DefaultHtmlBuilder;
import j2html.rendering.HtmlBuilder;

import java.io.IOException;
import java.io.UncheckedIOException;

@@ -42,9 +41,10 @@ default <T extends Appendable> T render(HtmlBuilder<T> builder) throws IOExcepti
* Create a StringBuilder and use it to render the Renderable and it's
* children
*/
@SuppressWarnings("deprecation")
default String render() {
try {
return render(FlatHtml.into(new StringBuilder(), Config.global())).toString();
return render(DefaultHtmlBuilder.withConfig(Config.global()).inMemory()).toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -60,7 +60,7 @@ default void render(Appendable writer) throws IOException {
if (writer instanceof HtmlBuilder) {
render((HtmlBuilder<? extends Appendable>) writer);
} else {
render(FlatHtml.into(writer, Config.global()));
render(DefaultHtmlBuilder.withConfig(Config.global()).into(writer));
}
}

5 changes: 2 additions & 3 deletions library/src/main/java/j2html/tags/Text.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package j2html.tags;

import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.DefaultHtmlBuilder;
import j2html.rendering.HtmlBuilder;

import java.io.IOException;

public class Text extends DomContent {
@@ -25,7 +24,7 @@ public <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) thr
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
: DefaultHtmlBuilder.withConfig(Config.global()).into(writer);

render(builder, model);
}
5 changes: 2 additions & 3 deletions library/src/main/java/j2html/tags/UnescapedText.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package j2html.tags;

import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.DefaultHtmlBuilder;
import j2html.rendering.HtmlBuilder;

import java.io.IOException;

public class UnescapedText extends DomContent {
@@ -25,7 +24,7 @@ public <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) thr
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
: DefaultHtmlBuilder.withConfig(Config.global()).into(writer);

render(builder, model);
}
11 changes: 11 additions & 0 deletions library/src/main/java/j2html/utils/Indenter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
package j2html.utils;

import java.util.Collections;

@FunctionalInterface
public interface Indenter {

String indent(int level, String text);

static Indenter with(String indentString) {
return (level, text) -> String.join("", Collections.nCopies(level, indentString)) + text;
}

static Indenter defaults() {
return with(" ");
}
}
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ public void renderModel(Appendable writer, Object model) throws IOException {

// Rendering with an HtmlBuilder defers to the original methods.
assertThat(
dom.render(FlatHtml.inMemory(), "success").toString(),
dom.render(DefaultHtmlBuilder.inMemory(), "success").toString(),
is("<div>success</div>")
);
}
@@ -85,19 +85,19 @@ public void client_classes_which_implement_attribute_rendering_continue_to_work_
assertThat(stringBuilder.toString(), is(" mock=\"null\""));

assertThat(
mock.render(FlatHtml.inMemory(), "success").toString(),
mock.render(DefaultHtmlBuilder.inMemory(), "success").toString(),
is(" mock=\"success\"")
);

// In empty tags.
assertThat(
input().attr(mock).render(FlatHtml.inMemory(), "success").toString(),
input().attr(mock).render(DefaultHtmlBuilder.inMemory(), "success").toString(),
is("<input mock=\"success\">")
);

// In container tags.
assertThat(
div().attr(mock).render(FlatHtml.inMemory(), "success").toString(),
div().attr(mock).render(DefaultHtmlBuilder.inMemory(), "success").toString(),
is("<div mock=\"success\"></div>")
);
}
14 changes: 6 additions & 8 deletions library/src/test/java/j2html/tags/TextTest.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package j2html.tags;

import j2html.rendering.FlatHtml;
import j2html.rendering.IndentedHtml;
import org.junit.Test;

import j2html.rendering.DefaultHtmlBuilder;
import java.io.IOException;
import org.junit.Test;

import static j2html.TagCreator.rawHtml;
import static j2html.TagCreator.text;
@@ -15,13 +13,13 @@ public class TextTest {

@Test
public void null_text_is_rendered_as_a_string_literal() throws IOException {
assertThat(text(null).render(FlatHtml.inMemory()).toString(), is("null"));
assertThat(text(null).render(IndentedHtml.inMemory()).toString(), is("null\n"));
assertThat(text(null).render(DefaultHtmlBuilder.inMemory()).toString(), is("null"));
assertThat(text(null).render(DefaultHtmlBuilder.indented(true).inMemory()).toString(), is("null\n"));
}

@Test
public void null_unescaped_text_is_rendered_as_a_string_literal() throws IOException {
assertThat(rawHtml(null).render(FlatHtml.inMemory()).toString(), is("null"));
assertThat(rawHtml(null).render(IndentedHtml.inMemory()).toString(), is("null\n"));
assertThat(rawHtml(null).render(DefaultHtmlBuilder.inMemory()).toString(), is("null"));
assertThat(rawHtml(null).render(DefaultHtmlBuilder.indented(true).inMemory()).toString(), is("null\n"));
}
}