241 Commits

Author SHA1 Message Date
David
dcc7258c8e [maven-release-plugin] prepare release j2html-1.6.0 2022-06-30 20:40:09 +02:00
Scott Embler
930ade9354 Upgrading several maven plugins. (#213)
- The maven-enforcer-plugin had an API incompatibility that might be fixed with a version upgrade.
- Several other plugins were out-of-date, and worth upgrading.
- Some plugins were not upgraded out of concern that they might break the build.
2022-06-30 08:12:09 +02:00
Scott Embler
d1c404d5db Web component support (#211)
* Foundational components for reading/processing Wattsi files into classes.

* Introducing tests for compliance with wattsi definitions.

- Several elements have been found to be missing from the code generator.
- A long-term strategy for dealing with obsolete elements will be needed.  Should we remove and change the API?  Or should we deprecate and leave in-place?
- Found one element that was accidentally added to the code generator but never used.  Hopefully.
- Fixes will be applied in following commits.

* Added newer elements/tags and cleaned up invalid Tag class.

- Added DataTag.
- Added SlotTag and TemplateTag to support web components.
- Added global attributes to support web components.
- Removed GenerateTag.  Accidentally introduced by string replacement in code generator.

* Upgrading revapi and maven plugin. Configured revapi to ignore removal of GenerateTag.

- The GenerateTag class was created accidentally.  It does not have any representation in the HTML standard is should not be provided in this library.
2022-06-30 02:13:46 +02:00
Scott Embler
c2177d0584 Updated readme file with latest version number. (#206) 2022-02-02 13:34:48 -05:00
Scott Embler
5eb202b0a9 Updated html files for website. (#205) 2022-01-24 10:57:48 -05:00
Scott Embler
4bda3635ab Website update 1.5.0 release (#204)
* Updated new items to include 1.5.0.

- Adding short upgrade guide for incompatibilities between 1.4.0 and 1.5.0.
2022-01-23 22:04:46 -05:00
David (javalin.io)
f083b2cc9c Update and rename README to README.md 2022-01-23 22:31:21 +01:00
Scott Embler
9ad0e428c1 Fixes #200. Adds support for the picture tag. (#201) 2021-10-03 18:43:33 -04:00
Scott Embler
83866be83f Resolves #194. Introduces Revapi into the build process. (#195)
- Switching to verify goal in main.yml.
2021-06-17 10:17:50 -04:00
David
5135cffc3f Bump website to 1.5.0 2021-06-13 23:10:30 +02:00
David
09e08f3465 [maven-release-plugin] prepare for next development iteration 2021-06-13 23:02:20 +02:00
David
26ba4c3cae [maven-release-plugin] prepare release j2html-1.5.0 2021-06-13 23:02:14 +02:00
David
dc676b767f bump release plugin 2021-06-13 23:00:16 +02:00
David
07dcbb3ec2 specify pom location for release plugin 2021-06-13 22:11:29 +02:00
Scott Embler
b18459c66f Bifunction each (#191)
Adding TagCreator.each() method to provide access to the collection index.
2021-06-13 16:03:04 -04:00
David
aa8fb7c763 format java code in website project 2021-06-12 22:55:23 +02:00
David
c4f2429ec1 website readme 2021-06-12 22:45:00 +02:00
Scott Embler
a5aaeff22f Merge pull request #190 from obecker/remove-generated
Change package for generated tags
2021-06-12 16:30:49 -04:00
David
f4a179160c move website into repo 2021-06-12 22:19:38 +02:00
Oliver Becker
787035f6b1 Change package for generated tags
- move all generated tag classes from j2html.tags.specialized.generated to j2html.tags.specialized
  since they are now only generated tags and in the long run there should be no difference for a user of j2html whether the classes have been generated or not
2021-06-12 22:13:52 +02:00
Scott Embler
8b08968a6b Merge pull request #187 from obecker/htmltag
Remove manual tags, use only generated tags
2021-06-12 15:14:01 -04:00
Oliver Becker
56f61e421f Remove manual tags, use only generated tags
- change html, head, body from manual to generated tags
- restore compatibility with j2html 1.4.0
- fix https://github.com/tipsy/j2html/issues/185
2021-06-12 20:49:02 +02:00
Scott Embler
afd00597f7 Adding Automatic-Module-Name to manifest to support JDK 9+. (#183)
* Adding Automatic-Module-Name to manifest to support JDK 9+.

- Using reverse-DNS naming convention for module.
2021-06-08 12:23:20 -04:00
Scott Embler
8cc0b7c2c7 Merge pull request #184 from obecker/contributing-fix
Adjust CONTRIBUTING.md to the latest code changes
2021-06-07 18:25:58 -04:00
Oliver Becker
89f0194be0 Adjust CONTRIBUTING.md to the latest code changes
IInstance.get() has been renamed to self() in https://github.com/tipsy/j2html/pull/180
2021-06-07 17:43:35 +02:00
Scott Embler
1079a01750 Merge pull request #182 from obecker/each-fix
Remove calls to render() during tree construction.
2021-06-05 13:42:53 -04:00
Oliver Becker
f89957eeab Fix implementation flaw that called render() during tree construction
* Enables the new render capabilities also for content that was constructed with
  - TagCreator.each(Map, Function) and
  - TagCreator.each(Map, BiFunction)
* Adds convenience method TagCreator.each(DomContent...)
2021-06-04 15:57:16 +02:00
Scott Embler
c07facd490 Merge pull request #181 from sembler/fix_style_and_script_escaping
Treating text as unescaped when using TagCreator methods for style and script elements.
2021-06-03 10:24:45 -04:00
Scott.Embler
1d43a25457 Treating text as unescaped when using TagCreator methods for style and script elements.
- Replicating PR #152, but avoiding conflicts and using more current conventions.
2021-06-02 13:32:37 -04:00
sagesmith-wf
2ecd734239 Make join method work as expected (#168)
- Avoids appending a delimiter to the end of the joined text.
- Add test to verify changes.
2021-06-02 10:11:44 -04:00
Scott Embler
8b2669cab1 Merge pull request #180 from obecker/polish-code
Minor code improvements
2021-05-21 19:39:02 -04:00
Oliver Becker
8c0d03e200 Minor code improvements
* add compiler flag -Xlint:all, resolve all warnings about unchecked or raw generics
* rename IInstance.get() to IInstance.self() because it better reflects its intention
* move MainTag from manual to generated tags
* remove unnecessary type casts in TagCreator
2021-05-21 12:36:51 +02:00
Scott Embler
15702ac0d7 Extracted rendering functionality into implementations of HtmlBuilder. (#179)
* Extracted rendering functionality into implementations of HtmlBuilder.

- Two HtmlBuilders are implemented, FlatHtml and IndentedHtml.  Each offers the equivalent output as ContainerTag.render() and ContainerTag.renderFormatted.
- Existing implementations of DomContent/Renderable were updated to support HtmlBuilder where possible.
- Attribute was altered to support the use of TagBuilder.
- Config was altered to allow instances to be created, which can be passed into factory methods for the HtmlBuilders. Config.defaults() can be used for library defaults, while Config.global() can be used for current static configuration.
- Retained compatibility with previous library version as much as possible. See RenderingCompatabilityTest.

* Fixing unchecked or unsafe operations

* Removing unnecessary @param from javadoc.

* Improving casting of HtmlBuilders in implementations of DomContent (tags, text, etc.).

* Preventing NPEs when text is null.

Co-authored-by: Oliver Becker <ob@obqo.de>
2021-05-20 10:47:06 -04:00
Scott Embler
fd41cccfe2 Merge pull request #176 from obecker/intellij
Add .idea folder to .gitignore for developers using IntelliJ IDEA
2021-04-25 10:11:57 -04:00
Oliver Becker
31a565235e Add .idea folder to .gitignore for developers using IntelliJ IDEA 2021-04-25 10:32:23 +02:00
Oliver Becker
da76ee0d2b Fix indent of tags without tag name when using renderFormatted() (#174)
https://github.com/tipsy/j2html/issues/173

Off topic: Set execute flag on mvnw
2021-04-24 21:52:50 +02:00
Scott Embler
4a4c6314d8 Minor restructuring of Tag internals, increased argument validation, and tests to clarify current behavior. (#175)
Co-authored-by: Scott.Embler <scott.embler@noaa.gov>
2021-04-24 11:37:00 +02:00
pointbazaar
be626b6b96 completely separate the generated interfaces from manual ones and completely separate the manual tags from the generated ones. Also wipe the directories for code generation before code generation (#167) 2020-10-20 10:52:38 +02:00
dependabot[bot]
226cfb9a28 Bump junit from 4.11 to 4.13.1 in /code_gen (#166)
Bumps [junit](https://github.com/junit-team/junit4) from 4.11 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.11...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-17 10:25:29 +02:00
pointbazaar
acf6bff72a Split j2html in 2 projects, "code_gen" and "library" (Issue #161) (#165)
* split the project in 2, to make it easier to iterate on the code generation without breaking the build. This could also help reduce the compiled size of the library.

* update CONTRIBUTING.md

* try to fix github workflow
2020-10-17 10:23:57 +02:00
dependabot[bot]
07427c1433 Bump junit from 4.12 to 4.13.1 (#164)
Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-13 15:10:36 +02:00
lambdaupb
7d98d4f2bd Escape Attribute on render instead of in constructor. Fixes #160 (#162)
Also initialize EscapeUtil StringBuilder with input length to avoid growing copying.
2020-09-24 08:50:01 +02:00
lambdaupb
94ad6e29a3 Use one Appendable instance that is passed down for all rendering (#158) 2020-09-23 20:53:32 +02:00
pointbazaar
9338efc7cd Add CONTRIBUTING.md (depends on PR156) (#157)
* start on CONTRIBUTING.md

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md
2020-08-31 16:24:44 +02:00
pointbazaar
312cabe69c Implementation of Attributes-per-Tag via Interfaces (#156) 2020-08-31 16:24:00 +02:00
pointbazaar
f091000bbe first iteration of the attribute per tag POC (#154)
* create HtmlTag, BodyTag, HeadTag. hopefully without too large diffs this time.

* add some forgotten variants

* remove 'final' on some methods changed during the last 2 commits, to make it more consistent with the rest of the code

* remove <head>,<body>,<html> from TagCreatorCodeGenerator
2020-08-16 10:39:13 +02:00
David
2ae40f9e6c Update README.md 2020-08-15 17:38:58 +02:00
David
dd2079a136 add github ci workflow 2020-08-15 17:35:47 +02:00
David
b0cf8e8c6f add maven wrapper 2020-08-15 17:34:50 +02:00
David
793dcca03c remove travis file 2020-08-15 17:32:54 +02:00
pointbazaar
379ddb82bf Remove test dependency lombok
* lombok was almost never used. also gave me errors on 'mvn install' on ubuntu 20.04 https://github.com/rzwitserloot/lombok/issues/1651 . unless there are plans to use it more extensively, maybe it is best to remove it, to clean up the dependencies and enable me (and maybe others) to build without errors.

* fix Employee.java without lombok
2020-08-15 10:31:25 +02:00
Arne Zelasko
8316035854 add step attribute (#150) 2020-05-19 19:10:21 +02:00
b-gyula
1fcecb961e #145 override toString calling render() allowing inline usage: (#146)
```
String content = "Some content already generated";
content += tr(th("Name"),th("Desc")) + "some other content";
```
2020-02-06 12:28:01 +01:00
Jamie Mansfield
5c9d62cdf3 bug-fix: Children of non-formatted tags (#139)
Resolves GH-138.
2019-09-14 00:29:55 +02:00
David
c31badd3e4 Update .travis.yml 2019-09-13 23:46:39 +02:00
labkey-matthewb
629038303c remove private constructor from Attr (#134) 2019-06-04 20:49:35 +02:00
mbellew
0f30bc9d9a generalize addTo() to enable other attr helpers besides ShortForm (#133)
* small changes to make for easier experimentation

* generalize addTo() to enable other attr helpers besides ShortForm
2019-05-31 23:28:56 +02:00
mbellew
ae65127dcc small changes to make for easier experimentation (#132) 2019-05-31 23:20:10 +02:00
David
dae578a523 Bump version in readme 2019-01-24 14:49:40 +01:00
David
b89435ca7c Cleanup after tests 2019-01-24 14:49:13 +01:00
David
3deb6b4ddb [maven-release-plugin] prepare for next development iteration 2019-01-24 14:43:12 +01:00
David
023922a7db [maven-release-plugin] prepare release j2html-1.4.0 2019-01-24 14:42:55 +01:00
David
00c0461669 Auto format project 2019-01-24 14:24:21 +01:00
Robin Karlsson
cd6e0084ef Add Stream<DomContent> variants of each and with (#118) 2018-05-20 21:45:36 +02:00
Moandji Ezana
764b5d7759 Add TagCreator::each(Map, BiFunction) (#115) 2018-05-07 00:18:36 +02:00
David
d9c4963ff0 bump version 2018-05-01 12:29:02 +02:00
David
3ec15d28a5 woops 2018-05-01 12:28:13 +02:00
Moandji Ezana
f1680464d1 Do not indent textarea contents (#113)
* Do not indent textarea contents.

Fixes #102

* Restore import style

* Handle <pre> and TagCreator::each
2018-05-01 02:06:45 +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
David
eb3f28a09f [maven-release-plugin] prepare release j2html-1.2.1 2017-11-28 00:05:25 +01:00
David
368241313d Allow reading static resources from jars 2017-11-27 19:41:20 +01:00
David
4288924f8f Fix greedy semi-colon stripper bug in CSSMin
If CSSMin encounters a CSS-rule without a semi-colon at the end,
it will strip one char too many from that rule. This commit fixes that.
2017-11-27 12:54:07 +01:00
Janning Vygen
9948095c08 Fix for https://github.com/tipsy/j2html/issues/80 (#82)
* Fix for https://github.com/tipsy/j2html/issues/79

* Fix for https://github.com/tipsy/j2html/issues/80
2017-11-10 16:11:58 +01:00
Janning Vygen
56090046b5 Fix for https://github.com/tipsy/j2html/issues/79 (#81) 2017-11-10 16:07:20 +01:00
Thomas Tanon
d45af42650 Adds Tag.withLang and Tag.withDir (#76)
* Adds Tag.withLang and Tag.withDir

Allows easiest addition of mixed languages

* Add withCond(Lang|Dir)
2017-10-23 14:21:29 +02:00
David
7d65f91f44 Fix javadoc bug 2017-09-03 11:30:05 +02:00
David
aecf5e71d6 Update README.md 2017-09-03 11:26:10 +02:00
David
cf47772c89 [maven-release-plugin] prepare for next development iteration 2017-09-03 11:16:05 +02:00
David
897c53d830 [maven-release-plugin] prepare release j2html-1.2.0 2017-09-03 11:15:46 +02:00
David
1e29d81107 Fix another javadoc violation 2017-09-03 11:14:41 +02:00
David
dee3efb8e7 Remove javadoc violation 2017-09-03 11:08:36 +02:00
David
ee82201dfb Misc cleanup
- Add javadoc to Config
- Make CSSMin/JSMin configurable (add Minifier interface)
- Change SimpleEscaper back to a util
2017-09-02 19:41:37 +02:00
David
691680ea51 Add simple formatter (fixed #65)
* Add simple formatter
* Create Indenter interface
* Shorten variable-names in renderFormatted
* Fix javadoc
2017-09-02 19:05:48 +02:00
David
0853692e80 Use diamond operator 2017-09-01 20:50:20 +02:00
David
c2bc4b3209 Add @FunctionalInterface annotation to TextEscaper 2017-09-01 20:40:57 +02:00
David
ff9d138f63 Add option to close empty tags (fixes #52) 2017-09-01 20:39:23 +02:00
David
f778f4df3c Add convenience method for title (fixes #71) 2017-09-01 20:12:47 +02:00
David
a0b060ac42 Let attr() take object value (fixes #57) 2017-09-01 20:09:10 +02:00
David
4161be67bb Fix escaper-test 2017-09-01 20:07:48 +02:00
David
863527f684 Update README.md 2017-08-14 17:58:37 +02:00
David
5ef2dd3ec5 [maven-release-plugin] prepare for next development iteration 2017-08-14 17:45:23 +02:00
David
fc3bb29b6a [maven-release-plugin] prepare release j2html-1.1.0 2017-08-14 17:45:02 +02:00
Sergey Bezkostnyi
ef5777e54a Add ability to change text escaper implementation (#70) 2017-08-14 17:10:02 +02:00
David
cfc1489399 Merge pull request #63 from maztan/master
Add method to get number of children of ContainerTag
2017-07-29 19:19:08 +02:00
Ed Savailonei
8112dad1bb Add methd to get number of children of ContainerTag 2017-07-03 12:41:10 +02:00
David
235dec78ed Merge pull request #62 from kiru/patch-1
Updaate Gradle Version
2017-05-19 23:05:12 +02:00
Kiru
6316dd2262 Updaate Gradle Version 2017-05-19 21:57:04 +02:00
David
5667d7c68d Update README.md 2017-05-16 18:49:27 +02:00
David
13911d5f57 [maven-release-plugin] prepare for next development iteration 2017-05-16 18:00:33 +02:00
David
0bc6e274db [maven-release-plugin] prepare release j2html-1.0.0 2017-05-16 18:00:10 +02:00
David
325afd463c Fix version 2017-05-16 17:58:03 +02:00
David
f331eb9eb3 Merge pull request #61 from EthanDRaymond/DomContentJoiner-Does-Not-Use-Delimiter
Fixed a bug (maybe) where a delimiter was not being used
2017-05-12 22:45:10 +02:00
Ethan Raymond
d37dc1cac6 Fixed a bug (maybe) where a delimiter was not being used. 2017-05-12 15:39:23 -04:00
David
dab61bd662 [maven-release-plugin] prepare for next development iteration 2017-05-03 19:57:56 +02:00
David
d559f05903 [maven-release-plugin] prepare release j2html-1.0.0-RC 2017-05-03 19:57:31 +02:00
David
97a8f34572 Make filereader java6 compatible, because why not 2017-05-02 22:39:59 +02:00
David
6305e364ca Experimental Java6/Java7 support 2017-05-02 03:12:17 +02:00
David
28ba518b12 Fix name collision + minor cleanup 2017-05-01 19:10:42 +02:00
David
5f04cde97c Merge pull request #56 from tipsy/id-class-shorthand
Add shorthand notation for id/class
2017-05-01 18:59:11 +02:00
David
b00ba50133 Add attrs method to tagcreator 2017-05-01 18:51:04 +02:00
David
e09918da12 Add missing test-case to attr.shortform 2017-05-01 18:06:10 +02:00
David
55b74e81aa Improve generics in Attr.addTo 2017-05-01 16:54:05 +02:00
David
75deeff13d Remove unwanted import 2017-05-01 16:29:22 +02:00
David
3aa05aa540 Merge branch 'master' into id-class-shorthand 2017-05-01 16:15:01 +02:00
David
fb24d1eabf Merge pull request #55 from chmuche/empty-attribute
Empty attribute
2017-05-01 15:50:07 +02:00
David
458f3baf98 Merge pull request #54 from chmuche/gradle-dependency
Add Gradle dependency in README.md
2017-05-01 15:48:25 +02:00
David
a661f37575 Add document() method that renders a html() child 2017-05-01 15:45:02 +02:00
David
26796cd30d Add shorthand notation for id/class 2017-05-01 15:22:48 +02:00
chmuche
75dc60c415 Add Test 2017-05-01 15:19:27 +02:00
chmuche
99b98f9b09 Create a method attr without value to create empty attribute inside the tag 2017-05-01 15:12:41 +02:00
chmuche
8d4756bab0 Add Gradle dependency in README.md 2017-05-01 15:07:50 +02:00
David
2c1f337348 Update README.md 2017-04-30 20:37:27 +02:00
David
d437e1affd Add a domcontentjoiner 2017-04-29 16:44:48 +02:00
David
4fdcc3c213 Remove need for with() 2017-04-29 12:15:51 +02:00
David
ba3261b210 Update README.md 2017-04-25 23:34:26 +02:00
David
ee0100d1a7 Set snapshot to 1.0.0 2017-04-20 23:17:07 +02:00
David
9ec3088d82 [maven-release-plugin] prepare for next development iteration 2017-04-20 23:13:36 +02:00
David
8052cdaff1 [maven-release-plugin] prepare release j2html-0.99 2017-04-20 23:13:16 +02:00
David
34b2410830 Add withClasses(String... classes) method 2017-04-20 23:08:12 +02:00
David
75d361fa20 Merge pull request #51 from tipsy/iff-else
Add generic iff-method to use in method calls
2017-04-20 21:34:07 +02:00
David
3e91da0640 Add generic iff-method to use in method calls 2017-04-17 16:20:12 +02:00
David
d1613b0570 Change Error to RuntimeException 2017-04-17 15:35:06 +02:00
David
a841271ba4 Merge pull request #50 from tipsy/inline-static-fix
Fix #14 (Unable to read files from directories other that /src/main/r…
2017-04-16 10:37:09 +02:00
David
9272438940 Simplify resource handling and throw exception 2017-04-13 21:21:01 +02:00
David
3d43eb159f Fix #14 (Unable to read files from directories other that /src/main/resources) 2017-04-13 01:25:16 +02:00
David
30bfe4ea7f Small formatting fix 2017-04-12 19:40:26 +02:00
David
7409772c20 Update README.md 2017-04-12 19:30:26 +02:00
David
29e16df057 Improve escaper performance 2017-03-28 22:23:33 +02:00
David
6903bcbe4d Update README.md 2017-01-30 00:28:58 +01:00
David
56b830782f [maven-release-plugin] prepare for next development iteration 2017-01-29 21:32:54 +01:00
David
10a400ac28 [maven-release-plugin] prepare release j2html-0.88 2017-01-29 21:32:34 +01:00
David
e0b0425da4 Remove stringutils and add simple escaper (#34) 2017-01-29 17:26:54 +01:00
David
f44d62d93a Change 'unsafeHtml' to 'rawHtml' (#44) 2017-01-29 16:43:50 +01:00
David
652b6921c7 Use assertThat instead of assertEquals 2017-01-29 16:27:19 +01:00
David
d7e56686d1 Add equals method to Tag (#28) 2017-01-29 15:49:36 +01:00
David
cc289b8430 Fix imports in rendertest 2017-01-29 14:46:14 +01:00
David
85d0ab023c Add withStyle method 2017-01-29 14:22:33 +01:00
David
0b3ca28cf3 Sort attributes 2017-01-29 14:16:14 +01:00
David
45a7c32d88 Auto format files 2017-01-29 13:20:18 +01:00
David
733199cd15 Remove closure in favor of a simple JSMin implementation
Closure is a great js-minifier, but js-minification is really
outside the scope of this project.
A simple space/line stripper should be suffcient.
2017-01-29 12:55:30 +01:00
David
df1e4da96d Autoformat CSSMin 2017-01-29 12:07:08 +01:00
David
05dcf6d679 Merge pull request #39 from dellgreen/java8doclintFixs
updated javadoc comments to pass doclint checks in java 8
2017-01-15 20:56:07 +01:00
David
b5d7f5fe18 Merge pull request #38 from dellgreen/renameTestResource
renamed test java resource to match its declared class name
2017-01-15 20:55:07 +01:00
David
872baeeeea Merge pull request #36 from charphi/optional-dep
Set closure-compiler dependency as optional.
2017-01-15 20:54:58 +01:00
David
fcc42cfd8f Merge pull request #35 from tipsy/pr/31
created render(Appendable)-method as a faster alternative to converting to string and writing then.
2017-01-15 20:54:47 +01:00
Dell Green
db8d968f7e updated javadoc comments to pass doclint checks in java 8 2017-01-13 11:42:11 +00:00
Dell Green
673a19faaa renamed test java resource to match its declared class name, otherwise Netbeans flags it as an error 2017-01-13 11:32:09 +00:00
Philippe Charles
96020f8396 Set closure-compiler dependency as optional. 2017-01-09 11:50:53 +01:00
Abius
91c3f42696 created render(Appendable)-method as a faster alternative to converting
to string and writing then.
2017-01-07 16:09:11 +01:00
David
0efd3c6f0c Tell travis to use latest sdk 2017-01-07 16:03:18 +01:00
David
b73c5d0c14 Merge pull request #27 from amaembo/master
Several cosmetic fixes
2016-06-12 10:19:00 +02:00
lan
977c31dad5 Cosmetic fixes:
1. Attr: all public static constants declared final
2. Tag: f-bounded type declaration
3. Tag::renderOpenTag: StringBuilder used
4. ContainerTag::with, condWith: Iterable and PECS arguments used
2016-06-06 15:49:08 +06:00
David
0c1cb2be10 Merge pull request #24 from DevFactory/release/general-code-quality-fix-1
Use isEmpty in TagContainer and collapse some if's in CSSMin
2016-04-26 22:36:27 +02:00
David
d09eb8597c Merge pull request #23 from DevFactory/release/exception-classes-should-be-immutable-fix-1
Code quality fix - Exception classes should be immutable.
2016-04-26 22:33:57 +02:00
David
b8a3882529 Merge pull request #22 from DevFactory/release/utility-classes-should-not-have-public-constructors-fix-1
Code quality fix - Utility classes should not have public constructors.
2016-04-26 22:33:12 +02:00
tipsy
b366207e30 Bump travis jdk version 2016-04-24 16:05:47 +02:00
tipsy
3821671a65 Add 'each' and 'filter' methods 2016-04-24 15:53:58 +02:00
Faisal Hameed
66fff8db69 Fixing squid:S1066, squid:S1155 2016-04-22 12:33:44 +05:00
Faisal Hameed
b11af765fa Fixing squid:S1165 - Exception classes should be immutable. 2016-04-22 12:03:36 +05:00
Faisal Hameed
d331789074 Fixing squid:S1118 - Utility classes should not have public constructors. 2016-04-22 11:55:40 +05:00
David
314de2459a Update README.md 2016-04-16 21:57:25 +02:00
tipsy
2beb4e903e Refactor core classes
- Introduce DomContent class with render method
- Make Tag and Text/UnescapedText extend DomContent (Text/UnescapedText don't extend Tag anymore)
- Use generics to remove duplicate code from ContainerTag and EmptyTag
- Remove setParent method
- Make setAttribute private
2016-04-02 18:08:37 +02:00
tipsy
d29da958e1 Auto format / organize imports 2016-04-01 22:45:01 +02:00
tipsy
595d658a15 Clean up CSSMin slightly 2016-04-01 22:44:42 +02:00
tipsy
dd4a025ad0 Add missing tests 2016-04-01 22:43:55 +02:00
David
3c42c7d4f4 Merge pull request #15 from arnzel/patch-1
Add Attribute "role"
2016-04-01 14:22:36 +02:00
Arne Zelasko
871405c414 Update EmptyTag.java 2016-04-01 10:54:22 +02:00
David
e7588aeb6a Merge pull request #16 from snaketl/master
Adjusted junit dependency to use only on scope test
2016-04-01 08:31:26 +02:00
Luiz Henrique Feltes
074aae4609 Adjusted junit dependency to use only on scope test 2016-03-31 21:10:17 -03:00
Arne Zelasko
66479f52c5 Update ContainerTag.java 2016-03-31 12:54:47 +02:00
Arne Zelasko
a5e79b536d Update Attr.java 2016-03-31 12:52:50 +02:00
tipsy
79e062355e Bump closure 2015-12-18 12:44:10 +01:00
David
947f12d5a1 Update README.md 2015-11-22 17:03:17 +01:00
tipsy
a46ba46bda Dat newline again 2015-11-22 16:39:41 +01:00
tipsy
41da131bbc Dat newline 2015-11-22 16:38:22 +01:00
tipsy
9428bf7397 Dat travis 2015-11-22 16:37:41 +01:00
tipsy
67e1c887b8 Formatting 2015-11-07 01:02:55 +01:00
David
bdd8dcbd2c Merge pull request #9 from ronanlg/master
Enable developpment under Linux and with Eclipse
2015-11-07 00:59:47 +01:00
RaG
b9d1f3a74d make end of line in test more independent from the OS 2015-11-06 20:56:00 +01:00
RaG
530565c9df add ignore rules specific to eclipse 2015-11-06 20:55:15 +01:00
David
30d1331c28 Update README.md 2015-10-25 11:45:11 +01:00
tipsy
58b2444ed4 [maven-release-plugin] prepare for next development iteration 2015-10-24 14:36:58 +02:00
tipsy
66b298efe4 [maven-release-plugin] prepare release j2html-0.7 2015-10-24 14:36:53 +02:00
tipsy
ed44fc79e0 Revert "Prepare for .7 release"
This reverts commit c926322fb6.
2015-10-24 13:40:12 +02:00
tipsy
c926322fb6 Prepare for .7 release 2015-10-24 13:35:05 +02:00
tipsy
d52f86dd39 Add uneeded test 2015-10-24 13:21:41 +02:00
tipsy
5692033f90 Rename inline-file-method names 2015-10-22 16:05:30 +02:00
tipsy
8667fd31d7 Methods for escaped and unescaped file as string 2015-10-22 01:39:31 +02:00
tipsy
9ef6d645d8 Add method for reading any file 2015-10-21 23:10:12 +02:00
David
4a2f502e5d Update README.md 2015-10-21 20:55:02 +02:00
tipsy
f54f0a53e4 Log using logger instead of sout 2015-10-21 19:56:28 +02:00
tipsy
04439d79de Use enum in ISR class 2015-10-21 17:41:53 +02:00
tipsy
f2d6621570 Tiny refactor 2015-10-21 09:15:10 +02:00
tipsy
4f05b26dc1 Stop using properties in POM 2015-10-20 23:47:37 +02:00
tipsy
c2691df9c5 EOF newlines 2015-10-20 23:18:45 +02:00
tipsy
91b12a6da0 Move package 2015-10-20 21:10:52 +02:00
tipsy
ccd76527bc Add filereader for inline static files 2015-10-20 19:40:54 +02:00
tipsy
ef43af72a3 Java 7 support, cleanup 2015-10-19 20:22:58 +02:00
tipsy
5ad63ad1d6 Use apache commons lang for escaping 2015-10-19 20:22:57 +02:00
tipsy
e92b7ce527 Change to non-deprecated assert 2015-10-19 20:22:57 +02:00
David
7bbb3a34da Update LICENSE
Woops x)
2015-10-05 20:19:18 +02:00
David
7e3e827af5 Update README.md 2015-05-28 20:08:56 +02:00
tipsy
0f5639660d use american english spelling of license 2015-05-27 20:09:21 +02:00
David
aa64aca294 Create LICENCE 2015-05-27 20:04:35 +02:00
tipsy
6f11845140 [maven-release-plugin] prepare for next development iteration 2015-05-26 19:38:01 +02:00
415 changed files with 143342 additions and 1352 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

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
text eol=crlf

28
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Test all JDKs on all OSes
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
java_version: [1.8, 9, 10, 11, 12, 13]
os: [windows-latest, macOS-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Set up JDK ${{ matrix.java_version }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java_version }}
- name: Make Maven Wrapper executable
if: contains(matrix.os, 'win') == false
run: chmod +x ./mvnw
- name: Build with Maven
run: ./mvnw verify --file library/pom.xml --batch-mode
env:
MAVEN_OPTS: -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn

96
.gitignore vendored
View File

@@ -1,96 +1,14 @@
# Created by https://www.gitignore.io
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
### Eclipse ###
.classpath
.project
.settings/
buildNumber.properties
### IntelliJ ###
.idea/

117
.mvn/wrapper/MavenWrapperDownloader.java vendored Normal file
View File

@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

2
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

153
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,153 @@
# Contributing
This Project is currently accepting Contributions.
Have a look at the Issues for Inspiration.
## Requirements
- JDK >= 1.8 (see pom.xml)
- Maven
## Project Goals
As stated in the **README**, the Goal of this Project is to enjoy typesafe, performant HTML generation in Java.
For preventing performance regressions, there are Tests.
## Coding Style
There is a `.editorconfig` and a `eclipse_formatting_profile.xml`
What sticks out is that end of line is CRLF `'\r\n'` for this Project.
This means that if you're on Linux `'\n'`, you have to configure git to handle this
correctly so that you have the correct EOL in your working directory,
and the EOL is also correct in the repository itself.
For this purpose, j2html has a `.gitattributes` file.
[Guide to configuring EOL with git](https://docs.github.com/en/github/using-git/configuring-git-to-handle-line-endings)
If you are on Windows, there should be no Problems.
### Reformatting of generated Java Code
As this Projects makes use of Code-Generation techniques in order to generate a more typesafe API without too much manual Work,
there is the `code_gen/` directory which contains everything needed to generate the code.
For simplicity (and also to avoid extra dependencies), they do not format the code correctly.
So if you change the Code-Generation Code, you may need to reformat the generated files to fit the Coding Style.
## Contribution Workflow
The workflow (most of the time) consists of:
- Comment (on Issue or PR) to find out what needs Work
- Get Feedback on your Ideas
- Fork this repo
- Open a PR
- Adjust the PR until it is merged or discarded
## Project Architecture
### library/src/main/java/j2html/TagCreator.java
This is **the** central class in J2HTML. It provides the methods
for users of J2HTML to generate all HTML Tags.
It contains methods like
```
public static HtmlTag html(DomContent... dc) {
return new HtmlTag().with(dc);
}
```
which can be used in Projects using this dependency as
```
html(
head(
script("https://example.com/my/js/files.js")
),
body(
div(
h1("Hello World")
).withClasses("container")
)
)
```
### How are the different HTML Tags implemented?
Each HTML Tag has it's own class, which makes it possible for each Tag to have
the correct Attributes and Methods to set those Attributes.
The classes are located in `library/src/main/java/j2html/tags/specialized` and follow the naming convention `tag_name + 'Tag.java'`, e.g. `BodyTag.java`.
Notice that the first letter of the Tag is in uppercase.
Each Tag-specific class `implements` interfaces which correspond to the Attributes that can be set on these Tags.
For Reference which Tags support which Attributes, see [HTML Attribute Reference](https://www.w3schools.com/tags/ref_attributes.asp).
For Example, `ButtonTag` might implement `IType<ButtonTag>` which says it can have an Attribute `type`, which may later show up like `<button type="submit"></button>`.
### How are the Attributes of HTML Tags implemented?
Each Attribute has it's own interface in `src/main/java/j2html/tags/attributes/` and follows the naming convention `"I" + attribute_name + '.java'`, e.g. `IAccept.java`. Notice that the first letter of the Attribute is in uppercase.
Dissecting `IAccept.java`:
```
public interface IAccept<T extends Tag> extends IInstance<T> {
default T withAccept(final String accept_) {
return self().attr("accept", accept_);
}
default T withCondAccept(final boolean enable, final String accept_) {
if (enable) {
self().attr("accept", accept_);
}
return self();
}
}
```
As you can see, **IAccept** extends `IInstance<T>` which provides only the `self()` Method to access an instance of type `T`.
All attribute-specific interfaces extend `IInstance<T>`.
```
public interface IInstance<T> {
default T self() { return (T) this; }
}
```
`IInstance<T>` is cheating the type system because `self()` returns an instance of type `T`, but the implementing class
technically does not have to supply it's own type as the type argument. But by convention, in this Project, the implementing class
always supplies it's own type as the type argument.
But in `default` methods in interfaces there is AFAIK no way to obtain the type of the class that is implementing the interface.
If you find a way, that would be a great PR.
### Special classes/interfaces besides TagCreator.java
There are 3 classes which contain code-generating methods in `code_gen/src/main/java/j2html_codegen/generators/`:
- `AttributeInterfaceCodeGenerator.java` (generating the interfaces for the attributes)
- `SpecializedTagClassCodeGenerator.java` (generating the classes for the tags)
- `TagCreatorCodeGenerator.java` (generating some contents of `TagCreator.java`)
### Other special classes / interfaces in J2HTML
- **Tag.java** is the base class for every tag and extends DomContent
- **EmptyTag.java** is the base class for all Tags which have no contents
- **ContainerTag.java** is the base class for all Tags which can contain other tags
- **DomContent.java**
### How is the Code generation for the Attribute specific Interfaces parameterized?
Attributes differ in their 'type' . Some of them can be set with numbers (which are converted into strings in the html).
Others can only be set or not set, others still have 3 states: set, unset, and not present.
To model these propertise, a single Attribute can be described by an instance of **AttrD.java**.
`library/src/main/java/j2html/tags/generators/AttributesList.java` contains the different Attributes, their properties,
and the Tags they can be set on. It is the starting point for adding new Attributes and customizing their properties.

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015 David Åse
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,4 +1,45 @@
[![Workflow](https://github.com/tipsy/j2html/workflows/Test%20all%20JDKs%20on%20all%20OSes/badge.svg)](https://github.com/tipsy/j2html/actions)
![](https://img.shields.io/github/license/tipsy/j2html.svg)
![](https://img.shields.io/maven-central/v/com.j2html/j2html.svg)
# j2html
Java to HTML generator. Enjoy typesafe HTML generation.
This project was inspired by [Gagawa](https://code.google.com/p/gagawa/)
The project webpage is [j2html.com](http://j2html.com).
## Getting started
### Add the maven dependency
```xml
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.5.0</version>
</dependency>
```
### Or the gradle dependency
```
compile 'com.j2html:j2html:1.5.0'
```
### Import TagCreator and start building HTML
```java
import static j2html.TagCreator.*;
public class Main {
public static void main(String[] args) {
body(
h1("Hello, World!"),
img().withSrc("/img/hello.png")
).render();
}
}
```
The above Java will result in the following HTML:
```html
<body>
<h1>Hello, World!</h1>
<img src="/img/hello.png">
</body>
```
Find more examples at http://j2html.com/examples.html

101
code_gen/.gitignore vendored Normal file
View File

@@ -0,0 +1,101 @@
# Created by https://www.gitignore.io
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
### Eclipse ###
.classpath
.project
.settings/
buildNumber.properties

85
code_gen/pom.xml Normal file
View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.j2html</groupId>
<artifactId>j2htmlcodegen</artifactId>
<version>1.0-SNAPSHOT</version>
<name>j2htmlcodegen</name>
<url>https://j2html.com/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,33 @@
package j2html_codegen;
import j2html_codegen.generators.AttributeInterfaceCodeGenerator;
import j2html_codegen.generators.SpecializedTagClassCodeGenerator;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public final class App
{
public static void main( String[] args )
{
final Path relPath = Paths.get("../library/src/main/java/j2html/");
final Path absPath = relPath.toAbsolutePath();
System.out.println("writing in "+absPath);
//decide if the files should be
//deleted or generated
final boolean delete = false;
try {
AttributeInterfaceCodeGenerator.generate(absPath, delete);
SpecializedTagClassCodeGenerator.generate(absPath, delete);
//TagCreatorCodeGenerator.print();
} catch (IOException e) {
e.printStackTrace();
}
//don't forget to auto-reformat the generated code.
}
}

View File

@@ -0,0 +1,16 @@
package j2html_codegen;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public final class GeneratorUtil {
public static final void deleteAllFilesInDir(final Path dir) throws IOException {
for(final File file : dir.toFile().listFiles()){
System.out.println("deleting " + file.toPath());
Files.delete(file.toPath());
}
}
}

View File

@@ -0,0 +1,184 @@
package j2html_codegen.generators;
import j2html_codegen.GeneratorUtil;
import j2html_codegen.model.AttrD;
import j2html_codegen.model.AttributesList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public final class AttributeInterfaceCodeGenerator {
private static final String relPath = "tags/attributes/";
public static void generate(final Path absPath, final boolean delete) throws IOException {
//delete all files in the directory for fresh generation
final Path dir = Paths.get(absPath.toString(),relPath);
GeneratorUtil.deleteAllFilesInDir(dir);
for (final AttrD attr : AttributesList.attributesDescriptive()) {
final Path path = makePath(attr.attr, absPath);
final String interfaceName = interfaceNameFromAttribute(attr.attr)+"<T extends Tag<T>>";
/*
IFormAction<T extends Tag<T>> extends IInstance<T>
default T withFormAction(String formAction){
return self().attr("formaction", formAction);
}
*/
final String interfaceStr = getInterfaceTemplate(
interfaceName,
Optional.of("IInstance<T>"),
Arrays.asList("j2html.tags.Tag","j2html.tags.IInstance"),
interfaceNameFromAttribute(attr.attr).substring(1),
attr
);
if (!delete) {
System.out.println("writing to "+path);
Files.write(path, interfaceStr.getBytes());
}
}
}
private static String getPackage(){
return "package j2html.tags.attributes;\n";
}
private static String makeReturnTypeAndMethodName(final String name){
return "default "+ "T "+name;
}
private static String getInterfaceTemplate(
final String interfaceName,
final Optional<String> optExtends,
final List<String> imports,
final String interfaceNameSimple,
final AttrD attrD
){
final StringBuilder sb = new StringBuilder();
sb.append(getPackage());
sb.append("\n");
for(String importName : imports){
sb.append("import ").append(importName).append(";\n");
}
sb.append("\n");
sb.append("public interface ")
.append(interfaceName);
optExtends.ifPresent(ext -> sb.append(" extends ").append(ext).append(" "));
sb.append(" {\n");
//interface contents
/*
IFormAction<T extends Tag> extends IInstance<T>
default T withFormAction(String formAction){
return self().attr("formaction", formAction);
}
*/
//IMPORTANT: '_' added as suffix to mitigate problems
//where attributes are java keywords. Just to make it consistent and avoid special cases.
final String attrName = interfaceNameSimple.toLowerCase();
final String paramName = attrName+"_";
//depending on if the attribute has an argument or not,
//generate methods according to the convention in Tag.java
// arg -> with$ATTR(arg), withCond$ATTR(condition, arg)
// no arg -> is$ATTR(), withCond$ATTR(condition)
//append the 'with$ATTR' method
writeAttributeMethod(interfaceNameSimple, attrD, sb, attrName, paramName);
writeAttributeMethodCond(interfaceNameSimple, attrD, sb, attrName, paramName);
sb.append("}\n");
return sb.toString();
}
private static void addAttributeNoArg(final StringBuilder sb, final String attrName){
//generate the code to add an attribute without an argument
//there are some special attributes
//which do take an argument, but where the argument
//is boolean (meaning on/off, yes/no and the like)
sb.append("self().attr(\"");
if (attrName.equals("autocomplete")){
sb.append(attrName).append("\",\"on\"");
} else {
sb.append(attrName).append("\"");
}
sb.append(");\n");
}
private static void writeAttributeMethodCond(String interfaceNameSimple, AttrD attrD, StringBuilder sb, String attrName, String paramName) {
sb.append(makeReturnTypeAndMethodName("withCond"+interfaceNameSimple));
if(attrD.hasArgument){
//add a variant where you can specify the argument
sb.append("(final boolean enable, final String ").append(paramName).append(") {");
sb.append("if (enable){\n");
sb.append("self().attr(\"").append(attrName).append("\", ").append(paramName).append(");\n");
sb.append("}\n");
sb.append("return self();\n");
}else{
//add a variant where you can toggle the attribute
sb.append("(final boolean enable) {");
sb.append("if (enable){\n");
addAttributeNoArg(sb, attrName);
sb.append("}\n");
sb.append("return self();\n");
}
sb.append("}\n");
}
private static void writeAttributeMethod(String interfaceNameSimple, AttrD attrD, StringBuilder sb, String attrName, String paramName) {
sb.append(makeReturnTypeAndMethodName(
((attrD.hasArgument)?"with":"is")+interfaceNameSimple)
);
if(attrD.hasArgument){
//add a variant where you can specify the argument
sb.append("(final String ").append(paramName).append(") {")
.append("return self().attr(\"").append(attrName).append("\", ").append(paramName).append(");\n");
}else{
//add a variant where you can toggle the attribute
sb.append("() {");
addAttributeNoArg(sb, attrName);
sb.append("return self();\n");
}
sb.append("}\n");
}
public static String interfaceNameFromAttribute(String attribute){
String res = attribute.substring(0,1).toUpperCase()+attribute.substring(1);
return "I" + res;
}
private static Path makePath(String tagLowerCase, final Path absPath){
final String filename = interfaceNameFromAttribute(tagLowerCase)+".java";
return Paths.get(absPath.toString(),relPath,filename);
}
}

View File

@@ -0,0 +1,166 @@
package j2html_codegen.generators;
import j2html_codegen.GeneratorUtil;
import j2html_codegen.model.AttributesList;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static j2html_codegen.generators.TagCreatorCodeGenerator.containerTags;
import static j2html_codegen.generators.TagCreatorCodeGenerator.emptyTags;
public final class SpecializedTagClassCodeGenerator {
private static final String relPath = "tags/specialized";
public static void generate(final Path absPath, final boolean delete) throws IOException {
//delete all files in the directory for fresh generation
final Path dir = Paths.get(absPath.toString(),relPath);
GeneratorUtil.deleteAllFilesInDir(dir);
//the delete argument serves to give the possibility
//to delete the classes that were written before
System.out.println("// EmptyTags, generated in " + SpecializedTagClassCodeGenerator.class);
for (final String tag : emptyTags()) {
final String className = classNameFromTag(tag);
final Path path = makePath(absPath,tag);
final List<String> interfaceNames = getInterfaceNamesForTag(tag);
final String classString =
getClassTemplate(
className,
Optional.of("EmptyTag<"+className+">"),
Arrays.asList(
"j2html.tags.EmptyTag",
"j2html.tags.attributes.*"
),
tag,
interfaceNames
);
/*
public InputTag() {
super("input");
}
*/
if(!delete){
System.out.println("writing to "+path);
Files.write(path, classString.getBytes());
}
}
System.out.println("// ContainerTags, generated in " + SpecializedTagClassCodeGenerator.class);
for (final String tag : containerTags()) {
final Path path = makePath(absPath, tag);
final String className = classNameFromTag(tag);
final List<String> interfaceNames = getInterfaceNamesForTag(tag);
final String classString =
getClassTemplate(
className,
Optional.of("ContainerTag<"+className+">"),
Arrays.asList(
"j2html.tags.ContainerTag",
"j2html.tags.attributes.*"
),
tag,
interfaceNames
);
if(delete){
if(Files.exists(path)) {
System.out.println("deleting " + path);
Files.delete(path);
}
}else {
System.out.println("writing to "+path);
Files.write(path, classString.getBytes());
}
}
}
public static String classNameFromTag(String tageNameLowerCase){
String res = tageNameLowerCase.substring(0,1).toUpperCase()+tageNameLowerCase.substring(1);
return res + "Tag";
}
private static Path makePath(final Path absPath, String tagLowerCase){
final String filename = classNameFromTag(tagLowerCase)+".java";
return Paths.get(absPath.toString(),relPath,filename);
}
private static String getPackage(){
return "package j2html.tags.specialized;\n";
}
private static String getClassTemplate(
final String className,
final Optional<String> optExtends,
final List<String> imports,
final String tag,
final List<String> interfaces
){
final StringBuilder sb = new StringBuilder();
sb.append(getPackage());
sb.append("\n");
for(String importName : imports){
sb.append("import ").append(importName).append(";\n");
}
sb.append("\n");
sb.append("public final class ")
.append(className)
.append(" ");
optExtends.ifPresent(ext -> sb.append("extends ").append(ext).append(" "));
//add the 'implements' clause
if(!interfaces.isEmpty()) {
sb.append("\n");
sb.append("implements ");
final List<String> genericInterfaceNames
= interfaces.stream().map(iName -> iName+"<"+className+">")
.collect(Collectors.toList());
sb.append(
String.join(",", genericInterfaceNames)
);
}
sb.append(" {\n");
//class contents
sb.append("public ")
.append(className)
.append("() {")
.append("super(\"").append(tag).append("\");")
.append("}\n");
sb.append("}\n");
return sb.toString();
}
private static List<String> getInterfaceNamesForTag(final String tagNameLowercase){
return AttributesList.getCustomAttributesForHtmlTag(tagNameLowercase)
.stream()
.map(
AttributeInterfaceCodeGenerator::interfaceNameFromAttribute
).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,189 @@
package j2html_codegen.generators;
import java.util.Arrays;
import java.util.List;
public final class TagCreatorCodeGenerator {
public static void print() {
System.out.println("// EmptyTags, generated in " + TagCreatorCodeGenerator.class);
for (String tag : emptyTags()) {
final String className = SpecializedTagClassCodeGenerator.classNameFromTag(tag);
final String publicstaticTypeMethod = "public static "+className+" "+tag+" ";
final String castReturn = " return ("+className+") ";
final String construct = " new "+className+"()";
String emptyA1 = publicstaticTypeMethod + "()";
String emptyA2 = "{ return "+construct+"; }";
// Attr shorthands
String emptyB1 = publicstaticTypeMethod + "(Attr.ShortForm shortAttr)";
String emptyB2 = "{ "+castReturn+" Attr.addTo("+construct+", shortAttr); }";
// Print
System.out.println(String.format("%-80s%1s", emptyA1, emptyA2));
System.out.println(String.format("%-80s%1s", emptyB1, emptyB2));
System.out.println();
}
System.out.println("// ContainerTags, generated in " + TagCreatorCodeGenerator.class);
for (String tag : containerTags()) {
final String className = SpecializedTagClassCodeGenerator.classNameFromTag(tag);
final String publicstaticTypeMethod = "public static "+className+" "+tag+" ";
final String castReturn = " return ("+className+") ";
final String construct = " new "+className+"()";
String containerA1 = publicstaticTypeMethod+ "()";
String containerA2 = "{ "+castReturn + construct + "; }";
String containerB1 = publicstaticTypeMethod + "(String text)";
String containerB2 = "{ "+castReturn + construct + ".withText(text); }";
String containerC1 = publicstaticTypeMethod + "(DomContent... dc)";
String containerC2 = "{ "+castReturn + construct+".with(dc); }";
// Attr shorthands
String containerD1 = publicstaticTypeMethod + "(Attr.ShortForm shortAttr)";
String containerD2 = "{ "+castReturn+" Attr.addTo("+construct+", shortAttr); }";
String containerE1 = publicstaticTypeMethod + "(Attr.ShortForm shortAttr, String text)";
String containerE2 = "{ "+castReturn+" Attr.addTo("+construct+".withText(text), shortAttr); }";
String containerF1 = publicstaticTypeMethod + "(Attr.ShortForm shortAttr, DomContent... dc)";
String containerF2 = "{ "+castReturn+" Attr.addTo("+construct+".with(dc), shortAttr); }";
// Print
System.out.println(String.format("%-80s%1s", containerA1, containerA2));
System.out.println(String.format("%-80s%1s", containerB1, containerB2));
System.out.println(String.format("%-80s%1s", containerC1, containerC2));
System.out.println(String.format("%-80s%1s", containerD1, containerD2));
System.out.println(String.format("%-80s%1s", containerE1, containerE2));
System.out.println(String.format("%-80s%1s", containerF1, containerF2));
System.out.println();
}
}
// This is a method that contains all ContainerTags, there is nothing below it
public static List<String> emptyTags() {
return Arrays.asList(
"area",
"base",
"br",
"col",
//"!DOCTYPE html",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr"
);
}
public static List<String> containerTags() {
return Arrays.asList(
"a",
"abbr",
"address",
"article",
"aside",
"audio",
"b",
"bdi",
"bdo",
"blockquote",
"body",
"button",
"canvas",
"caption",
"cite",
"code",
"colgroup",
"data",
"datalist",
"dd",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"em",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"html",
"i",
"iframe",
"ins",
"kbd",
"label",
"legend",
"li",
"main",
"map",
"mark",
"menu",
"menuitem",
"meter",
"nav",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"picture",
"pre",
"progress",
"q",
"rp",
"rt",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"slot",
"small",
"span",
"strong",
"style",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"u",
"ul",
"var",
"video"
);
}
}

View File

@@ -0,0 +1,94 @@
package j2html_codegen.generators;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import j2html_codegen.wattsi.AttributeDefinition;
import j2html_codegen.wattsi.ElementDefinition;
import j2html_codegen.wattsi.WattsiSource;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import javax.lang.model.element.Modifier;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class WattsiGenerator {
public static void main(String... args) throws IOException {
Path source = Paths.get(args[0]);
Document doc = Jsoup.parse(source.toFile(), "UTF-8", "https://html.spec.whatwg.org/");
WattsiSource wattsi = new WattsiSource(doc);
List<ElementDefinition> elements = wattsi.elementDefinitions();
List<AttributeDefinition> attributes = wattsi.attributeDefinitions();
// for (ElementDefinition element : elements) {
// System.out.println((element.isObsolete() ? "!" : "") + element.name());
// for (AttributeDefinition attribute : attributes) {
// if (attribute.appliesTo(element)) {
// System.out.println(" " + (attribute.isObsolete() ? "!" : "") + attribute.name());
// }
// }
// System.out.println();
// }
for (ElementDefinition element : elements) {
ClassName className = ClassName.get(
"com.j2html",
capitalize(element.name()) + "Tag"
);
TypeSpec.Builder type = TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC);
if (element.isObsolete()) {
type.addAnnotation(Deprecated.class);
}
for (AttributeDefinition attribute : attributes) {
if (attribute.appliesTo(element)) {
String name = methodName("with", attribute.name().split("-"));
MethodSpec.Builder setter = MethodSpec.methodBuilder(name)
.addModifiers(Modifier.PUBLIC)
.returns(className)
.addStatement("return this");
if(attribute.isObsolete()){
setter.addAnnotation(Deprecated.class);
}
type.addMethod(setter.build());
}
}
// System.out.println(type.build().toString());
}
System.out.println(doc.select("dfn"));
}
private static String methodName(String prefix, String... words){
String[] tmp = new String[words.length + 1];
tmp[0] = prefix;
for(int i = 0; i < words.length; i++){
tmp[i+1] = words[i];
}
return methodName(tmp);
}
private static String methodName(String... words){
String[] camelCase = new String[words.length];
camelCase[0] = words[0];
for(int i = 1; i < words.length; i++){
camelCase[i] = capitalize(words[i]);
}
return String.join("", camelCase);
}
private static String capitalize(String word){
return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase();
}
}

View File

@@ -0,0 +1,24 @@
package j2html_codegen.model;
public final class AttrD {
//attribute descriptor
public final String attr;
public final boolean hasArgument;
//the html tags that this attribute can be used on
public final String[] tags;
public AttrD(final String attr, boolean hasArgument){
this.attr = attr;
this.hasArgument = hasArgument;
this.tags = new String[]{};
}
public AttrD(final String attr, boolean hasArgument, final String... tags) {
this.attr = attr;
this.hasArgument = hasArgument;
this.tags = tags;
}
}

View File

@@ -0,0 +1,182 @@
package j2html_codegen.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class AttributesList {
//https://www.w3schools.com/tags/ref_attributes.asp
public static List<String> getCustomAttributesForHtmlTag(final String tagLowercase){
final List<String> attrs = new ArrayList<>();
for(AttrD attrD : attributesDescriptive()){
if(
Arrays.asList(attrD.tags).contains(tagLowercase)
){
attrs.add(attrD.attr);
}
}
return attrs;
}
public static List<AttrD> attributesDescriptive() {
return Arrays.asList(
new AttrD("accept", true, "input"),
//new AttrD("accept-charset","form"), //contains dashes, TODO
//new AttrD("accesskey"), //global attribute
new AttrD("action", true, "form"),
//"align", not supported in HTML5
new AttrD("alt", true, "area","img","input"),
new AttrD("async", false, "script"),
new AttrD("autocomplete", false, "form","input"),
new AttrD("autofocus", false, "button","input","select","textarea"),
new AttrD("autoplay", false, "audio","video"),
//"bgcolor", not supported in HTMTL5
//"border", not supported in HTML5
new AttrD("charset", true, "meta","script"),
new AttrD("checked", false, "input"),
new AttrD("cite", true, "blockquote","del","ins","q"),
//"class" already implemented in Tag.java // global attribute
new AttrD("cols", true, "textarea"),
new AttrD("colspan", true, "td","th"),
new AttrD("content", true, "meta"),
//"contenteditable" global attribute, should be in Tag.java
new AttrD("controls", false, "audio","video"),
new AttrD("coords", true, "area"),
new AttrD("data", true, "object"),
new AttrD("datetime", true, "del","ins","time"),
new AttrD("default", false, "track"),
new AttrD("defer", false, "script"),
//new AttrD("dir"), //global attribute
new AttrD("dirname", true, "input","textarea"),
new AttrD("disabled",false, "button","fieldset","input","optgroup","option","select","textarea"),
new AttrD("download",false, "a","area"),
//new AttrD("draggable") global attribute, should be in Tag.java
new AttrD("enctype", true, "form"),
new AttrD("for", true, "label","output"),
new AttrD("form", true, "button","fieldset","input","label","meter","object","output","select","textarea"),
new AttrD("formaction", true, "button","input"),
new AttrD("headers", true, "td","th"),
new AttrD("height", true, "canvas","embed","iframe","img","input","object","video"),
//new AttrD("hidden"), global attribute
new AttrD("high", true, "meter"),
new AttrD("href", true, "a","area","base","link"),
new AttrD("hreflang", true, "a","area","link"),
//"http-equiv", //TODO: '-' is problematic in code generation
//"id" global attribute, should be in Tag.java
new AttrD("ismap", false, "img"),
new AttrD("kind", true, "track"),
new AttrD("label", true, "track","option","optgroup"),
//"lang" global attribute, should be in Tag.java
new AttrD("list", true, "input"),
new AttrD("loop", false, "audio","video"),
new AttrD("low", true, "meter"),
new AttrD("max", true, "input","meter","progress"),
new AttrD("maxlength", true, "input","textarea"),
new AttrD("media", true, "a","area","link","source","style"),
new AttrD("method", true, "form"),
new AttrD("min", true, "input","meter"),
new AttrD("multiple", false, "input","select"),
new AttrD("muted", false, "video","audio"),
new AttrD("name", true, "button","fieldset","form","iframe","input","map","meta","object","output","param","select","slot","textarea"),
new AttrD("novalidate", false, "form"),
new AttrD("onabort", true, "audio","embed","img","object","video"),
new AttrD("onafterprint", true, "body"),
new AttrD("onbeforeprint", true, "body"),
new AttrD("onbeforeunload", true, "body"),
//new AttrD("onblur"), global attribute
new AttrD("oncanplay", true, "audio","embed","object","video"),
new AttrD("oncanplaythrough", true, "audio","video"),
/* a bunch of event attributes that are on all visible elements (so should be in Tag.java)
"onchange",
"onclick",
"oncontextmenu",
"oncopy",
*/
new AttrD("oncuechange", true, "track"),
/*
"oncut",
...
"ondrop",
*/
new AttrD("ondurationchange", true, "audio","video"),
new AttrD("onemptied", true, "audio","video"),
new AttrD("onended", true, "audio","video"),
new AttrD("onerror", true, "audio","body","embed","img","object","script","style","video"),
//new AttrD("onfocus"),// global attribute
new AttrD("onhashchange", true, "body"),
// ... a bunch of event attributes visible on all elements
new AttrD("onload", true, "body","iframe","img","input","link","script","style"),
new AttrD("onloadeddata", true, "audio","video"),
new AttrD("onloadedmetadata", true, "audio","video"),
new AttrD("onloadstart", true, "audio","video"),
// ... a bunch of event attributes visible on all elements
new AttrD("onoffline", true, "body"),
new AttrD("ononline", true, "body"),
new AttrD("onpagehide", true, "body"),
new AttrD("onpageshow", true, "body"),
//new AttrD("onpaste"),// global attribute
new AttrD("onpause", true, "audio","video"),
new AttrD("onplay", true, "audio","video"),
new AttrD("onplaying", true, "audio","video"),
new AttrD("onpopstate", true, "body"),
new AttrD("onprogress", true, "audio","video"),
new AttrD("onratechange", true, "audio","video"),
new AttrD("onreset", true, "form"),
new AttrD("onresize", true, "body"),
//new AttrD("onscroll"), //global attribute
new AttrD("onsearch", true, "input"),
new AttrD("onseeked", true, "audio","video"),
new AttrD("onseeking", true, "audio","video"),
//new AttrD("onselect"), //global attribute
new AttrD("onstalled", true, "audio","video"),
new AttrD("onstorage", true, "body"),
new AttrD("onsubmit", true, "form"),
new AttrD("onsuspend", true, "audio","video"),
new AttrD("ontimeupdate", true, "audio","video"),
new AttrD("ontoggle", true, "details"),
new AttrD("onunload", true, "body"),
new AttrD("onvolumechanged", true, "audio","video"),
new AttrD("onwaiting", true, "audio","video"),
//new AttrD("onwheel"), //global attribute
new AttrD("open", false, "details"),
new AttrD("optimum", true, "meter"),
new AttrD("pattern", true, "input"),
new AttrD("placeholder", true, "input","textarea"),
new AttrD("poster", true, "video"),
new AttrD("preload", true, "audio","video"),
new AttrD("readonly", false, "input","textarea"),
new AttrD("rel", true, "a","area","form","link"),
new AttrD("required", false, "input","select","textarea"),
new AttrD("reversed", false, "ol"),
new AttrD("rows", true, "textarea"),
new AttrD("rowspan", true, "td","th"),
new AttrD("sandbox", false, "iframe"),
new AttrD("scope", true, "th"),
new AttrD("selected", false, "option"),
new AttrD("shape", true, "area"),
new AttrD("size", true, "input","select"),
new AttrD("sizes", true, "img","link","source"),
new AttrD("span", true, "col","colgroup"),
//new AttrD("spellcheck"), //global attribute
new AttrD("src", true, "audio","embed","iframe","img","input","script","source","track","video"),
new AttrD("srcdoc", true, "iframe"),
new AttrD("srclang", true, "track"),
new AttrD("srcset", true, "img","source"),
new AttrD("start", true, "ol"),
new AttrD("step", true, "input"),
//new AttrD("style"), //global attribute
//new AttrD("tabindex"), //global attribute
new AttrD("target", true, "a","area","base","form"),
//new AttrD("title"), //global attribute
//new AttrD("translate"),// global attribute
new AttrD("type", true, "a","button","embed","input","link","menu","object","script","source","style"),
new AttrD("usemap", true, "img","object"),
new AttrD("value", true, "button","data","input","li","option","meter","progress","param"),
new AttrD("width", true, "canvas","embed","iframe","img","input","object","video"),
new AttrD("wrap", true, "textarea")
);
}
}

View File

@@ -0,0 +1,10 @@
package j2html_codegen.wattsi;
public interface AttributeDefinition {
String name();
boolean appliesTo(ElementDefinition element);
boolean isObsolete();
}

View File

@@ -0,0 +1,9 @@
package j2html_codegen.wattsi;
public interface ElementDefinition {
String name();
boolean isObsolete();
}

View File

@@ -0,0 +1,204 @@
package j2html_codegen.wattsi;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
public class WattsiSource {
private final Document doc;
private final Set<Reference> obsolete = new HashSet<>();
public WattsiSource(Document doc) {
this.doc = doc;
// Find where obsolete elements are defined or referenced.
Elements obsoleteElements = doc.select("p:contains(Elements in the following list are entirely obsolete) + dl");
// Convert definitions into references to record obsolete elements.
obsoleteElements.select("dt > dfn[element]")
.stream()
.map(WattsiElement::new)
.map(WattsiElement::reference)
.forEach(obsolete::add);
// Extract references to record obsolete elements.
obsoleteElements.select("dt > code")
.stream()
.map(Element::childNodes)
.map(Reference::from)
.forEach(obsolete::add);
// Find where obsolete attributes are defined or referenced.
Elements obsoleteAttributes = doc.select("p:contains(The following attributes are obsolete) + dl");
// Convert definitions into references to record obsolete attributes.
obsoleteAttributes.select("dt > dfn[element-attr]").stream()
.map(WattsiAttribute::new)
.map(WattsiAttribute::reference)
.forEach(obsolete::add);
// System.out.println(obsoleteAttributes.select("dt"));
// obsoleteAttributes.select("dt > code").stream()
// .map(Element::childNodes)
// .map(Reference::from)
// .forEach(System.err::println);
// System.out.println(
// doc.select("dfn[obsolete]")
// );
}
public List<ElementDefinition> elementDefinitions() {
return doc.select("dfn[element]").stream()
.map(WattsiElement::new)
.collect(toList());
}
public List<AttributeDefinition> attributeDefinitions() {
return doc.select("dfn[element-attr]").stream()
.map(WattsiAttribute::new)
.collect(toList());
}
public class WattsiElement implements ElementDefinition {
private final Element dfn;
WattsiElement(Element dfn) {
if (!"dfn".equals(dfn.tagName())) {
throw new IllegalArgumentException("Element cannot be defined from: " + dfn);
}
if (!dfn.hasAttr("element")) {
throw new IllegalArgumentException("Does not define an element: " + dfn);
}
if (dfn.childrenSize() != 1) {
throw new IllegalArgumentException("Element cannot have multiple definitions: " + dfn);
}
this.dfn = dfn;
}
private Reference reference() {
return Reference.from(dfn.childNodes());
}
@Override
public String name() {
if (dfn.hasAttr("data-x")) {
return dfn.attr("data-x");
}
return Reference.from(dfn.childNodes()).key;
}
@Override
public boolean isObsolete() {
return obsolete.contains(reference());
}
}
public class WattsiAttribute implements AttributeDefinition {
private final Element dfn;
WattsiAttribute(Element dfn) {
if (!"dfn".equals(dfn.tagName())) {
throw new IllegalArgumentException("Attribute cannot be defined from: " + dfn);
}
if (!dfn.hasAttr("element-attr")) {
throw new IllegalArgumentException("Does not define an attribute: " + dfn);
}
if (dfn.childrenSize() != 1) {
throw new IllegalArgumentException("Attribute cannot have multiple definitions: " + dfn);
}
this.dfn = dfn;
}
private Reference reference() {
return Reference.from(dfn.childNodes());
}
@Override
public String name() {
return reference().text;
}
private List<String> targets() {
if (dfn.hasAttr("for")) {
return Arrays.asList(dfn.attr("for").trim().split(","));
}
return new ArrayList<>();
}
@Override
public boolean appliesTo(ElementDefinition element) {
return targets().contains(element.name());
}
@Override
public boolean isObsolete() {
return obsolete.contains(reference());
}
}
private static class Reference {
private final String key;
private final String text;
Reference(String key, String text) {
this.key = key;
this.text = text;
}
@Override
public String toString() {
return key + "[" + text + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Reference reference = (Reference) o;
return key.equals(reference.key);
}
@Override
public int hashCode() {
return Objects.hash(key);
}
public static Reference from(List<Node> nodes) {
if (nodes.stream().allMatch(n -> n instanceof TextNode)) {
String txt = nodes.stream()
.map(n -> (TextNode) n)
.map(TextNode::text)
.collect(Collectors.joining(" "));
return new Reference(txt, txt);
}
for (Node node : nodes) {
if (node instanceof Element) {
Element element = (Element) node;
if (element.is("code") || element.is("span")) {
if (element.hasAttr("data-x")) {
return new Reference(element.attr("data-x").toLowerCase(), element.text());
} else {
return new Reference(element.text().toLowerCase(), element.text());
}
}
}
}
return null;
}
}
}

View File

@@ -0,0 +1,16 @@
package j2html_codegen;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class AppTest
{
@Test
public void shouldAnswerWithTrue()
{
//dummy, just to conform to the default mvn
//directory layout
assertTrue( true );
}
}

View File

@@ -0,0 +1,77 @@
package j2html_codegen;
import j2html_codegen.generators.TagCreatorCodeGenerator;
import j2html_codegen.wattsi.ElementDefinition;
import j2html_codegen.wattsi.WattsiSource;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
public class CodeGeneratorComplianceTests {
private WattsiSource specification;
@Before
public void setUp() throws IOException {
Path source = Paths.get("src","test","resources","2022-01.wattsi");
Document doc = Jsoup.parse(source.toFile(), "UTF-8", "https://html.spec.whatwg.org/");
specification = new WattsiSource(doc);
}
private Set<String> generatedElements(){
Set<String> elements = new HashSet<>();
elements.addAll(TagCreatorCodeGenerator.emptyTags());
elements.addAll(TagCreatorCodeGenerator.containerTags());
return elements;
}
private Set<String> specifiedElements(WattsiSource source){
Set<String> elements = new HashSet<>();
for(ElementDefinition element : source.elementDefinitions()){
elements.add(element.name());
}
return elements;
}
@Test
@Ignore
// TODO restore this test once a policy has been determined for obsolete elements.
public void all_wattsi_elements_are_defined_in_the_code_generator() {
Set<String> generated = generatedElements();
List<String> undefined = specification.elementDefinitions().stream()
.filter(element -> !element.isObsolete())
.filter(element -> !generated.contains(element.name()))
.map(ElementDefinition::name)
.collect(toList());
assertEquals("HTML elements are missing", emptyList(), undefined);
// Currently missing (and mostly deprecated):
// hgroup
}
@Test
public void only_wattsi_elements_are_defined_in_the_code_generator(){
Set<String> specified = specifiedElements(specification);
List<String> invalid = generatedElements().stream()
.filter(element -> !specified.contains(element))
.collect(toList());
assertEquals("HTML elements are invalid", emptyList(), invalid);
}
}

File diff suppressed because it is too large Load Diff

19
docs/404.html Normal file

File diff suppressed because one or more lines are too long

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
j2html.com

3
docs/README Normal file
View File

@@ -0,0 +1,3 @@
# j2html.com
Don't edit these files manually, they are generated from `j2html/website`.

121
docs/css/prism.css Normal file
View File

@@ -0,0 +1,121 @@
/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+java */
/**
* okaidia theme for JavaScript, CSS and HTML
* Loosely based on Monokai textmate theme by http://www.monokai.nl/
* @author ocodia
*/
code[class*="language-"],
pre[class*="language-"] {
color: #f8f8f2;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #272822;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #f8f8f2;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: #f92672;
}
.token.boolean,
.token.number {
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a6e22e;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: #f8f8f2;
}
.token.atrule,
.token.attr-value,
.token.function {
color: #e6db74;
}
.token.keyword {
color: #66d9ef;
}
.token.regex,
.token.important {
color: #fd971f;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

24
docs/download.html Normal file

File diff suppressed because one or more lines are too long

5
docs/download_html.bat Normal file
View File

@@ -0,0 +1,5 @@
curl "http://localhost:8888/" > index.html
curl "http://localhost:8888/download.html" > download.html
curl "http://localhost:8888/examples.html" > examples.html
curl "http://localhost:8888/news.html" > news.html
curl "http://localhost:8888/404.html" > 404.html

426
docs/examples.html Normal file

File diff suppressed because one or more lines are too long

32
docs/img/favicon.svg Normal file
View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="512px" height="512px" viewBox="0 0 512 512" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<desc>Created with Lunacy</desc>
<defs>
<path d="M0 0L512 0L512 512L0 512L0 0Z" id="path_1" />
<rect width="512" height="512" id="artboard_1" />
<clipPath id="clip_1">
<use xlink:href="#artboard_1" clip-rule="evenodd" />
</clipPath>
<clipPath id="mask_1">
<use xlink:href="#path_1" />
</clipPath>
</defs>
<g id="Artboard-Copy-3" clip-path="url(#clip_1)">
<g id="HTML5_Badge">
<path d="M0 0L512 0L512 512L0 512L0 0Z" id="Background" fill="none" stroke="none" />
<g clip-path="url(#mask_1)">
<path d="M41 460L0 0L451 0L410 460L225 512" transform="translate(30 0)" id="Shape" fill="#1272BF" stroke="none" />
<path d="M0 435L149 394L184 0L0 0" transform="translate(256 37)" id="Shape" fill="#FFFFFF" fill-opacity="0.21176471" stroke="none" />
</g>
</g>
<g id="coffee-icon-12" transform="translate(122.26813 68.45154)">
<g id="Group">
<path d="M109.76 63.5233C72.71 61.7926 37.5831 55.1903 18.2249 46.4086C5.14845 40.4472 -1.64617 32.627 0.340938 25.8965C3.22545 16.2815 18.7377 7.94844 45.8521 1.41021L51.7493 0L56.2363 4.23062C58.7362 6.53823 61.8771 9.16634 63.2232 10.1278C64.6975 11.0893 65.9154 12.4355 66.1718 13.4611C66.3641 14.4226 67.582 16.7302 68.864 18.5891C74.1202 26.2811 84.5686 31.1527 101.812 33.8449C112.452 35.5756 153.028 35.5756 164.117 33.909C181.424 31.2809 192.193 26.3452 197.449 18.5891C198.731 16.7302 199.949 14.4226 200.141 13.4611C200.398 12.4996 201.551 11.0893 202.897 10.1919C204.244 9.35865 207.384 6.66643 209.884 4.35882L214.564 1.95618e-05L220.461 1.41023C251.742 8.78175 269.177 19.9993 265.972 30.7681C264.818 34.55 261.677 38.2678 256.87 41.4728C233.025 57.3056 171.937 66.4719 109.76 63.5233L109.76 63.5233Z" transform="translate(0 276.47668)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M83.9789 173.473C64.877 172.256 51.8006 168.217 47.9546 162.32C47.3777 161.423 46.7367 159.435 46.6084 157.897C46.2879 155.397 45.9033 154.82 43.2752 152.961C38.5959 149.564 29.8142 140.334 25.0708 133.731C20.0069 126.68 12.1225 111.04 9.30215 102.45C3.14853 83.9255 0.199922 64.5031 0.00761933 41.8116C-0.0564799 29.1198 0.199922 27.8378 4.11003 22.838C6.73814 19.633 14.1738 14.6332 20.5197 12.0051C54.3005 -2.09699 127.952 -4.14819 171.732 7.83854C187.565 12.1974 198.334 18.6074 202.436 26.1712C204.038 29.0557 204.359 30.4659 204.615 35.8503L204.622 35.9837C204.936 41.9426 204.946 42.1293 206.282 41.7475C206.987 41.4911 210.833 41.2988 214.679 41.2988C225.384 41.3629 232.371 43.991 238.012 50.1447C250.96 64.2467 246.729 91.297 228.525 110.271C217.371 121.873 203.333 129.116 186.924 131.744L180.193 132.834L177.95 135.718C172.822 142.128 167.373 147.769 162.886 151.423C158.591 154.884 158.079 155.525 157.822 157.961C157.374 161.358 156.092 163.41 152.694 165.846C143.72 172.32 115.452 175.461 83.9789 173.473ZM179.103 35.2734C179.103 41.1706 159.104 46.9396 130.708 49.119C121.285 49.8241 97.4399 50.401 89.6838 50.0805C57.2491 48.6703 33.0833 44.1192 26.7374 38.1579C23.5965 35.2093 25.4554 31.9402 32.0577 28.9274C40.2625 25.1455 55.0056 22.0687 74.2997 20.2098C85.1967 19.1842 119.362 19.1842 130.067 20.2739C160.322 23.2225 179.103 28.9915 179.103 35.2734ZM48.5956 75.2078C49.9416 100.591 56.0312 124.565 65.3898 141.295C66.6077 143.539 67.5051 145.333 67.3128 145.333C66.159 145.333 50.9673 133.09 47.6981 129.501C36.737 117.514 28.8527 101.168 24.3657 81.2332C22.9555 74.695 20.5838 59.4391 20.9684 58.9904C21.0966 58.9263 23.8529 59.8878 27.1861 61.1698C30.5193 62.3877 36.4165 64.1185 40.3266 65.0159C44.1726 65.9133 47.5058 66.6824 47.7622 66.8107C47.9545 67.003 48.3391 70.7208 48.5956 75.2078ZM201.731 105.399C221.41 95.2071 231.089 77.4513 222.884 66.5543C220.256 63.0929 216.474 61.8109 210.064 62.1314C207.115 62.2596 204.423 62.7083 204.039 63.0929C203.654 63.4775 202.757 67.5158 202.116 72.0669C200.577 82.7075 198.205 92.9636 195.129 102.13C194.955 102.641 194.789 103.12 194.634 103.57C193.539 106.749 192.961 108.429 193.474 108.889C194.05 109.405 196 108.388 200.133 106.231C200.633 105.97 201.165 105.693 201.731 105.399Z" transform="translate(30.973198 125.50244)" id="Shape" fill="#FFFFFF" fill-rule="evenodd" stroke="none" />
<path d="M1.14148 89.3819C4.64379 86.2444 7.12459 81.9395 8.43796 76.759C9.75133 71.5055 9.6054 66.5439 7.63534 50.4917C4.93565 29.113 10.335 17.4386 27.7007 6.93166C32.2975 4.23196 34.0486 3.28342 39.375 1.09447L41.9288 0L38.6454 2.77266C32.8812 7.66131 29.8896 11.3095 27.3358 16.563C23.5417 24.2243 22.885 30.2074 24.3443 43.633C25.7306 56.7666 25.8036 61.2175 24.4902 66.6169C22.4472 75.2997 15.5885 82.961 5.00862 88.3604C-0.536715 91.1331 -0.901539 91.206 1.14148 89.3819L1.14148 89.3819Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 109.50348 7.280884)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M2.2619 64.5395C7.44241 59.1401 8.53688 53.3759 6.63979 41.6286C4.15899 25.8682 5.54532 19.1554 12.9148 12.0048C16.0523 8.86735 19.1168 6.82434 24.6621 4.1976C34.2935 -0.472146 36.8472 -1.20179 32.6882 1.78976C27.9455 5.29208 24.5891 8.94032 22.4002 13.0993C20.5031 16.7476 20.4301 17.1853 20.722 26.3789C21.3057 46.7361 21.2328 49.5817 19.8464 52.1355C16.8549 57.6808 9.77728 63.2991 2.18894 66.1447L0 66.9473L2.26191 64.5395L2.2619 64.5395Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 67.97293 38.71814)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M2.43573 63.7984C7.25141 58.326 7.98106 53.5833 5.86508 40.8875C3.01946 23.5948 6.30288 14.7661 18.1961 7.32363C22.72 4.55097 33.2269 -0.410636 33.7376 0.0271519C33.8836 0.173082 32.2054 1.70534 30.0164 3.38353C25.2737 7.10474 22.2092 11.3367 20.458 16.5902C19.5095 19.6547 19.3635 21.7707 19.7284 27.0971C21.1877 47.3813 21.1877 47.4543 19.4365 51.4674C17.3935 56.356 12.3589 61.0257 5.64618 64.3821C2.80055 65.8414 0.319755 67.0089 0.0278784 67.0089C-0.191007 67.0089 0.903465 65.5496 2.43571 63.7984L2.43573 63.7984Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 160.54498 22.258545)" id="Shape" fill="#FFFFFF" stroke="none" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

33
docs/img/logo.svg Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="1720px" height="512px" viewBox="0 0 1720 512" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<desc>Created with Lunacy</desc>
<defs>
<path d="M0 0L512 0L512 512L0 512L0 0Z" id="path_1" />
<rect width="1720" height="512" id="artboard_1" />
<clipPath id="clip_1">
<use xlink:href="#artboard_1" clip-rule="evenodd" />
</clipPath>
<clipPath id="mask_1">
<use xlink:href="#path_1" />
</clipPath>
</defs>
<g id="Artboard-Copy-2" clip-path="url(#clip_1)">
<g id="HTML5_Badge">
<path d="M0 0L512 0L512 512L0 512L0 0Z" id="Background" fill="none" stroke="none" />
<g clip-path="url(#mask_1)">
<path d="M41 460L0 0L451 0L410 460L225 512" transform="translate(30 0)" id="Shape" fill="#1272BF" stroke="none" />
<path d="M0 435L149 394L184 0L0 0" transform="translate(256 37)" id="Shape" fill="#FFFFFF" fill-opacity="0.21176471" stroke="none" />
</g>
</g>
<g id="coffee-icon-12" transform="translate(122.26813 68.45154)">
<g id="Group">
<path d="M109.76 63.5233C72.71 61.7926 37.5831 55.1903 18.2249 46.4086C5.14845 40.4472 -1.64617 32.627 0.340938 25.8965C3.22545 16.2815 18.7377 7.94844 45.8521 1.41021L51.7493 0L56.2363 4.23062C58.7362 6.53823 61.8771 9.16634 63.2232 10.1278C64.6975 11.0893 65.9154 12.4355 66.1718 13.4611C66.3641 14.4226 67.582 16.7302 68.864 18.5891C74.1202 26.2811 84.5686 31.1527 101.812 33.8449C112.452 35.5756 153.028 35.5756 164.117 33.909C181.424 31.2809 192.193 26.3452 197.449 18.5891C198.731 16.7302 199.949 14.4226 200.141 13.4611C200.398 12.4996 201.551 11.0893 202.897 10.1919C204.244 9.35865 207.384 6.66643 209.884 4.35882L214.564 1.95618e-05L220.461 1.41023C251.742 8.78175 269.177 19.9993 265.972 30.7681C264.818 34.55 261.677 38.2678 256.87 41.4728C233.025 57.3056 171.937 66.4719 109.76 63.5233L109.76 63.5233Z" transform="translate(0 276.47668)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M83.9789 173.473C64.877 172.256 51.8006 168.217 47.9546 162.32C47.3777 161.423 46.7367 159.435 46.6084 157.897C46.2879 155.397 45.9033 154.82 43.2752 152.961C38.5959 149.564 29.8142 140.334 25.0708 133.731C20.0069 126.68 12.1225 111.04 9.30215 102.45C3.14853 83.9255 0.199922 64.5031 0.00761933 41.8116C-0.0564799 29.1198 0.199922 27.8378 4.11003 22.838C6.73814 19.633 14.1738 14.6332 20.5197 12.0051C54.3005 -2.09699 127.952 -4.14819 171.732 7.83854C187.565 12.1974 198.334 18.6074 202.436 26.1712C204.038 29.0557 204.359 30.4659 204.615 35.8503L204.622 35.9837C204.936 41.9426 204.946 42.1293 206.282 41.7475C206.987 41.4911 210.833 41.2988 214.679 41.2988C225.384 41.3629 232.371 43.991 238.012 50.1447C250.96 64.2467 246.729 91.297 228.525 110.271C217.371 121.873 203.333 129.116 186.924 131.744L180.193 132.834L177.95 135.718C172.822 142.128 167.373 147.769 162.886 151.423C158.591 154.884 158.079 155.525 157.822 157.961C157.374 161.358 156.092 163.41 152.694 165.846C143.72 172.32 115.452 175.461 83.9789 173.473ZM179.103 35.2734C179.103 41.1706 159.104 46.9396 130.708 49.119C121.285 49.8241 97.4399 50.401 89.6838 50.0805C57.2491 48.6703 33.0833 44.1192 26.7374 38.1579C23.5965 35.2093 25.4554 31.9402 32.0577 28.9274C40.2625 25.1455 55.0056 22.0687 74.2997 20.2098C85.1967 19.1842 119.362 19.1842 130.067 20.2739C160.322 23.2225 179.103 28.9915 179.103 35.2734ZM48.5956 75.2078C49.9416 100.591 56.0312 124.565 65.3898 141.295C66.6077 143.539 67.5051 145.333 67.3128 145.333C66.159 145.333 50.9673 133.09 47.6981 129.501C36.737 117.514 28.8527 101.168 24.3657 81.2332C22.9555 74.695 20.5838 59.4391 20.9684 58.9904C21.0966 58.9263 23.8529 59.8878 27.1861 61.1698C30.5193 62.3877 36.4165 64.1185 40.3266 65.0159C44.1726 65.9133 47.5058 66.6824 47.7622 66.8107C47.9545 67.003 48.3391 70.7208 48.5956 75.2078ZM201.731 105.399C221.41 95.2071 231.089 77.4513 222.884 66.5543C220.256 63.0929 216.474 61.8109 210.064 62.1314C207.115 62.2596 204.423 62.7083 204.039 63.0929C203.654 63.4775 202.757 67.5158 202.116 72.0669C200.577 82.7075 198.205 92.9636 195.129 102.13C194.955 102.641 194.789 103.12 194.634 103.57C193.539 106.749 192.961 108.429 193.474 108.889C194.05 109.405 196 108.388 200.133 106.231C200.633 105.97 201.165 105.693 201.731 105.399Z" transform="translate(30.973198 125.50244)" id="Shape" fill="#FFFFFF" fill-rule="evenodd" stroke="none" />
<path d="M1.14148 89.3819C4.64379 86.2444 7.12459 81.9395 8.43796 76.759C9.75133 71.5055 9.6054 66.5439 7.63534 50.4917C4.93565 29.113 10.335 17.4386 27.7007 6.93166C32.2975 4.23196 34.0486 3.28342 39.375 1.09447L41.9288 0L38.6454 2.77266C32.8812 7.66131 29.8896 11.3095 27.3358 16.563C23.5417 24.2243 22.885 30.2074 24.3443 43.633C25.7306 56.7666 25.8036 61.2175 24.4902 66.6169C22.4472 75.2997 15.5885 82.961 5.00862 88.3604C-0.536715 91.1331 -0.901539 91.206 1.14148 89.3819L1.14148 89.3819Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 109.50348 7.280884)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M2.2619 64.5395C7.44241 59.1401 8.53688 53.3759 6.63979 41.6286C4.15899 25.8682 5.54532 19.1554 12.9148 12.0048C16.0523 8.86735 19.1168 6.82434 24.6621 4.1976C34.2935 -0.472146 36.8472 -1.20179 32.6882 1.78976C27.9455 5.29208 24.5891 8.94032 22.4002 13.0993C20.5031 16.7476 20.4301 17.1853 20.722 26.3789C21.3057 46.7361 21.2328 49.5817 19.8464 52.1355C16.8549 57.6808 9.77728 63.2991 2.18894 66.1447L0 66.9473L2.26191 64.5395L2.2619 64.5395Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 67.97293 38.71814)" id="Shape" fill="#FFFFFF" stroke="none" />
<path d="M2.43573 63.7984C7.25141 58.326 7.98106 53.5833 5.86508 40.8875C3.01946 23.5948 6.30288 14.7661 18.1961 7.32363C22.72 4.55097 33.2269 -0.410636 33.7376 0.0271519C33.8836 0.173082 32.2054 1.70534 30.0164 3.38353C25.2737 7.10474 22.2092 11.3367 20.458 16.5902C19.5095 19.6547 19.3635 21.7707 19.7284 27.0971C21.1877 47.3813 21.1877 47.4543 19.4365 51.4674C17.3935 56.356 12.3589 61.0257 5.64618 64.3821C2.80055 65.8414 0.319755 67.0089 0.0278784 67.0089C-0.191007 67.0089 0.903465 65.5496 2.43571 63.7984L2.43573 63.7984Z" transform="matrix(0.9848077 -0.17364818 0.17364818 0.9848077 160.54498 22.258545)" id="Shape" fill="#FFFFFF" stroke="none" />
</g>
</g>
<path d="M364 10.8L376.4 0L438 0L422.8 125.2C428.667 115.067 436.267 106.867 445.6 100.6C454.933 94.3334 465.867 91.2 478.4 91.2Q502.8 91.2 519 106.4C529.8 116.533 533.867 132.267 531.2 153.6L521.2 236L544.4 236L540.8 265.2L528.8 275.2L467.2 275.2L479.6 173.6C481.733 158.133 480.667 147.067 476.4 140.4C472.133 133.733 465.067 130.4 455.2 130.4C443.733 130.4 435.067 134 429.2 141.2Q420.4 152 417.2 169.6L404.4 275.2L354.8 275.2L383.6 39.2L360.4 39.2L364 10.8ZM1052 0L1039.6 10.8L1036 39.2L1060.8 39.2L1032 275.2L1094 275.2L1106 265.2L1109.6 236L1086.4 236L1115.2 0L1052 0ZM79.2 62.8L82.0851 35.1857Q82.1542 34.5246 82.2534 33.8673Q82.3527 33.2101 82.482 32.5581Q82.6113 31.9061 82.7704 31.2607Q82.9294 30.6154 83.1178 29.9779Q83.3063 29.3405 83.5237 28.7124Q83.7411 28.0843 83.9872 27.4668Q84.2331 26.8493 84.5072 26.2437Q84.7812 25.6381 85.0827 25.0458Q85.3842 24.4534 85.7125 23.8754Q86.0408 23.2975 86.3953 22.7352Q86.7497 22.1729 87.1295 21.6274Q87.5094 21.0819 87.9138 20.5545Q88.3183 20.027 88.7464 19.5186Q89.1746 19.0101 89.6256 18.5219Q90.0767 18.0336 90.5496 17.5666Q91.0225 17.0995 91.5163 16.6546Q92.0101 16.2097 92.5238 15.7878Q93.0375 15.366 93.57 14.9682Q94.1025 14.5703 94.6526 14.1973Q95.2028 13.8243 95.7694 13.4768Q96.3361 13.1294 96.9181 12.8083Q97.5 12.4872 98.0961 12.1931Q98.6922 11.899 99.3012 11.6325Q99.9101 11.366 100.531 11.1277Q101.151 10.8894 101.782 10.6798Q102.413 10.4702 103.052 10.2897Q103.692 10.1092 104.339 9.95819Q104.987 9.80719 105.64 9.68601Q106.294 9.56483 106.952 9.47372Q107.611 9.38261 108.273 9.32177Q108.934 9.26092 109.598 9.23047Q110.262 9.20001 110.927 9.20001L132.8 9.20001L129.915 36.8144Q129.846 37.4754 129.747 38.1327Q129.647 38.7899 129.518 39.4419Q129.389 40.0939 129.23 40.7393Q129.071 41.3847 128.882 42.0221Q128.694 42.6595 128.476 43.2876Q128.259 43.9157 128.013 44.5332Q127.767 45.1507 127.493 45.7563Q127.219 46.3619 126.917 46.9543Q126.616 47.5466 126.288 48.1246Q125.959 48.7025 125.605 49.2648Q125.25 49.8271 124.87 50.3726Q124.491 50.9181 124.086 51.4456Q123.682 51.9731 123.254 52.4815Q122.825 52.9899 122.374 53.4781Q121.923 53.9664 121.45 54.4334Q120.978 54.9005 120.484 55.3454Q119.99 55.7904 119.476 56.2122Q118.963 56.634 118.43 57.0319Q117.898 57.4297 117.347 57.8027Q116.797 58.1758 116.231 58.5232Q115.664 58.8706 115.082 59.1917Q114.5 59.5128 113.904 59.8069Q113.308 60.101 112.699 60.3675Q112.09 60.634 111.469 60.8723Q110.849 61.1106 110.218 61.3202Q109.587 61.5298 108.948 61.7103Q108.308 61.8908 107.661 62.0418Q107.013 62.1928 106.36 62.314Q105.706 62.4352 105.048 62.5263Q104.389 62.6174 103.727 62.6782Q103.066 62.7391 102.402 62.7695Q101.738 62.8 101.073 62.8L79.2 62.8ZM578.8 94.8L565.2 107.2L561.6 134L585.6 134L574.8 221.2C572.667 239.867 576.867 254.2 587.4 264.2C597.933 274.2 612.8 279.2 632 279.2C649.867 279.2 663.733 274.4 673.6 264.8C683.467 255.2 690.933 240 696 219.2L661.2 207.6Q656 228.4 649.8 234.2C645.667 238.067 641.467 240 637.2 240Q632.752 240 629.894 237.868Q623.241 232.907 625.2 216.4L635.2 134L676.8 134L690.4 121.2L694 94.8L640 94.8L646.8 40.0001L610.8 40.0001L595.2 56L590.4 94.8L578.8 94.8ZM158.4 139.6L198.4 144L207.6 114.4C211.867 112.267 217.2 110.733 223.6 109.8C230 108.867 235.467 108.4 240 108.4C248.8 108.4 256.333 110 262.6 113.2C268.867 116.4 272 122 272 130C272 140.933 265.933 151.733 253.8 162.4Q235.6 178.4 206.2 195.4C186.6 206.733 165.467 219.2 142.8 232.8L143.2 275.2L321.2 275.2L330 204.4L288.8 200.4L284.4 229.6L206.8 229.6C225.2 220.267 243.867 210.667 262.8 200.8C281.733 190.933 297.6 179.4 310.4 166.2Q329.6 146.4 329.6 118.4Q329.6 96 313.2 79.4C302.267 68.3333 282.533 62.8 254 62.8Q240 62.8 218.4 65.8Q196.8 68.8 173.6 78.4L158.4 139.6ZM724 94.8L779.6 94.8L781.2 129.6C787.333 118.133 795.2 108.867 804.8 101.8C814.4 94.7334 826 91.2 839.6 91.2C852.667 91.2 863.6 94.4667 872.4 101C881.2 107.533 886.533 117.6 888.4 131.2Q897.6 113.6 912.2 102.4C921.933 94.9333 933.733 91.2 947.6 91.2C963.867 91.2 976.733 96.2667 986.2 106.4C995.667 116.533 999.067 132.267 996.4 153.6L986.4 236L1009.6 236L1006 265.2L994 275.2L932.4 275.2L944.8 173.6C946.667 158.133 945.733 147.067 942 140.4C938.267 133.733 931.467 130.4 921.6 130.4Q903.6 130.4 896 142.4C890.933 150.4 887.6 160.667 886 173.2L873.6 275.2L824.4 275.2L836.8 173.6C838.667 158.133 837.733 147.067 834 140.4C830.267 133.733 823.467 130.4 813.6 130.4Q795.6 130.4 788 142.4C782.933 150.4 779.6 160.667 778 173.2L765.6 275.2L716 275.2L733.2 134L708 134L711.6 105.6L724 94.8ZM57.2 94.8L44.8 105.6L41.2 134L70.4 134L54 268.8Q48.8 312 35.4 319.2C26.4667 324 15.3333 323.867 2 318.8L0 352Q17.2 364 40 364C58.9333 364 73.3333 354.933 83.2 336.8C93.0667 318.667 99.7333 296 103.2 268.8L124.8 94.8L57.2 94.8Z" transform="translate(592 103.83917)" id="j2html" fill="#222222" fill-rule="evenodd" stroke="none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

33
docs/index.html Normal file

File diff suppressed because one or more lines are too long

7
docs/js/prism.js Normal file
View File

@@ -0,0 +1,7 @@
/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+java */
self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=t.util.clone(e[r]));return a;case"Array":return e.map(function(e){return t.util.clone(e)})}return e}},languages:{extend:function(e,n){var a=t.util.clone(t.languages[e]);for(var r in n)a[r]=n[r];return a},insertBefore:function(e,n,a,r){r=r||t.languages;var i=r[e];if(2==arguments.length){a=arguments[1];for(var l in a)a.hasOwnProperty(l)&&(i[l]=a[l]);return i}var s={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var l in a)a.hasOwnProperty(l)&&(s[l]=a[l]);s[o]=i[o]}return t.languages.DFS(t.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=s)}),r[e]=s},DFS:function(e,n,a){for(var r in e)e.hasOwnProperty(r)&&(n.call(e,r,e[r],a||r),"Object"===t.util.type(e[r])?t.languages.DFS(e[r],n):"Array"===t.util.type(e[r])&&t.languages.DFS(e[r],n,r))}},highlightAll:function(e,n){for(var a,r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),i=0;a=r[i++];)t.highlightElement(a,e===!0,n)},highlightElement:function(a,r,i){for(var l,s,o=a;o&&!e.test(o.className);)o=o.parentNode;if(o&&(l=(o.className.match(e)||[,""])[1],s=t.languages[l]),s){a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=a.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var u=a.textContent;if(u){u=u.replace(/^(?:\r?\n|\r)/,"");var g={element:a,language:l,grammar:s,code:u};if(t.hooks.run("before-highlight",g),r&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){g.highlightedCode=n.stringify(JSON.parse(e.data),l),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(g.element),t.hooks.run("after-highlight",g)},c.postMessage(JSON.stringify({language:g.language,code:g.code}))}else g.highlightedCode=t.highlight(g.code,g.grammar,g.language),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(a),t.hooks.run("after-highlight",g)}}},highlight:function(e,a,r){var i=t.tokenize(e,a);return n.stringify(t.util.encode(i),r)},tokenize:function(e,n){var a=t.Token,r=[e],i=n.rest;if(i){for(var l in i)n[l]=i[l];delete n.rest}e:for(var l in n)if(n.hasOwnProperty(l)&&n[l]){var s=n[l];s="Array"===t.util.type(s)?s:[s];for(var o=0;o<s.length;++o){var u=s[o],g=u.inside,c=!!u.lookbehind,f=0,h=u.alias;u=u.pattern||u;for(var p=0;p<r.length;p++){var d=r[p];if(r.length>e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),N=[p,1];b&&N.push(b);var O=new a(l,g?t.tokenize(m,g):m,h);N.push(O),w&&N.push(w),Array.prototype.splice.apply(r,N)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var i={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code;self.postMessage(JSON.stringify(t.util.encode(t.tokenize(r,t.languages[a])))),self.close()},!1),self.Prism):self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);;
Prism.languages.markup={comment:/<!--[\w\W]*?-->/,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/i,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/=|>|"/}},punctuation:/\/?>/,"attr-name":{pattern:/[\w:-]+/,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(t){"entity"===t.type&&(t.attributes.title=t.content.replace(/&amp;/,"&"))});;
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{punctuation:/[;:]/}},url:/url\((?:(["'])(\\\n|\\?.)*?\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/,string:/("|')(\\\n|\\?.)*?\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,punctuation:/[\{\};:]/,"function":/[-a-z0-9]+(?=\()/i},Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/<style[\w\W]*?>[\w\W]*?<\/style>/i,inside:{tag:{pattern:/<style[\w\W]*?>|<\/style>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css},alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));;
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/("|')(\\\n|\\?.)*?\1/,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":{pattern:/[a-z0-9_]+\(/i,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|~|\^|%/,ignore:/&(lt|gt|amp);/i,punctuation:/[{}[\];(),.:]/};;
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|-?Infinity)\b/,"function":/(?!\d)[a-z0-9_$]+(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/<script[\w\W]*?>[\w\W]*?<\/script>/i,inside:{tag:{pattern:/<script[\w\W]*?>|<\/script>/i,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript},alias:"language-javascript"}});;
Prism.languages.java=Prism.languages.extend("clike",{keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+[e]?[\d]*[df]\b|\b\d*\.?\d+\b/i,operator:{pattern:/(^|[^\.])(?:\+=|\+\+?|-=|--?|!=?|<{1,2}=?|>{1,3}=?|==?|&=|&&?|\|=|\|\|?|\?|\*=?|\/=?|%=?|\^=?|:|~)/m,lookbehind:!0}});;

19
docs/news.html Normal file

File diff suppressed because one or more lines are too long

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>

101
library/.gitignore vendored Normal file
View File

@@ -0,0 +1,101 @@
# Created by https://www.gitignore.io
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### Java ###
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
### Eclipse ###
.classpath
.project
.settings/
buildNumber.properties

239
library/pom.xml Normal file
View File

@@ -0,0 +1,239 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.6.0</version>
<name>j2html</name>
<description>Java to HTML builder with a fluent API</description>
<url>http://j2html.com</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<connection>scm:git:git@github.com:tipsy/j2html.git</connection>
<developerConnection>scm:git:git@github.com:tipsy/j2html.git</developerConnection>
<url>https://github.com/tipsy/j2html.git</url>
<tag>j2html-1.6.0</tag>
</scm>
<developers>
<developer>
<name>David Åse</name>
</developer>
</developers>
<issueManagement>
<system>GitHub Issue Tracker</system>
<url>https://github.com/tipsy/j2html/issues</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.carrotsearch</groupId>
<artifactId>junit-benchmarks</artifactId>
<version>0.7.2</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>
</dependencies>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>perform</goal>
</goals>
<configuration>
<pomFileName>library/pom.xml</pomFileName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<optimize>true</optimize>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>enforce-java</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[1.8,)</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.0</version>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Automatic-Module-Name>com.j2html</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>5.1.6</version>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.revapi</groupId>
<artifactId>revapi-maven-plugin</artifactId>
<version>0.14.6</version>
<dependencies>
<dependency>
<groupId>org.revapi</groupId>
<artifactId>revapi-java</artifactId>
<version>0.26.1</version>
</dependency>
</dependencies>
<configuration>
<oldArtifacts>
<artifact>com.j2html:j2html:1.5.0</artifact>
</oldArtifacts>
<analysisConfiguration>
<revapi.differences>
<differences>
<item>
<ignore>true</ignore>
<code>java.class.removed</code>
<old>class j2html.tags.specialized.GenerateTag</old>
<justification>
This class should never have been used. It was introduced
accidentally by find+replace in the code generator class.
</justification>
</item>
</differences>
</revapi.differences>
</analysisConfiguration>
</configuration>
<executions>
<execution>
<id>check</id>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>sign-artifacts</id>
<activation>
<property>
<name>sign</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,148 @@
package j2html;
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 {
/**
* Change this to configure text-escaping
* For example, to disable escaping, do <code>{@code Config.textEscaper = text -> text;}</code>
*/
public static TextEscaper textEscaper = EscapeUtil::escape;
/**
* Change this to configure css-minification.
* The default minifier is https://github.com/barryvan/CSSMin
*/
public static Minifier cssMinifier = CSSMin::compressCss;
/**
* Change this to configure js-minification.
* The default minifier is a simple whitespace/newline stripper
*/
public static Minifier jsMinifier = JSMin::compressJs;
/**
* Change this to configure enable/disable closing empty tags
* The default is to NOT close them
*/
public static boolean closeEmptyTags = false;
private static String FOUR_SPACES = " ";
/**
* Change this to configure indentation when rendering formatted html
* The default is four spaces
*/
public static Indenter indenter = (level, text) -> String.join("", Collections.nCopies(level, FOUR_SPACES)) + text;
private TextEscaper _textEscaper;
private Minifier _cssMinifier;
private Minifier _jsMinifier;
private boolean _closeEmptyTags;
private Indenter _indenter;
private Config(
TextEscaper _textEscaper,
Minifier _cssMinifier,
Minifier _jsMinifier,
boolean _closeEmptyTags,
Indenter _indenter
) {
this._textEscaper = _textEscaper;
this._cssMinifier = _cssMinifier;
this._jsMinifier = _jsMinifier;
this._closeEmptyTags = _closeEmptyTags;
this._indenter = _indenter;
}
/**
* A copy constructor.
*
* @param original The Config to copy fields from.
*/
private Config(Config original) {
this._textEscaper = original._textEscaper;
this._cssMinifier = original._cssMinifier;
this._jsMinifier = original._jsMinifier;
this._closeEmptyTags = original._closeEmptyTags;
this._indenter = original._indenter;
}
public TextEscaper textEscaper() {
return _textEscaper;
}
public Minifier cssMinifier() {
return _cssMinifier;
}
public Minifier jsMinifier() {
return _jsMinifier;
}
public boolean closeEmptyTags() {
return _closeEmptyTags;
}
public Indenter indenter() {
return _indenter;
}
public Config withTextEscaper(TextEscaper textEscaper){
Config copy = new Config(this);
copy._textEscaper = textEscaper;
return copy;
}
public Config withCssMinifier(Minifier cssMinifier){
Config copy = new Config(this);
copy._cssMinifier = cssMinifier;
return copy;
}
public Config withJsMinifier(Minifier jsMinifier){
Config copy = new Config(this);
copy._jsMinifier = jsMinifier;
return copy;
}
public Config withEmptyTagsClosed(boolean closeEmptyTags){
Config copy = new Config(this);
copy._closeEmptyTags = closeEmptyTags;
return copy;
}
public Config withIndenter(Indenter indenter){
Config copy = new Config(this);
copy._indenter = indenter;
return copy;
}
private static final Config DEFAULTS = new Config(
EscapeUtil::escape,
CSSMin::compressCss,
JSMin::compressJs,
false,
(level, text) -> String.join("", Collections.nCopies(level, FOUR_SPACES)) + text
);
public static final Config defaults() {
return DEFAULTS;
}
public static final Config global() {
return new Config(
textEscaper,
cssMinifier,
jsMinifier,
closeEmptyTags,
indenter
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
package j2html.attributes;
import j2html.tags.Tag;
public abstract class Attr {
public static final String ACCEPT = "accept";
public static final String ACCEPT_CHARSET = "accept-charset";
public static final String ACCESSKEY = "accesskey";
public static final String ACTION = "action";
public static final String ALIGN = "align";
public static final String ALT = "alt";
public static final String ASYNC = "async";
public static final String AUTOCOMPLETE = "autocomplete";
public static final String AUTOFOCUS = "autofocus";
public static final String AUTOPLAY = "autoplay";
public static final String AUTOSAVE = "autosave";
public static final String BORDER = "border";
public static final String BUFFERED = "buffered";
public static final String CHALLENGE = "challenge";
public static final String CHARSET = "charset";
public static final String CHECKED = "checked";
public static final String CITE = "cite";
public static final String CLASS = "class";
public static final String COLOR = "color";
public static final String COLS = "cols";
public static final String COLSPAN = "colspan";
public static final String CONTENT = "content";
public static final String CONTENTEDITABLE = "contenteditable";
public static final String CONTEXTMENU = "contextmenu";
public static final String CONTROLS = "controls";
public static final String COORDS = "coords";
public static final String DATA = "data";
public static final String DATETIME = "datetime";
public static final String DEFAULT = "default";
public static final String DEFER = "defer";
public static final String DIR = "dir";
public static final String DIRNAME = "dirname";
public static final String DISABLED = "disabled";
public static final String DOWNLOAD = "download";
public static final String DRAGGABLE = "draggable";
public static final String DROPZONE = "dropzone";
public static final String ENCTYPE = "enctype";
public static final String FOR = "for";
public static final String FORM = "form";
public static final String FORMACTION = "formaction";
public static final String HEADERS = "headers";
public static final String HEIGHT = "height";
public static final String HIDDEN = "hidden";
public static final String HIGH = "high";
public static final String HREF = "href";
public static final String HREFLANG = "hreflang";
public static final String HTTP_EQUIV = "http-equiv";
public static final String ICON = "icon";
public static final String ID = "id";
public static final String IS = "is";
public static final String ISMAP = "ismap";
public static final String ITEMPROP = "itemprop";
public static final String KEYTYPE = "keytype";
public static final String KIND = "kind";
public static final String LABEL = "label";
public static final String LANG = "lang";
public static final String LANGUAGE = "language";
public static final String LIST = "list";
public static final String LOOP = "loop";
public static final String LOW = "low";
public static final String MANIFEST = "manifest";
public static final String MAX = "max";
public static final String MAXLENGTH = "maxlength";
public static final String MEDIA = "media";
public static final String METHOD = "method";
public static final String MIN = "min";
public static final String MULTIPLE = "multiple";
public static final String NAME = "name";
public static final String NOVALIDATE = "novalidate";
public static final String OPEN = "open";
public static final String OPTIMUM = "optimum";
public static final String PATTERN = "pattern";
public static final String PING = "ping";
public static final String PLACEHOLDER = "placeholder";
public static final String POSTER = "poster";
public static final String PRELOAD = "preload";
public static final String PUBDATE = "pubdate";
public static final String RADIOGROUP = "radiogroup";
public static final String READONLY = "readonly";
public static final String REL = "rel";
public static final String REQUIRED = "required";
public static final String REVERSED = "reversed";
public static final String ROLE = "role";
public static final String ROWS = "rows";
public static final String ROWSPAN = "rowspan";
public static final String SANDBOX = "sandbox";
public static final String SCOPE = "scope";
public static final String SCOPED = "scoped";
public static final String SEAMLESS = "seamless";
public static final String SELECTED = "selected";
public static final String SHAPE = "shape";
public static final String SIZE = "size";
public static final String SIZES = "sizes";
public static final String SLOT = "slot";
public static final String SPAN = "span";
public static final String SPELLCHECK = "spellcheck";
public static final String SRC = "src";
public static final String SRCDOC = "srcdoc";
public static final String SRCLANG = "srclang";
public static final String SRCSET = "srcset";
public static final String START = "start";
public static final String STEP = "step";
public static final String STYLE = "style";
public static final String SUMMARY = "summary";
public static final String TABINDEX = "tabindex";
public static final String TARGET = "target";
public static final String TITLE = "title";
public static final String TYPE = "type";
public static final String USEMAP = "usemap";
public static final String VALUE = "value";
public static final String WIDTH = "width";
public static final String WRAP = "wrap";
public static final String TRANSLATE = "translate";
public static ShortForm shortFormFromAttrsString(String attrs) {
if (!attrs.contains(".") && !attrs.contains(("#"))) {
throw new IllegalArgumentException("String must contain either id (#) or class (.)");
}
if (attrs.split("#").length > 2) {
throw new IllegalArgumentException("Only one id (#) allowed");
}
String id = "";
StringBuilder classes = new StringBuilder();
for (String attr : attrs.split("\\.")) {
if (attr.contains("#")) {
if (!attr.startsWith("#")) {
throw new IllegalArgumentException("# cannot be in the middle of string");
}
id = attr.replace("#", "");
} else {
classes.append(attr).append(" ");
}
}
return new ShortForm(id.trim(), classes.toString().trim());
}
public static <T extends Tag<T>> T addTo(T tag, Attr attr) {
if (null != attr)
attr.addTo(tag);
return tag;
}
public abstract <T extends Tag<T>> T addTo(T tag);
public static class ShortForm extends Attr {
String id;
String classes;
private ShortForm(String id, String classes) {
this.id = id;
this.classes = classes;
}
boolean hasId() {
return id != null && !"".equals(id);
}
boolean hasClasses() {
return classes != null && !"".equals(classes);
}
@Override
public <T extends Tag<T>> T addTo(T tag) {
if (hasId() && hasClasses()) {
return tag.withId(id).withClass(classes);
}
if (hasId()) {
return tag.withId(id);
}
if (hasClasses()) {
return tag.withClass(classes);
}
return tag;
}
}
}

View File

@@ -0,0 +1,64 @@
package j2html.attributes;
import j2html.Config;
import j2html.rendering.TagBuilder;
import j2html.tags.Renderable;
import java.io.IOException;
public class Attribute implements Renderable {
private String name;
private String value;
public Attribute(String name, String value) {
this.name = name;
this.value = value;
}
public Attribute(String name) {
this.name = name;
this.value = null;
}
@Override
@Deprecated
public void renderModel(Appendable writer, Object model) throws IOException {
if (writer instanceof TagBuilder) {
if (name != null) {
if (value != null) {
((TagBuilder) writer).appendAttribute(name, value);
} else {
((TagBuilder) writer).appendBooleanAttribute(name);
}
}
} else {
if (name == null) {
return;
}
writer.append(' ');
writer.append(name);
if (value != null) {
writer.append("=\"");
writer.append(Config.textEscaper.escape(value));
writer.append('"');
}
}
}
public void render(TagBuilder builder, Object model) throws IOException {
// Maintain compatibility with classes that extend Attribute, for now...
renderModel(builder, model);
}
public String getName() {
return name;
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View File

@@ -0,0 +1,182 @@
package j2html.rendering;
import j2html.Config;
import j2html.utils.TextEscaper;
import java.io.IOException;
/**
* Composes HTML without any extra line breaks or indentation.
*
* @param <T> The type of the Appendable to which HTML will be appended.
*/
public class FlatHtml<T extends Appendable> implements HtmlBuilder<T> {
/**
* Returns an HtmlBuilder that will generate flat HTML using
* Config defaults.
*
* @param out The Appendable to which HTML will be appended.
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for flat HTML.
*/
public static final <T extends Appendable> FlatHtml<T> into(T out) {
return new FlatHtml<>(out, Config.defaults());
}
/**
* Returns an HtmlBuilder that will generate flat HTML using
* the given Config.
*
* @param out The Appendable to which HTML will be appended.
* @param config The Config which will specify text escapement, tag closing, etc.
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for flat HTML.
*/
public static final <T extends Appendable> FlatHtml<T> into(T out, Config config) {
return new FlatHtml<>(out, config);
}
/**
* Returns an HtmlBuilder that will generate flat HTML in memory
* using Config defaults.
*
* @return An HtmlBuilder for flat HTML.
*/
public static final FlatHtml<StringBuilder> inMemory() {
return into(new StringBuilder());
}
/**
* Returns an HtmlBuilder that will generate flat HTML in memory
* using the given Config.
* @param config The Config which will specify text escapement, tag closing, etc.
* @return An HtmlBuilder for flat HTML.
*/
public static final FlatHtml<StringBuilder> inMemory(Config config) {
return into(new StringBuilder(), config);
}
private final T out;
private final TextEscaper textEscaper;
private final TagBuilder enclosingElementAttributes;
private final TagBuilder emptyElementAttributes;
private FlatHtml(T out, Config config) {
this.out = out;
this.textEscaper = config.textEscaper();
this.enclosingElementAttributes = new FlatTagBuilder(false);
this.emptyElementAttributes = new FlatTagBuilder(config.closeEmptyTags());
}
public T output() {
return out;
}
@Override
@Deprecated
public HtmlBuilder<T> append(CharSequence csq) throws IOException {
out.append(csq);
return this;
}
@Override
@Deprecated
public HtmlBuilder<T> append(CharSequence csq, int start, int end) throws IOException {
out.append(csq, start, end);
return this;
}
@Override
@Deprecated
public HtmlBuilder<T> append(char c) throws IOException {
out.append(c);
return this;
}
@Override
public TagBuilder appendStartTag(String name) throws IOException {
out.append("<").append(name);
return enclosingElementAttributes;
}
@Override
public HtmlBuilder<T> appendEndTag(String name) throws IOException {
out.append("</").append(name).append(">");
return this;
}
@Override
public TagBuilder appendEmptyTag(String name) throws IOException {
out.append("<").append(name);
return emptyElementAttributes;
}
@Override
public HtmlBuilder<T> appendEscapedText(String txt) throws IOException {
out.append(textEscaper.escape(txt));
return this;
}
@Override
public HtmlBuilder<T> appendUnescapedText(String txt) throws IOException {
out.append(txt);
return this;
}
private class FlatTagBuilder implements TagBuilder {
private final boolean closeTag;
private FlatTagBuilder(boolean closeTag) {
this.closeTag = closeTag;
}
@Override
public TagBuilder appendAttribute(String name, String value) throws IOException {
out.append(" ")
.append(name)
.append("=\"")
.append(textEscaper.escape(value))
.append("\"");
return this;
}
@Override
public TagBuilder appendBooleanAttribute(String name) throws IOException {
out.append(" ").append(name);
return this;
}
@Override
public HtmlBuilder<T> completeTag() throws IOException {
if (closeTag) {
out.append("/");
}
out.append(">");
return FlatHtml.this;
}
@Override
@Deprecated
public TagBuilder append(CharSequence csq) throws IOException {
out.append(csq);
return this;
}
@Override
@Deprecated
public TagBuilder append(CharSequence csq, int start, int end) throws IOException {
out.append(csq, start, end);
return this;
}
@Override
@Deprecated
public TagBuilder append(char c) throws IOException {
out.append(c);
return this;
}
}
}

View File

@@ -0,0 +1,89 @@
package j2html.rendering;
import java.io.IOException;
/**
* Implementations of HtmlBuilder are wrappers around an
* Appendable, and support appending HTML-specific character
* sequences to that Appendable.
* <p>
* Note: HtmlBuilder extends Appendable for compatibility with
* previous version of this library. This extension will probably be
* removed in the future, so avoid relying on the deprecated methods
* of this interface.
*
* @param <T> The type of the Appendable. Used so that the
* same type can be returned to the caller, allowing
* for additional work to be done on the Appendable
* without the need for manual casting.
*/
public interface HtmlBuilder<T extends Appendable> extends Appendable {
/**
* Appends a start tag with the given name to the output. The
* returned TagBuilder is then used to append attributes
* and eventually complete the start tag.
*
* @param name The name of the start tag.
* @return An TagBuilder which can append attributes to the start tag.
* @throws IOException When the Appendable throws an IOException.
*/
TagBuilder appendStartTag(String name) throws IOException;
/**
* Appends an end tag with the given name to the output.
*
* @param name The name of the end tag.
* @return An HtmlBuilder that can continue appending HTML to the output.
* @throws IOException When the Appendable throws an IOException.
*/
HtmlBuilder<T> appendEndTag(String name) throws IOException;
/**
* Appends an empty tag with the given name to the output. The
* returned TagBuilder is then used to append attributes
* and eventually complete the empty tag.
*
* @param name The name of the empty tag.
* @return An TagBuilder which can append attributes to the empty tag.
* @throws IOException When the Appendable throws an IOException.
*/
TagBuilder appendEmptyTag(String name) throws IOException;
/**
* Appends escaped text to the output.
*
* @param txt The text to append.
* @return An HtmlBuilder that can continue appending HTML to the output.
* @throws IOException When the Appendable throws an IOException.
*/
HtmlBuilder<T> appendEscapedText(String txt) throws IOException;
/**
* Appends unescaped text to the output.
*
* @param txt The text to append.
* @return An HtmlBuilder that can continue appending HTML to the output.
* @throws IOException When the Appendable throws an IOException.
*/
HtmlBuilder<T> appendUnescapedText(String txt) throws IOException;
/**
* Returns the Appendable that was being wrapped.
*
* @return The original Appendable.
*/
T output();
@Override
@Deprecated
HtmlBuilder<T> append(CharSequence csq) throws IOException;
@Override
@Deprecated
HtmlBuilder<T> append(CharSequence csq, int start, int end) throws IOException;
@Override
@Deprecated
HtmlBuilder<T> append(char c) throws IOException;
}

View File

@@ -0,0 +1,246 @@
package j2html.rendering;
import j2html.Config;
import j2html.utils.Indenter;
import j2html.utils.TextEscaper;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Composes HTML with lines breaks and indentation between tags and text.
*
* @param <T> The type of the Appendable to which HTML will be appended.
*/
public class IndentedHtml<T extends Appendable> implements HtmlBuilder<T> {
/**
* Returns an HtmlBuilder that will generate indented HTML using
* Config defaults.
*
* @param out The Appendable to which HTML will be appended.
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for indented HTML.
*/
public static final <T extends Appendable> IndentedHtml<T> into(T out) {
return new IndentedHtml<>(out, Config.defaults());
}
/**
* Returns an HtmlBuilder that will generate indented HTML using
* the given Config.
*
* @param out The Appendable to which HTML will be appended.
* @param config The Config which will specify indentation, text escapement, tag closing, etc.
* @param <T> The type of the Appendable to which HTML will be appended.
* @return An HtmlBuilder for indented HTML.
*/
public static final <T extends Appendable> IndentedHtml<T> into(T out, Config config) {
return new IndentedHtml<>(out, config);
}
/**
* Returns an HtmlBuilder that will generate indented HTML in memory using
* Config defaults.
*
* @return An HtmlBuilder for indented HTML.
*/
public static final IndentedHtml<StringBuilder> inMemory() {
return into(new StringBuilder());
}
/**
* Returns an HtmlBuilder that will generate indented HTML in memory using
* the given Config.
*
* @param config The Config which will specify indentation, text escapement, tag closing, etc.
* @return An HtmlBuilder for indented HTML.
*/
public static final IndentedHtml<StringBuilder> inMemory(Config config) {
return into(new StringBuilder(), config);
}
private final T out;
private final Indenter indenter;
private final TextEscaper textEscaper;
private final TagBuilder enclosingElementAttributes;
private final TagBuilder emptyElementAttributes;
// Dealing with preformatted elements (pre and textarea) requires
// that we know what our parent elements are. To do that we use
// a stack; adding items as start tags are created, and removing them
// as those tags are closed. Determining whether or not we are
// currently rendering into a preformatted element is as simple as
// asking if any tags on the stack match a preformatted element name.
private final Deque<String> trace = new ArrayDeque<>();
private IndentedHtml(T out, Config config) {
this.out = out;
this.indenter = config.indenter();
this.textEscaper = config.textEscaper();
this.enclosingElementAttributes = new IndentedTagBuilder(false);
this.emptyElementAttributes = new IndentedTagBuilder(config.closeEmptyTags());
}
private boolean isContentSelfFormatting() {
return trace.contains("pre") || trace.contains("textarea");
}
private int lvl() {
return trace.size();
}
@Override
public TagBuilder appendStartTag(String name) throws IOException {
if (!isContentSelfFormatting()) {
out.append(indenter.indent(lvl(), ""));
}
trace.push(name);
out.append("<").append(name);
return enclosingElementAttributes;
}
@Override
public HtmlBuilder<T> appendEndTag(String name) throws IOException {
if (!name.equals(trace.peek())) {
throw new RuntimeException("Incorrect element closed: " + name + ". Expected: " + trace.peek());
}
if (!isContentSelfFormatting()) {
trace.pop();
out.append(indenter.indent(lvl(), ""));
} else {
trace.pop();
}
out.append("</").append(name).append(">");
if (!isContentSelfFormatting()) {
out.append("\n");
}
return this;
}
@Override
public TagBuilder appendEmptyTag(String name) throws IOException {
if (!isContentSelfFormatting()) {
out.append(indenter.indent(lvl(), ""));
}
out.append("<").append(name);
return emptyElementAttributes;
}
private void appendLines(String txt) throws IOException {
if (!isContentSelfFormatting()) {
String[] lines = txt.split("\n");
for (String line : lines) {
out.append(indenter.indent(lvl(), line)).append("\n");
}
} else {
out.append(txt);
}
}
@Override
public HtmlBuilder<T> appendEscapedText(String txt) throws IOException {
appendLines(textEscaper.escape(txt));
return this;
}
@Override
public HtmlBuilder<T> appendUnescapedText(String txt) throws IOException {
appendLines(txt);
return this;
}
@Override
public T output() {
return out;
}
@Override
@Deprecated
public HtmlBuilder<T> append(CharSequence csq) throws IOException {
out.append(csq);
return this;
}
@Override
@Deprecated
public HtmlBuilder<T> append(CharSequence csq, int start, int end) throws IOException {
out.append(csq, start, end);
return this;
}
@Override
@Deprecated
public HtmlBuilder<T> append(char c) throws IOException {
out.append(c);
return this;
}
private class IndentedTagBuilder implements TagBuilder {
private final boolean closeTag;
private IndentedTagBuilder(boolean closeTag) {
this.closeTag = closeTag;
}
@Override
public TagBuilder appendAttribute(String name, String value) throws IOException {
out.append(" ")
.append(name)
.append("=\"")
.append(textEscaper.escape(value))
.append("\"");
return this;
}
@Override
public TagBuilder appendBooleanAttribute(String name) throws IOException {
out.append(" ").append(name);
return this;
}
@Override
public HtmlBuilder<T> completeTag() throws IOException {
if (closeTag) {
out.append("/");
}
out.append(">");
if (!isContentSelfFormatting()) {
out.append("\n");
}
return IndentedHtml.this;
}
@Override
@Deprecated
public TagBuilder append(CharSequence csq) throws IOException {
out.append(csq);
return this;
}
@Override
@Deprecated
public TagBuilder append(CharSequence csq, int start, int end) throws IOException {
out.append(csq, start, end);
return this;
}
@Override
@Deprecated
public TagBuilder append(char c) throws IOException {
out.append(c);
return this;
}
}
}

View File

@@ -0,0 +1,57 @@
package j2html.rendering;
import java.io.IOException;
/**
* Implementations of TagBuilder are used to append HTML tag
* attributes to an Appendable. TagBuilders are scoped to the
* creation and completion of a specific tag, and should not be used
* outside of that tag.
* <p>
* Note: TagBuilder extends Appendable for compatibility with
* previous version of this library. This extension will probably be
* removed in the future, so avoid relying on the deprecated methods
* of this interface.
*/
public interface TagBuilder extends Appendable {
/**
* Appends an key/value pair as an HTML attribute to the current tag.
*
* @param name The name of an attribute.
* @param value The value of an attribute.
* @return An TagBuilder which can continue appending attributes.
* @throws IOException When the Appendable throws an IOException.
*/
TagBuilder appendAttribute(String name, String value) throws IOException;
/**
* Appends a name, as a boolean HTML attribute to the current tag.
*
* @param name The name of the boolean attribute.
* @return An TagBuilder which can continue appending attributes.
* @throws IOException When the Appendable throws an IOException.
*/
TagBuilder appendBooleanAttribute(String name) throws IOException;
/**
* Appends any characters which are necessary to close the current tag,
* and returns an HtmlBuilder that can continue appending to the output.
*
* @return An HtmlBuilder that can continue appending HTML to the output.
* @throws IOException When the Appendable throws an IOException.
*/
HtmlBuilder<? extends Appendable> completeTag() throws IOException;
@Override
@Deprecated
TagBuilder append(CharSequence csq) throws IOException;
@Override
@Deprecated
TagBuilder append(CharSequence csq, int start, int end) throws IOException;
@Override
@Deprecated
TagBuilder append(char c) throws IOException;
}

View File

@@ -0,0 +1,186 @@
package j2html.tags;
import j2html.Config;
import j2html.attributes.Attribute;
import j2html.rendering.TagBuilder;
import j2html.rendering.FlatHtml;
import j2html.rendering.HtmlBuilder;
import j2html.rendering.IndentedHtml;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class ContainerTag<T extends ContainerTag<T>> extends Tag<T> {
protected List<DomContent> children;
public ContainerTag(String tagName) {
super(tagName);
this.children = new ArrayList<>();
}
/**
* Appends a DomContent-object to the end of this element
*
* @param child DomContent-object to be appended
* @return itself for easy chaining
*/
public T with(DomContent child) {
if (this == child) {
throw new RuntimeException("Cannot append a tag to itself.");
}
if (child != null) {
// in some cases, like when using iff(), we ignore null children
children.add(child);
}
return self();
}
/**
* Call with-method based on condition
* {@link #with(DomContent child)}
*
* @param condition the condition to use
* @param child DomContent-object to be appended if condition met
* @return itself for easy chaining
*/
public T condWith(boolean condition, DomContent child) {
return condition ? this.with(child) : self();
}
/**
* Appends a list of DomContent-objects to the end of this element
*
* @param children DomContent-objects to be appended
* @return itself for easy chaining
*/
public T with(Iterable<? extends DomContent> children) {
if (children != null) {
for (DomContent child : children) {
this.with(child);
}
}
return self();
}
/**
* Call with-method based on condition
* {@link #with(java.lang.Iterable)}
*
* @param condition the condition to use
* @param children DomContent-objects to be appended if condition met
* @return itself for easy chaining
*/
public T condWith(boolean condition, Iterable<? extends DomContent> children) {
return condition ? this.with(children) : self();
}
/**
* Appends the DomContent-objects to the end of this element
*
* @param children DomContent-objects to be appended
* @return itself for easy chaining
*/
public T with(DomContent... children) {
for (DomContent child : children) {
with(child);
}
return self();
}
/**
* Appends the DomContent-objects in the stream to the end of this element
*
* @param children Stream of DomContent-objects to be appended
* @return itself for easy chaining
*/
public T with(Stream<DomContent> children) {
children.forEach(this::with);
return self();
}
/**
* Call with-method based on condition
* {@link #with(DomContent... children)}
*
* @param condition the condition to use
* @param children DomContent-objects to be appended if condition met
* @return itself for easy chaining
*/
public T condWith(boolean condition, DomContent... children) {
return condition ? this.with(children) : self();
}
/**
* Appends a Text-object to this element
*
* @param text the text to be appended
* @return itself for easy chaining
*/
public T withText(String text) {
return with(new Text(text));
}
/**
* Gets number of child nodes this tag element contains
*/
public int getNumChildren() {
return children.size();
}
/**
* Render the ContainerTag and its children, adding newlines before each
* child and using Config.indenter to indent child based on how deep
* in the tree it is
*
* @return the rendered and formatted string
*/
public String renderFormatted() {
try {
return render(IndentedHtml.into(new StringBuilder(), Config.global())).toString();
}catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public <A extends Appendable> A render(HtmlBuilder<A> builder, Object model) throws IOException {
if (hasTagName()) {
TagBuilder tagBuilder = builder.appendStartTag(getTagName());
for(Attribute attribute : getAttributes()){
attribute.render(tagBuilder, model);
}
tagBuilder.completeTag();
}
for(DomContent child : children){
child.render(builder, model);
}
if(hasTagName()) {
builder.appendEndTag(getTagName());
}
return builder.output();
}
@Override
@Deprecated
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
render(builder, model);
}
}

View File

@@ -0,0 +1,8 @@
package j2html.tags;
public abstract class DomContent implements Renderable {
@Override
public String toString() {
return render();
}
}

View File

@@ -0,0 +1,31 @@
package j2html.tags;
public class DomContentJoiner {
public static UnescapedText join(CharSequence delimiter, boolean fixPeriodAndCommaSpacing, Object... stringOrDomObjects) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < stringOrDomObjects.length; i++) {
Object o = stringOrDomObjects[i];
if (o instanceof String) {
sb.append(((String) o).trim());
} else if (o instanceof DomContent) {
sb.append(((DomContent) o).render().trim());
} else if (o == null) {
//Discard null objects so iff/iffelse can be used with join
continue;
} else {
throw new RuntimeException("You can only join DomContent and String objects");
}
if (i < stringOrDomObjects.length-1) {
sb.append(delimiter);
}
}
String joined = sb.toString().trim();
if (fixPeriodAndCommaSpacing) {
joined = joined.replaceAll("\\s\\.", ".");
joined = joined.replaceAll("\\s\\,", ",");
}
return new UnescapedText(joined);
}
}

View File

@@ -0,0 +1,42 @@
package j2html.tags;
import j2html.Config;
import j2html.attributes.Attribute;
import j2html.rendering.TagBuilder;
import j2html.rendering.FlatHtml;
import j2html.rendering.HtmlBuilder;
import java.io.IOException;
public class EmptyTag<T extends EmptyTag<T>> extends Tag<T> {
public EmptyTag(String tagName) {
super(tagName);
if (tagName == null) {
throw new IllegalArgumentException("Illegal tag name: null");
}
if ("".equals(tagName)) {
throw new IllegalArgumentException("Illegal tag name: \"\"");
}
}
@Override
public <A extends Appendable> A render(HtmlBuilder<A> builder, Object model) throws IOException {
TagBuilder attrs = builder.appendEmptyTag(getTagName());
for (Attribute attr : getAttributes()) {
attr.render(attrs, model);
}
attrs.completeTag();
return builder.output();
}
@Override
@Deprecated
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
render(builder, model);
}
}

View File

@@ -0,0 +1,20 @@
package j2html.tags;
public interface IInstance<T> {
//to get the actual instance
// (every implementing class would have to implement: { return this; }
// public T self();
// this method shows up in autocomplete.
// this is really undesireable as it does not do anything.
@SuppressWarnings("unchecked")
default T self() {
//we know that the implementing class will supply
//its own type as the type argument.
//therefore every instance of IInstance can assume it
//is also of type T
return (T) this;
}
}

View File

@@ -0,0 +1,50 @@
package j2html.tags;
import j2html.Config;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Scanner;
import static j2html.TagCreator.rawHtml;
import static j2html.TagCreator.script;
import static j2html.TagCreator.style;
public class InlineStaticResource {
public static ContainerTag<? extends Tag<?>> 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");
}
}
public static String getFileAsString(String path) {
try {
return streamToString(InlineStaticResource.class.getResourceAsStream(path));
} catch (Exception expected) { // we don't ask users to specify classpath or file-system
try {
return streamToString(new FileInputStream(path));
} catch (Exception exception) {
throw new RuntimeException("Couldn't find file with path='" + path + "'");
}
}
}
private static String streamToString(InputStream inputStream) {
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
public enum TargetFormat {CSS_MIN, CSS, JS_MIN, JS}
}

View File

@@ -0,0 +1,81 @@
package j2html.tags;
import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.HtmlBuilder;
import java.io.IOException;
import java.io.UncheckedIOException;
public interface Renderable {
/**
* Render the Renderable and it's children using the supplied builder.
*
* @param builder A builder that can compose HTML elements.
* @param model A model object to provide data for children to render.
* @param <T> The type of the Appendable which HTML is being appended to.
* @return The Appendable to which HTML has been appended.
* @throws IOException
*/
default <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) throws IOException {
// This method should be overridden by any internal classes.
// renderModel() is only being called to support backwards
// compatibility.
renderModel(builder, model);
return builder.output();
}
/**
* Render the Renderable and it's children using the supplied builder.
*
* @param builder A builder that can compose HTML elements.
* @param <T> The type of the Appendable to which HTML is being appended.
* @return The Appendable to which HTML has been appended.
* @throws IOException
*/
default <T extends Appendable> T render(HtmlBuilder<T> builder) throws IOException {
return render(builder, null);
}
/**
* Create a StringBuilder and use it to render the Renderable and it's
* children
*/
default String render() {
try {
return render(FlatHtml.into(new StringBuilder(), Config.global())).toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* Render the Renderable and it's children using the supplied writer
*
* @param writer the current writer
*/
@Deprecated
default void render(Appendable writer) throws IOException {
if (writer instanceof HtmlBuilder) {
render((HtmlBuilder<? extends Appendable>) writer);
} else {
render(FlatHtml.into(writer, Config.global()));
}
}
/**
* 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
*/
@Deprecated
default void renderModel(Appendable writer, Object model) throws IOException {
// This method is a placeholder to support any client classes
// which previously extended Renderable implementers, such as Tags.
// No internal classes should implement this method; except to support
// compatibility. Instead they should implement rendering with an HtmlBuilder.
throw new RuntimeException("Renderable.renderModel(Appendable writer, Object model) has been deprecated. Please use Renderable.render(HtmlBuilder<T> builder, Object model) instead.");
}
}

View File

@@ -0,0 +1,213 @@
package j2html.tags;
import j2html.attributes.Attr;
import j2html.attributes.Attribute;
import java.util.ArrayList;
import java.util.Iterator;
public abstract class Tag<T extends Tag<T>> extends DomContent implements IInstance<T> {
private final String tagName;
private final ArrayList<Attribute> attributes;
protected Tag(String tagName) {
this.tagName = tagName;
this.attributes = new ArrayList<>();
}
public String getTagName() {
return this.tagName;
}
protected boolean hasTagName() {
return tagName != null && !tagName.isEmpty();
}
protected ArrayList<Attribute> getAttributes() {
return attributes;
}
/**
* Sets an attribute on an element
*
* @param name the attribute
* @param value the attribute value
*/
boolean setAttribute(String name, String value) {
if (value == null) {
return attributes.add(new Attribute(name));
}
for (Attribute attribute : attributes) {
if (attribute.getName().equals(name)) {
attribute.setValue(value); // update with new value
return true;
}
}
return attributes.add(new Attribute(name, value));
}
/**
* Sets a custom attribute
*
* @param attribute the attribute name
* @param value the attribute value
* @return itself for easy chaining
*/
public T attr(String attribute, Object value) {
setAttribute(attribute, value == null ? null : String.valueOf(value));
return self();
}
/**
* 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 self();
}
/**
* Sets a custom attribute without value
*
* @param attribute the attribute name
* @return itself for easy chaining
* @see Tag#attr(String, Object)
*/
public T attr(String attribute) {
return attr(attribute, null);
}
/**
* Call attr-method based on condition
* {@link #attr(String attribute, Object value)}
*
* @param condition the condition
* @param attribute the attribute name
* @param value the attribute value
* @return itself for easy chaining
*/
public T condAttr(boolean condition, String attribute, String value) {
return (condition ? attr(attribute, value) : self());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Tag)) {
return false;
}
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) {
sb.append(s != null ? s : "").append(" ");
}
return attr(Attr.CLASS, sb.toString().trim());
}
/*
Tag.java contains all Global Attributes, Attributes which are
valid on all HTML Tags. Reference:
https://www.w3schools.com/tags/ref_standardattributes.asp
Attributes:
accesskey
class
contenteditable
data-*
dir
draggable
hidden
id
lang
spellcheck
style
tabindex
title
translate
*/
public T withAccesskey(String accesskey){ return attr(Attr.ACCESSKEY, accesskey); }
public T withClass(String className) { return attr(Attr.CLASS, className); }
public T isContenteditable(){ return attr(Attr.CONTENTEDITABLE, "true"); }
public T withData(String dataAttr, String value) { return attr(Attr.DATA + "-" + dataAttr, value); }
public T withDir(String dir) { return attr(Attr.DIR, dir); }
public T isDraggable(){ return attr(Attr.DRAGGABLE, "true"); }
public T isHidden() { return attr(Attr.HIDDEN, null); }
public T withId(String id) { return attr(Attr.ID, id); }
public T withIs(String element){ return attr(Attr.IS, element); }
public T withLang(String lang) { return attr(Attr.LANG, lang); }
public T withSlot(String name){ return attr(Attr.SLOT, name); }
public T isSpellcheck(){ return attr(Attr.SPELLCHECK, "true"); }
public T withStyle(String style) { return attr(Attr.STYLE, style); }
public T withTabindex(int index){ return attr(Attr.TABINDEX, index); }
public T withTitle(String title) { return attr(Attr.TITLE, title); }
public T isTranslate(){ return attr(Attr.TRANSLATE, "yes"); }
// ----- start of withCond$ATTR variants -----
public T withCondAccessKey(boolean condition, String accesskey){ return condAttr(condition, Attr.ACCESSKEY, accesskey); }
public T withCondClass(boolean condition, String className) { return condAttr(condition, Attr.CLASS, className); }
public T withCondContenteditable(boolean condition){ return attr(Attr.CONTENTEDITABLE, (condition)?"true":"false");}
public T withCondData(boolean condition, String dataAttr, String value) { return condAttr(condition, Attr.DATA + "-" + dataAttr, value); }
public T withCondDir(boolean condition, String dir) { return condAttr(condition, Attr.DIR, dir); }
public T withCondDraggable(boolean condition){ return attr(Attr.DRAGGABLE, (condition)?"true":"false"); }
public T withCondHidden(boolean condition) { return condAttr(condition, Attr.HIDDEN, null); }
public T withCondId(boolean condition, String id) { return condAttr(condition, Attr.ID, id); }
public T withCondIs(boolean condition, String element){ return condAttr(condition, Attr.IS, element); }
public T withCondLang(boolean condition, String lang) { return condAttr(condition, Attr.LANG, lang); }
public T withCondSlot(boolean condition, String name){ return condAttr(condition, Attr.SLOT, name); }
public T withCondSpellcheck(boolean condition){ return attr(Attr.SPELLCHECK, (condition)?"true":"false"); }
public T withCondStyle(boolean condition, String style) { return condAttr(condition, Attr.STYLE, style); }
public T withCondTabindex(boolean condition, int index){ return condAttr(condition, Attr.TABINDEX, index+""); }
public T withCondTitle(boolean condition, String title) { return condAttr(condition, Attr.TITLE, title); }
public T withCondTranslate(boolean condition){ return attr(Attr.TRANSLATE, (condition)?"yes":"no"); }
}

View File

@@ -0,0 +1,33 @@
package j2html.tags;
import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.HtmlBuilder;
import java.io.IOException;
public class Text extends DomContent {
private final String text;
public Text(String text) {
this.text = text;
}
@Override
public <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) throws IOException {
builder.appendEscapedText(String.valueOf(text));
return builder.output();
}
@Override
@Deprecated
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
render(builder, model);
}
}

View File

@@ -0,0 +1,40 @@
package j2html.tags;
import j2html.Config;
import j2html.rendering.FlatHtml;
import j2html.rendering.HtmlBuilder;
import java.io.IOException;
public class UnescapedText extends DomContent {
private final String text;
public UnescapedText(String text) {
this.text = text;
}
@Override
public <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) throws IOException {
builder.appendUnescapedText(String.valueOf(text));
return builder.output();
}
@Override
@Deprecated
public void renderModel(Appendable writer, Object model) throws IOException {
HtmlBuilder<?> builder = (writer instanceof HtmlBuilder)
? (HtmlBuilder<?>) writer
: FlatHtml.into(writer, Config.global());
render(builder, model);
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof UnescapedText)) {
return false;
}
return ((UnescapedText) obj).render().equals(this.render());
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAccept<T extends Tag<T>> extends IInstance<T> {
default T withAccept(final String accept_) {
return self().attr("accept", accept_);
}
default T withCondAccept(final boolean enable, final String accept_) {
if (enable) {
self().attr("accept", accept_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAction<T extends Tag<T>> extends IInstance<T> {
default T withAction(final String action_) {
return self().attr("action", action_);
}
default T withCondAction(final boolean enable, final String action_) {
if (enable) {
self().attr("action", action_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAlt<T extends Tag<T>> extends IInstance<T> {
default T withAlt(final String alt_) {
return self().attr("alt", alt_);
}
default T withCondAlt(final boolean enable, final String alt_) {
if (enable) {
self().attr("alt", alt_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAsync<T extends Tag<T>> extends IInstance<T> {
default T isAsync() {
self().attr("async");
return self();
}
default T withCondAsync(final boolean enable) {
if (enable) {
self().attr("async");
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAutocomplete<T extends Tag<T>> extends IInstance<T> {
default T isAutocomplete() {
self().attr("autocomplete", "on");
return self();
}
default T withCondAutocomplete(final boolean enable) {
if (enable) {
self().attr("autocomplete", "on");
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAutofocus<T extends Tag<T>> extends IInstance<T> {
default T isAutofocus() {
self().attr("autofocus");
return self();
}
default T withCondAutofocus(final boolean enable) {
if (enable) {
self().attr("autofocus");
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IAutoplay<T extends Tag<T>> extends IInstance<T> {
default T isAutoplay() {
self().attr("autoplay");
return self();
}
default T withCondAutoplay(final boolean enable) {
if (enable) {
self().attr("autoplay");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ICharset<T extends Tag<T>> extends IInstance<T> {
default T withCharset(final String charset_) {
return self().attr("charset", charset_);
}
default T withCondCharset(final boolean enable, final String charset_) {
if (enable) {
self().attr("charset", charset_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IChecked<T extends Tag<T>> extends IInstance<T> {
default T isChecked() {
self().attr("checked");
return self();
}
default T withCondChecked(final boolean enable) {
if (enable) {
self().attr("checked");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ICite<T extends Tag<T>> extends IInstance<T> {
default T withCite(final String cite_) {
return self().attr("cite", cite_);
}
default T withCondCite(final boolean enable, final String cite_) {
if (enable) {
self().attr("cite", cite_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ICols<T extends Tag<T>> extends IInstance<T> {
default T withCols(final String cols_) {
return self().attr("cols", cols_);
}
default T withCondCols(final boolean enable, final String cols_) {
if (enable) {
self().attr("cols", cols_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IColspan<T extends Tag<T>> extends IInstance<T> {
default T withColspan(final String colspan_) {
return self().attr("colspan", colspan_);
}
default T withCondColspan(final boolean enable, final String colspan_) {
if (enable) {
self().attr("colspan", colspan_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IContent<T extends Tag<T>> extends IInstance<T> {
default T withContent(final String content_) {
return self().attr("content", content_);
}
default T withCondContent(final boolean enable, final String content_) {
if (enable) {
self().attr("content", content_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IControls<T extends Tag<T>> extends IInstance<T> {
default T isControls() {
self().attr("controls");
return self();
}
default T withCondControls(final boolean enable) {
if (enable) {
self().attr("controls");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ICoords<T extends Tag<T>> extends IInstance<T> {
default T withCoords(final String coords_) {
return self().attr("coords", coords_);
}
default T withCondCoords(final boolean enable, final String coords_) {
if (enable) {
self().attr("coords", coords_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IData<T extends Tag<T>> extends IInstance<T> {
default T withData(final String data_) {
return self().attr("data", data_);
}
default T withCondData(final boolean enable, final String data_) {
if (enable) {
self().attr("data", data_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDatetime<T extends Tag<T>> extends IInstance<T> {
default T withDatetime(final String datetime_) {
return self().attr("datetime", datetime_);
}
default T withCondDatetime(final boolean enable, final String datetime_) {
if (enable) {
self().attr("datetime", datetime_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDefault<T extends Tag<T>> extends IInstance<T> {
default T isDefault() {
self().attr("default");
return self();
}
default T withCondDefault(final boolean enable) {
if (enable) {
self().attr("default");
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDefer<T extends Tag<T>> extends IInstance<T> {
default T isDefer() {
self().attr("defer");
return self();
}
default T withCondDefer(final boolean enable) {
if (enable) {
self().attr("defer");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDirname<T extends Tag<T>> extends IInstance<T> {
default T withDirname(final String dirname_) {
return self().attr("dirname", dirname_);
}
default T withCondDirname(final boolean enable, final String dirname_) {
if (enable) {
self().attr("dirname", dirname_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDisabled<T extends Tag<T>> extends IInstance<T> {
default T isDisabled() {
self().attr("disabled");
return self();
}
default T withCondDisabled(final boolean enable) {
if (enable) {
self().attr("disabled");
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IDownload<T extends Tag<T>> extends IInstance<T> {
default T isDownload() {
self().attr("download");
return self();
}
default T withCondDownload(final boolean enable) {
if (enable) {
self().attr("download");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IEnctype<T extends Tag<T>> extends IInstance<T> {
default T withEnctype(final String enctype_) {
return self().attr("enctype", enctype_);
}
default T withCondEnctype(final boolean enable, final String enctype_) {
if (enable) {
self().attr("enctype", enctype_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IFor<T extends Tag<T>> extends IInstance<T> {
default T withFor(final String for_) {
return self().attr("for", for_);
}
default T withCondFor(final boolean enable, final String for_) {
if (enable) {
self().attr("for", for_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IForm<T extends Tag<T>> extends IInstance<T> {
default T withForm(final String form_) {
return self().attr("form", form_);
}
default T withCondForm(final boolean enable, final String form_) {
if (enable) {
self().attr("form", form_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IFormaction<T extends Tag<T>> extends IInstance<T> {
default T withFormaction(final String formaction_) {
return self().attr("formaction", formaction_);
}
default T withCondFormaction(final boolean enable, final String formaction_) {
if (enable) {
self().attr("formaction", formaction_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IHeaders<T extends Tag<T>> extends IInstance<T> {
default T withHeaders(final String headers_) {
return self().attr("headers", headers_);
}
default T withCondHeaders(final boolean enable, final String headers_) {
if (enable) {
self().attr("headers", headers_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IHeight<T extends Tag<T>> extends IInstance<T> {
default T withHeight(final String height_) {
return self().attr("height", height_);
}
default T withCondHeight(final boolean enable, final String height_) {
if (enable) {
self().attr("height", height_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IHigh<T extends Tag<T>> extends IInstance<T> {
default T withHigh(final String high_) {
return self().attr("high", high_);
}
default T withCondHigh(final boolean enable, final String high_) {
if (enable) {
self().attr("high", high_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IHref<T extends Tag<T>> extends IInstance<T> {
default T withHref(final String href_) {
return self().attr("href", href_);
}
default T withCondHref(final boolean enable, final String href_) {
if (enable) {
self().attr("href", href_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IHreflang<T extends Tag<T>> extends IInstance<T> {
default T withHreflang(final String hreflang_) {
return self().attr("hreflang", hreflang_);
}
default T withCondHreflang(final boolean enable, final String hreflang_) {
if (enable) {
self().attr("hreflang", hreflang_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IIsmap<T extends Tag<T>> extends IInstance<T> {
default T isIsmap() {
self().attr("ismap");
return self();
}
default T withCondIsmap(final boolean enable) {
if (enable) {
self().attr("ismap");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IKind<T extends Tag<T>> extends IInstance<T> {
default T withKind(final String kind_) {
return self().attr("kind", kind_);
}
default T withCondKind(final boolean enable, final String kind_) {
if (enable) {
self().attr("kind", kind_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ILabel<T extends Tag<T>> extends IInstance<T> {
default T withLabel(final String label_) {
return self().attr("label", label_);
}
default T withCondLabel(final boolean enable, final String label_) {
if (enable) {
self().attr("label", label_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IList<T extends Tag<T>> extends IInstance<T> {
default T withList(final String list_) {
return self().attr("list", list_);
}
default T withCondList(final boolean enable, final String list_) {
if (enable) {
self().attr("list", list_);
}
return self();
}
}

View File

@@ -0,0 +1,18 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ILoop<T extends Tag<T>> extends IInstance<T> {
default T isLoop() {
self().attr("loop");
return self();
}
default T withCondLoop(final boolean enable) {
if (enable) {
self().attr("loop");
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface ILow<T extends Tag<T>> extends IInstance<T> {
default T withLow(final String low_) {
return self().attr("low", low_);
}
default T withCondLow(final boolean enable, final String low_) {
if (enable) {
self().attr("low", low_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IMax<T extends Tag<T>> extends IInstance<T> {
default T withMax(final String max_) {
return self().attr("max", max_);
}
default T withCondMax(final boolean enable, final String max_) {
if (enable) {
self().attr("max", max_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IMaxlength<T extends Tag<T>> extends IInstance<T> {
default T withMaxlength(final String maxlength_) {
return self().attr("maxlength", maxlength_);
}
default T withCondMaxlength(final boolean enable, final String maxlength_) {
if (enable) {
self().attr("maxlength", maxlength_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IMedia<T extends Tag<T>> extends IInstance<T> {
default T withMedia(final String media_) {
return self().attr("media", media_);
}
default T withCondMedia(final boolean enable, final String media_) {
if (enable) {
self().attr("media", media_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IMethod<T extends Tag<T>> extends IInstance<T> {
default T withMethod(final String method_) {
return self().attr("method", method_);
}
default T withCondMethod(final boolean enable, final String method_) {
if (enable) {
self().attr("method", method_);
}
return self();
}
}

View File

@@ -0,0 +1,17 @@
package j2html.tags.attributes;
import j2html.tags.IInstance;
import j2html.tags.Tag;
public interface IMin<T extends Tag<T>> extends IInstance<T> {
default T withMin(final String min_) {
return self().attr("min", min_);
}
default T withCondMin(final boolean enable, final String min_) {
if (enable) {
self().attr("min", min_);
}
return self();
}
}

Some files were not shown because too many files have changed in this diff Show More