Compare commits
65 Commits
j2html-0.7
...
j2html-0.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8052cdaff1 | ||
|
|
34b2410830 | ||
|
|
75d361fa20 | ||
|
|
3e91da0640 | ||
|
|
d1613b0570 | ||
|
|
a841271ba4 | ||
|
|
9272438940 | ||
|
|
3d43eb159f | ||
|
|
30bfe4ea7f | ||
|
|
7409772c20 | ||
|
|
29e16df057 | ||
|
|
6903bcbe4d | ||
|
|
56b830782f | ||
|
|
10a400ac28 | ||
|
|
e0b0425da4 | ||
|
|
f44d62d93a | ||
|
|
652b6921c7 | ||
|
|
d7e56686d1 | ||
|
|
cc289b8430 | ||
|
|
85d0ab023c | ||
|
|
0b3ca28cf3 | ||
|
|
45a7c32d88 | ||
|
|
733199cd15 | ||
|
|
df1e4da96d | ||
|
|
05dcf6d679 | ||
|
|
b5d7f5fe18 | ||
|
|
872baeeeea | ||
|
|
fcc42cfd8f | ||
|
|
db8d968f7e | ||
|
|
673a19faaa | ||
|
|
96020f8396 | ||
|
|
91c3f42696 | ||
|
|
0efd3c6f0c | ||
|
|
b73c5d0c14 | ||
|
|
977c31dad5 | ||
|
|
0c1cb2be10 | ||
|
|
d09eb8597c | ||
|
|
b8a3882529 | ||
|
|
b366207e30 | ||
|
|
3821671a65 | ||
|
|
66fff8db69 | ||
|
|
b11af765fa | ||
|
|
d331789074 | ||
|
|
314de2459a | ||
|
|
2beb4e903e | ||
|
|
d29da958e1 | ||
|
|
595d658a15 | ||
|
|
dd4a025ad0 | ||
|
|
3c42c7d4f4 | ||
|
|
871405c414 | ||
|
|
e7588aeb6a | ||
|
|
074aae4609 | ||
|
|
66479f52c5 | ||
|
|
a5e79b536d | ||
|
|
79e062355e | ||
|
|
947f12d5a1 | ||
|
|
a46ba46bda | ||
|
|
41da131bbc | ||
|
|
9428bf7397 | ||
|
|
67e1c887b8 | ||
|
|
bdd8dcbd2c | ||
|
|
b9d1f3a74d | ||
|
|
530565c9df | ||
|
|
30d1331c28 | ||
|
|
58b2444ed4 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -93,4 +93,9 @@ pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
### Eclipse ###
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
buildNumber.properties
|
||||
|
||||
8
.travis.yml
Normal file
8
.travis.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- oracle-java8-installer
|
||||
14
README.md
14
README.md
@@ -1,19 +1,23 @@
|
||||

|
||||

|
||||

|
||||
|
||||
# j2html
|
||||
Java to HTML generator. Enjoy typesafe HTML generation.
|
||||
|
||||
The project webpage is [j2html.com](http://j2html.com)
|
||||
The project webpage is [j2html.com](http://j2html.com).
|
||||
|
||||
##Getting started
|
||||
###Add the maven dependency
|
||||
## Getting started
|
||||
### Add the maven dependency
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.j2html</groupId>
|
||||
<artifactId>j2html</artifactId>
|
||||
<version>0.5.0</version>
|
||||
<version>0.88</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
###Import TagCreator and start building HTML
|
||||
### Import TagCreator and start building HTML
|
||||
```java
|
||||
import static j2html.TagCreator.*;
|
||||
|
||||
|
||||
24
pom.xml
24
pom.xml
@@ -10,7 +10,7 @@
|
||||
|
||||
<groupId>com.j2html</groupId>
|
||||
<artifactId>j2html</artifactId>
|
||||
<version>0.7</version>
|
||||
<version>0.99</version>
|
||||
|
||||
<name>j2html</name>
|
||||
<description>Java to HTML builder with a fluent API</description>
|
||||
@@ -44,16 +44,19 @@
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.javascript</groupId>
|
||||
<artifactId>closure-compiler</artifactId>
|
||||
<version>r2388</version>
|
||||
<version>3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -66,8 +69,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -84,7 +87,7 @@
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireJavaVersion>
|
||||
<version>[1.7,)</version>
|
||||
<version>[1.8,)</version>
|
||||
</requireJavaVersion>
|
||||
</rules>
|
||||
</configuration>
|
||||
@@ -99,7 +102,6 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -1,24 +1,98 @@
|
||||
package j2html;
|
||||
|
||||
import j2html.tags.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
import j2html.tags.DomContent;
|
||||
import j2html.tags.EmptyTag;
|
||||
import j2html.tags.InlineStaticResource;
|
||||
import j2html.tags.Text;
|
||||
import j2html.tags.UnescapedText;
|
||||
|
||||
public class TagCreator {
|
||||
|
||||
private TagCreator() {}
|
||||
|
||||
/**
|
||||
* Generic if-expression to do if'ing inside method calls
|
||||
*
|
||||
* @param <T> The derived generic parameter type
|
||||
* @param condition the condition to if-on
|
||||
* @param ifValue the value to return if condition is true
|
||||
* @return value if condition is true, null otherwise
|
||||
*/
|
||||
public static <T> T iff(boolean condition, T ifValue) {
|
||||
return condition ? ifValue : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link j2html.TagCreator#iff}, but returns else-value instead of null
|
||||
*/
|
||||
public static <T> T iffElse(boolean condition, T ifValue, T elseValue) {
|
||||
return condition ? ifValue : elseValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DomContent object containing HTML using a mapping function on a collection
|
||||
* Intended usage: {@literal each(numbers, n -> li(n.toString()))}
|
||||
*
|
||||
* @param <T> The derived generic parameter type
|
||||
* @param collection the collection to iterate over, ex: a list of values "1, 2, 3"
|
||||
* @param mapper the mapping function, ex: {@literal "n -> li(n.toString())"}
|
||||
* @return rawHtml containing mapped data {@literal (ex. docs: <li>1</li><li>2</li><li>3</li>)}
|
||||
*/
|
||||
public static <T> DomContent each(Collection<T> collection, Function<? super T, DomContent> mapper) {
|
||||
return rawHtml(collection.stream().map(mapper.andThen(DomContent::render)).collect(Collectors.joining()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a collection to a list, to be used with {@link j2html.TagCreator#each}
|
||||
* Intended usage: {@literal each(filter(numbers, n -> n % 2 == 0), n -> li(n.toString()))}
|
||||
*
|
||||
* @param <T> The derived generic parameter type
|
||||
* @param collection the collection to filter, ex: a list of values "1, 2, 3"
|
||||
* @param filter the filter predicate, {@literal ex: "n -> n % 2 == 0"}
|
||||
* @return the filtered collection as a list (ex. docs: 2)
|
||||
*/
|
||||
public static <T> List<T> filter(Collection<T> collection, Predicate<? super T> filter) {
|
||||
return collection.stream().filter(filter).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a String in an UnescapedText element
|
||||
*
|
||||
* @param html the input html
|
||||
* @return the input html wrapped in an UnescapedText element
|
||||
*/
|
||||
public static UnescapedText rawHtml(String html) {
|
||||
return new UnescapedText(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a String in a Text element (does html-escaping)
|
||||
*
|
||||
* @param text the input string
|
||||
* @return the input string, html-escaped
|
||||
*/
|
||||
public static Text text(String text) {
|
||||
return new Text(text);
|
||||
}
|
||||
|
||||
//Special tags
|
||||
public static ContainerTag tag(String tagName) { return new ContainerTag(tagName); }
|
||||
public static EmptyTag emptyTag(String tagName) { return new EmptyTag(tagName); }
|
||||
|
||||
public static Text text(String text) { return new Text(text); }
|
||||
public static UnescapedText unsafeHtml(String html) { return new UnescapedText(html); }
|
||||
|
||||
public static Tag styleWithInlineFile(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.CSS); }
|
||||
public static Tag scriptWithInlineFile(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.JS); }
|
||||
public static Tag styleWithInlineFile_min(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.CSS_MIN); }
|
||||
public static Tag scriptWithInlineFile_min(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.JS_MIN); }
|
||||
|
||||
public static UnescapedText fileAsString(String path) { return new UnescapedText(InlineStaticResource.getFileAsString(path)); }
|
||||
public static Text fileAsEscapedString(String path) { return new Text(InlineStaticResource.getFileAsString(path)); }
|
||||
public static Text fileAsEscapedString(String path) { return text(InlineStaticResource.getFileAsString(path)); }
|
||||
public static UnescapedText fileAsString(String path) { return rawHtml(InlineStaticResource.getFileAsString(path)); }
|
||||
|
||||
public static ContainerTag styleWithInlineFile(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.CSS); }
|
||||
public static ContainerTag scriptWithInlineFile(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.JS); }
|
||||
public static ContainerTag styleWithInlineFile_min(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.CSS_MIN); }
|
||||
public static ContainerTag scriptWithInlineFile_min(String path) { return InlineStaticResource.get(path, InlineStaticResource.TargetFormat.JS_MIN); }
|
||||
|
||||
//EmptyTags
|
||||
public static EmptyTag area() { return new EmptyTag("area"); }
|
||||
|
||||
@@ -1,114 +1,119 @@
|
||||
package j2html.attributes;
|
||||
|
||||
public class Attr {
|
||||
public static String HIDDEN = "hidden";
|
||||
public static String HIGH = "high";
|
||||
public static String HREF = "href";
|
||||
public static String HREFLANG = "hreflang";
|
||||
public static String HTTP_EQUIV = "http-equiv";
|
||||
public static String ICON = "icon";
|
||||
public static String ID = "id";
|
||||
public static String ISMAP = "ismap";
|
||||
public static String ITEMPROP = "itemprop";
|
||||
public static String KEYTYPE = "keytype";
|
||||
public static String KIND = "kind";
|
||||
public static String LABEL = "label";
|
||||
public static String LANG = "lang";
|
||||
public static String LANGUAGE = "language";
|
||||
public static String LIST = "list";
|
||||
public static String LOOP = "loop";
|
||||
public static String LOW = "low";
|
||||
public static String MANIFEST = "manifest";
|
||||
public static String MAX = "max";
|
||||
public static String MAXLENGTH = "maxlength";
|
||||
public static String MEDIA = "media";
|
||||
public static String METHOD = "method";
|
||||
public static String MIN = "min";
|
||||
public static String MULTIPLE = "multiple";
|
||||
public static String NAME = "name";
|
||||
public static String NOVALIDATE = "novalidate";
|
||||
public static String OPEN = "open";
|
||||
public static String OPTIMUM = "optimum";
|
||||
public static String PATTERN = "pattern";
|
||||
public static String PING = "ping";
|
||||
public static String PLACEHOLDER = "placeholder";
|
||||
public static String POSTER = "poster";
|
||||
public static String PRELOAD = "preload";
|
||||
public static String PUBDATE = "pubdate";
|
||||
public static String RADIOGROUP = "radiogroup";
|
||||
public static String READONLY = "readonly";
|
||||
public static String REL = "rel";
|
||||
public static String REQUIRED = "required";
|
||||
public static String REVERSED = "reversed";
|
||||
public static String ROWS = "rows";
|
||||
public static String ROWSPAN = "rowspan";
|
||||
public static String SANDBOX = "sandbox";
|
||||
public static String SPELLCHECK = "spellcheck";
|
||||
public static String SCOPE = "scope";
|
||||
public static String SCOPED = "scoped";
|
||||
public static String SEAMLESS = "seamless";
|
||||
public static String SELECTED = "selected";
|
||||
public static String SHAPE = "shape";
|
||||
public static String SIZE = "size";
|
||||
public static String SIZES = "sizes";
|
||||
public static String SPAN = "span";
|
||||
public static String SRC = "src";
|
||||
public static String SRCDOC = "srcdoc";
|
||||
public static String SRCLANG = "srclang";
|
||||
public static String SRCSET = "srcset";
|
||||
public static String START = "start";
|
||||
public static String STEP = "step";
|
||||
public static String STYLE = "style";
|
||||
public static String SUMMARY = "summary";
|
||||
public static String TABINDEX = "tabindex";
|
||||
public static String TARGET = "target";
|
||||
public static String TITLE = "title";
|
||||
public static String TYPE = "type";
|
||||
public static String USEMAP = "usemap";
|
||||
public static String VALUE = "value";
|
||||
public static String WIDTH = "width";
|
||||
public static String WRAP = "wrap";
|
||||
public static String BORDER = "border";
|
||||
public static String BUFFERED = "buffered";
|
||||
public static String CHALLENGE = "challenge";
|
||||
public static String CHARSET = "charset";
|
||||
public static String CHECKED = "checked";
|
||||
public static String CITE = "cite";
|
||||
public static String CLASS = "class";
|
||||
public static String COLOR = "color";
|
||||
public static String COLS = "cols";
|
||||
public static String COLSPAN = "colspan";
|
||||
public static String CONTENT = "content";
|
||||
public static String CONTENTEDITABLE = "contenteditable";
|
||||
public static String CONTEXTMENU = "contextmenu";
|
||||
public static String CONTROLS = "controls";
|
||||
public static String COORDS = "coords";
|
||||
public static String DATA = "data";
|
||||
public static String DATETIME = "datetime";
|
||||
public static String DEFAULT = "default";
|
||||
public static String DEFER = "defer";
|
||||
public static String DIR = "dir";
|
||||
public static String DIRNAME = "dirname";
|
||||
public static String DISABLED = "disabled";
|
||||
public static String DOWNLOAD = "download";
|
||||
public static String DRAGGABLE = "draggable";
|
||||
public static String DROPZONE = "dropzone";
|
||||
public static String ENCTYPE = "enctype";
|
||||
public static String FOR = "for";
|
||||
public static String FORM = "form";
|
||||
public static String FORMACTION = "formaction";
|
||||
public static String HEADERS = "headers";
|
||||
public static String HEIGHT = "height";
|
||||
public static String ACCEPT = "accept";
|
||||
public static String ACCEPT_CHARSET = "accept-charset";
|
||||
public static String ACCESSKEY = "accesskey";
|
||||
public static String ACTION = "action";
|
||||
public static String ALIGN = "align";
|
||||
public static String ALT = "alt";
|
||||
public static String ASYNC = "async";
|
||||
public static String AUTOCOMPLETE = "autocomplete";
|
||||
public static String AUTOFOCUS = "autofocus";
|
||||
public static String AUTOPLAY = "autoplay";
|
||||
public static String AUTOSAVE = "autosave";
|
||||
|
||||
private Attr() {
|
||||
}
|
||||
|
||||
public static final String ACCEPT = "accept";
|
||||
public static final String ACCEPT_CHARSET = "accept-charset";
|
||||
public static final String ACCESSKEY = "accesskey";
|
||||
public static final String ACTION = "action";
|
||||
public static final String ALIGN = "align";
|
||||
public static final String ALT = "alt";
|
||||
public static final String ASYNC = "async";
|
||||
public static final String AUTOCOMPLETE = "autocomplete";
|
||||
public static final String AUTOFOCUS = "autofocus";
|
||||
public static final String AUTOPLAY = "autoplay";
|
||||
public static final String AUTOSAVE = "autosave";
|
||||
public static final String BORDER = "border";
|
||||
public static final String BUFFERED = "buffered";
|
||||
public static final String CHALLENGE = "challenge";
|
||||
public static final String CHARSET = "charset";
|
||||
public static final String CHECKED = "checked";
|
||||
public static final String CITE = "cite";
|
||||
public static final String CLASS = "class";
|
||||
public static final String COLOR = "color";
|
||||
public static final String COLS = "cols";
|
||||
public static final String COLSPAN = "colspan";
|
||||
public static final String CONTENT = "content";
|
||||
public static final String CONTENTEDITABLE = "contenteditable";
|
||||
public static final String CONTEXTMENU = "contextmenu";
|
||||
public static final String CONTROLS = "controls";
|
||||
public static final String COORDS = "coords";
|
||||
public static final String DATA = "data";
|
||||
public static final String DATETIME = "datetime";
|
||||
public static final String DEFAULT = "default";
|
||||
public static final String DEFER = "defer";
|
||||
public static final String DIR = "dir";
|
||||
public static final String DIRNAME = "dirname";
|
||||
public static final String DISABLED = "disabled";
|
||||
public static final String DOWNLOAD = "download";
|
||||
public static final String DRAGGABLE = "draggable";
|
||||
public static final String DROPZONE = "dropzone";
|
||||
public static final String ENCTYPE = "enctype";
|
||||
public static final String FOR = "for";
|
||||
public static final String FORM = "form";
|
||||
public static final String FORMACTION = "formaction";
|
||||
public static final String HEADERS = "headers";
|
||||
public static final String HEIGHT = "height";
|
||||
public static final String HIDDEN = "hidden";
|
||||
public static final String HIGH = "high";
|
||||
public static final String HREF = "href";
|
||||
public static final String HREFLANG = "hreflang";
|
||||
public static final String HTTP_EQUIV = "http-equiv";
|
||||
public static final String ICON = "icon";
|
||||
public static final String ID = "id";
|
||||
public static final String ISMAP = "ismap";
|
||||
public static final String ITEMPROP = "itemprop";
|
||||
public static final String KEYTYPE = "keytype";
|
||||
public static final String KIND = "kind";
|
||||
public static final String LABEL = "label";
|
||||
public static final String LANG = "lang";
|
||||
public static final String LANGUAGE = "language";
|
||||
public static final String LIST = "list";
|
||||
public static final String LOOP = "loop";
|
||||
public static final String LOW = "low";
|
||||
public static final String MANIFEST = "manifest";
|
||||
public static final String MAX = "max";
|
||||
public static final String MAXLENGTH = "maxlength";
|
||||
public static final String MEDIA = "media";
|
||||
public static final String METHOD = "method";
|
||||
public static final String MIN = "min";
|
||||
public static final String MULTIPLE = "multiple";
|
||||
public static final String NAME = "name";
|
||||
public static final String NOVALIDATE = "novalidate";
|
||||
public static final String OPEN = "open";
|
||||
public static final String OPTIMUM = "optimum";
|
||||
public static final String PATTERN = "pattern";
|
||||
public static final String PING = "ping";
|
||||
public static final String PLACEHOLDER = "placeholder";
|
||||
public static final String POSTER = "poster";
|
||||
public static final String PRELOAD = "preload";
|
||||
public static final String PUBDATE = "pubdate";
|
||||
public static final String RADIOGROUP = "radiogroup";
|
||||
public static final String READONLY = "readonly";
|
||||
public static final String REL = "rel";
|
||||
public static final String REQUIRED = "required";
|
||||
public static final String REVERSED = "reversed";
|
||||
public static final String ROLE = "role";
|
||||
public static final String ROWS = "rows";
|
||||
public static final String ROWSPAN = "rowspan";
|
||||
public static final String SANDBOX = "sandbox";
|
||||
public static final String SCOPE = "scope";
|
||||
public static final String SCOPED = "scoped";
|
||||
public static final String SEAMLESS = "seamless";
|
||||
public static final String SELECTED = "selected";
|
||||
public static final String SHAPE = "shape";
|
||||
public static final String SIZE = "size";
|
||||
public static final String SIZES = "sizes";
|
||||
public static final String SPAN = "span";
|
||||
public static final String SPELLCHECK = "spellcheck";
|
||||
public static final String SRC = "src";
|
||||
public static final String SRCDOC = "srcdoc";
|
||||
public static final String SRCLANG = "srclang";
|
||||
public static final String SRCSET = "srcset";
|
||||
public static final String START = "start";
|
||||
public static final String STEP = "step";
|
||||
public static final String STYLE = "style";
|
||||
public static final String SUMMARY = "summary";
|
||||
public static final String TABINDEX = "tabindex";
|
||||
public static final String TARGET = "target";
|
||||
public static final String TITLE = "title";
|
||||
public static final String TYPE = "type";
|
||||
public static final String USEMAP = "usemap";
|
||||
public static final String VALUE = "value";
|
||||
public static final String WIDTH = "width";
|
||||
public static final String WRAP = "wrap";
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package j2html.attributes;
|
||||
|
||||
import static org.apache.commons.lang3.StringEscapeUtils.*;
|
||||
|
||||
import j2html.utils.SimpleEscaper;
|
||||
|
||||
public class Attribute {
|
||||
private String name;
|
||||
@@ -8,7 +9,7 @@ public class Attribute {
|
||||
|
||||
public Attribute(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = escapeHtml4(value);
|
||||
this.value = SimpleEscaper.escape(value);
|
||||
}
|
||||
|
||||
public Attribute(String name) {
|
||||
@@ -17,9 +18,13 @@ public class Attribute {
|
||||
}
|
||||
|
||||
public String render() {
|
||||
if (name == null) { return ""; }
|
||||
if (value == null) { return " "+name; }
|
||||
return(" "+name+"=\""+value+"\"");
|
||||
if (name == null) {
|
||||
return "";
|
||||
}
|
||||
if (value == null) {
|
||||
return " " + name;
|
||||
}
|
||||
return (" " + name + "=\"" + value + "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,88 +1,108 @@
|
||||
package j2html.tags;
|
||||
|
||||
import j2html.attributes.Attr;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ContainerTag extends Tag {
|
||||
public class ContainerTag extends Tag<ContainerTag> {
|
||||
|
||||
public List<Tag> children;
|
||||
private List<DomContent> children;
|
||||
|
||||
public ContainerTag(String tagType) {
|
||||
super(tagType);
|
||||
public ContainerTag(String tagName) {
|
||||
super(tagName);
|
||||
this.children = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a tag to the end of this element
|
||||
* Appends a DomContent-object to the end of this element
|
||||
*
|
||||
* @param child tag to be appended
|
||||
* @param child DomContent-object to be appended
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag with(Tag child) {
|
||||
public ContainerTag with(DomContent child) {
|
||||
if (this == child) {
|
||||
throw new Error("Cannot append a tag to itself.");
|
||||
throw new RuntimeException("Cannot append a tag to itself.");
|
||||
}
|
||||
if (child == null) {
|
||||
return this; // in some cases, like when using iff(), we ignore null children
|
||||
}
|
||||
child.setParent(this);
|
||||
children.add(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call with-method based on condition
|
||||
* {@link #with(Tag child)}
|
||||
* {@link #with(DomContent child)}
|
||||
*
|
||||
* @param condition the condition to use
|
||||
* @param child DomContent-object to be appended if condition met
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag condWith(boolean condition, Tag child) {
|
||||
public ContainerTag condWith(boolean condition, DomContent child) {
|
||||
return condition ? this.with(child) : this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a list of tags to the end of this element
|
||||
* Appends a list of DomContent-objects to the end of this element
|
||||
*
|
||||
* @param children tags to be appended
|
||||
* @param children DomContent-objects to be appended
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag with(List<Tag> children) {
|
||||
public ContainerTag with(Iterable<? extends DomContent> children) {
|
||||
if (children != null) {
|
||||
for (Tag child : children) {
|
||||
for (DomContent child : children) {
|
||||
this.with(child);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call with-method based on condition
|
||||
* {@link #with(List children)}
|
||||
* {@link #with(java.lang.Iterable)}
|
||||
*
|
||||
* @param condition the condition to use
|
||||
* @param children DomContent-objects to be appended if condition met
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag condWith(boolean condition, List<Tag> children) {
|
||||
public ContainerTag condWith(boolean condition, Iterable<? extends DomContent> children) {
|
||||
return condition ? this.with(children) : this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends the tags to the end of this element
|
||||
* Appends the DomContent-objects to the end of this element
|
||||
*
|
||||
* @param children tags to be appended
|
||||
* @param children DomContent-objects to be appended
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag with(Tag... children) {
|
||||
for (Tag aChildren : children) {
|
||||
with(aChildren);
|
||||
public ContainerTag with(DomContent... children) {
|
||||
for (DomContent child : children) {
|
||||
with(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call with-method based on condition
|
||||
* {@link #with(Tag... children)}
|
||||
* {@link #with(DomContent... children)}
|
||||
*
|
||||
* @param condition the condition to use
|
||||
* @param children DomContent-objects to be appended if condition met
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag condWith(boolean condition, Tag... children) {
|
||||
public ContainerTag condWith(boolean condition, DomContent... children) {
|
||||
return condition ? this.with(children) : this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a text tag to this element
|
||||
* Appends a Text-object to this element
|
||||
*
|
||||
* @param text the text to be appended
|
||||
* @return itself for easy chaining
|
||||
@@ -91,34 +111,17 @@ public class ContainerTag extends Tag {
|
||||
return with(new Text(text));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a custom attribute
|
||||
* Render the ContainerTag and its children
|
||||
*
|
||||
* @param attribute the attribute name
|
||||
* @param value the attribute value
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public ContainerTag attr(String attribute, String value) {
|
||||
setAttribute(attribute, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call attr-method based on condition
|
||||
* {@link #attr(String attribute, String value)}
|
||||
*/
|
||||
public ContainerTag condAttr(boolean condition, String attribute, String value) {
|
||||
return condition ? attr(attribute, value) : this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the tag and its children
|
||||
* @return the rendered string
|
||||
*/
|
||||
@Override
|
||||
public String render() {
|
||||
StringBuilder rendered = new StringBuilder(renderOpenTag());
|
||||
if (children != null && children.size() > 0) {
|
||||
for (Tag child : children) {
|
||||
if (children != null && !children.isEmpty()) {
|
||||
for (DomContent child : children) {
|
||||
rendered.append(child.render());
|
||||
}
|
||||
}
|
||||
@@ -127,56 +130,14 @@ public class ContainerTag extends Tag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.render();
|
||||
public void render(Appendable writer) throws IOException {
|
||||
writer.append(renderOpenTag());
|
||||
if (children != null && !children.isEmpty()) {
|
||||
for (DomContent child : children) {
|
||||
child.render(writer);
|
||||
}
|
||||
}
|
||||
writer.append(renderCloseTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods below this point are convenience methods
|
||||
* that call attr with a predefined attribute.
|
||||
*/
|
||||
|
||||
//TODO: TEST ?
|
||||
public ContainerTag isAutoComplete() { return attr(Attr.AUTOCOMPLETE, null); }
|
||||
public ContainerTag isAutoFocus() { return attr(Attr.AUTOFOCUS, null); }
|
||||
public ContainerTag isHidden() { return attr(Attr.HIDDEN, null); }
|
||||
public ContainerTag isRequired() { return attr(Attr.REQUIRED, null); }
|
||||
public ContainerTag withAlt(String alt) { return attr(Attr.ALT, alt); }
|
||||
public ContainerTag withAction(String action) { return attr(Attr.ACTION, action); }
|
||||
public ContainerTag withCharset(String charset) { return attr(Attr.CHARSET, charset); }
|
||||
public ContainerTag withClass(String className) { return attr(Attr.CLASS, className); }
|
||||
public ContainerTag withContent(String content) { return attr(Attr.CONTENT, content); }
|
||||
public ContainerTag withHref(String href) { return attr(Attr.HREF, href); }
|
||||
public ContainerTag withId(String id) { return attr(Attr.ID, id); }
|
||||
public ContainerTag withData(String dataAttr, String value) { return attr(Attr.DATA + "-" + dataAttr, value); }
|
||||
public ContainerTag withMethod(String method) { return attr(Attr.METHOD, method); }
|
||||
public ContainerTag withName(String name) { return attr(Attr.NAME, name); }
|
||||
public ContainerTag withPlaceholder(String placeholder) { return attr(Attr.PLACEHOLDER, placeholder); }
|
||||
public ContainerTag withTarget(String target) { return attr(Attr.TARGET, target); }
|
||||
public ContainerTag withType(String type) { return attr(Attr.TYPE, type); }
|
||||
public ContainerTag withRel(String rel) { return attr(Attr.REL, rel); }
|
||||
public ContainerTag withSrc(String src) { return attr(Attr.SRC, src); }
|
||||
public ContainerTag withValue(String value) { return attr(Attr.VALUE, value); }
|
||||
|
||||
public ContainerTag withCondAutoComplete(boolean condition) { return condAttr(condition, Attr.AUTOCOMPLETE, null); }
|
||||
public ContainerTag withCondAutoFocus(boolean condition) { return condAttr(condition, Attr.AUTOFOCUS, null); }
|
||||
public ContainerTag withCondHidden(boolean condition) { return condAttr(condition, Attr.HIDDEN, null); }
|
||||
public ContainerTag withCondRequired(boolean condition) { return condAttr(condition, Attr.REQUIRED, null); }
|
||||
public ContainerTag withCondAlt(boolean condition, String alt) { return condAttr(condition, Attr.ALT, alt); }
|
||||
public ContainerTag withCondAction(boolean condition, String action) { return condAttr(condition, Attr.ACTION, action); }
|
||||
public ContainerTag withCharset(boolean condition, String charset) { return condAttr(condition, Attr.CHARSET, charset); }
|
||||
public ContainerTag withCondClass(boolean condition, String className) { return condAttr(condition, Attr.CLASS, className); }
|
||||
public ContainerTag withCondContent(boolean condition, String content) { return condAttr(condition, Attr.CONTENT, content); }
|
||||
public ContainerTag withCondHref(boolean condition, String href) { return condAttr(condition, Attr.HREF, href); }
|
||||
public ContainerTag withCondId(boolean condition, String id) { return condAttr(condition, Attr.ID, id); }
|
||||
public ContainerTag withCondData(boolean condition, String dataAttr, String value) { return condAttr(condition, Attr.DATA + "-" + dataAttr, value); }
|
||||
public ContainerTag withCondMethod(boolean condition, String method) { return condAttr(condition, Attr.METHOD, method); }
|
||||
public ContainerTag withCondName(boolean condition, String name) { return condAttr(condition, Attr.NAME, name); }
|
||||
public ContainerTag withCondPlaceholder(boolean condition, String placeholder) { return condAttr(condition, Attr.PLACEHOLDER, placeholder); }
|
||||
public ContainerTag withCondTarget(boolean condition, String target) { return condAttr(condition, Attr.TARGET, target); }
|
||||
public ContainerTag withCondType(boolean condition, String type) { return condAttr(condition, Attr.TYPE, type); }
|
||||
public ContainerTag withCondRel(boolean condition, String rel) { return condAttr(condition, Attr.REL, rel); }
|
||||
public ContainerTag withCondSrc(boolean condition, String src) { return condAttr(condition, Attr.SRC, src); }
|
||||
public ContainerTag withCondValue(boolean condition, String value) { return condAttr(condition, Attr.VALUE, value); }
|
||||
|
||||
}
|
||||
|
||||
18
src/main/java/j2html/tags/DomContent.java
Normal file
18
src/main/java/j2html/tags/DomContent.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package j2html.tags;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class DomContent {
|
||||
|
||||
public abstract String render();
|
||||
|
||||
public void render(Appendable writer) throws IOException {
|
||||
writer.append(render());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return render();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +1,14 @@
|
||||
package j2html.tags;
|
||||
|
||||
import j2html.attributes.Attr;
|
||||
import j2html.attributes.Attribute;
|
||||
public class EmptyTag extends Tag<EmptyTag> {
|
||||
|
||||
public class EmptyTag extends Tag {
|
||||
|
||||
public EmptyTag(String tagType) {
|
||||
super(tagType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom attribute
|
||||
*
|
||||
* @param attribute the attribute name
|
||||
* @param value the attribute value
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public EmptyTag attr(String attribute, String value) {
|
||||
setAttribute(attribute, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call attr-method based on condition
|
||||
* {@link #attr(String attribute, String value)}
|
||||
*/
|
||||
public EmptyTag condAttr(boolean condition, String attribute, String value) {
|
||||
return condition ? attr(attribute, value) : this;
|
||||
}
|
||||
|
||||
public String render() {
|
||||
String tagAttributes = "";
|
||||
for (Attribute attribute : attributes) {
|
||||
tagAttributes += attribute;
|
||||
}
|
||||
return "<" + tag + tagAttributes + ">";
|
||||
public EmptyTag(String tagName) {
|
||||
super(tagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.render();
|
||||
public String render() {
|
||||
return renderOpenTag();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Methods below this point are convenience methods
|
||||
* that call attr with a predefined attribute.
|
||||
*/
|
||||
|
||||
//TODO: TEST ?
|
||||
public EmptyTag isAutoComplete() { return attr(Attr.AUTOCOMPLETE, null); }
|
||||
public EmptyTag isAutoFocus() { return attr(Attr.AUTOFOCUS, null); }
|
||||
public EmptyTag isHidden() { return attr(Attr.HIDDEN, null); }
|
||||
public EmptyTag isRequired() { return attr(Attr.REQUIRED, null); }
|
||||
public EmptyTag withAlt(String alt) { return attr(Attr.ALT, alt); }
|
||||
public EmptyTag withAction(String action) { return attr(Attr.ACTION, action); }
|
||||
public EmptyTag withCharset(String charset) { return attr(Attr.CHARSET, charset); }
|
||||
public EmptyTag withClass(String className) { return attr(Attr.CLASS, className); }
|
||||
public EmptyTag withContent(String content) { return attr(Attr.CONTENT, content); }
|
||||
public EmptyTag withHref(String href) { return attr(Attr.HREF, href); }
|
||||
public EmptyTag withId(String id) { return attr(Attr.ID, id); }
|
||||
public EmptyTag withData(String dataAttr, String value) { return attr(Attr.DATA + "-" + dataAttr, value); }
|
||||
public EmptyTag withMethod(String method) { return attr(Attr.METHOD, method); }
|
||||
public EmptyTag withName(String name) { return attr(Attr.NAME, name); }
|
||||
public EmptyTag withPlaceholder(String placeholder) { return attr(Attr.PLACEHOLDER, placeholder); }
|
||||
public EmptyTag withTarget(String target) { return attr(Attr.TARGET, target); }
|
||||
public EmptyTag withType(String type) { return attr(Attr.TYPE, type); }
|
||||
public EmptyTag withRel(String rel) { return attr(Attr.REL, rel); }
|
||||
public EmptyTag withSrc(String src) { return attr(Attr.SRC, src); }
|
||||
public EmptyTag withValue(String value) { return attr(Attr.VALUE, value); }
|
||||
|
||||
public EmptyTag withCondAutoComplete(boolean condition) { return condAttr(condition, Attr.AUTOCOMPLETE, null); }
|
||||
public EmptyTag withCondAutoFocus(boolean condition) { return condAttr(condition, Attr.AUTOFOCUS, null); }
|
||||
public EmptyTag withCondHidden(boolean condition) { return condAttr(condition, Attr.HIDDEN, null); }
|
||||
public EmptyTag withCondRequired(boolean condition) { return condAttr(condition, Attr.REQUIRED, null); }
|
||||
public EmptyTag withCondAlt(boolean condition, String alt) { return condAttr(condition, Attr.ALT, alt); }
|
||||
public EmptyTag withCondAction(boolean condition, String action) { return condAttr(condition, Attr.ACTION, action); }
|
||||
public EmptyTag withCharset(boolean condition, String charset) { return condAttr(condition, Attr.CHARSET, charset); }
|
||||
public EmptyTag withCondClass(boolean condition, String className) { return condAttr(condition, Attr.CLASS, className); }
|
||||
public EmptyTag withCondContent(boolean condition, String content) { return condAttr(condition, Attr.CONTENT, content); }
|
||||
public EmptyTag withCondHref(boolean condition, String href) { return condAttr(condition, Attr.HREF, href); }
|
||||
public EmptyTag withCondId(boolean condition, String id) { return condAttr(condition, Attr.ID, id); }
|
||||
public EmptyTag withCondData(boolean condition, String dataAttr, String value) { return condAttr(condition, Attr.DATA + "-" + dataAttr, value); }
|
||||
public EmptyTag withCondMethod(boolean condition, String method) { return condAttr(condition, Attr.METHOD, method); }
|
||||
public EmptyTag withCondName(boolean condition, String name) { return condAttr(condition, Attr.NAME, name); }
|
||||
public EmptyTag withCondPlaceholder(boolean condition, String placeholder) { return condAttr(condition, Attr.PLACEHOLDER, placeholder); }
|
||||
public EmptyTag withCondTarget(boolean condition, String target) { return condAttr(condition, Attr.TARGET, target); }
|
||||
public EmptyTag withCondType(boolean condition, String type) { return condAttr(condition, Attr.TYPE, type); }
|
||||
public EmptyTag withCondRel(boolean condition, String rel) { return condAttr(condition, Attr.REL, rel); }
|
||||
public EmptyTag withCondSrc(boolean condition, String src) { return condAttr(condition, Attr.SRC, src); }
|
||||
public EmptyTag withCondValue(boolean condition, String value) { return condAttr(condition, Attr.VALUE, value); }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +1,46 @@
|
||||
package j2html.tags;
|
||||
|
||||
import j2html.utils.*;
|
||||
import java.nio.file.*;
|
||||
import static j2html.TagCreator.*;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import j2html.utils.CSSMin;
|
||||
import j2html.utils.JSMin;
|
||||
|
||||
import static j2html.TagCreator.rawHtml;
|
||||
import static j2html.TagCreator.script;
|
||||
import static j2html.TagCreator.style;
|
||||
|
||||
public class InlineStaticResource {
|
||||
|
||||
public enum TargetFormat { CSS_MIN, CSS, JS_MIN, JS }
|
||||
public enum TargetFormat {CSS_MIN, CSS, JS_MIN, JS}
|
||||
|
||||
public static ContainerTag get(String path, TargetFormat format) {
|
||||
ContainerTag errorAlert = script().with(unsafeHtml("alert('Unable to read file. File: \"" + path + "\", Type: \"" + format + "\"')"));
|
||||
String fileString = getFileAsString(path);
|
||||
if(fileString != null) {
|
||||
switch(format) {
|
||||
case CSS_MIN : return style().with(unsafeHtml(compressCss(fileString)));
|
||||
case JS_MIN : return script().with(unsafeHtml(compressJs(fileString, path)));
|
||||
case CSS : return style().with(unsafeHtml(fileString));
|
||||
case JS : return script().with(unsafeHtml(fileString));
|
||||
default : return errorAlert;
|
||||
}
|
||||
switch (format) {
|
||||
case CSS_MIN : return style().with(rawHtml(CSSMin.compress(fileString)));
|
||||
case JS_MIN : return script().with(rawHtml(JSMin.compressJs(fileString)));
|
||||
case CSS : return style().with(rawHtml(fileString));
|
||||
case JS : return script().with(rawHtml(fileString));
|
||||
default : throw new RuntimeException("Invalid target format");
|
||||
}
|
||||
return errorAlert;
|
||||
}
|
||||
|
||||
public static String getFileAsString(String path) {
|
||||
try {
|
||||
return new String(Files.readAllBytes(Paths.get(InlineStaticResource.class.getResource(path).toURI())), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
return readFileAsString(Paths.get(InlineStaticResource.class.getResource(path).toURI()));
|
||||
} catch (Exception e1) {
|
||||
try {
|
||||
return readFileAsString(Paths.get(path));
|
||||
} catch (Exception e2) {
|
||||
throw new RuntimeException("Couldn't find file with path='" + path + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String compressCss(String code) {
|
||||
return CSSMin.compress(code);
|
||||
}
|
||||
|
||||
private static String compressJs(String code, String debugPath) {
|
||||
return JSMin.compressJs(code, debugPath);
|
||||
private static String readFileAsString(Path path) throws IOException {
|
||||
return new String(Files.readAllBytes(path), "UTF-8");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +1,45 @@
|
||||
package j2html.tags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import j2html.attributes.Attr;
|
||||
import j2html.attributes.Attribute;
|
||||
|
||||
import java.util.ArrayList;
|
||||
public abstract class Tag<T extends Tag<T>> extends DomContent {
|
||||
|
||||
public abstract class Tag {
|
||||
protected String tagName;
|
||||
private ArrayList<Attribute> attributes;
|
||||
|
||||
protected String tag;
|
||||
protected ArrayList<Attribute> attributes;
|
||||
protected Tag parent;
|
||||
|
||||
protected Tag(String tagType) {
|
||||
this.tag = tagType;
|
||||
protected Tag(String tagName) {
|
||||
this.tagName = tagName;
|
||||
this.attributes = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void setParent(Tag parent) {
|
||||
this.parent = parent;
|
||||
|
||||
String renderOpenTag() {
|
||||
StringBuilder sb = new StringBuilder("<").append(tagName);
|
||||
for (Attribute attribute : attributes) {
|
||||
sb.append(attribute.render());
|
||||
}
|
||||
sb.append(">");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
String renderCloseTag() {
|
||||
return "</" + tagName + ">";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets an attribute on an element
|
||||
*
|
||||
* @param name the attribute
|
||||
* @param value the attribute value
|
||||
*/
|
||||
public boolean setAttribute(String name, String value) {
|
||||
boolean setAttribute(String name, String value) {
|
||||
if (value == null) {
|
||||
return attributes.add(new Attribute(name));
|
||||
}
|
||||
@@ -38,25 +52,100 @@ public abstract class Tag {
|
||||
return attributes.add(new Attribute(name, value));
|
||||
}
|
||||
|
||||
public String render() {
|
||||
return renderOpenTag() + renderCloseTag();
|
||||
|
||||
/**
|
||||
* Sets a custom attribute
|
||||
*
|
||||
* @param attribute the attribute name
|
||||
* @param value the attribute value
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public T attr(String attribute, String value) {
|
||||
setAttribute(attribute, value);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call attr-method based on condition
|
||||
* {@link #attr(String attribute, String value)}
|
||||
*
|
||||
* @param condition the condition
|
||||
* @param attribute the attribute name
|
||||
* @param value the attribute value
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
public T condAttr(boolean condition, String attribute, String value) {
|
||||
return (condition ? attr(attribute, value) : (T) this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.render();
|
||||
}
|
||||
|
||||
public String renderOpenTag() {
|
||||
String tagAttributes = "";
|
||||
for (Attribute attribute : attributes) {
|
||||
tagAttributes += attribute.render();
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof Tag)) {
|
||||
return false;
|
||||
}
|
||||
return "<" + tag + tagAttributes + ">";
|
||||
return ((Tag) obj).render().equals(this.render());
|
||||
}
|
||||
|
||||
public String renderCloseTag() {
|
||||
return "</" + tag + ">";
|
||||
|
||||
/**
|
||||
* Convenience methods that call attr with predefined attributes
|
||||
* @return itself for easy chaining
|
||||
*/
|
||||
|
||||
public T withClasses(String... classes) {
|
||||
return attr(Attr.CLASS,
|
||||
Stream.of(classes)
|
||||
.map(c -> c != null ? c : "")
|
||||
.collect(Collectors.joining(" "))
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
public T isAutoComplete() { return attr(Attr.AUTOCOMPLETE, null); }
|
||||
public T isAutoFocus() { return attr(Attr.AUTOFOCUS, null); }
|
||||
public T isHidden() { return attr(Attr.HIDDEN, null); }
|
||||
public T isRequired() { return attr(Attr.REQUIRED, null); }
|
||||
public T withAlt(String alt) { return attr(Attr.ALT, alt); }
|
||||
public T withAction(String action) { return attr(Attr.ACTION, action); }
|
||||
public T withCharset(String charset) { return attr(Attr.CHARSET, charset); }
|
||||
public T withClass(String className) { return attr(Attr.CLASS, className); }
|
||||
public T withContent(String content) { return attr(Attr.CONTENT, content); }
|
||||
public T withHref(String href) { return attr(Attr.HREF, href); }
|
||||
public T withId(String id) { return attr(Attr.ID, id); }
|
||||
public T withData(String dataAttr, String value) { return attr(Attr.DATA + "-" + dataAttr, value); }
|
||||
public T withMethod(String method) { return attr(Attr.METHOD, method); }
|
||||
public T withName(String name) { return attr(Attr.NAME, name); }
|
||||
public T withPlaceholder(String placeholder) { return attr(Attr.PLACEHOLDER, placeholder); }
|
||||
public T withTarget(String target) { return attr(Attr.TARGET, target); }
|
||||
public T withType(String type) { return attr(Attr.TYPE, type); }
|
||||
public T withRel(String rel) { return attr(Attr.REL, rel); }
|
||||
public T withRole(String role) { return attr(Attr.ROLE, role); }
|
||||
public T withSrc(String src) { return attr(Attr.SRC, src); }
|
||||
public T withStyle(String style) { return attr(Attr.STYLE, style); }
|
||||
public T withValue(String value) { return attr(Attr.VALUE, value); }
|
||||
|
||||
public T withCondAutoComplete(boolean condition) { return condAttr(condition, Attr.AUTOCOMPLETE, null); }
|
||||
public T withCondAutoFocus(boolean condition) { return condAttr(condition, Attr.AUTOFOCUS, null); }
|
||||
public T withCondHidden(boolean condition) { return condAttr(condition, Attr.HIDDEN, null); }
|
||||
public T withCondRequired(boolean condition) { return condAttr(condition, Attr.REQUIRED, null); }
|
||||
public T withCondAlt(boolean condition, String alt) { return condAttr(condition, Attr.ALT, alt); }
|
||||
public T withCondAction(boolean condition, String action) { return condAttr(condition, Attr.ACTION, action); }
|
||||
public T withCharset(boolean condition, String charset) { return condAttr(condition, Attr.CHARSET, charset); }
|
||||
public T withCondClass(boolean condition, String className) { return condAttr(condition, Attr.CLASS, className); }
|
||||
public T withCondContent(boolean condition, String content) { return condAttr(condition, Attr.CONTENT, content); }
|
||||
public T withCondHref(boolean condition, String href) { return condAttr(condition, Attr.HREF, href); }
|
||||
public T withCondId(boolean condition, String id) { return condAttr(condition, Attr.ID, id); }
|
||||
public T withCondData(boolean condition, String dataAttr, String value) { return condAttr(condition, Attr.DATA + "-" + dataAttr, value); }
|
||||
public T withCondMethod(boolean condition, String method) { return condAttr(condition, Attr.METHOD, method); }
|
||||
public T withCondName(boolean condition, String name) { return condAttr(condition, Attr.NAME, name); }
|
||||
public T withCondPlaceholder(boolean condition, String placeholder) { return condAttr(condition, Attr.PLACEHOLDER, placeholder); }
|
||||
public T withCondTarget(boolean condition, String target) { return condAttr(condition, Attr.TARGET, target); }
|
||||
public T withCondType(boolean condition, String type) { return condAttr(condition, Attr.TYPE, type); }
|
||||
public T withCondRel(boolean condition, String rel) { return condAttr(condition, Attr.REL, rel); }
|
||||
public T withCondSrc(boolean condition, String src) { return condAttr(condition, Attr.SRC, src); }
|
||||
public T withCondStyle(boolean condition, String style) { return condAttr(condition, Attr.STYLE, style); }
|
||||
public T withCondValue(boolean condition, String value) { return condAttr(condition, Attr.VALUE, value); }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
package j2html.tags;
|
||||
|
||||
import static org.apache.commons.lang3.StringEscapeUtils.*;
|
||||
import j2html.utils.SimpleEscaper;
|
||||
|
||||
public class Text extends Tag {
|
||||
public class Text extends DomContent {
|
||||
|
||||
private String text;
|
||||
|
||||
public Text(String text) {
|
||||
super(text);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render() {
|
||||
return escapeHtml4(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.render();
|
||||
return SimpleEscaper.escape(text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
package j2html.tags;
|
||||
|
||||
public class UnescapedText extends Tag {
|
||||
public class UnescapedText extends DomContent {
|
||||
|
||||
private String text;
|
||||
|
||||
public UnescapedText(String text) {
|
||||
super(text);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String render() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.render();
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/**
|
||||
* * CSSMin Copyright License Agreement (BSD License)
|
||||
*
|
||||
* <p>
|
||||
* Copyright (c) 2011-2014, Barry van Oudtshoorn
|
||||
* All rights reserved.
|
||||
*
|
||||
* <p>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* <p>
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer.
|
||||
*
|
||||
* <p>
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* <p>
|
||||
* - Neither the name of Barryvan nor the names of its
|
||||
* contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@@ -33,17 +33,17 @@
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* <p>
|
||||
* CSSMin takes in well-formed, human-readable CSS and reduces its size substantially.
|
||||
* It removes unnecessary whitespace and comments, and orders the contents of CSS
|
||||
* selectors alphabetically to enhance GZIP compression.
|
||||
*
|
||||
* <p>
|
||||
* Originally by Barry van Oudtshoorn, with bug reports, fixes, and contributions by
|
||||
* <ul>
|
||||
* <li>Kevin de Groote</li>
|
||||
* <li>Pedro Pinheiro</li>
|
||||
* <li>Asier Lostalé</li>
|
||||
* <li>David Åse</li>
|
||||
* <li>Kevin de Groote</li>
|
||||
* <li>Pedro Pinheiro</li>
|
||||
* <li>Asier Lostalé</li>
|
||||
* <li>David Åse</li>
|
||||
* </ul>
|
||||
* Some code is based on the YUI CssCompressor code, by Julien Lecomte.
|
||||
*
|
||||
@@ -53,27 +53,37 @@
|
||||
|
||||
package j2html.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.*;
|
||||
import java.util.regex.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Vector;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class CSSMin {
|
||||
|
||||
private CSSMin() {
|
||||
}
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(CSSMin.class.getName());
|
||||
|
||||
protected static boolean debugLogging = false;
|
||||
static boolean debugLogging = false;
|
||||
|
||||
|
||||
/**
|
||||
* Minify CSS from a reader to a printstream.
|
||||
* Minify supplied CSS.
|
||||
*
|
||||
* @param input Where to read the CSS from
|
||||
* @param input the CSS
|
||||
* @return the compressed version
|
||||
*/
|
||||
public static String compress(String input) {
|
||||
try {
|
||||
int k,
|
||||
j, // Number of open braces
|
||||
n; // Current position in stream
|
||||
j, // Number of open braces
|
||||
n; // Current position in stream
|
||||
char curr;
|
||||
|
||||
BufferedReader br = new BufferedReader(new StringReader(input));
|
||||
@@ -84,7 +94,9 @@ public class CSSMin {
|
||||
}
|
||||
String s;
|
||||
while ((s = br.readLine()) != null) {
|
||||
if (s.trim().equals("")) continue;
|
||||
if (s.trim().equals("")) {
|
||||
continue;
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
|
||||
@@ -178,7 +190,7 @@ class Selector {
|
||||
* @param selector The selector; for example, "div { border: solid 1px red; color: blue; }"
|
||||
* @throws IncompleteSelectorException, UnterminatedSelectorException, EmptySelectorBodyException If the selector is incomplete and cannot be parsed.
|
||||
*/
|
||||
public Selector(String selector) throws IncompleteSelectorException, UnterminatedSelectorException, EmptySelectorBodyException {
|
||||
Selector(String selector) throws IncompleteSelectorException, UnterminatedSelectorException, EmptySelectorBodyException {
|
||||
String[] parts = selector.split("\\{"); // We have to escape the { with a \ for the regex, which itself requires escaping for the string. Sigh.
|
||||
if (parts.length < 2) {
|
||||
throw new IncompleteSelectorException(selector);
|
||||
@@ -189,7 +201,6 @@ class Selector {
|
||||
// Simplify combinators
|
||||
this.selector = this.selector.replaceAll("\\s?(\\+|~|,|=|~=|\\^=|\\$=|\\*=|\\|=|>)\\s?", "$1");
|
||||
|
||||
|
||||
// We're dealing with a nested property, eg @-webkit-keyframes
|
||||
if (parts.length > 2) {
|
||||
this.subSelectors = new Vector<>();
|
||||
@@ -266,15 +277,21 @@ class Selector {
|
||||
} else if (contents.charAt(i) == '"') {
|
||||
bInsideString = true;
|
||||
} else if (contents.charAt(i) == '(') {
|
||||
if ((i - 3) > 0 && "url".equals(contents.substring(i - 3, i))) bInsideURL = true;
|
||||
if ((i - 3) > 0 && "url".equals(contents.substring(i - 3, i))) {
|
||||
bInsideURL = true;
|
||||
}
|
||||
} else if (contents.charAt(i) == ';') {
|
||||
substr = contents.substring(j, i);
|
||||
if (!(substr.trim().equals(""))) parts.add(substr);
|
||||
if (!(substr.trim().equals(""))) {
|
||||
parts.add(substr);
|
||||
}
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
substr = contents.substring(j, contents.length());
|
||||
if (!(substr.trim().equals(""))) parts.add(substr);
|
||||
if (!(substr.trim().equals(""))) {
|
||||
parts.add(substr);
|
||||
}
|
||||
|
||||
ArrayList<Property> results = new ArrayList<>();
|
||||
for (String part : parts) {
|
||||
@@ -302,8 +319,8 @@ class Property implements Comparable<Property> {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(Property.class.getName());
|
||||
|
||||
protected String property;
|
||||
protected Part[] parts;
|
||||
private String property;
|
||||
private Part[] parts;
|
||||
|
||||
/**
|
||||
* Creates a new Property using the supplied strings. Parses out the values of the property selector.
|
||||
@@ -311,7 +328,7 @@ class Property implements Comparable<Property> {
|
||||
* @param property The property; for example, "border: solid 1px red;" or "-moz-box-shadow: 3px 3px 3px rgba(255, 255, 0, 0.5);".
|
||||
* @throws IncompletePropertyException If the property is incomplete and cannot be parsed.
|
||||
*/
|
||||
public Property(String property) throws IncompletePropertyException {
|
||||
Property(String property) throws IncompletePropertyException {
|
||||
try {
|
||||
// Parse the property.
|
||||
ArrayList<String> parts = new ArrayList<>();
|
||||
@@ -326,14 +343,18 @@ class Property implements Comparable<Property> {
|
||||
bCanSplit = (property.charAt(i) == '"');
|
||||
} else if (property.charAt(i) == '"') {
|
||||
bCanSplit = false;
|
||||
} else if (property.charAt(i) == ':' && parts.size() < 1) {
|
||||
} else if (property.charAt(i) == ':' && parts.isEmpty()) {
|
||||
substr = property.substring(j, i);
|
||||
if (!(substr.trim().equals(""))) parts.add(substr);
|
||||
if (!(substr.trim().equals(""))) {
|
||||
parts.add(substr);
|
||||
}
|
||||
j = i + 1;
|
||||
}
|
||||
}
|
||||
substr = property.substring(j, property.length());
|
||||
if (!(substr.trim().equals(""))) parts.add(substr);
|
||||
if (!(substr.trim().equals(""))) {
|
||||
parts.add(substr);
|
||||
}
|
||||
if (parts.size() < 2) {
|
||||
throw new IncompletePropertyException(property);
|
||||
}
|
||||
@@ -375,24 +396,17 @@ class Property implements Comparable<Property> {
|
||||
*/
|
||||
public int compareTo(Property other) {
|
||||
// We can't just use String.compareTo(), because we need to sort properties that have hack prefixes last -- eg, *display should come after display.
|
||||
String thisProp = this.property;
|
||||
String thatProp = other.property;
|
||||
return sort(this.property).compareTo(sort(other.property));
|
||||
}
|
||||
|
||||
private String sort(String thisProp) {
|
||||
if (thisProp.charAt(0) == '-') {
|
||||
thisProp = thisProp.substring(1);
|
||||
thisProp = thisProp.substring(thisProp.indexOf('-') + 1);
|
||||
} else if (thisProp.charAt(0) < 65) {
|
||||
thisProp = thisProp.substring(1);
|
||||
}
|
||||
|
||||
if (thatProp.charAt(0) == '-') {
|
||||
thatProp = thatProp.substring(1);
|
||||
thatProp = thatProp.substring(thatProp.indexOf('-') + 1);
|
||||
} else if (thatProp.charAt(0) < 65) {
|
||||
thatProp = thatProp.substring(1);
|
||||
}
|
||||
|
||||
return thisProp.compareTo(thatProp);
|
||||
return thisProp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,8 +470,8 @@ class Property implements Comparable<Property> {
|
||||
}
|
||||
|
||||
class Part {
|
||||
String contents;
|
||||
String property;
|
||||
private String contents;
|
||||
private String property;
|
||||
|
||||
/**
|
||||
* Create a new property by parsing the given string.
|
||||
@@ -465,7 +479,7 @@ class Part {
|
||||
* @param contents The string to parse.
|
||||
* @throws Exception If the part cannot be parsed.
|
||||
*/
|
||||
public Part(String contents, String property) throws Exception {
|
||||
Part(String contents, String property) throws Exception {
|
||||
// Many of these regular expressions are adapted from those used in the YUI CSS Compressor.
|
||||
|
||||
// For simpler regexes.
|
||||
@@ -486,9 +500,15 @@ class Part {
|
||||
this.contents = this.contents.trim();
|
||||
|
||||
// Simplify multiple zeroes
|
||||
if (this.contents.equals("0 0 0 0")) this.contents = "0";
|
||||
if (this.contents.equals("0 0 0")) this.contents = "0";
|
||||
if (this.contents.equals("0 0")) this.contents = "0";
|
||||
if (this.contents.equals("0 0 0 0")) {
|
||||
this.contents = "0";
|
||||
}
|
||||
if (this.contents.equals("0 0 0")) {
|
||||
this.contents = "0";
|
||||
}
|
||||
if (this.contents.equals("0 0")) {
|
||||
this.contents = "0";
|
||||
}
|
||||
|
||||
// Simplify multiple-parameter properties
|
||||
simplifyParameters();
|
||||
@@ -505,31 +525,27 @@ class Part {
|
||||
}
|
||||
|
||||
private void simplifyParameters() {
|
||||
if (this.property.equals("background-size")) return;
|
||||
if (this.property.equals("background-size")) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder newContents = new StringBuilder();
|
||||
|
||||
String[] params = this.contents.split(" ");
|
||||
if (params.length == 4) {
|
||||
if (params.length == 4 && params[1].equalsIgnoreCase(params[3])) {
|
||||
// We can drop off the fourth item if the second and fourth items match
|
||||
// ie turn 3px 0 3px 0 into 3px 0 3px
|
||||
if (params[1].equalsIgnoreCase(params[3])) {
|
||||
params = Arrays.copyOf(params, 3);
|
||||
}
|
||||
params = Arrays.copyOf(params, 3);
|
||||
}
|
||||
if (params.length == 3) {
|
||||
if (params.length == 3 && params[0].equalsIgnoreCase(params[2])) {
|
||||
// We can drop off the third item if the first and third items match
|
||||
// ie turn 3px 0 3px into 3px 0
|
||||
if (params[0].equalsIgnoreCase(params[2])) {
|
||||
params = Arrays.copyOf(params, 2);
|
||||
}
|
||||
params = Arrays.copyOf(params, 2);
|
||||
}
|
||||
if (params.length == 2) {
|
||||
if (params.length == 2 && params[0].equalsIgnoreCase(params[1])) {
|
||||
// We can drop off the second item if the first and second items match
|
||||
// ie turn 3px 3px into 3px
|
||||
if (params[0].equalsIgnoreCase(params[1])) {
|
||||
params = Arrays.copyOf(params, 1);
|
||||
}
|
||||
params = Arrays.copyOf(params, 1);
|
||||
}
|
||||
|
||||
for (String param : params) {
|
||||
@@ -541,7 +557,9 @@ class Part {
|
||||
}
|
||||
|
||||
private void simplifyFontWeights() {
|
||||
if (!this.property.equals("font-weight")) return;
|
||||
if (!this.property.equals("font-weight")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String lcContents = this.contents.toLowerCase();
|
||||
|
||||
@@ -615,14 +633,16 @@ class Part {
|
||||
}
|
||||
}
|
||||
|
||||
class UnterminatedCommentException extends Exception {}
|
||||
class UnterminatedCommentException extends Exception {
|
||||
}
|
||||
|
||||
class UnbalancedBracesException extends Exception {}
|
||||
class UnbalancedBracesException extends Exception {
|
||||
}
|
||||
|
||||
class IncompletePropertyException extends Exception {
|
||||
String message = null;
|
||||
private final String message;
|
||||
|
||||
public IncompletePropertyException(String message) {
|
||||
IncompletePropertyException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -632,9 +652,9 @@ class IncompletePropertyException extends Exception {
|
||||
}
|
||||
|
||||
class EmptySelectorBodyException extends Exception {
|
||||
String message = null;
|
||||
private final String message;
|
||||
|
||||
public EmptySelectorBodyException(String message) {
|
||||
EmptySelectorBodyException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -644,9 +664,9 @@ class EmptySelectorBodyException extends Exception {
|
||||
}
|
||||
|
||||
class UnterminatedSelectorException extends Exception {
|
||||
String message = null;
|
||||
private final String message;
|
||||
|
||||
public UnterminatedSelectorException(String message) {
|
||||
UnterminatedSelectorException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -656,9 +676,9 @@ class UnterminatedSelectorException extends Exception {
|
||||
}
|
||||
|
||||
class IncompleteSelectorException extends Exception {
|
||||
String message = null;
|
||||
private final String message;
|
||||
|
||||
public IncompleteSelectorException(String message) {
|
||||
IncompleteSelectorException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -668,8 +688,8 @@ class IncompleteSelectorException extends Exception {
|
||||
}
|
||||
|
||||
class Constants {
|
||||
static final String[] htmlColourNames = { "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", "hotpink", "indianred ", "indigo ", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgrey", "lightgreen", "lightpink", "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen" };
|
||||
static final String[] htmlColourValues = { "#f0f8ff", "#faebd7", "#00ffff", "#7fffd4", "#f0ffff", "#f5f5dc", "#ffe4c4", "#000", "#ffebcd", "#00f", "#8a2be2", "#a52a2a", "#deb887", "#5f9ea0", "#7fff00", "#d2691e", "#ff7f50", "#6495ed", "#fff8dc", "#dc143c", "#0ff", "#00008b", "#008b8b", "#b8860b", "#a9a9a9", "#006400", "#bdb76b", "#8b008b", "#556b2f", "#ff8c00", "#9932cc", "#8b0000", "#e9967a", "#8fbc8f", "#483d8b", "#2f4f4f", "#00ced1", "#9400d3", "#ff1493", "#00bfff", "#696969", "#1e90ff", "#b22222", "#fffaf0", "#228b22", "#f0f", "#dcdcdc", "#f8f8ff", "#ffd700", "#daa520", "#808080", "#008000", "#adff2f", "#f0fff0", "#ff69b4", "#cd5c5c", "#4b0082", "#fffff0", "#f0e68c", "#e6e6fa", "#fff0f5", "#7cfc00", "#fffacd", "#add8e6", "#f08080", "#e0ffff", "#fafad2", "#d3d3d3", "#90ee90", "#ffb6c1", "#ffa07a", "#20b2aa", "#87cefa", "#789", "#b0c4de", "#ffffe0", "#0f0", "#32cd32", "#faf0e6", "#f0f", "#800000", "#66cdaa", "#0000cd", "#ba55d3", "#9370d8", "#3cb371", "#7b68ee", "#00fa9a", "#48d1cc", "#c71585", "#191970", "#f5fffa", "#ffe4e1", "#ffe4b5", "#ffdead", "#000080", "#fdf5e6", "#808000", "#6b8e23", "#ffa500", "#ff4500", "#da70d6", "#eee8aa", "#98fb98", "#afeeee", "#d87093", "#ffefd5", "#ffdab9", "#cd853f", "#ffc0cb", "#dda0dd", "#b0e0e6", "#800080", "#f00", "#bc8f8f", "#4169e1", "#8b4513", "#fa8072", "#f4a460", "#2e8b57", "#fff5ee", "#a0522d", "#c0c0c0", "#87ceeb", "#6a5acd", "#708090", "#fffafa", "#00ff7f", "#4682b4", "#d2b48c", "#008080", "#d8bfd8", "#ff6347", "#40e0d0", "#ee82ee", "#f5deb3", "#fff", "#f5f5f5", "#ff0", "#9acd32" };
|
||||
static final String[] fontWeightNames = { "normal", "bold", "bolder", "lighter" };
|
||||
static final String[] fontWeightValues = { "400", "700", "900", "100" };
|
||||
static final String[] htmlColourNames = {"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", "gold", "goldenrod", "gray", "green", "greenyellow", "honeydew", "hotpink", "indianred ", "indigo ", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgrey", "lightgreen", "lightpink", "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "whitesmoke", "yellow", "yellowgreen"};
|
||||
static final String[] htmlColourValues = {"#f0f8ff", "#faebd7", "#00ffff", "#7fffd4", "#f0ffff", "#f5f5dc", "#ffe4c4", "#000", "#ffebcd", "#00f", "#8a2be2", "#a52a2a", "#deb887", "#5f9ea0", "#7fff00", "#d2691e", "#ff7f50", "#6495ed", "#fff8dc", "#dc143c", "#0ff", "#00008b", "#008b8b", "#b8860b", "#a9a9a9", "#006400", "#bdb76b", "#8b008b", "#556b2f", "#ff8c00", "#9932cc", "#8b0000", "#e9967a", "#8fbc8f", "#483d8b", "#2f4f4f", "#00ced1", "#9400d3", "#ff1493", "#00bfff", "#696969", "#1e90ff", "#b22222", "#fffaf0", "#228b22", "#f0f", "#dcdcdc", "#f8f8ff", "#ffd700", "#daa520", "#808080", "#008000", "#adff2f", "#f0fff0", "#ff69b4", "#cd5c5c", "#4b0082", "#fffff0", "#f0e68c", "#e6e6fa", "#fff0f5", "#7cfc00", "#fffacd", "#add8e6", "#f08080", "#e0ffff", "#fafad2", "#d3d3d3", "#90ee90", "#ffb6c1", "#ffa07a", "#20b2aa", "#87cefa", "#789", "#b0c4de", "#ffffe0", "#0f0", "#32cd32", "#faf0e6", "#f0f", "#800000", "#66cdaa", "#0000cd", "#ba55d3", "#9370d8", "#3cb371", "#7b68ee", "#00fa9a", "#48d1cc", "#c71585", "#191970", "#f5fffa", "#ffe4e1", "#ffe4b5", "#ffdead", "#000080", "#fdf5e6", "#808000", "#6b8e23", "#ffa500", "#ff4500", "#da70d6", "#eee8aa", "#98fb98", "#afeeee", "#d87093", "#ffefd5", "#ffdab9", "#cd853f", "#ffc0cb", "#dda0dd", "#b0e0e6", "#800080", "#f00", "#bc8f8f", "#4169e1", "#8b4513", "#fa8072", "#f4a460", "#2e8b57", "#fff5ee", "#a0522d", "#c0c0c0", "#87ceeb", "#6a5acd", "#708090", "#fffafa", "#00ff7f", "#4682b4", "#d2b48c", "#008080", "#d8bfd8", "#ff6347", "#40e0d0", "#ee82ee", "#f5deb3", "#fff", "#f5f5f5", "#ff0", "#9acd32"};
|
||||
static final String[] fontWeightNames = {"normal", "bold", "bolder", "lighter"};
|
||||
static final String[] fontWeightValues = {"400", "700", "900", "100"};
|
||||
}
|
||||
|
||||
@@ -1,18 +1,305 @@
|
||||
package j2html.utils;
|
||||
/*
|
||||
* JSMin.java 2006-02-13
|
||||
*
|
||||
* Copyright (c) 2006 John Reilly (www.inconspicuous.org)
|
||||
*
|
||||
* This work is a translation from C to Java of jsmin.c published by
|
||||
* Douglas Crockford. Permission is hereby granted to use the Java
|
||||
* version under the same conditions as the jsmin.c on which it is
|
||||
* based.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* jsmin.c 2003-04-21
|
||||
*
|
||||
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* The Software shall be used for Good, not Evil.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
// package org.inconspicuous.jsmin;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
import com.google.javascript.jscomp.*;
|
||||
import com.google.javascript.jscomp.Compiler;
|
||||
|
||||
public class JSMin {
|
||||
|
||||
public static String compressJs(String code, String sourcePath) {
|
||||
com.google.javascript.jscomp.Compiler compiler = new Compiler();
|
||||
CompilerOptions options = new CompilerOptions();
|
||||
CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
|
||||
SourceFile extern = SourceFile.fromCode("externs.js", "");
|
||||
SourceFile input = SourceFile.fromCode(sourcePath, code);
|
||||
compiler.compile(extern, input, options);
|
||||
return compiler.toSource();
|
||||
/**
|
||||
* Compress a JS-string
|
||||
*
|
||||
* @param code the js-code you want to compress
|
||||
* @return the compressed code
|
||||
*/
|
||||
public static String compressJs(String code) {
|
||||
InputStream inStream = new ByteArrayInputStream(code.getBytes());
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
JSMin jsmin = new JSMin(inStream, outStream);
|
||||
try {
|
||||
jsmin.jsmin();
|
||||
return outStream.toString().trim();
|
||||
} catch (IOException | UnterminatedRegExpLiteralException | UnterminatedCommentException | UnterminatedStringLiteralException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static final int EOF = -1;
|
||||
|
||||
private PushbackInputStream in;
|
||||
private OutputStream out;
|
||||
|
||||
private int theA;
|
||||
private int theB;
|
||||
|
||||
private JSMin(InputStream in, OutputStream out) {
|
||||
this.in = new PushbackInputStream(in);
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* isAlphanum -- return true if the character is a letter, digit,
|
||||
* underscore, dollar sign, or non-ASCII character.
|
||||
*/
|
||||
private static boolean isAlphanum(int c) {
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
c == '_' ||
|
||||
c == '$' ||
|
||||
c == '\\' ||
|
||||
c > 126);
|
||||
}
|
||||
|
||||
/**
|
||||
* get -- return the next character from stdin. Watch out for lookahead. If
|
||||
* the character is a control character, translate it to a space or
|
||||
* linefeed.
|
||||
*/
|
||||
private int get() throws IOException {
|
||||
int c = in.read();
|
||||
|
||||
if (c >= ' ' || c == '\n' || c == EOF) {
|
||||
return c;
|
||||
}
|
||||
|
||||
if (c == '\r') {
|
||||
return '\n';
|
||||
}
|
||||
|
||||
return ' ';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next character without getting it.
|
||||
*/
|
||||
private int peek() throws IOException {
|
||||
int lookaheadChar = in.read();
|
||||
in.unread(lookaheadChar);
|
||||
return lookaheadChar;
|
||||
}
|
||||
|
||||
/**
|
||||
* next -- get the next character, excluding comments. peek() is used to see
|
||||
* if a '/' is followed by a '/' or '*'.
|
||||
*/
|
||||
private int next() throws IOException, UnterminatedCommentException {
|
||||
int c = get();
|
||||
if (c == '/') {
|
||||
switch (peek()) {
|
||||
case '/':
|
||||
for (; ; ) {
|
||||
c = get();
|
||||
if (c <= '\n') {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
case '*':
|
||||
get();
|
||||
for (; ; ) {
|
||||
switch (get()) {
|
||||
case '*':
|
||||
if (peek() == '/') {
|
||||
get();
|
||||
return ' ';
|
||||
}
|
||||
break;
|
||||
case EOF:
|
||||
throw new UnterminatedCommentException();
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* action -- do something! What you do is determined by the argument: 1
|
||||
* Output A. Copy B to A. Get the next B. 2 Copy B to A. Get the next B.
|
||||
* (Delete A). 3 Get the next B. (Delete B). action treats a string as a
|
||||
* single character. Wow! action recognizes a regular expression if it is
|
||||
* preceded by ( or , or =.
|
||||
*/
|
||||
|
||||
private void action(int d) throws IOException, UnterminatedRegExpLiteralException,
|
||||
UnterminatedCommentException, UnterminatedStringLiteralException {
|
||||
switch (d) {
|
||||
case 1:
|
||||
out.write(theA);
|
||||
case 2:
|
||||
theA = theB;
|
||||
|
||||
if (theA == '\'' || theA == '"') {
|
||||
for (; ; ) {
|
||||
out.write(theA);
|
||||
theA = get();
|
||||
if (theA == theB) {
|
||||
break;
|
||||
}
|
||||
if (theA <= '\n') {
|
||||
throw new UnterminatedStringLiteralException();
|
||||
}
|
||||
if (theA == '\\') {
|
||||
out.write(theA);
|
||||
theA = get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 3:
|
||||
theB = next();
|
||||
if (theB == '/' && (theA == '(' || theA == ',' || theA == '=')) {
|
||||
out.write(theA);
|
||||
out.write(theB);
|
||||
for (; ; ) {
|
||||
theA = get();
|
||||
if (theA == '/') {
|
||||
break;
|
||||
} else if (theA == '\\') {
|
||||
out.write(theA);
|
||||
theA = get();
|
||||
} else if (theA <= '\n') {
|
||||
throw new UnterminatedRegExpLiteralException();
|
||||
}
|
||||
out.write(theA);
|
||||
}
|
||||
theB = next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jsmin -- Copy the input to the output, deleting the characters which are
|
||||
* insignificant to JavaScript. Comments will be removed. Tabs will be
|
||||
* replaced with spaces. Carriage returns will be replaced with linefeeds.
|
||||
* Most spaces and linefeeds will be removed.
|
||||
*/
|
||||
public void jsmin() throws IOException, UnterminatedRegExpLiteralException, UnterminatedCommentException, UnterminatedStringLiteralException {
|
||||
theA = '\n';
|
||||
action(3);
|
||||
while (theA != EOF) {
|
||||
switch (theA) {
|
||||
case ' ':
|
||||
if (isAlphanum(theB)) {
|
||||
action(1);
|
||||
} else {
|
||||
action(2);
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
switch (theB) {
|
||||
case '{':
|
||||
case '[':
|
||||
case '(':
|
||||
case '+':
|
||||
case '-':
|
||||
action(1);
|
||||
break;
|
||||
case ' ':
|
||||
action(3);
|
||||
break;
|
||||
default:
|
||||
if (isAlphanum(theB)) {
|
||||
action(1);
|
||||
} else {
|
||||
action(2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (theB) {
|
||||
case ' ':
|
||||
if (isAlphanum(theA)) {
|
||||
action(1);
|
||||
break;
|
||||
}
|
||||
action(3);
|
||||
break;
|
||||
case '\n':
|
||||
switch (theA) {
|
||||
case '}':
|
||||
case ']':
|
||||
case ')':
|
||||
case '+':
|
||||
case '-':
|
||||
case '"':
|
||||
case '\'':
|
||||
action(1);
|
||||
break;
|
||||
default:
|
||||
if (isAlphanum(theA)) {
|
||||
action(1);
|
||||
} else {
|
||||
action(3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
action(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
private class UnterminatedCommentException extends Exception {
|
||||
}
|
||||
|
||||
private class UnterminatedStringLiteralException extends Exception {
|
||||
}
|
||||
|
||||
private class UnterminatedRegExpLiteralException extends Exception {
|
||||
}
|
||||
|
||||
}
|
||||
36
src/main/java/j2html/utils/SimpleEscaper.java
Normal file
36
src/main/java/j2html/utils/SimpleEscaper.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package j2html.utils;
|
||||
|
||||
public class SimpleEscaper {
|
||||
|
||||
public static String escape(String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder escapedText = new StringBuilder();
|
||||
char currentChar;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
currentChar = s.charAt(i);
|
||||
switch (currentChar) {
|
||||
case '<':
|
||||
escapedText.append("<");
|
||||
break;
|
||||
case '>':
|
||||
escapedText.append(">");
|
||||
break;
|
||||
case '&':
|
||||
escapedText.append("&");
|
||||
break;
|
||||
case '"':
|
||||
escapedText.append(""");
|
||||
break;
|
||||
case '\'':
|
||||
escapedText.append("'");
|
||||
break;
|
||||
default:
|
||||
escapedText.append(currentChar);
|
||||
}
|
||||
}
|
||||
return escapedText.toString();
|
||||
}
|
||||
|
||||
}
|
||||
7
src/test/files/test.css
Normal file
7
src/test/files/test.css
Normal file
@@ -0,0 +1,7 @@
|
||||
body {
|
||||
background: goldenrod;
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
3
src/test/files/test.html
Normal file
3
src/test/files/test.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<body>
|
||||
Any content
|
||||
</body>
|
||||
6
src/test/files/test.js
Normal file
6
src/test/files/test.js
Normal file
@@ -0,0 +1,6 @@
|
||||
(function () {
|
||||
var test = 5;
|
||||
var tast = 10;
|
||||
var testTast = test + tast;
|
||||
console.log(testTast);
|
||||
})();
|
||||
49
src/test/java/j2html/PerformanceTest.java
Normal file
49
src/test/java/j2html/PerformanceTest.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package j2html;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import j2html.utils.SimpleEscaper;
|
||||
|
||||
public class PerformanceTest {
|
||||
|
||||
private String shortTestString = "<body>\n"
|
||||
+ " <h1 class=\"example\">Heading!</h1>\n"
|
||||
+ " <img src=\"img/hello.png\">\n"
|
||||
+ "</body>";
|
||||
|
||||
// syntax-highlighted getting started example from j2html.com:
|
||||
private String longTestString =
|
||||
"<pre class=\" language-java\"><code class=\" language-java\"><span class=\"token keyword\">import</span> <span class=\"token keyword\">static</span> j2html<span class=\"token punctuation\">.</span>TagCreator<span class=\"token punctuation\">.</span>*<span class=\"token punctuation\">;</span>\n"
|
||||
+ "\n"
|
||||
+ "<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Main</span> <span class=\"token punctuation\">{</span>\n"
|
||||
+ " <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main<span class=\"token punctuation\">(</span></span>String<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> args<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n"
|
||||
+ " <span class=\"token function\">body<span class=\"token punctuation\">(</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">with<span class=\"token punctuation\">(</span></span>\n"
|
||||
+ " <span class=\"token function\">h1<span class=\"token punctuation\">(</span></span><span class=\"token string\">\"Heading!\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">withClass<span class=\"token punctuation\">(</span></span><span class=\"token string\">\"example\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n"
|
||||
+ " <span class=\"token function\">img<span class=\"token punctuation\">(</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">withSrc<span class=\"token punctuation\">(</span></span><span class=\"token string\">\"img/hello.png\"</span><span class=\"token punctuation\">)</span>\n"
|
||||
+ " <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render<span class=\"token punctuation\">(</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n"
|
||||
+ " <span class=\"token punctuation\">}</span>\n"
|
||||
+ "<span class=\"token punctuation\">}</span>\n"
|
||||
+ "</code></pre>";
|
||||
|
||||
@Test
|
||||
public void test_escaper_performnce() throws Exception {
|
||||
timeEscaper("SimpleEscaper#short", () -> SimpleEscaper.escape(shortTestString));
|
||||
timeEscaper("SimpleEscaper#long", () -> SimpleEscaper.escape(longTestString));
|
||||
timeEscaper("ApacheEscaper#short", () -> StringEscapeUtils.escapeHtml4(shortTestString));
|
||||
timeEscaper("ApacheEscaper#long", () -> StringEscapeUtils.escapeHtml4(longTestString));
|
||||
}
|
||||
|
||||
private void timeEscaper(String name, Callable escaper) throws Exception {
|
||||
long startTime = System.nanoTime();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
escaper.call();
|
||||
}
|
||||
long endTime = System.nanoTime();
|
||||
long durationMs = (endTime - startTime) / 1000000;
|
||||
System.out.println(String.format("%-21s%s", name + ":", +durationMs + "ms"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,30 +1,32 @@
|
||||
package j2html.attributes;
|
||||
|
||||
import j2html.tags.ContainerTag;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import j2html.tags.ContainerTag;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class AttributeTest {
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception {
|
||||
Attribute attributeWithValue = new Attribute("href", "http://example.com");
|
||||
assertEquals(attributeWithValue.render(), " href=\"http://example.com\"");
|
||||
assertThat(attributeWithValue.render(), is(" href=\"http://example.com\""));
|
||||
|
||||
Attribute attribute = new Attribute("required", null);
|
||||
assertEquals(attribute.render(), " required");
|
||||
assertThat(attribute.render(), is(" required"));
|
||||
|
||||
Attribute nullAttribute = new Attribute(null, null);
|
||||
assertEquals(nullAttribute.render(), "");
|
||||
assertThat(nullAttribute.render(), is(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttribute() throws Exception {
|
||||
ContainerTag testTag = new ContainerTag("a");
|
||||
testTag.setAttribute("href", "http://example.com");
|
||||
testTag.setAttribute("href", "http://example.org");
|
||||
assertEquals(testTag.render(), "<a href=\"http://example.org\"></a>");
|
||||
testTag.attr("href", "http://example.com");
|
||||
testTag.attr("href", "http://example.org");
|
||||
assertThat(testTag.render(), is("<a href=\"http://example.org\"></a>"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,26 @@ package j2html.tags;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import j2html.attributes.Attr;
|
||||
|
||||
import static j2html.TagCreator.a;
|
||||
import static j2html.TagCreator.body;
|
||||
import static j2html.TagCreator.button;
|
||||
import static j2html.TagCreator.div;
|
||||
import static j2html.TagCreator.document;
|
||||
import static j2html.TagCreator.footer;
|
||||
import static j2html.TagCreator.h1;
|
||||
import static j2html.TagCreator.h2;
|
||||
import static j2html.TagCreator.head;
|
||||
import static j2html.TagCreator.header;
|
||||
import static j2html.TagCreator.html;
|
||||
import static j2html.TagCreator.input;
|
||||
import static j2html.TagCreator.main;
|
||||
import static j2html.TagCreator.script;
|
||||
import static j2html.TagCreator.text;
|
||||
import static j2html.TagCreator.title;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class ComplexRenderTest {
|
||||
|
||||
@@ -17,20 +35,21 @@ public class ComplexRenderTest {
|
||||
),
|
||||
body().with(
|
||||
header().with(
|
||||
h1("Test Header")
|
||||
h1().with(
|
||||
text("Test Header "),
|
||||
a("with link").withHref("http://example.com"),
|
||||
text(".")
|
||||
)
|
||||
),
|
||||
main().with(
|
||||
h2("Test Form"),
|
||||
div().with(
|
||||
input().withType("email").withName("email").withPlaceholder("Email"),
|
||||
input().withType("password").withName("password").withPlaceholder("Password")
|
||||
).condWith(USER_SHOULD_LOG_IN,
|
||||
button().withType("submit").withText("Login")
|
||||
).condWith(USER_SHOULD_SIGN_UP,
|
||||
button().withType("submit").withText("Signup")
|
||||
)
|
||||
).condWith(USER_SHOULD_LOG_IN, button().withType("submit").withText("Login")
|
||||
).condWith(USER_SHOULD_SIGN_UP, button().withType("submit").withText("Signup"))
|
||||
),
|
||||
footer().withText("Test Footer"),
|
||||
footer().attr(Attr.CLASS, "footer").condAttr(1 == 1, Attr.ID, "id").withText("Test Footer"),
|
||||
script().withSrc("/testScript.js")
|
||||
)
|
||||
).render();
|
||||
@@ -38,7 +57,7 @@ public class ComplexRenderTest {
|
||||
|
||||
@Test
|
||||
public void testComplexRender() {
|
||||
String expectedResult = "<!DOCTYPE html><html><head><title>Test</title></head><body><header><h1>Test Header</h1></header><main><h2>Test Form</h2><div><input type=\"email\" name=\"email\" placeholder=\"Email\"><input type=\"password\" name=\"password\" placeholder=\"Password\"><button type=\"submit\">Login</button></div></main><footer>Test Footer</footer><script src=\"/testScript.js\"></script></body></html>";
|
||||
assertEquals(renderTest(), expectedResult);
|
||||
String expectedResult = "<!DOCTYPE html><html><head><title>Test</title></head><body><header><h1>Test Header <a href=\"http://example.com\">with link</a>.</h1></header><main><h2>Test Form</h2><div><input type=\"email\" name=\"email\" placeholder=\"Email\"><input type=\"password\" name=\"password\" placeholder=\"Password\"><button type=\"submit\">Login</button></div></main><footer class=\"footer\" id=\"id\">Test Footer</footer><script src=\"/testScript.js\"></script></body></html>";
|
||||
assertThat(renderTest(), is(expectedResult));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,41 @@ package j2html.tags;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static j2html.TagCreator.a;
|
||||
import static j2html.TagCreator.div;
|
||||
import static j2html.TagCreator.form;
|
||||
import static j2html.TagCreator.img;
|
||||
import static j2html.TagCreator.input;
|
||||
import static j2html.TagCreator.link;
|
||||
import static j2html.TagCreator.meta;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class ConvenienceMethodTest {
|
||||
|
||||
@Test
|
||||
public void testAllConvenienceMethods() throws Exception {
|
||||
assertEquals(input().isAutoComplete().render(), "<input autocomplete>");
|
||||
assertEquals(input().isAutoFocus().render(), "<input autofocus>");
|
||||
assertEquals(input().isHidden().render(), "<input hidden>");
|
||||
assertEquals(input().isRequired().render(), "<input required>");
|
||||
assertEquals(img().withAlt("An image").render(), "<img alt=\"An image\">");
|
||||
assertEquals(form().withAction("post").render(), "<form action=\"post\"></form>");
|
||||
assertEquals(meta().withCharset("UTF-8").render(), "<meta charset=\"UTF-8\">");
|
||||
assertEquals(div().withClass("test-class").render(), "<div class=\"test-class\"></div>");
|
||||
assertEquals(meta().withContent("Test Content").render(), "<meta content=\"Test Content\">");
|
||||
assertEquals(a().withHref("http://example.com").render(), "<a href=\"http://example.com\"></a>");
|
||||
assertEquals(div().withId("test-id").render(), "<div id=\"test-id\"></div>");
|
||||
assertEquals(div().withData("testdata", "test").render(), "<div data-testdata=\"test\"></div>");
|
||||
assertEquals(form().withMethod("get").render(), "<form method=\"get\"></form>");
|
||||
assertEquals(input().withName("test-name").render(), "<input name=\"test-name\">");
|
||||
assertEquals(input().withPlaceholder("test-placeholder").render(), "<input placeholder=\"test-placeholder\">");
|
||||
assertEquals(a().withTarget("_blank").render(), "<a target=\"_blank\"></a>");
|
||||
assertEquals(input().withType("email").render(), "<input type=\"email\">");
|
||||
assertEquals(link().withRel("stylesheet").render(), "<link rel=\"stylesheet\">");
|
||||
assertEquals(img().withSrc("/img/test.png").render(), "<img src=\"/img/test.png\">");
|
||||
assertEquals(input().withValue("test-value").render(), "<input value=\"test-value\">");
|
||||
assertThat(input().isAutoComplete().render(), is("<input autocomplete>"));
|
||||
assertThat(input().isAutoFocus().render(), is("<input autofocus>"));
|
||||
assertThat(input().isHidden().render(), is("<input hidden>"));
|
||||
assertThat(input().isRequired().render(), is("<input required>"));
|
||||
assertThat(img().withAlt("An image").render(), is("<img alt=\"An image\">"));
|
||||
assertThat(form().withAction("post").render(), is("<form action=\"post\"></form>"));
|
||||
assertThat(meta().withCharset("UTF-8").render(), is("<meta charset=\"UTF-8\">"));
|
||||
assertThat(div().withClass("test-class").render(), is("<div class=\"test-class\"></div>"));
|
||||
assertThat(meta().withContent("Test Content").render(), is("<meta content=\"Test Content\">"));
|
||||
assertThat(a().withHref("http://example.com").render(), is("<a href=\"http://example.com\"></a>"));
|
||||
assertThat(div().withId("test-id").render(), is("<div id=\"test-id\"></div>"));
|
||||
assertThat(div().withData("testdata", "test").render(), is("<div data-testdata=\"test\"></div>"));
|
||||
assertThat(form().withMethod("get").render(), is("<form method=\"get\"></form>"));
|
||||
assertThat(input().withName("test-name").render(), is("<input name=\"test-name\">"));
|
||||
assertThat(input().withPlaceholder("test-placeholder").render(), is("<input placeholder=\"test-placeholder\">"));
|
||||
assertThat(a().withTarget("_blank").render(), is("<a target=\"_blank\"></a>"));
|
||||
assertThat(input().withType("email").render(), is("<input type=\"email\">"));
|
||||
assertThat(link().withRel("stylesheet").render(), is("<link rel=\"stylesheet\">"));
|
||||
assertThat(link().withRole("role").render(), is("<link role=\"role\">"));
|
||||
assertThat(img().withSrc("/img/test.png").render(), is("<img src=\"/img/test.png\">"));
|
||||
assertThat(div().withStyle("background:red;").render(), is("<div style=\"background:red;\"></div>"));
|
||||
assertThat(input().withValue("test-value").render(), is("<input value=\"test-value\">"));
|
||||
}
|
||||
}
|
||||
|
||||
45
src/test/java/j2html/tags/InlineStaticResourceTest.java
Normal file
45
src/test/java/j2html/tags/InlineStaticResourceTest.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package j2html.tags;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.fileAsEscapedString;
|
||||
import static j2html.TagCreator.fileAsString;
|
||||
import static j2html.TagCreator.scriptWithInlineFile_min;
|
||||
import static j2html.TagCreator.styleWithInlineFile_min;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class InlineStaticResourceTest {
|
||||
|
||||
private static final String EOL = System.getProperty("line.separator"); // System independent End Of Line
|
||||
|
||||
@Test
|
||||
public void testAllTags() throws Exception {
|
||||
|
||||
String expectedCss = "<style>body{background:#daa520;margin-bottom:10px;margin-left:10px;margin-right:10px;margin-top:10px}</style>";
|
||||
String expectedJs = "<script>(function(){var test=5;var tast=10;var testTast=test+tast;console.log(testTast);})();</script>";
|
||||
String expectedHtml = "<body>" + EOL + " Any content" + EOL + "</body>" + EOL;
|
||||
String expectedEscapedHtml = "<body>" + EOL + " Any content" + EOL + "</body>" + EOL;
|
||||
String expectedAnyContent = "public class AnyContent{}" + EOL;
|
||||
|
||||
// classpath files
|
||||
assertThat(styleWithInlineFile_min("/test.css").render(), is(expectedCss));
|
||||
assertThat(scriptWithInlineFile_min("/test.js").render(), is(expectedJs));
|
||||
assertThat(fileAsString("/test.html").render(), is(expectedHtml));
|
||||
assertThat(fileAsEscapedString("/test.html").render(), is(expectedEscapedHtml));
|
||||
assertThat(fileAsString("/AnyContent.java").render(), is(expectedAnyContent));
|
||||
|
||||
// files outside classpath
|
||||
assertThat(styleWithInlineFile_min("src/test/files/test.css").render(), is(expectedCss));
|
||||
assertThat(scriptWithInlineFile_min("src/test/files/test.js").render(), is(expectedJs));
|
||||
assertThat(fileAsString("src/test/files/test.html").render(), is(expectedHtml));
|
||||
assertThat(fileAsEscapedString("src/test/files/test.html").render(), is(expectedEscapedHtml));
|
||||
assertThat(fileAsString("src/test/files/AnyContent.java").render(), is(expectedAnyContent));
|
||||
}
|
||||
|
||||
@Test(expected=RuntimeException.class)
|
||||
public void testExceptionForBadPath() throws Exception {
|
||||
styleWithInlineFile_min("NOT A FILE");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,178 +1,242 @@
|
||||
package j2html.tags;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class TagCreatorTest {
|
||||
|
||||
private static final String EOL = System.getProperty("line.separator"); // System independent End Of Line
|
||||
|
||||
List<Employee> employees = Arrays.asList(new Employee(1, "Name 1", "Title 1"), new Employee(2, "Name 2", "Title 2"), new Employee(3, "Name 3", "Title 3"));
|
||||
|
||||
@Test
|
||||
public void testIff() throws Exception {
|
||||
String expected = "<div><p>Test</p><a href=\"#\">Test</a></div>";
|
||||
String actual = div().with(
|
||||
p("Test"),
|
||||
iff(1 == 1, a("Test").withHref("#")),
|
||||
iff(1 == 2, a("Tast").withHref("#"))
|
||||
).render();
|
||||
assertThat(actual, is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIffElse() throws Exception {
|
||||
String expected = "<div><p>Tast</p></div>";
|
||||
String actual = div().with(iffElse(1 == 2, p("Test"), p("Tast"))).render();
|
||||
assertThat(actual, is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEach() throws Exception {
|
||||
String j2htmlMap = ul().with(
|
||||
li("Begin list"),
|
||||
each(employees, employee -> li().with(
|
||||
h2(employee.name),
|
||||
p(employee.title)
|
||||
))
|
||||
).render();
|
||||
String javaMap = ul().with(
|
||||
li("Begin list"),
|
||||
rawHtml(employees.stream().map(employee -> li().with(
|
||||
h2(employee.name),
|
||||
p(employee.title)
|
||||
)).map(DomContent::render).collect(Collectors.joining()))
|
||||
).render();
|
||||
assertThat(j2htmlMap.equals(javaMap), is(true));
|
||||
assertThat(j2htmlMap, is("<ul><li>Begin list</li><li><h2>Name 1</h2><p>Title 1</p></li><li><h2>Name 2</h2><p>Title 2</p></li><li><h2>Name 3</h2><p>Title 3</p></li></ul>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilter() throws Exception {
|
||||
String j2htmlFilter = ul().with(
|
||||
li("Begin list"),
|
||||
each(filter(employees, e -> e.id % 2 == 1), employee -> li().with(
|
||||
h2(employee.name),
|
||||
p(employee.title)
|
||||
))
|
||||
).render();
|
||||
String javaFilter = ul().with(
|
||||
li("Begin list"),
|
||||
rawHtml(employees.stream().filter(e -> e.id % 2 == 1).map(employee -> li().with(
|
||||
h2(employee.name),
|
||||
p(employee.title)
|
||||
)).map(DomContent::render).collect(Collectors.joining()))
|
||||
).render();
|
||||
assertThat(j2htmlFilter.equals(javaFilter), is(true));
|
||||
assertThat(j2htmlFilter, is("<ul><li>Begin list</li><li><h2>Name 1</h2><p>Title 1</p></li><li><h2>Name 3</h2><p>Title 3</p></li></ul>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllTags() throws Exception {
|
||||
|
||||
//Special Tags
|
||||
assertEquals(tag("tagname").render(), "<tagname></tagname>");
|
||||
assertEquals(emptyTag("tagname").render(), "<tagname>");
|
||||
assertEquals(text("text").render(), "text");
|
||||
assertEquals(text("<script> and \"</script>\"").render(), "<script> and "</script>"");
|
||||
assertEquals(unsafeHtml("<script>").render(), "<script>");
|
||||
assertEquals(styleWithInlineFile_min("/test.css").render(), "<style>body{background:#daa520;margin-bottom:10px;margin-left:10px;margin-right:10px;margin-top:10px}</style>");
|
||||
assertEquals(scriptWithInlineFile_min("/test.js").render(), "<script>(function(){console.log(15)})();</script>");
|
||||
assertEquals(fileAsString("/test.html").render(), "<body>\r\n"+" Any content\r\n"+"</body>\r\n");
|
||||
assertEquals(fileAsEscapedString("/test.html").render(), "<body>\r\n"+" Any content\r\n"+"</body>\r\n");
|
||||
assertEquals(fileAsString("/test.java").render(), "public class AnyContent{}\r\n");
|
||||
assertThat(tag("tagname").render(), is("<tagname></tagname>"));
|
||||
assertThat(emptyTag("tagname").render(), is("<tagname>"));
|
||||
assertThat(text("text").render(), is("text"));
|
||||
assertThat(text("<script> and \"</script>\"").render(), is("<script> and "</script>""));
|
||||
assertThat(rawHtml("<script>").render(), is("<script>"));
|
||||
|
||||
//EmptyTags
|
||||
assertEquals(document().render(), "<!DOCTYPE html>");
|
||||
assertEquals(area().render(), "<area>");
|
||||
assertEquals(base().render(), "<base>");
|
||||
assertEquals(br().render(), "<br>");
|
||||
assertEquals(col().render(), "<col>");
|
||||
assertEquals(embed().render(), "<embed>");
|
||||
assertEquals(hr().render(), "<hr>");
|
||||
assertEquals(img().render(), "<img>");
|
||||
assertEquals(input().render(), "<input>");
|
||||
assertEquals(keygen().render(), "<keygen>");
|
||||
assertEquals(link().render(), "<link>");
|
||||
assertEquals(meta().render(), "<meta>");
|
||||
assertEquals(param().render(), "<param>");
|
||||
assertEquals(source().render(), "<source>");
|
||||
assertEquals(track().render(), "<track>");
|
||||
assertEquals(wbr().render(), "<wbr>");
|
||||
assertThat(document().render(), is("<!DOCTYPE html>"));
|
||||
assertThat(area().render(), is("<area>"));
|
||||
assertThat(base().render(), is("<base>"));
|
||||
assertThat(br().render(), is("<br>"));
|
||||
assertThat(col().render(), is("<col>"));
|
||||
assertThat(embed().render(), is("<embed>"));
|
||||
assertThat(hr().render(), is("<hr>"));
|
||||
assertThat(img().render(), is("<img>"));
|
||||
assertThat(input().render(), is("<input>"));
|
||||
assertThat(keygen().render(), is("<keygen>"));
|
||||
assertThat(link().render(), is("<link>"));
|
||||
assertThat(meta().render(), is("<meta>"));
|
||||
assertThat(param().render(), is("<param>"));
|
||||
assertThat(source().render(), is("<source>"));
|
||||
assertThat(track().render(), is("<track>"));
|
||||
assertThat(wbr().render(), is("<wbr>"));
|
||||
|
||||
//ContainerTags
|
||||
assertEquals(a().render(), "<a></a>");
|
||||
assertEquals(a("Text").render(), "<a>Text</a>");
|
||||
assertEquals(abbr().render(), "<abbr></abbr>");
|
||||
assertEquals(address().render(), "<address></address>");
|
||||
assertEquals(article().render(), "<article></article>");
|
||||
assertEquals(aside().render(), "<aside></aside>");
|
||||
assertEquals(audio().render(), "<audio></audio>");
|
||||
assertEquals(b().render(), "<b></b>");
|
||||
assertEquals(b("Text").render(), "<b>Text</b>");
|
||||
assertEquals(bdi().render(), "<bdi></bdi>");
|
||||
assertEquals(bdi("Text").render(), "<bdi>Text</bdi>");
|
||||
assertEquals(bdo().render(), "<bdo></bdo>");
|
||||
assertEquals(bdo("Text").render(), "<bdo>Text</bdo>");
|
||||
assertEquals(blockquote().render(), "<blockquote></blockquote>");
|
||||
assertEquals(blockquote("Text").render(), "<blockquote>Text</blockquote>");
|
||||
assertEquals(body().render(), "<body></body>");
|
||||
assertEquals(button().render(), "<button></button>");
|
||||
assertEquals(button("Text").render(), "<button>Text</button>");
|
||||
assertEquals(canvas().render(), "<canvas></canvas>");
|
||||
assertEquals(caption().render(), "<caption></caption>");
|
||||
assertEquals(caption("Text").render(), "<caption>Text</caption>");
|
||||
assertEquals(cite().render(), "<cite></cite>");
|
||||
assertEquals(cite("Text").render(), "<cite>Text</cite>");
|
||||
assertEquals(code().render(), "<code></code>");
|
||||
assertEquals(colgroup().render(), "<colgroup></colgroup>");
|
||||
assertEquals(datalist().render(), "<datalist></datalist>");
|
||||
assertEquals(dd().render(), "<dd></dd>");
|
||||
assertEquals(dd("Text").render(), "<dd>Text</dd>");
|
||||
assertEquals(del().render(), "<del></del>");
|
||||
assertEquals(del("Text").render(), "<del>Text</del>");
|
||||
assertEquals(details().render(), "<details></details>");
|
||||
assertEquals(dfn().render(), "<dfn></dfn>");
|
||||
assertEquals(dfn("Text").render(), "<dfn>Text</dfn>");
|
||||
assertEquals(dialog().render(), "<dialog></dialog>");
|
||||
assertEquals(dialog("Text").render(), "<dialog>Text</dialog>");
|
||||
assertEquals(div().render(), "<div></div>");
|
||||
assertEquals(dl().render(), "<dl></dl>");
|
||||
assertEquals(dt().render(), "<dt></dt>");
|
||||
assertEquals(dt("Text").render(), "<dt>Text</dt>");
|
||||
assertEquals(em().render(), "<em></em>");
|
||||
assertEquals(em("Text").render(), "<em>Text</em>");
|
||||
assertEquals(fieldset().render(), "<fieldset></fieldset>");
|
||||
assertEquals(figcaption().render(), "<figcaption></figcaption>");
|
||||
assertEquals(figcaption("Text").render(), "<figcaption>Text</figcaption>");
|
||||
assertEquals(figure().render(), "<figure></figure>");
|
||||
assertEquals(footer().render(), "<footer></footer>");
|
||||
assertEquals(form().render(), "<form></form>");
|
||||
assertEquals(h1().render(), "<h1></h1>");
|
||||
assertEquals(h1("Text").render(), "<h1>Text</h1>");
|
||||
assertEquals(h2().render(), "<h2></h2>");
|
||||
assertEquals(h2("Text").render(), "<h2>Text</h2>");
|
||||
assertEquals(h3().render(), "<h3></h3>");
|
||||
assertEquals(h3("Text").render(), "<h3>Text</h3>");
|
||||
assertEquals(h4().render(), "<h4></h4>");
|
||||
assertEquals(h4("Text").render(), "<h4>Text</h4>");
|
||||
assertEquals(h5().render(), "<h5></h5>");
|
||||
assertEquals(h5("Text").render(), "<h5>Text</h5>");
|
||||
assertEquals(h6().render(), "<h6></h6>");
|
||||
assertEquals(h6("Text").render(), "<h6>Text</h6>");
|
||||
assertEquals(head().render(), "<head></head>");
|
||||
assertEquals(header().render(), "<header></header>");
|
||||
assertEquals(html().render(), "<html></html>");
|
||||
assertEquals(i().render(), "<i></i>");
|
||||
assertEquals(i("Text").render(), "<i>Text</i>");
|
||||
assertEquals(iframe().render(), "<iframe></iframe>");
|
||||
assertEquals(ins().render(), "<ins></ins>");
|
||||
assertEquals(ins("Text").render(), "<ins>Text</ins>");
|
||||
assertEquals(kbd().render(), "<kbd></kbd>");
|
||||
assertEquals(label().render(), "<label></label>");
|
||||
assertEquals(label("Text").render(), "<label>Text</label>");
|
||||
assertEquals(legend().render(), "<legend></legend>");
|
||||
assertEquals(legend("Text").render(), "<legend>Text</legend>");
|
||||
assertEquals(li().render(), "<li></li>");
|
||||
assertEquals(li("Text").render(), "<li>Text</li>");
|
||||
assertEquals(main().render(), "<main></main>");
|
||||
assertEquals(map().render(), "<map></map>");
|
||||
assertEquals(mark().render(), "<mark></mark>");
|
||||
assertEquals(menu().render(), "<menu></menu>");
|
||||
assertEquals(menuitem().render(), "<menuitem></menuitem>");
|
||||
assertEquals(meter().render(), "<meter></meter>");
|
||||
assertEquals(nav().render(), "<nav></nav>");
|
||||
assertEquals(noscript().render(), "<noscript></noscript>");
|
||||
assertEquals(object().render(), "<object></object>");
|
||||
assertEquals(ol().render(), "<ol></ol>");
|
||||
assertEquals(optgroup().render(), "<optgroup></optgroup>");
|
||||
assertEquals(option().render(), "<option></option>");
|
||||
assertEquals(option("Text").render(), "<option>Text</option>");
|
||||
assertEquals(output().render(), "<output></output>");
|
||||
assertEquals(p().render(), "<p></p>");
|
||||
assertEquals(p("Text").render(), "<p>Text</p>");
|
||||
assertEquals(pre().render(), "<pre></pre>");
|
||||
assertEquals(progress().render(), "<progress></progress>");
|
||||
assertEquals(q().render(), "<q></q>");
|
||||
assertEquals(q("Text").render(), "<q>Text</q>");
|
||||
assertEquals(rp().render(), "<rp></rp>");
|
||||
assertEquals(rt().render(), "<rt></rt>");
|
||||
assertEquals(ruby().render(), "<ruby></ruby>");
|
||||
assertEquals(s().render(), "<s></s>");
|
||||
assertEquals(samp().render(), "<samp></samp>");
|
||||
assertEquals(script().render(), "<script></script>");
|
||||
assertEquals(section().render(), "<section></section>");
|
||||
assertEquals(select().render(), "<select></select>");
|
||||
assertEquals(small().render(), "<small></small>");
|
||||
assertEquals(small("Text").render(), "<small>Text</small>");
|
||||
assertEquals(span().render(), "<span></span>");
|
||||
assertEquals(span("Text").render(), "<span>Text</span>");
|
||||
assertEquals(strong().render(), "<strong></strong>");
|
||||
assertEquals(strong("Text").render(), "<strong>Text</strong>");
|
||||
assertEquals(style().render(), "<style></style>");
|
||||
assertEquals(sub().render(), "<sub></sub>");
|
||||
assertEquals(sub("Text").render(), "<sub>Text</sub>");
|
||||
assertEquals(summary().render(), "<summary></summary>");
|
||||
assertEquals(summary("Text").render(), "<summary>Text</summary>");
|
||||
assertEquals(sup().render(), "<sup></sup>");
|
||||
assertEquals(sup("Text").render(), "<sup>Text</sup>");
|
||||
assertEquals(table().render(), "<table></table>");
|
||||
assertEquals(tbody().render(), "<tbody></tbody>");
|
||||
assertEquals(td().render(), "<td></td>");
|
||||
assertEquals(td("Text").render(), "<td>Text</td>");
|
||||
assertEquals(textarea().render(), "<textarea></textarea>");
|
||||
assertEquals(tfoot().render(), "<tfoot></tfoot>");
|
||||
assertEquals(th().render(), "<th></th>");
|
||||
assertEquals(th("Text").render(), "<th>Text</th>");
|
||||
assertEquals(thead().render(), "<thead></thead>");
|
||||
assertEquals(time().render(), "<time></time>");
|
||||
assertEquals(title().render(), "<title></title>");
|
||||
assertEquals(tr().render(), "<tr></tr>");
|
||||
assertEquals(u().render(), "<u></u>");
|
||||
assertEquals(u("Text").render(), "<u>Text</u>");
|
||||
assertEquals(ul().render(), "<ul></ul>");
|
||||
assertEquals(var().render(), "<var></var>");
|
||||
assertEquals(video().render(), "<video></video>");
|
||||
assertThat(a().render(), is("<a></a>"));
|
||||
assertThat(a("Text").render(), is("<a>Text</a>"));
|
||||
assertThat(abbr().render(), is("<abbr></abbr>"));
|
||||
assertThat(address().render(), is("<address></address>"));
|
||||
assertThat(article().render(), is("<article></article>"));
|
||||
assertThat(aside().render(), is("<aside></aside>"));
|
||||
assertThat(audio().render(), is("<audio></audio>"));
|
||||
assertThat(b().render(), is("<b></b>"));
|
||||
assertThat(b("Text").render(), is("<b>Text</b>"));
|
||||
assertThat(bdi().render(), is("<bdi></bdi>"));
|
||||
assertThat(bdi("Text").render(), is("<bdi>Text</bdi>"));
|
||||
assertThat(bdo().render(), is("<bdo></bdo>"));
|
||||
assertThat(bdo("Text").render(), is("<bdo>Text</bdo>"));
|
||||
assertThat(blockquote().render(), is("<blockquote></blockquote>"));
|
||||
assertThat(blockquote("Text").render(), is("<blockquote>Text</blockquote>"));
|
||||
assertThat(body().render(), is("<body></body>"));
|
||||
assertThat(button().render(), is("<button></button>"));
|
||||
assertThat(button("Text").render(), is("<button>Text</button>"));
|
||||
assertThat(canvas().render(), is("<canvas></canvas>"));
|
||||
assertThat(caption().render(), is("<caption></caption>"));
|
||||
assertThat(caption("Text").render(), is("<caption>Text</caption>"));
|
||||
assertThat(cite().render(), is("<cite></cite>"));
|
||||
assertThat(cite("Text").render(), is("<cite>Text</cite>"));
|
||||
assertThat(code().render(), is("<code></code>"));
|
||||
assertThat(colgroup().render(), is("<colgroup></colgroup>"));
|
||||
assertThat(datalist().render(), is("<datalist></datalist>"));
|
||||
assertThat(dd().render(), is("<dd></dd>"));
|
||||
assertThat(dd("Text").render(), is("<dd>Text</dd>"));
|
||||
assertThat(del().render(), is("<del></del>"));
|
||||
assertThat(del("Text").render(), is("<del>Text</del>"));
|
||||
assertThat(details().render(), is("<details></details>"));
|
||||
assertThat(dfn().render(), is("<dfn></dfn>"));
|
||||
assertThat(dfn("Text").render(), is("<dfn>Text</dfn>"));
|
||||
assertThat(dialog().render(), is("<dialog></dialog>"));
|
||||
assertThat(dialog("Text").render(), is("<dialog>Text</dialog>"));
|
||||
assertThat(div().render(), is("<div></div>"));
|
||||
assertThat(dl().render(), is("<dl></dl>"));
|
||||
assertThat(dt().render(), is("<dt></dt>"));
|
||||
assertThat(dt("Text").render(), is("<dt>Text</dt>"));
|
||||
assertThat(em().render(), is("<em></em>"));
|
||||
assertThat(em("Text").render(), is("<em>Text</em>"));
|
||||
assertThat(fieldset().render(), is("<fieldset></fieldset>"));
|
||||
assertThat(figcaption().render(), is("<figcaption></figcaption>"));
|
||||
assertThat(figcaption("Text").render(), is("<figcaption>Text</figcaption>"));
|
||||
assertThat(figure().render(), is("<figure></figure>"));
|
||||
assertThat(footer().render(), is("<footer></footer>"));
|
||||
assertThat(form().render(), is("<form></form>"));
|
||||
assertThat(h1().render(), is("<h1></h1>"));
|
||||
assertThat(h1("Text").render(), is("<h1>Text</h1>"));
|
||||
assertThat(h2().render(), is("<h2></h2>"));
|
||||
assertThat(h2("Text").render(), is("<h2>Text</h2>"));
|
||||
assertThat(h3().render(), is("<h3></h3>"));
|
||||
assertThat(h3("Text").render(), is("<h3>Text</h3>"));
|
||||
assertThat(h4().render(), is("<h4></h4>"));
|
||||
assertThat(h4("Text").render(), is("<h4>Text</h4>"));
|
||||
assertThat(h5().render(), is("<h5></h5>"));
|
||||
assertThat(h5("Text").render(), is("<h5>Text</h5>"));
|
||||
assertThat(h6().render(), is("<h6></h6>"));
|
||||
assertThat(h6("Text").render(), is("<h6>Text</h6>"));
|
||||
assertThat(head().render(), is("<head></head>"));
|
||||
assertThat(header().render(), is("<header></header>"));
|
||||
assertThat(html().render(), is("<html></html>"));
|
||||
assertThat(i().render(), is("<i></i>"));
|
||||
assertThat(i("Text").render(), is("<i>Text</i>"));
|
||||
assertThat(iframe().render(), is("<iframe></iframe>"));
|
||||
assertThat(ins().render(), is("<ins></ins>"));
|
||||
assertThat(ins("Text").render(), is("<ins>Text</ins>"));
|
||||
assertThat(kbd().render(), is("<kbd></kbd>"));
|
||||
assertThat(label().render(), is("<label></label>"));
|
||||
assertThat(label("Text").render(), is("<label>Text</label>"));
|
||||
assertThat(legend().render(), is("<legend></legend>"));
|
||||
assertThat(legend("Text").render(), is("<legend>Text</legend>"));
|
||||
assertThat(li().render(), is("<li></li>"));
|
||||
assertThat(li("Text").render(), is("<li>Text</li>"));
|
||||
assertThat(main().render(), is("<main></main>"));
|
||||
assertThat(map().render(), is("<map></map>"));
|
||||
assertThat(mark().render(), is("<mark></mark>"));
|
||||
assertThat(menu().render(), is("<menu></menu>"));
|
||||
assertThat(menuitem().render(), is("<menuitem></menuitem>"));
|
||||
assertThat(meter().render(), is("<meter></meter>"));
|
||||
assertThat(nav().render(), is("<nav></nav>"));
|
||||
assertThat(noscript().render(), is("<noscript></noscript>"));
|
||||
assertThat(object().render(), is("<object></object>"));
|
||||
assertThat(ol().render(), is("<ol></ol>"));
|
||||
assertThat(optgroup().render(), is("<optgroup></optgroup>"));
|
||||
assertThat(option().render(), is("<option></option>"));
|
||||
assertThat(option("Text").render(), is("<option>Text</option>"));
|
||||
assertThat(output().render(), is("<output></output>"));
|
||||
assertThat(p().render(), is("<p></p>"));
|
||||
assertThat(p("Text").render(), is("<p>Text</p>"));
|
||||
assertThat(pre().render(), is("<pre></pre>"));
|
||||
assertThat(progress().render(), is("<progress></progress>"));
|
||||
assertThat(q().render(), is("<q></q>"));
|
||||
assertThat(q("Text").render(), is("<q>Text</q>"));
|
||||
assertThat(rp().render(), is("<rp></rp>"));
|
||||
assertThat(rt().render(), is("<rt></rt>"));
|
||||
assertThat(ruby().render(), is("<ruby></ruby>"));
|
||||
assertThat(s().render(), is("<s></s>"));
|
||||
assertThat(s("Text").render(), is("<s>Text</s>"));
|
||||
assertThat(samp().render(), is("<samp></samp>"));
|
||||
assertThat(script().render(), is("<script></script>"));
|
||||
assertThat(section().render(), is("<section></section>"));
|
||||
assertThat(select().render(), is("<select></select>"));
|
||||
assertThat(small().render(), is("<small></small>"));
|
||||
assertThat(small("Text").render(), is("<small>Text</small>"));
|
||||
assertThat(span().render(), is("<span></span>"));
|
||||
assertThat(span("Text").render(), is("<span>Text</span>"));
|
||||
assertThat(strong().render(), is("<strong></strong>"));
|
||||
assertThat(strong("Text").render(), is("<strong>Text</strong>"));
|
||||
assertThat(style().render(), is("<style></style>"));
|
||||
assertThat(sub().render(), is("<sub></sub>"));
|
||||
assertThat(sub("Text").render(), is("<sub>Text</sub>"));
|
||||
assertThat(summary().render(), is("<summary></summary>"));
|
||||
assertThat(summary("Text").render(), is("<summary>Text</summary>"));
|
||||
assertThat(sup().render(), is("<sup></sup>"));
|
||||
assertThat(sup("Text").render(), is("<sup>Text</sup>"));
|
||||
assertThat(table().render(), is("<table></table>"));
|
||||
assertThat(tbody().render(), is("<tbody></tbody>"));
|
||||
assertThat(td().render(), is("<td></td>"));
|
||||
assertThat(td("Text").render(), is("<td>Text</td>"));
|
||||
assertThat(textarea().render(), is("<textarea></textarea>"));
|
||||
assertThat(tfoot().render(), is("<tfoot></tfoot>"));
|
||||
assertThat(th().render(), is("<th></th>"));
|
||||
assertThat(th("Text").render(), is("<th>Text</th>"));
|
||||
assertThat(thead().render(), is("<thead></thead>"));
|
||||
assertThat(time().render(), is("<time></time>"));
|
||||
assertThat(title().render(), is("<title></title>"));
|
||||
assertThat(title("Text").render(), is("<title>Text</title>"));
|
||||
assertThat(tr().render(), is("<tr></tr>"));
|
||||
assertThat(u().render(), is("<u></u>"));
|
||||
assertThat(u("Text").render(), is("<u>Text</u>"));
|
||||
assertThat(ul().render(), is("<ul></ul>"));
|
||||
assertThat(var().render(), is("<var></var>"));
|
||||
assertThat(video().render(), is("<video></video>"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,17 @@ package j2html.tags;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static j2html.TagCreator.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static j2html.TagCreator.body;
|
||||
import static j2html.TagCreator.div;
|
||||
import static j2html.TagCreator.footer;
|
||||
import static j2html.TagCreator.header;
|
||||
import static j2html.TagCreator.html;
|
||||
import static j2html.TagCreator.iff;
|
||||
import static j2html.TagCreator.main;
|
||||
import static j2html.TagCreator.p;
|
||||
import static j2html.TagCreator.tag;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class TagTest {
|
||||
|
||||
@@ -11,28 +20,43 @@ public class TagTest {
|
||||
public void testRender() throws Exception {
|
||||
ContainerTag testTag = new ContainerTag("a");
|
||||
testTag.setAttribute("href", "http://example.com");
|
||||
assertEquals(testTag.render(), "<a href=\"http://example.com\"></a>");
|
||||
assertThat(testTag.render(), is("<a href=\"http://example.com\"></a>"));
|
||||
|
||||
ContainerTag complexTestTag = html().with(body().with(header(),main().with(p("Main stuff...")),footer().condWith(1 == 1,p("Conditional with!"))));
|
||||
String expectedResult ="<html><body><header></header><main><p>Main stuff...</p></main><footer><p>Conditional with!</p></footer></body></html>";
|
||||
assertEquals(complexTestTag.render(), (expectedResult));
|
||||
ContainerTag complexTestTag = html().with(body().with(header(), main().with(p("Main stuff...")), footer().condWith(1 == 1, p("Conditional with!"))));
|
||||
String expectedResult = "<html><body><header></header><main><p>Main stuff...</p></main><footer><p>Conditional with!</p></footer></body></html>";
|
||||
assertThat(complexTestTag.render(), is((expectedResult)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenTag() throws Exception {
|
||||
ContainerTag testTag = new ContainerTag("a");
|
||||
assertEquals(testTag.renderOpenTag(), "<a>");
|
||||
assertThat(testTag.renderOpenTag(), is("<a>"));
|
||||
|
||||
ContainerTag complexTestTag = new ContainerTag("input");
|
||||
complexTestTag.withType("password").withId("password").withName("password").withPlaceholder("Password").isRequired();
|
||||
String expectedResult = "<input type=\"password\" id=\"password\" name=\"password\" placeholder=\"Password\" required>";
|
||||
assertEquals(complexTestTag.renderOpenTag(), expectedResult);
|
||||
assertThat(complexTestTag.renderOpenTag(), is(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseTag() throws Exception {
|
||||
ContainerTag testTag = new ContainerTag("a");
|
||||
assertEquals(testTag.renderCloseTag(), "</a>");
|
||||
assertThat(testTag.renderCloseTag(), is("</a>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() throws Exception {
|
||||
Tag tagOne = tag("p").withClass("class").withText("Test");
|
||||
Tag tagTwo = p("Test").withClass("class");
|
||||
assertThat(tagOne.equals(tagTwo), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithClasses() throws Exception {
|
||||
String expected = "<div class=\"c1 c2\"></div>";
|
||||
String actual = div().withClasses("c1", iff(1 == 1, "c2"), iff(1 == 2, "c3")).render();
|
||||
assertThat(actual, is(expected));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
13
src/test/java/j2html/tags/TestClasses.java
Normal file
13
src/test/java/j2html/tags/TestClasses.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package j2html.tags;
|
||||
|
||||
class Employee {
|
||||
final int id;
|
||||
final String name;
|
||||
final String title;
|
||||
|
||||
Employee(int id, String name, String title) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
1
src/test/resources/AnyContent.java
Normal file
1
src/test/resources/AnyContent.java
Normal file
@@ -0,0 +1 @@
|
||||
public class AnyContent{}
|
||||
Reference in New Issue
Block a user