29 Commits

Author SHA1 Message Date
David
8ce386830d [maven-release-plugin] prepare release j2html-1.3.0 2018-05-01 12:15:27 +02:00
David
6c5083512c formatting draft 2018-04-30 23:22:21 +02:00
Matthias
f497b5c8b5 support osgi meta data (#112) 2018-04-17 23:54:31 +02:00
Matthias
f212895eb2 Let each() take Map in addition to Collection (#110)
* add support for maps for 'each' method.

* add missing imports.
2018-04-16 20:11:37 +02:00
Rupert Madden-Abbott
62cafb9b31 Allow nulls in join() (fix #109)
* Discard nulls in join.

* Add test.
2018-04-16 20:07:11 +02:00
David
af7c986dd6 reorder asserts in each/fitler test 2018-02-05 01:36:46 +01:00
David
3aaab8b0fe unignore tests 2018-02-05 01:34:45 +01:00
David
cf9558b6ab fix formatting 2018-02-05 01:14:29 +01:00
Paul N. Baker
f87f9d8647 Overloaded method of iff for java8 Optional<>'s. (Includes test) (#103)
Using an optional as a condition is really tricky. Even if the optional is not present, the right value of ifValue must be evaluated eagerly in order to be passed to the method. Passing a lambda function for ifFunction allows the value to be evaluated lazily. This avoids the need to manually map and "elseGet" a null value to preserve current functionality.
2018-01-17 22:10:21 +01:00
David
b42ba41697 Update README.md 2017-12-31 12:25:35 +01:00
David
0c7f75f5b8 Update README.md 2017-12-31 12:25:05 +01:00
Janning Vygen
754003ebf6 Add attr(Attribute attribute) to Tag 2017-12-10 16:50:15 +01:00
David
6968478894 add multiplication-table to perf-test 2017-12-08 19:36:41 +01:00
David
0b92a963e9 add some ignored performance-tests 2017-12-07 22:10:34 +01:00
David
ac92facca7 Update README.md 2017-12-06 18:11:29 +01:00
David
4cf16320ad [maven-release-plugin] prepare for next development iteration 2017-12-06 17:04:20 +01:00
David
7d9ad230c1 [maven-release-plugin] prepare release j2html-1.2.2 2017-12-06 17:03:56 +01:00
David
7ebf4792b4 auto format 2017-12-06 14:08:24 +01:00
Janning Vygen
889fd2a3ac Add renderModel(writer, model) to Renderable (#93) 2017-12-06 14:04:13 +01:00
David
4acda0c6bb auto format project 2017-12-05 19:46:47 +01:00
Janning Vygen
17dac2871e Pass StringBuilder around instead of returning/concating strings (#88)
- Also remove retrolambda
2017-12-05 19:40:14 +01:00
David
1bfceaa62c Auto-format project (#92) 2017-12-02 12:17:32 +01:00
Janning Vygen
13134d042a Add Eclipse formatting config (#91) 2017-12-02 11:57:32 +01:00
Janning Vygen
b808d70a0d Addin root=true to .editorconfig (#90) 2017-12-02 11:47:24 +01:00
David
b068024070 Rewrite escaper-performance-test 2017-12-02 00:37:38 +01:00
David
5448c41887 Add basic editorconfig 2017-12-02 00:26:11 +01:00
Janning Vygen
d853c9cb1e Adding a performance test for https://github.com/tipsy/j2html/issues/86 (#87)
* Fix for https://github.com/tipsy/j2html/issues/79

* Adding PerformanceTest to measure execution time of rendering and GC

Signed-off-by: Janning Vygen <vygen@kicktipp.de>
2017-12-01 19:55:17 +01:00
David
eff53e073f Update README.md 2017-11-28 00:14:12 +01:00
David
98d7a6e912 [maven-release-plugin] prepare for next development iteration 2017-11-28 00:05:42 +01:00
48 changed files with 4006 additions and 998 deletions

8
.editorconfig Normal file
View File

@@ -0,0 +1,8 @@
root=true
[*]
charset=utf-8
end_of_line=crlf
insert_final_newline=true
indent_style=space
indent_size=4

View File

@@ -13,12 +13,12 @@ The project webpage is [j2html.com](http://j2html.com).
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.2.0</version>
<version>1.2.2</version>
</dependency>
```
### OR the gradle dependency
### Or the gradle dependency
```
compile 'com.j2html:j2html:1.2.0'
compile 'com.j2html:j2html:1.2.2'
```
### Import TagCreator and start building HTML
@@ -27,9 +27,9 @@ import static j2html.TagCreator.*;
public class Main {
public static void main(String[] args) {
body().with(
h1("Heading!").withClass("example"),
img().withSrc("img/hello.png")
body(
h1("Hello, World!"),
img().withSrc("/img/hello.png")
).render();
}
}
@@ -37,8 +37,8 @@ public class Main {
The above Java will result in the following HTML:
```html
<body>
<h1 class="example">Heading!</h1>
<img src="img/hello.png">
<h1>Hello, World!</h1>
<img src="/img/hello.png">
</body>
```

View File

@@ -0,0 +1,313 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="j2html" version="12">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="64"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="64"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="64"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="52"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

73
pom.xml
View File

@@ -10,7 +10,7 @@
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.2.1</version>
<version>1.3.0</version>
<name>j2html</name>
<description>Java to HTML builder with a fluent API</description>
@@ -58,29 +58,39 @@
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.carrotsearch</groupId>
<artifactId>junit-benchmarks</artifactId>
<version>0.7.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.0-jre</version>
<scope>test</scope>
</dependency>
<!-- performance test dependencies -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>test</scope>
</dependency>
</dependencies>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>net.orfjackal.retrolambda</groupId>
<artifactId>retrolambda-maven-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<?m2e ignore?>
<goals>
<goal>process-main</goal>
<goal>process-test</goal>
</goals>
</execution>
</executions>
<configuration>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@@ -118,6 +128,33 @@
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -1,13 +1,12 @@
package j2html;
import java.util.Collections;
import j2html.utils.CSSMin;
import j2html.utils.EscapeUtil;
import j2html.utils.Indenter;
import j2html.utils.JSMin;
import j2html.utils.Minifier;
import j2html.utils.TextEscaper;
import java.util.Collections;
public class Config {

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,10 @@
package j2html.attributes;
import j2html.Config;
import j2html.tags.Renderable;
import java.io.IOException;
public class Attribute {
public class Attribute implements Renderable {
private String name;
private String value;
@@ -17,19 +18,18 @@ public class Attribute {
this.value = null;
}
public String render() {
if (name == null) {
return "";
}
if (value == null) {
return " " + name;
}
return (" " + name + "=\"" + value + "\"");
}
@Override
public String toString() {
return this.render();
public void renderModel(Appendable writer, Object model) throws IOException {
if (name == null) {
return;
}
writer.append(" ");
writer.append(name);
if (value != null) {
writer.append("=\"");
writer.append(value);
writer.append("\"");
}
}
public String getName() {

View File

@@ -1,11 +1,10 @@
package j2html.tags;
import j2html.Config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import j2html.Config;
public class ContainerTag extends Tag<ContainerTag> {
private List<DomContent> children;
@@ -120,23 +119,6 @@ public class ContainerTag extends Tag<ContainerTag> {
return children.size();
}
/**
* Render the ContainerTag and its children
*
* @return the rendered string
*/
@Override
public String render() {
StringBuilder rendered = new StringBuilder(renderOpenTag());
if (!children.isEmpty()) {
for (DomContent child : children) {
rendered.append(child.render());
}
}
rendered.append(renderCloseTag());
return rendered.toString();
}
/**
* Render the ContainerTag and its children, adding newlines before each
* child and using Config.indenter to indent child based on how deep
@@ -145,11 +127,20 @@ public class ContainerTag extends Tag<ContainerTag> {
* @return the rendered and formatted string
*/
public String renderFormatted() {
return renderFormatted(0);
try {
return renderFormatted(0);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private String renderFormatted(int lvl) {
StringBuilder sb = new StringBuilder(renderOpenTag() + "\n");
private String renderFormatted(int lvl) throws IOException {
StringBuilder sb = new StringBuilder();
renderOpenTag(sb, null);
if ("pre".equals(tagName) || "textarea".equals(tagName)) {
return this.render() + "\n";
}
sb.append("\n");
if (!children.isEmpty()) {
for (DomContent c : children) {
lvl++;
@@ -161,19 +152,21 @@ public class ContainerTag extends Tag<ContainerTag> {
lvl--;
}
}
sb.append(Config.indenter.indent(lvl, renderCloseTag())).append("\n");
sb.append(Config.indenter.indent(lvl, ""));
renderCloseTag(sb);
sb.append("\n");
return sb.toString();
}
@Override
public void render(Appendable writer) throws IOException {
writer.append(renderOpenTag());
public void renderModel(Appendable writer, Object model) throws IOException {
renderOpenTag(writer, model);
if (children != null && !children.isEmpty()) {
for (DomContent child : children) {
child.render(writer);
child.renderModel(writer, model);
}
}
writer.append(renderCloseTag());
renderCloseTag(writer);
}
}

View File

@@ -1,18 +1,4 @@
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();
}
public abstract class DomContent implements Renderable {
}

View File

@@ -9,6 +9,8 @@ public class DomContentJoiner {
sb.append(((String) o).trim()).append(delimiter);
} else if (o instanceof DomContent) {
sb.append(((DomContent) o).render().trim()).append(delimiter);
} else if (o == null) {
//Discard null objects so iff/iffelse can be used with join
} else {
throw new RuntimeException("You can only join DomContent and String objects");
}

View File

@@ -1,6 +1,8 @@
package j2html.tags;
import j2html.Config;
import j2html.attributes.Attribute;
import java.io.IOException;
public class EmptyTag extends Tag<EmptyTag> {
@@ -9,12 +11,19 @@ public class EmptyTag extends Tag<EmptyTag> {
}
@Override
public String render() {
if (Config.closeEmptyTags) {
String tag = renderOpenTag();
return tag.substring(0, tag.length() - 1) + "/>";
}
return renderOpenTag();
public void render(Appendable writer) throws IOException {
renderModel(writer, null);
}
@Override
public void renderModel(Appendable writer, Object model) throws IOException {
writer.append("<").append(tagName);
for (Attribute attribute : getAttributes()) {
attribute.renderModel(writer, model);
}
if (Config.closeEmptyTags) {
writer.append("/");
}
writer.append(">");
}
}

View File

@@ -1,12 +1,12 @@
package j2html.tags;
import j2html.Config;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Scanner;
import j2html.Config;
import static j2html.TagCreator.*;
import static j2html.TagCreator.rawHtml;
import static j2html.TagCreator.script;
import static j2html.TagCreator.style;
public class InlineStaticResource {
@@ -15,11 +15,16 @@ public class InlineStaticResource {
public static ContainerTag get(String path, TargetFormat format) {
String fileString = getFileAsString(path);
switch (format) {
case CSS_MIN : return style().with(rawHtml(Config.cssMinifier.minify(fileString)));
case JS_MIN : return script().with(rawHtml(Config.jsMinifier.minify((fileString))));
case CSS : return style().with(rawHtml(fileString));
case JS : return script().with(rawHtml(fileString));
default : throw new RuntimeException("Invalid target format");
case CSS_MIN:
return style().with(rawHtml(Config.cssMinifier.minify(fileString)));
case JS_MIN:
return script().with(rawHtml(Config.jsMinifier.minify((fileString))));
case CSS:
return style().with(rawHtml(fileString));
case JS:
return script().with(rawHtml(fileString));
default:
throw new RuntimeException("Invalid target format");
}
}

View File

@@ -0,0 +1,37 @@
package j2html.tags;
import java.io.IOException;
public interface Renderable {
/**
* Create a StringBuilder and use it to render the Renderable and it's
* children
*/
default String render() {
StringBuilder stringBuilder = new StringBuilder();
try {
render(stringBuilder);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
return stringBuilder.toString();
}
/**
* Render the Renderable and it's children using the supplied writer
*
* @param writer the current writer
*/
default void render(Appendable writer) throws IOException {
renderModel(writer, null);
}
/**
* Render the Renderable and it's children using the supplied writer and a model.
*
* @param writer the current writer
* @param model a model object to provide data for children to render
*/
void renderModel(Appendable writer, Object model) throws IOException;
}

View File

@@ -1,12 +1,12 @@
package j2html.tags;
import java.util.ArrayList;
import j2html.attributes.Attr;
import j2html.attributes.Attribute;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
public abstract class Tag<T extends Tag<T>> extends DomContent {
protected String tagName;
private ArrayList<Attribute> attributes;
@@ -19,20 +19,41 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return this.tagName;
}
String renderOpenTag() {
StringBuilder sb = new StringBuilder("<").append(tagName);
for (Attribute attribute : attributes) {
sb.append(attribute.render());
String renderOpenTag() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
renderOpenTag(stringBuilder, null);
return stringBuilder.toString();
}
String renderCloseTag() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
renderCloseTag(stringBuilder);
return stringBuilder.toString();
}
void renderOpenTag(Appendable writer, Object model) throws IOException {
if (tagName == null || tagName.equals("")) { // avoid <null> and <> tags
return;
}
sb.append(">");
return sb.toString();
writer.append("<").append(tagName);
for (Attribute attribute : attributes) {
attribute.renderModel(writer, model);
}
writer.append(">");
}
String renderCloseTag() {
return "</" + tagName + ">";
void renderCloseTag(Appendable writer) throws IOException {
if (tagName == null || tagName.equals("")) {
return;
}
writer.append("</");
writer.append(tagName);
writer.append(">");
}
ArrayList<Attribute> getAttributes() {
return attributes;
}
/**
* Sets an attribute on an element
@@ -46,14 +67,13 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
}
for (Attribute attribute : attributes) {
if (attribute.getName().equals(name)) {
attribute.setValue(value); //update with new value
attribute.setValue(value); // update with new value
return true;
}
}
return attributes.add(new Attribute(name, value));
}
/**
* Sets a custom attribute
*
@@ -66,6 +86,28 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return (T) this;
}
/**
* Adds the specified attribute. If the Tag previously contained an attribute with the same name, the old attribute is replaced by the specified attribute.
*
* @param attribute the attribute
* @return itself for easy chaining
*/
public T attr(Attribute attribute) {
Iterator<Attribute> iterator = attributes.iterator();
String name = attribute.getName();
if (name != null) {
// name == null is allowed, but those Attributes are not rendered. So we add them anyway.
while (iterator.hasNext()) {
Attribute existingAttribute = iterator.next();
if (existingAttribute.getName().equals(name)) {
iterator.remove();
}
}
}
attributes.add(attribute);
return (T) this;
}
/**
* Sets a custom attribute without value
*
@@ -77,7 +119,6 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return attr(attribute, null);
}
/**
* Call attr-method based on condition
* {@link #attr(String attribute, Object value)}
@@ -91,7 +132,6 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return (condition ? attr(attribute, value) : (T) this);
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Tag)) {
@@ -100,13 +140,11 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return ((Tag) obj).render().equals(this.render());
}
/**
* Convenience methods that call attr with predefined attributes
*
* @return itself for easy chaining
*/
public T withClasses(String... classes) {
StringBuilder sb = new StringBuilder();
for (String s : classes) {
@@ -115,55 +153,199 @@ public abstract class Tag<T extends Tag<T>> extends DomContent {
return attr(Attr.CLASS, sb.toString().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 withDir(String dir) { return attr(Attr.DIR, dir); }
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 withLang(String lang) { return attr(Attr.LANG, lang); }
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 withTitle(String title) { return attr(Attr.TITLE, title); }
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 isAutoComplete() {
return attr(Attr.AUTOCOMPLETE, null);
}
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 withCondDir(boolean condition, String dir) { return condAttr(condition, Attr.DIR, dir); }
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 withCondLang(boolean condition, String lang) { return condAttr(condition, Attr.LANG, lang); }
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 withCondTitle(boolean condition, String title) { return condAttr(condition, Attr.TITLE, title); }
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); }
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 withDir(String dir) {
return attr(Attr.DIR, dir);
}
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 withLang(String lang) {
return attr(Attr.LANG, lang);
}
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 withTitle(String title) {
return attr(Attr.TITLE, title);
}
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 withCondDir(boolean condition, String dir) {
return condAttr(condition, Attr.DIR, dir);
}
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 withCondLang(boolean condition, String lang) {
return condAttr(condition, Attr.LANG, lang);
}
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 withCondTitle(boolean condition, String title) {
return condAttr(condition, Attr.TITLE, title);
}
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);
}
}

View File

@@ -1,6 +1,7 @@
package j2html.tags;
import j2html.Config;
import java.io.IOException;
public class Text extends DomContent {
@@ -11,8 +12,13 @@ public class Text extends DomContent {
}
@Override
public String render() {
return Config.textEscaper.escape(text);
public void render(Appendable writer) throws IOException {
renderModel(writer, null);
}
@Override
public void renderModel(Appendable writer, Object model) throws IOException {
writer.append(Config.textEscaper.escape(text));
}
}

View File

@@ -1,5 +1,7 @@
package j2html.tags;
import java.io.IOException;
public class UnescapedText extends DomContent {
private String text;
@@ -9,8 +11,13 @@ public class UnescapedText extends DomContent {
}
@Override
public String render() {
return text;
public void render(Appendable writer) throws IOException {
renderModel(writer, null);
}
@Override
public void renderModel(Appendable writer, Object model) throws IOException {
writer.append(text);
}
}

View File

@@ -1,4 +1,5 @@
package j2html.utils;
/*
* JSMin.java 2006-02-13
*
@@ -37,8 +38,6 @@ package j2html.utils;
* SOFTWARE.
*/
// package org.inconspicuous.jsmin;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -46,7 +45,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
public class JSMin {
/**
@@ -87,12 +85,12 @@ public class JSMin {
*/
private static boolean isAlphanum(int c) {
return ((c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
c == '_' ||
c == '$' ||
c == '\\' ||
c > 126);
(c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
c == '_' ||
c == '$' ||
c == '\\' ||
c > 126);
}
/**
@@ -172,7 +170,7 @@ public class JSMin {
*/
private void action(int d) throws IOException, UnterminatedRegExpLiteralException,
UnterminatedCommentException, UnterminatedStringLiteralException {
UnterminatedCommentException, UnterminatedStringLiteralException {
switch (d) {
case 1:
out.write(theA);

View File

@@ -1,49 +1,59 @@
package j2html;
import java.util.concurrent.Callable;
import org.apache.commons.lang3.StringEscapeUtils;
import org.junit.Test;
import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
import com.carrotsearch.junitbenchmarks.BenchmarkRule;
import com.carrotsearch.junitbenchmarks.Clock;
import j2html.utils.EscapeUtil;
import org.apache.commons.lang3.StringEscapeUtils;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@BenchmarkOptions(callgc = false, benchmarkRounds = 10000, warmupRounds = 200, concurrency = 2, clock = Clock.NANO_TIME)
public class PerformanceTest {
@Rule
public TestRule benchmarkRun = new BenchmarkRule();
private String shortTestString = "<body>\n"
+ " <h1 class=\"example\">Heading!</h1>\n"
+ " <img src=\"img/hello.png\">\n"
+ "</body>";
+ " <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>";
"<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", () -> EscapeUtil.escape(shortTestString));
timeEscaper("SimpleEscaper#long", () -> EscapeUtil.escape(longTestString));
timeEscaper("ApacheEscaper#short", () -> StringEscapeUtils.escapeHtml4(shortTestString));
timeEscaper("ApacheEscaper#long", () -> StringEscapeUtils.escapeHtml4(longTestString));
public void testSimpleEscaperShort() throws Exception {
EscapeUtil.escape(shortTestString);
}
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"));
@Test
public void testSimpleEscaperLong() throws Exception {
EscapeUtil.escape(longTestString);
}
@Test
public void testApacheEscaperShort() throws Exception {
StringEscapeUtils.escapeHtml4(shortTestString);
}
@Test
public void testApacheEscaperLong() throws Exception {
StringEscapeUtils.escapeHtml4(longTestString);
}
}

View File

@@ -0,0 +1,124 @@
package j2html;
import static j2html.TagCreator.attrs;
import static j2html.TagCreator.body;
import static j2html.TagCreator.div;
import static j2html.TagCreator.h1;
import static j2html.TagCreator.h2;
import static j2html.TagCreator.head;
import static j2html.TagCreator.html;
import static j2html.TagCreator.p;
import static j2html.TagCreator.title;
import static org.junit.Assert.assertEquals;
import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
import com.carrotsearch.junitbenchmarks.BenchmarkRule;
import com.carrotsearch.junitbenchmarks.Clock;
import j2html.model.BrowserTitle;
import j2html.model.Button;
import j2html.model.ButtonModel;
import j2html.model.PageModel;
import j2html.model.TextTemplate;
import j2html.tags.DomContent;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@BenchmarkOptions(callgc = false, benchmarkRounds = 50000, warmupRounds = 200, concurrency = 2, clock = Clock.NANO_TIME)
public class RenderPerformanceTest {
String expected = "<html><head><title>Browsertitle</title></head><body><h1>Hello World!</h1><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2 id=\"title\" class=\"visible-small\">Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2 id=\"title\" class=\"visible-small\">Hello World!</h2><div class=\"button\"><div class=\"button-text\">Action!</div></div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h1>Hello World!</h1><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div><h2>Hello World!</h2><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><p>Hello World!</p></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></body></html>";
@Rule
public TestRule benchmarkRun = new BenchmarkRule();
private DomContent template;
public RenderPerformanceTest() {
this.template =
// @formatter:off
html(
head(
title(new BrowserTitle())
),
body(
h1(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(attrs("#title.visible-small"),new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(attrs("#title.visible-small"),new TextTemplate()),
new Button(),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h1(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate()))))))))))))))))))))))))))),
h2(new TextTemplate()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(new TextTemplate())))))))))))))))))))))))))))
)
);
// @formatter:on
}
private DomContent getDomContent(PageModel pageModel) throws Exception {
return
// @formatter:off
html(
head(
title(pageModel.getTitle())
),
body(
h1(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(attrs("#title.visible-small"), pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(attrs("#title.visible-small"),pageModel.getText()),
div()
.withClass("button")
.with(
div()
.withClass("button-text")
.withText(pageModel.getButtonModel().getText())
),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h1(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText()))))))))))))))))))))))))))),
h2(pageModel.getText()),
div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(div(p(pageModel.getText())))))))))))))))))))))))))))
)
);
// @formatter:on
}
@Test
public void templatePerfomanceTest() throws Exception {
PageModel pageModel = new PageModel("Browsertitle", "Hello World!", new ButtonModel("Action!"));
StringBuilder stringBuilder = new StringBuilder();
template.renderModel(stringBuilder, pageModel);
assertEquals(expected, stringBuilder.toString());
}
@Test
public void staticPerfomanceTest() throws Exception {
PageModel pageModel = new PageModel("Browsertitle", "Hello World!", new ButtonModel("Action!"));
String result = getDomContent(pageModel).render();
assertEquals(expected, result);
}
}

View File

@@ -1,12 +1,11 @@
package j2html;
import org.junit.Test;
import j2html.utils.EscapeUtil;
import j2html.utils.TextEscaper;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
public class TextEscaperTest {
@@ -14,15 +13,15 @@ public class TextEscaperTest {
public void testTextEscaper() throws Exception {
String expected = "&lt;div&gt;&lt;/div&gt;";
assertThat("default text escaper works",
Config.textEscaper.escape("<div></div>"), is(expected));
Config.textEscaper.escape("<div></div>"), is(expected));
Config.textEscaper = new NoOpEscaper();
assertThat("user can change text escaper implementation",
Config.textEscaper, is(instanceOf(NoOpEscaper.class)));
Config.textEscaper, is(instanceOf(NoOpEscaper.class)));
expected = "<div></div>";
assertThat("user provided text escaper actually works",
Config.textEscaper.escape("<div></div>"), is(expected));
Config.textEscaper.escape("<div></div>"), is(expected));
Config.textEscaper = EscapeUtil::escape; // reset escaper
}

View File

@@ -1,13 +1,14 @@
package j2html.attributes;
import org.junit.Test;
import static j2html.TagCreator.*;
import static j2html.TagCreator.attrs;
import static j2html.TagCreator.div;
import static j2html.TagCreator.input;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class AttrShortFormTest {
@Test
public void addTo_emptyTag() throws Exception {
String expected = "<input id=\"some-id\" class=\"some-class\">";

View File

@@ -1,9 +1,7 @@
package j2html.attributes;
import org.junit.Test;
import j2html.tags.ContainerTag;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

View File

@@ -0,0 +1,17 @@
package j2html.comparison;
import j2html.comparison.model.Employee;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ComparisonData {
public static List<Employee> fiveHundredEmployees() {
return IntStream.range(0, 500).mapToObj(i -> new Employee(i, "Some name", "Some title")).collect(Collectors.toList());
}
public static List<Integer> tableNumbers = IntStream.range(1, 51).boxed().collect(Collectors.toList());
}

View File

@@ -0,0 +1,34 @@
package j2html.comparison;
import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
import com.carrotsearch.junitbenchmarks.BenchmarkRule;
import com.carrotsearch.junitbenchmarks.Clock;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@Ignore
@BenchmarkOptions(callgc = false, benchmarkRounds = 20_000, warmupRounds = 200, concurrency = 2, clock = Clock.NANO_TIME)
public class RenderPerformanceComparisonTest {
@Rule
public TestRule benchmarkRun = new BenchmarkRule();
@Test
public void j2htmlPerformance() throws Exception {
TestJ2html.helloWorld();
TestJ2html.fiveHundredEmployees();
TestJ2html.macros();
TestJ2html.multiplicationTable();
}
@Test
public void velocityPerformance() throws Exception {
TestVelocity.helloWorld();
TestVelocity.fiveHundredEmployees();
TestVelocity.macros();
TestVelocity.multiplicationTable();
}
}

View File

@@ -0,0 +1,30 @@
package j2html.comparison;
import j2html.comparison.j2html.FiveHundredEmployees;
import j2html.comparison.j2html.HelloWorld;
import j2html.comparison.j2html.Macros;
import j2html.comparison.j2html.MultiplicationTable;
public class TestJ2html {
public static String helloWorld() {
return HelloWorld.tag.render();
}
public static String fiveHundredEmployees() {
return FiveHundredEmployees.tag.render();
}
public static String macros() {
return Macros.tag.render();
}
public static String multiplicationTable() {
return MultiplicationTable.tag.render();
}
public static void main(String[] args) {
System.out.println(MultiplicationTable.tag.renderFormatted());
}
}

View File

@@ -0,0 +1,52 @@
package j2html.comparison;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
public class TestVelocity {
private static VelocityEngine velocityEngine;
static {
velocityEngine = new VelocityEngine();
velocityEngine.setProperty("resource.loader", "class");
velocityEngine.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
}
private static String render(String templatePath, Map<String, Object> model) {
StringWriter stringWriter = new StringWriter();
velocityEngine.getTemplate(templatePath, StandardCharsets.UTF_8.name()).merge(
new VelocityContext(model), stringWriter
);
return stringWriter.toString();
}
public static String helloWorld() {
return render("/comparison/velocity/helloWorld.vm", null);
}
public static String fiveHundredEmployees() {
Map<String, Object> model = new HashMap<>();
model.put("employees", ComparisonData.fiveHundredEmployees());
return render("/comparison/velocity/fiveHundredEmployees.vm", model);
}
public static String macros() {
return render("/comparison/velocity/macros.vm", null);
}
public static String multiplicationTable() {
Map<String, Object> model = new HashMap<>();
model.put("tableNumbers", ComparisonData.tableNumbers);
return render("/comparison/velocity/multiplicationTable.vm", model);
}
public static void main(String[] args) {
System.out.println(multiplicationTable());
}
}

View File

@@ -0,0 +1,18 @@
package j2html.comparison.j2html;
import j2html.comparison.ComparisonData;
import j2html.tags.ContainerTag;
import static j2html.TagCreator.each;
import static j2html.TagCreator.li;
import static j2html.TagCreator.ul;
import static org.apache.commons.lang3.StringUtils.join;
public class FiveHundredEmployees {
public static ContainerTag tag = ul(
each(ComparisonData.fiveHundredEmployees(), employee ->
li(join(employee.getId(), employee.getName(), employee.getTitle()))
)
);
}

View File

@@ -0,0 +1,27 @@
package j2html.comparison.j2html;
import j2html.tags.ContainerTag;
import static j2html.TagCreator.attrs;
import static j2html.TagCreator.body;
import static j2html.TagCreator.h1;
import static j2html.TagCreator.head;
import static j2html.TagCreator.html;
import static j2html.TagCreator.link;
import static j2html.TagCreator.main;
import static j2html.TagCreator.title;
public class HelloWorld {
public static ContainerTag tag = html(
head(
title("Title"),
link().withRel("stylesheet").withHref("/css/main.css")
),
body(
main(attrs("#main.content"),
h1("Heading!")
)
)
);
}

View File

@@ -0,0 +1,46 @@
package j2html.comparison.j2html;
import j2html.tags.ContainerTag;
import j2html.tags.DomContent;
import static j2html.TagCreator.attrs;
import static j2html.TagCreator.body;
import static j2html.TagCreator.div;
import static j2html.TagCreator.h1;
import static j2html.TagCreator.head;
import static j2html.TagCreator.html;
import static j2html.TagCreator.link;
import static j2html.TagCreator.main;
import static j2html.TagCreator.title;
public class Macros {
public static ContainerTag tag = mainLayout(
div(
h1("Example content"),
someMacro(1),
someMacro(2),
someMacro(3)
)
);
private static ContainerTag mainLayout(DomContent content) {
return html(
head(
title("Title"),
link().withRel("stylesheet").withHref("/css/main.css")
),
body(
main(attrs("#main.content"),
content
)
)
);
}
private static ContainerTag someMacro(int i) {
return div(
"Macro call " + i
);
}
}

View File

@@ -0,0 +1,19 @@
package j2html.comparison.j2html;
import j2html.comparison.ComparisonData;
import j2html.tags.ContainerTag;
import static j2html.TagCreator.*;
public class MultiplicationTable {
public static ContainerTag tag = table(
tbody(
each(ComparisonData.tableNumbers, i -> tr(
each(ComparisonData.tableNumbers, j -> td(
String.valueOf(i * j)
))
))
)
);
}

View File

@@ -0,0 +1,10 @@
package j2html.comparison.model;
import lombok.Value;
@Value
public class Employee {
int id;
String name;
String title;
}

View File

@@ -0,0 +1,11 @@
package j2html.model;
import java.io.IOException;
public class BrowserTitle extends Template<PageModel> {
@Override
public void renderTemplate(Appendable writer, PageModel pageModel) throws IOException {
writer.append(pageModel.getTitle());
}
}

View File

@@ -0,0 +1,40 @@
package j2html.model;
import static j2html.TagCreator.div;
import java.io.IOException;
import j2html.tags.ContainerTag;
public class Button extends Template<PageModel> {
private ContainerTag template;
public Button() {
// @formatter:off
template =
div()
.withClass("button")
.with(
div()
.withClass("button-text")
.with(
new ButtonText()
)
);
// @formatter:on
}
@Override
public void renderTemplate(Appendable writer, PageModel model) throws IOException {
template.renderModel(writer, model.getButtonModel().getText());
}
}
class ButtonText extends Template<String> {
@Override
public void renderTemplate(Appendable writer, String model) throws IOException {
writer.append(model);
}
}

View File

@@ -0,0 +1,12 @@
package j2html.model;
public class ButtonModel {
private String text;
public ButtonModel(String text) {
this.text = text;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,24 @@
package j2html.model;
import j2html.attributes.Attribute;
import java.io.IOException;
public class DynamicHrefAttribute extends Attribute {
public DynamicHrefAttribute() {
super("href");
}
@Override
public void renderModel(Appendable writer, Object model) throws IOException {
writer.append(" ");
writer.append(getName());
writer.append("=\"");
writer.append(getUrl(model));
writer.append("\"");
}
public String getUrl(Object model) {
return "/";
}
}

View File

@@ -0,0 +1,26 @@
package j2html.model;
public class PageModel {
private String title;
private String text;
private ButtonModel buttonModel;
public PageModel(String title, String text, ButtonModel buttonModel) {
this.title = title;
this.text = text;
this.buttonModel = buttonModel;
}
public ButtonModel getButtonModel() {
return buttonModel;
}
public String getTitle() {
return title;
}
public String getText() {
return text;
}
}

View File

@@ -0,0 +1,16 @@
package j2html.model;
import java.io.IOException;
import j2html.tags.DomContent;
public abstract class Template<T> extends DomContent {
@Override
@SuppressWarnings("unchecked")
public final void renderModel(Appendable writer, Object model) throws IOException {
renderTemplate(writer, (T) model);
}
public abstract void renderTemplate(Appendable writer, T model) throws IOException;
}

View File

@@ -0,0 +1,11 @@
package j2html.model;
import java.io.IOException;
public class TextTemplate extends Template<PageModel> {
@Override
public void renderTemplate(Appendable writer, PageModel pageModel) throws IOException {
writer.append(pageModel.getText());
}
}

View File

@@ -1,11 +1,24 @@
package j2html.tags;
import org.junit.Test;
import j2html.TagCreator;
import j2html.attributes.Attr;
import static j2html.TagCreator.*;
import org.junit.Test;
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.iff;
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;
@@ -113,41 +126,41 @@ public class ComplexRenderTest {
@Test
public void testComplexRender_formatted() {
assertThat(renderTest3(),
is("<!DOCTYPE html>\n"
+ "<html>\n"
+ " <head>\n"
+ " <title>\n"
+ " Test\n"
+ " </title>\n"
+ " </head>\n"
+ " <body>\n"
+ " <header>\n"
+ " <h1>\n"
+ " Test Header \n"
+ " <a href=\"http://example.com\">\n"
+ " with link\n"
+ " </a>\n"
+ " .\n"
+ " </h1>\n"
+ " </header>\n"
+ " <main>\n"
+ " <h2>\n"
+ " Test Form\n"
+ " </h2>\n"
+ " <div>\n"
+ " <input type=\"email\" name=\"email\" placeholder=\"Email\">\n"
+ " <input type=\"password\" name=\"password\" placeholder=\"Password\">\n"
+ " <button type=\"submit\">\n"
+ " Login\n"
+ " </button>\n"
+ " </div>\n"
+ " </main>\n"
+ " <footer class=\"footer\" id=\"id\">\n"
+ " Test Footer\n"
+ " </footer>\n"
+ " <script src=\"/testScript.js\">\n"
+ " </script>\n"
+ " </body>\n"
+ "</html>\n"));
is("<!DOCTYPE html>\n"
+ "<html>\n"
+ " <head>\n"
+ " <title>\n"
+ " Test\n"
+ " </title>\n"
+ " </head>\n"
+ " <body>\n"
+ " <header>\n"
+ " <h1>\n"
+ " Test Header \n"
+ " <a href=\"http://example.com\">\n"
+ " with link\n"
+ " </a>\n"
+ " .\n"
+ " </h1>\n"
+ " </header>\n"
+ " <main>\n"
+ " <h2>\n"
+ " Test Form\n"
+ " </h2>\n"
+ " <div>\n"
+ " <input type=\"email\" name=\"email\" placeholder=\"Email\">\n"
+ " <input type=\"password\" name=\"password\" placeholder=\"Password\">\n"
+ " <button type=\"submit\">\n"
+ " Login\n"
+ " </button>\n"
+ " </div>\n"
+ " </main>\n"
+ " <footer class=\"footer\" id=\"id\">\n"
+ " Test Footer\n"
+ " </footer>\n"
+ " <script src=\"/testScript.js\">\n"
+ " </script>\n"
+ " </body>\n"
+ "</html>\n"));
}
}

View File

@@ -1,7 +1,6 @@
package j2html.tags;
import org.junit.Test;
import static j2html.TagCreator.a;
import static j2html.TagCreator.div;
import static j2html.TagCreator.form;

View File

@@ -1,7 +1,6 @@
package j2html.tags;
import org.junit.Test;
import static j2html.TagCreator.fileAsEscapedString;
import static j2html.TagCreator.fileAsString;
import static j2html.TagCreator.scriptWithInlineFile_min;
@@ -38,7 +37,7 @@ public class InlineStaticResourceTest {
assertThat(fileAsString("src/test/files/AnyContent.java").render(), is(expectedAnyContent));
}
@Test(expected=RuntimeException.class)
@Test(expected = RuntimeException.class)
public void testExceptionForBadPath() throws Exception {
styleWithInlineFile_min("NOT A FILE");
}

View File

@@ -0,0 +1,60 @@
package j2html.tags;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import static j2html.TagCreator.div;
import static j2html.TagCreator.each;
import static j2html.TagCreator.li;
import static j2html.TagCreator.p;
import static j2html.TagCreator.pre;
import static j2html.TagCreator.textarea;
import static j2html.TagCreator.ul;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class RenderFormattedTest {
@Test
public void testFormattedTags() throws Exception {
assertThat(div(p("Hello")).renderFormatted(), is("<div>\n <p>\n Hello\n </p>\n</div>\n"));
}
@Test
public void testFormattedTags_doesntFormatPre() throws Exception {
assertThat(div(pre("public void renderModel(Appendable writer, Object model) throws IOException {\n" +
" writer.append(text);\n" +
" }")).renderFormatted(), is("<div>\n" +
" <pre>public void renderModel(Appendable writer, Object model) throws IOException {\n" +
" writer.append(text);\n" +
" }</pre>\n" +
"</div>\n"));
}
@Test
public void testFormattedTags_doesntFormatTextArea() throws Exception {
assertThat(div(textarea("fred\ntom")).renderFormatted(), is("<div>\n" +
" <textarea>fred\n" +
"tom</textarea>\n" +
"</div>\n"));
}
@Test
public void testFormattedTags_each() throws Exception {
assertThat(ul(each(ImmutableList.of(1, 2, 3), i -> li("Number " + i))).renderFormatted(), is(
"<ul>\n" +
" \n" +
" <li>\n" +
" Number 1\n" +
" </li>\n" +
" <li>\n" +
" Number 2\n" +
" </li>\n" +
" <li>\n" +
" Number 3\n" +
" </li>\n" +
" \n" +
"</ul>\n"
));
}
}

View File

@@ -1,13 +1,15 @@
package j2html.tags;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.*;
import j2html.Config;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static j2html.TagCreator.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -19,6 +21,14 @@ public class TagCreatorTest {
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"));
Map<Integer, Employee> employeeMap = new HashMap<>();
@Before
public void setUp() {
employeeMap.put(1, new Employee(1, "Name 1", "Title 1"));
employeeMap.put(2, new Employee(2, "Name 2", "Title 2"));
employeeMap.put(3, new Employee(3, "Name 3", "Title 3"));
}
@Test
public void testDocument() throws Exception {
@@ -40,6 +50,17 @@ public class TagCreatorTest {
).render();
assertThat(actual, is(expected));
}
@Test
public void testIffOptional() {
String expected = "<div><p>Test</p><a href=\"#1\">Test</a></div>";
String actual = div(
p("Test"),
iff(Optional.of(1), i -> a("Test").withHref("#" + i)),
iff(Optional.empty(), i -> a("Tast").withHref("#2"))
).render();
assertThat(actual, is(expected));
}
@Test
public void testIffElse() throws Exception {
@@ -56,7 +77,13 @@ public class TagCreatorTest {
}
@Test
@Ignore // Having some trouble with RetroLambda setup
public void testJoinWithNulls() throws Exception {
String expected = "This is my joined string. It has ignored null content in the middle.";
String actual = join("This is my joined string.", iff(false, "this should not be displayed"), "It has ignored null content in the middle.").render();
assertThat(actual, is(expected));
}
@Test
public void testEach() throws Exception {
String j2htmlMap = ul().with(
li("Begin list"),
@@ -72,12 +99,21 @@ public class TagCreatorTest {
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>"));
assertThat(j2htmlMap.equals(javaMap), is(true));
}
@Test
public void testEachWithMap() {
final String j2htmlMap = ul().with(
li("Begin list"),
each(employeeMap, entry -> li(entry.getKey() + "-" + entry.getValue().name))
).render();
assertThat(j2htmlMap, is("<ul><li>Begin list</li><li>1-Name 1</li><li>2-Name 2</li><li>3-Name 3</li></ul>"));
}
@Test
@Ignore // Having some trouble with RetroLambda setup
public void testFilter() throws Exception {
String j2htmlFilter = ul().with(
li("Begin list"),
@@ -93,8 +129,8 @@ public class TagCreatorTest {
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>"));
assertThat(j2htmlFilter.equals(javaFilter), is(true));
}
@Test

View File

@@ -1,12 +1,21 @@
package j2html.tags;
import org.junit.Test;
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.img;
import static j2html.TagCreator.input;
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;
import j2html.Config;
import static j2html.TagCreator.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import j2html.model.DynamicHrefAttribute;
import org.junit.Test;
public class TagTest {
@@ -46,11 +55,6 @@ public class TagTest {
Config.closeEmptyTags = false;
}
@Test
public void testFormattedTags() throws Exception { // better test in ComplexRenderTest.java
assertThat(div(p("Hello")).renderFormatted(), is("<div>\n <p>\n Hello\n </p>\n</div>\n"));
}
@Test
public void testEquals() throws Exception {
Tag tagOne = tag("p").withClass("class").withText("Test");
@@ -84,5 +88,16 @@ public class TagTest {
assertThat(testTagAttrWithoutAttr.render(), is("<a attribute></a>"));
}
@Test
public void testDynamicAttribute() throws Exception {
ContainerTag testTagWithAttrValueNull = new ContainerTag("a").attr(new DynamicHrefAttribute());
assertThat(testTagWithAttrValueNull.render(), is("<a href=\"/\"></a>"));
}
@Test
public void testDynamicAttributeReplacement() throws Exception {
ContainerTag testTagWithAttrValueNull = new ContainerTag("a").attr("href", "/link").attr(new DynamicHrefAttribute());
assertThat(testTagWithAttrValueNull.render(), is("<a href=\"/\"></a>"));
}
}

View File

@@ -0,0 +1,7 @@
#* @vtlvariable name="employees" type="java.util.List<j2html.comparison.ComparisonData.Employee>" *#
<ul>
#foreach($employee in $employees)
<li>$employee.id $employee.name $employee.title</li>
#end
</ul>

View File

@@ -0,0 +1,11 @@
<html>
<head>
<title>Title</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<main id="main" class="content">
<h1>Heading!</h1>
</main>
</body>
</html>

View File

@@ -0,0 +1,28 @@
#macro(mainLayout)
<html>
<head>
<title>Title</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<main id="main" class="content">
$!bodyContent
</main>
</body>
</html>
#end
#@mainLayout()
<div>
<h1>Example content</h1>
#someMacro(1)
#someMacro(2)
#someMacro(3)
</div>
#end
#macro(someMacro $callNumber)
<div>
Macro call $callNumber
</div>
#end

View File

@@ -0,0 +1,12 @@
<table>
<tbody>
#foreach($i in $tableNumbers)
<tr>
#foreach($j in $tableNumbers)
#set($product = $i * $j)
<td>$product</td>
#end
</tr>
#end
</tbody>
</table>