15 Commits

Author SHA1 Message Date
Scott Embler
55abbec0ba Adding extension project to support MathML syntax through j2html. (#223)
- Based on PR #220 by matthew-mccall.
2022-12-26 15:36:54 -05:00
Scott Embler
94c82398ad Maven multi module support (#222)
* Restructuring to a Maven multi-module project.

- Renamed directories to match artifact ids.
- Added parent POM.
- Added developers to parent POM.
- Added dependency management and plugin management.  No expectation that the build or release process is fully functional.
- Extracted versions into properties like other projects.

* Fixed file paths for workflow and documentation.

- Added junit to j2html-codegen module.

* Temporarily setting packaging for j2html-codegen to pom, to allow workflow to complete.

* Removed copied configuration of maven-jar-plugin from parent POM.

* Integrating code generation into the main build process.

- j2html-codegen is now supplying a Maven plugin that can read a model file and generate corresponding attribute and tag classes as part of the project build.
- j2html classes that would conflict with the generated classes have been removed.

* Targeting LTS versions only.

- JDK 9 & 10 support ended  in 2018
2022-12-26 09:51:00 -05:00
Scott Embler
38c08d4724 Updating README.md and website documents to match with release 1.6.0. (#214) 2022-06-30 17:49:14 -04:00
David
1c164a0773 [maven-release-plugin] prepare for next development iteration 2022-06-30 20:40:14 +02:00
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
397 changed files with 132312 additions and 3457 deletions

View File

@@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [1.8, 9, 10, 11, 12, 13]
java_version: [1.8, 11, 17]
os: [windows-latest, macOS-latest, ubuntu-latest]
steps:
@@ -23,6 +23,6 @@ jobs:
if: contains(matrix.os, 'win') == false
run: chmod +x ./mvnw
- name: Build with Maven
run: ./mvnw package --file library/pom.xml --batch-mode
run: ./mvnw verify --file pom.xml --batch-mode
env:
MAVEN_OPTS: -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn

1
.gitignore vendored
View File

@@ -11,4 +11,5 @@ hs_err_pid*
buildNumber.properties
### IntelliJ ###
*.iml
.idea/

View File

@@ -33,7 +33,7 @@ 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.
there is the `j2html-codegen/` directory which contains everything needed to generate the code.
For simplicity (and also to avoid extra dependencies), they do not format the code correctly.
@@ -51,7 +51,7 @@ The workflow (most of the time) consists of:
## Project Architecture
### library/src/main/java/j2html/TagCreator.java
### j2html/src/main/java/j2html/TagCreator.java
This is **the** central class in J2HTML. It provides the methods
for users of J2HTML to generate all HTML Tags.
@@ -80,7 +80,7 @@ html(
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`.
The classes are located in `j2html/src/main/java/j2html/tags/specialized` and follow the naming convention `tag_name + 'Tag.java'`, e.g. `BodyTag.java`.
Notice that the first letter of the Tag is in uppercase.
Each Tag-specific class `implements` interfaces which correspond to the Attributes that can be set on these Tags.
@@ -128,7 +128,7 @@ 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/`:
There are 3 classes which contain code-generating methods in `j2html-codegen/src/main/java/j2html_codegen/generators/`:
- `AttributeInterfaceCodeGenerator.java` (generating the interfaces for the attributes)
- `SpecializedTagClassCodeGenerator.java` (generating the classes for the tags)
@@ -147,7 +147,7 @@ Attributes differ in their 'type' . Some of them can be set with numbers (which
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,
`j2html/src/main/java/j2html/tags/generators/AttributesList.java` contains the different Attributes, their properties,
and the Tags they can be set on. It is the starting point for adding new Attributes and customizing their properties.

View File

@@ -13,12 +13,12 @@ The project webpage is [j2html.com](http://j2html.com).
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.4.0</version>
<version>1.6.0</version>
</dependency>
```
### Or the gradle dependency
```
compile 'com.j2html:j2html:1.4.0'
compile 'com.j2html:j2html:1.6.0'
```
### Import TagCreator and start building HTML

View File

@@ -1,74 +0,0 @@
<?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>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.1.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.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.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

@@ -11,9 +11,9 @@
<header class="top-header"><nav class="width-limit"><a id="logo" href="/"><span><img src="/img/logo.svg" alt="j2html logo"></span></a><ul><li><a href="/">Home</a></li><li><a href="/download.html">Download</a></li><li><a href="/examples.html">Examples</a></li><li><a href="/news.html">News</a></li></ul></nav></header><header class="banner"><h1 class="width-limit">Maven and GitHub</h1></header><main class="width-limit"><section id="download"><h2>Maven dependency</h2><p>To experience the joy of generating HTML with a Java HTML builder, add the j2html dependency to your POM:</p><pre><code class="language-markup">&lt;dependency&gt;
&lt;groupId&gt;com.j2html&lt;/groupId&gt;
&lt;artifactId&gt;j2html&lt;/artifactId&gt;
&lt;version&gt;1.4.0&lt;/version&gt;
&lt;version&gt;1.6.0&lt;/version&gt;
&lt;/dependency&gt;
</code></pre><h2>Clone the repo on GitHub</h2><p>Please clone and/or fork the repo on <a href="https://github.com/tipsy/j2html" target="_blank">GitHub</a>, make changes, and create pull requests! We will go through pull requests every sunday, so don't be shy.</p></section></main><div id="javalin-suggestion"><span class="close"></span> Want a simple and modern web framework? <br> Try our other project: <a href="https://javalin.io?from=j2html">https://javalin.io</a></div><footer>This page was created using <a href="https://github.com/tipsy/j2html" target="_blank">j2html</a> and <a href="https://javalin.io/" target="_blank">Javalin</a>. Webpage source on <a href="https://github.com/j2html/j2html-webpage" target="_blank">Github</a>. <br> <p class="lols">A static page generator or a template engine would be better suited than a HTML builder for creating this page, but we had to do it.</p></footer><script>/* http://prismjs.com/download.html?themes=prism-okaidia&languages=markup+css+clike+javascript+java */
</code></pre><a id="upgrade"></a><h2>Steps for upgrading</h2><p>From 1.4.0 to 1.5.0</p><ul><li>Change return types from <code>Tag</code>, <code>ContainerTag</code> or <code>EmptyTag</code> to the specific tag being returned.</li><li>Change missing method calls on tags, such as <code>withRole(&quot;value&quot;)</code> to <code>.attr(&quot;role&quot;, &quot;value&quot;)</code>.</li><li>Method parameters of <code>Tag</code>, <code>ContainerTag</code> or <code>EmptyTag</code> should have a wildcard (&lt;?&gt;) added, or be changed to a specific tag.</li><li>Replace ambiguous method references like <code>each(list, TagCreator::li)</code> with lambdas such as <code>each(list, str -&gt; li(str))</code>.</li></ul><h2>Clone the repo on GitHub</h2><p>Please clone and/or fork the repo on <a href="https://github.com/tipsy/j2html" target="_blank">GitHub</a>, make changes, and create pull requests! We will go through pull requests every sunday, so don't be shy.</p></section></main><div id="javalin-suggestion"><span class="close"></span> Want a simple and modern web framework? <br> Try our other project: <a href="https://javalin.io?from=j2html">https://javalin.io</a></div><footer>This page was created using <a href="https://github.com/tipsy/j2html" target="_blank">j2html</a> and <a href="https://javalin.io/" target="_blank">Javalin</a>. Webpage source on <a href="https://github.com/j2html/j2html-webpage" target="_blank">Github</a>. <br> <p class="lols">A static page generator or a template engine would be better suited than a HTML builder for creating this page, but we had to do it.</p></footer><script>/* 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));;

View File

@@ -45,8 +45,12 @@
import static j2html.TagCreator.*; // Use static star import
Config.class // Static config class which holds all configuration
Config.closeEmptyTags = true // all options are public and static, assign using &#x27;=&#x27; operator
Config.class // Holds all configuration. Offers global configuration or customizable instances
Config.closeEmptyTags = true // Global options are public, static and mutable.
Config.global() // Copy all static Config fields into an instance. Instances are immutable
Config.defaults() // A Config with defaults that are independent of global options
Config.global().withEmptyTagsClosed(true) // A Config that is different from the global options
Config.defaults().withEmptyTagsClosed(true) // A Config that is different from the default options
TagCreator.join() // Method for joining small snippets, like:
@@ -64,6 +68,17 @@ div().withClasses(&quot;menu-element&quot;, iffElse(isActive, &quot;active&quot;
Tag.class // Is extended by ContainerTag (ex &lt;div&gt;&lt;/div&gt; and EmptyTag (ex &lt;br&gt;)
Tag.attr(String attribute, Object value) // Set an attribute on the tag
Tag.withXyz(String value) // Calls attr with predefined attribute (ex .withId, .withClass, etc.)
Tag.render(HtmlBuilder builder) // Render HTML using the given builder.
Tag.render() // Shortcut for rendering flat HTML into a string using global Config.
ContainerTag.renderFormatted() // Shortcut for rendering indented HTML into a string using global Config.
HtmlBuilder.class // Interface for composing HTML. Implemented by FlatHtml and IndentedHtml
FlatHtml.into(Appendable) // Render into a stream, file, etc. without indentation or line breaks
FlatHtml.into(Appendable appendable, Config config) // Customize rendering of flat html
IndentedHtml.into(Appendable) // Render human-readable HTML into an stream, file, etc.
IndentedHtml.into(Appendable appendable, Config config) // Customize rendering of intended html
ul(li(&quot;one&quot;), li(&quot;two&quot;)).render(IndentedHtml.inMemory()).toString() // Similar to renderFormatted()
ul(li(&quot;one&quot;), li(&quot;two&quot;)).render(IndentedHtml.into(filewriter)) // Write HTML into a file
</code></pre><h2 id="loops">Loops, each() and filter()</h2><p>Using Java 8&#x27;s lambda syntax, you can write loops (via streams) inside your HTML-builder:</p><div class="code-compare nowith"><ul><li class="nowith-switch active">version 1.0.0 +</li><li class="with-switch">earlier versions</li></ul><pre class="nowith-pre"><code class="language-java">body(
div(attrs(&quot;#employees&quot;),
employees.stream().map(employee -&gt;

File diff suppressed because one or more lines are too long

86
j2html-codegen/pom.xml Normal file
View File

@@ -0,0 +1,86 @@
<?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>com.j2html</groupId>
<artifactId>j2html-parent</artifactId>
<version>1.6.1-SNAPSHOT</version>
</parent>
<name>j2html-codegen</name>
<artifactId>j2html-codegen-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.8.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<!--
Note: The use of version properties below is to avoid
redefining these versions when using this maven plugin
in other projects. Using the more concise dependency-
management strategy for versioning doesn't work when
another project tries to detect this plugin's dependency
versions.
-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
<version>${javapoet.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.4</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -1,7 +1,7 @@
package j2html_codegen;
package com.j2html.codegen;
import j2html_codegen.generators.AttributeInterfaceCodeGenerator;
import j2html_codegen.generators.SpecializedTagClassCodeGenerator;
import com.j2html.codegen.generators.SpecializedTagClassCodeGenerator;
import com.j2html.codegen.generators.AttributeInterfaceCodeGenerator;
import java.io.IOException;
import java.nio.file.Path;

View File

@@ -0,0 +1,50 @@
package com.j2html.codegen;
import com.j2html.codegen.model.AttrD;
import static com.j2html.codegen.generators.TagCreatorCodeGenerator.containerTags;
import static com.j2html.codegen.generators.TagCreatorCodeGenerator.emptyTags;
import static com.j2html.codegen.model.AttributesList.attributesDescriptive;
import static com.j2html.codegen.model.AttributesList.getCustomAttributesForHtmlTag;
import static java.lang.System.*;
public class Export {
public static void main(String[] args){
for (final String tag : emptyTags()) {
out.print("EMPTY-ELEMENT[");
out.print(tag);
out.print("]");
out.println();
}
for (final String tag : containerTags()) {
out.print("ELEMENT[");
out.print(tag);
out.print("]");
out.println();
}
out.println();
for(AttrD attr : attributesDescriptive()){
if(attr.hasArgument){
out.print("STRING");
}else{
out.print("BOOLEAN");
}
out.print("[");
out.print(attr.attr);
out.print("]");
out.println();
for(String tag : attr.tags){
out.print("ATTRIBUTE[");
out.print(tag);
out.print(":");
out.print(attr.attr);
out.print("]");
out.println();
}
out.println();
}
}
}

View File

@@ -0,0 +1,199 @@
package com.j2html.codegen;
import com.j2html.codegen.Model.Node;
import com.squareup.javapoet.*;
import javax.lang.model.element.Modifier;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import static com.j2html.codegen.Model.Metadata.ON_OFF;
import static com.j2html.codegen.Model.Metadata.SELF_CLOSING;
public class Generator {
public static final ClassName INSTANCE = ClassName.get("j2html.tags", "IInstance");
public static final ClassName TAG = ClassName.get("j2html.tags", "Tag");
public static final ClassName EMPTY_TAG = ClassName.get("j2html.tags", "EmptyTag");
public static final ClassName CONTAINER_TAG = ClassName.get("j2html.tags", "ContainerTag");
public static void main(String... args) throws IOException {
Path path = Paths.get("j2html-codegen", "src", "test", "resources", "html.model");
String definitions = new String(Files.readAllBytes(path));
Model model = new Model();
Parser.parse(definitions, model);
Path dir = Paths.get("/j2html/generated-source");
Files.createDirectories(dir);
generate(dir, "j2html.tags.attributes", "j2html.tags.specialized", model);
}
public static void generate(Path root, String attributePkg, String elementPkg, Model model) throws IOException {
Map<String, JavaFile> attributes = generateAttributePackage(attributePkg, model);
for (JavaFile file : attributes.values()) {
file.writeTo(root);
}
Map<String, JavaFile> elements = generateElementPackage(elementPkg, model, attributes);
for (JavaFile file : elements.values()) {
file.writeTo(root);
}
}
private static Map<String, JavaFile> generateElementPackage(String pkg, Model model, Map<String, JavaFile> attributes) {
Map<String, JavaFile> files = new HashMap<>();
// Convert all elements into classes.
for (Node element : model.elements()) {
ClassName className = ClassName.get(pkg, capitalize(element.name) + "Tag");
TypeSpec.Builder type = defineElementClass(element, className);
// Assign attributes to this element.
for (Node attribute : element.children) {
JavaFile file = attributes.get(attribute.name);
type.addSuperinterface(
ParameterizedTypeName.get(
ClassName.get(file.packageName, file.typeSpec.name),
className
)
);
}
files.put(
element.name,
JavaFile.builder(pkg, type.build())
.skipJavaLangImports(true)
.build()
);
}
return files;
}
private static Map<String, JavaFile> generateAttributePackage(String pkg, Model model) {
Map<String, JavaFile> files = new HashMap<>();
// Convert all attributes into classes.
for (Node attribute : model.attributes()) {
TypeSpec.Builder type = defineAttributeClass(pkg, attribute);
if (attribute.type.equals(Node.Type.STRING)) {
defineStringAttributeMethods(attribute, type);
} else if (attribute.type.equals(Node.Type.BOOLEAN) && !attribute.is(ON_OFF)) {
defineBooleanAttributeMethods(attribute, type);
} else if (attribute.type.equals(Node.Type.BOOLEAN) && attribute.is(ON_OFF)) {
defineOnOffAttributeMethods(attribute, type);
}
files.put(
attribute.name,
JavaFile.builder(pkg, type.build())
.skipJavaLangImports(true)
.build()
);
}
return files;
}
private static TypeSpec.Builder defineElementClass(Node element, ClassName className) {
MethodSpec constructor = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addStatement("super(\"" + element.name + "\")")
.build();
TypeSpec.Builder type = TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC)
.superclass(
ParameterizedTypeName.get(element.is(SELF_CLOSING) ? EMPTY_TAG : CONTAINER_TAG, className)
)
.addMethod(constructor);
return type;
}
private static TypeSpec.Builder defineAttributeClass(String pkg, Node attribute) {
ClassName name = ClassName.get(pkg, "I" + capitalize(attribute.name));
return TypeSpec.interfaceBuilder(name)
.addSuperinterface(ParameterizedTypeName.get(INSTANCE, TypeVariableName.get("T")))
.addTypeVariable(TypeVariableName.get("T", ParameterizedTypeName.get(TAG, TypeVariableName.get("T"))))
.addModifiers(Modifier.PUBLIC);
}
private static void defineBooleanAttributeMethods(Node attribute, TypeSpec.Builder type) {
MethodSpec with = MethodSpec.methodBuilder(methodName("is", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addStatement("return self().attr(\"" + attribute.name + "\")")
.returns(TypeVariableName.get("T"))
.build();
MethodSpec withCond = MethodSpec.methodBuilder(methodName("withCond", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addParameter(TypeName.BOOLEAN, "enable", Modifier.FINAL)
.addStatement("return enable ? self().attr(\"" + attribute.name + "\") : self()")
.returns(TypeVariableName.get("T"))
.build();
type.addMethod(with);
type.addMethod(withCond);
}
private static void defineOnOffAttributeMethods(Node attribute, TypeSpec.Builder type) {
MethodSpec with = MethodSpec.methodBuilder(methodName("is", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addStatement("return self().attr(\"" + attribute.name + "\", \"on\")")
.returns(TypeVariableName.get("T"))
.build();
MethodSpec withCond = MethodSpec.methodBuilder(methodName("withCond", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addParameter(TypeName.BOOLEAN, "enable", Modifier.FINAL)
.addStatement("return enable ? self().attr(\"" + attribute.name + "\", \"on\") : self()")
.returns(TypeVariableName.get("T"))
.build();
type.addMethod(with);
type.addMethod(withCond);
}
private static void defineStringAttributeMethods(Node attribute, TypeSpec.Builder type) {
MethodSpec with = MethodSpec.methodBuilder(methodName("with", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addParameter(String.class, parameter(attribute), Modifier.FINAL)
.addStatement("return self().attr(\"" + attribute.name + "\", " + parameter(attribute) + ")")
.returns(TypeVariableName.get("T"))
.build();
MethodSpec withCond = MethodSpec.methodBuilder(methodName("withCond", attribute.name))
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addParameter(TypeName.BOOLEAN, "enable", Modifier.FINAL)
.addParameter(String.class, parameter(attribute), Modifier.FINAL)
.addStatement("return enable ? self().attr(\"" + attribute.name + "\", " + parameter(attribute) + ") : self()")
.returns(TypeVariableName.get("T"))
.build();
type.addMethod(with);
type.addMethod(withCond);
}
private static String parameter(Node attribute) {
return attribute.name + "_";
}
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

@@ -1,4 +1,4 @@
package j2html_codegen;
package com.j2html.codegen;
import java.io.File;
import java.io.IOException;

View File

@@ -0,0 +1,65 @@
package com.j2html.codegen;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@Mojo(name = "generate-source-files", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class J2htmlCodeGeneratorMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;
@Parameter(property = "modelFile", required = true)
String modelFile;
@Parameter(property = "attributePackage", required = true)
String attributePackage;
@Parameter(property = "tagPackage", required = true)
String tagPackage;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().debug("Model File: " + modelFile);
getLog().debug("Attribute Package: " + attributePackage);
getLog().debug("Tag Package: " + tagPackage);
String outputDirectory = project.getBuild().getDirectory() + "/generated-sources/j2html-codegen";
project.addCompileSourceRoot(outputDirectory);
getLog().debug("Generating J2Html sources in: " + outputDirectory);
String definitions;
try {
definitions = new String(Files.readAllBytes(Paths.get(modelFile)));
} catch (IOException e) {
throw new MojoFailureException("Unable to locate model file: " + modelFile, e);
}
Model model = new Model();
try {
Parser.parse(definitions, model);
}catch (RuntimeException e){
throw new MojoFailureException("Unable to parse model file.", e);
}
try {
Generator.generate(
Paths.get(outputDirectory).toAbsolutePath(),
attributePackage,
tagPackage,
model
);
} catch (IOException e) {
throw new MojoFailureException("Failed to generate source files.", e);
}
}
}

View File

@@ -0,0 +1,171 @@
package com.j2html.codegen;
import java.util.*;
import static com.j2html.codegen.Model.Metadata.ON_OFF;
import static com.j2html.codegen.Model.Metadata.SELF_CLOSING;
import static com.j2html.codegen.Model.Node.Type.*;
public class Model implements Parser.Listener {
private Map<String, Node> elements;
private Map<String, Node> attributes;
public Model() {
elements = new LinkedHashMap<>();
attributes = new LinkedHashMap<>();
}
public Collection<Node> elements(){
return elements.values();
}
public Collection<Node> attributes(){
return attributes.values();
}
public Node addElement(String name) {
return add(ELEMENT, name, elements);
}
public Node addBooleanAttribute(String name) {
return add(BOOLEAN, name, attributes);
}
public Node addStringAttribute(String name) {
return add(STRING, name, attributes);
}
public Node element(String name) {
if (!elements.containsKey(name)) {
throw new NodeDoesNotExist(name);
}
return elements.get(name);
}
public Node attribute(String name) {
if (!attributes.containsKey(name)) {
throw new NodeDoesNotExist(name);
}
return attributes.get(name);
}
private Node add(Node.Type type, String name, Map<String, Node> nodes) {
if (nodes.containsKey(name)) {
throw new NodeAlreadyExists(name);
}
Node node = new Node(type, name);
nodes.put(name, node);
return node;
}
@Override
public void lineCommented(int line, String txt) {
// Ignore.
}
@Override
public void elementDefined(int line, String name) {
attempt(() -> addElement(name), line);
}
@Override
public void emptyElementDefined(int line, String name) {
attempt(() -> addElement(name).annotate(SELF_CLOSING), line);
}
@Override
public void booleanDefined(int line, String name) {
attempt(() -> addBooleanAttribute(name), line);
}
@Override
public void onOffDefined(int line, String name) {
attempt(() -> addBooleanAttribute(name).annotate(ON_OFF), line);
}
@Override
public void stringDefined(int line, String name) {
attempt(() -> addStringAttribute(name), line);
}
@Override
public void attributeDefined(int line, String element, String name) {
attempt(() -> element(element).addChild(attribute(name)), line);
}
@Override
public void invalidLine(int line, String txt) {
throw new RuntimeException("Invalid line [" + line + "]: " + txt);
}
@FunctionalInterface
private interface Unsafe {
void call() throws RuntimeException;
}
private void attempt(Unsafe operation, int line) {
try {
operation.call();
} catch (RuntimeException e) {
throw new InvalidModel(e, line);
}
}
public static class Node {
enum Type {
ELEMENT,
BOOLEAN,
STRING
}
public final Type type;
public final String name;
public final List<Metadata> metadata;
public final List<Node> children;
private Node(Type type, String name) {
this.type = type;
this.name = name;
this.metadata = new ArrayList<>();
this.children = new ArrayList<>();
}
public void annotate(Metadata meta) {
metadata.add(meta);
}
public void addChild(Node node) {
children.add(node);
}
public boolean is(Metadata annotation){
return metadata.contains(annotation);
}
}
public enum Metadata {
SELF_CLOSING,
ON_OFF,
OBSOLETE
}
public static class InvalidModel extends RuntimeException {
public InvalidModel(Exception cause, int line) {
super(cause.getMessage() + ". At line " + line, cause);
}
}
public static class NodeAlreadyExists extends RuntimeException {
public NodeAlreadyExists(String name) {
super("Node already exists: " + name);
}
}
public static class NodeDoesNotExist extends RuntimeException {
public NodeDoesNotExist(String name) {
super("Node does not exist: " + name);
}
}
}

View File

@@ -0,0 +1,91 @@
package com.j2html.codegen;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Parser {
private static final Pattern EMPTY_LINE_PATTERN = Pattern.compile("\\s*");
private static final Pattern COMMENT_PATTERN = Pattern.compile("#.*");
private static final Pattern NODE_PATTERN = Pattern.compile("(?<type>ELEMENT|EMPTY-ELEMENT|BOOLEAN|ONOFF|STRING)\\[(?<name>\\S+)\\]");
private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile("ATTRIBUTE\\[(?<element>\\S+):(?<name>\\S+)\\]");
public interface Listener {
void lineCommented(int line, String txt);
void elementDefined(int line, String name);
void emptyElementDefined(int line, String name);
void booleanDefined(int line, String name);
void onOffDefined(int line, String name);
void stringDefined(int line, String name);
void attributeDefined(int line, String element, String name);
void invalidLine(int line, String txt);
}
public static void parse(String txt, Listener listener) {
String[] lines = txt.split("[\r\n]+");
for (int i = 0; i < lines.length; i++) {
int number = i + 1;
String line = lines[i];
if (match(EMPTY_LINE_PATTERN, line)) continue;
if (match(COMMENT_PATTERN, line, matcher -> {
listener.lineCommented(number, line);
})) continue;
if (match(NODE_PATTERN, line, matcher -> {
String type = matcher.group("type");
String name = matcher.group("name");
switch (type) {
case "ELEMENT":
listener.elementDefined(number, name);
break;
case "EMPTY-ELEMENT":
listener.emptyElementDefined(number, name);
break;
case "BOOLEAN":
listener.booleanDefined(number, name);
break;
case "ONOFF":
listener.onOffDefined(number, name);
break;
case "STRING":
listener.stringDefined(number, name);
break;
}
})) continue;
if (match(ATTRIBUTE_PATTERN, line, matcher -> {
listener.attributeDefined(
number,
matcher.group("element"),
matcher.group("name")
);
})) continue;
listener.invalidLine(number, line);
}
}
private static boolean match(Pattern pattern, String txt) {
return pattern.matcher(txt).matches();
}
private static boolean match(Pattern pattern, String txt, Consumer<Matcher> onMatch) {
Matcher matcher = pattern.matcher(txt);
if (matcher.matches()) {
onMatch.accept(matcher);
return true;
}
return false;
}
}

View File

@@ -1,8 +1,9 @@
package j2html_codegen.generators;
package com.j2html.codegen.generators;
import com.j2html.codegen.GeneratorUtil;
import com.j2html.codegen.model.AttrD;
import com.j2html.codegen.model.AttributesList;
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;

View File

@@ -1,8 +1,8 @@
package j2html_codegen.generators;
package com.j2html.codegen.generators;
import j2html_codegen.GeneratorUtil;
import j2html_codegen.model.AttributesList;
import com.j2html.codegen.GeneratorUtil;
import com.j2html.codegen.model.AttributesList;
import java.io.IOException;
import java.nio.file.Files;
@@ -13,8 +13,8 @@ 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;
import static com.j2html.codegen.generators.TagCreatorCodeGenerator.containerTags;
import static com.j2html.codegen.generators.TagCreatorCodeGenerator.emptyTags;
public final class SpecializedTagClassCodeGenerator {

View File

@@ -1,4 +1,4 @@
package j2html_codegen.generators;
package com.j2html.codegen.generators;
import java.util.Arrays;
import java.util.List;
@@ -63,7 +63,7 @@ public final class TagCreatorCodeGenerator {
}
// This is a method that contains all ContainerTags, there is nothing below it
static List<String> emptyTags() {
public static List<String> emptyTags() {
return Arrays.asList(
"area",
"base",
@@ -84,7 +84,7 @@ public final class TagCreatorCodeGenerator {
);
}
static List<String> containerTags() {
public static List<String> containerTags() {
return Arrays.asList(
"a",
"abbr",
@@ -103,6 +103,7 @@ public final class TagCreatorCodeGenerator {
"cite",
"code",
"colgroup",
"data",
"datalist",
"dd",
"del",
@@ -134,7 +135,6 @@ public final class TagCreatorCodeGenerator {
"label",
"legend",
"li",
"generate",
"main",
"map",
"mark",
@@ -149,6 +149,7 @@ public final class TagCreatorCodeGenerator {
"option",
"output",
"p",
"picture",
"pre",
"progress",
"q",
@@ -160,6 +161,7 @@ public final class TagCreatorCodeGenerator {
"script",
"section",
"select",
"slot",
"small",
"span",
"strong",
@@ -170,6 +172,7 @@ public final class TagCreatorCodeGenerator {
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",

View File

@@ -0,0 +1,94 @@
package com.j2html.codegen.generators;
import com.j2html.codegen.wattsi.AttributeDefinition;
import com.j2html.codegen.wattsi.ElementDefinition;
import com.j2html.codegen.wattsi.WattsiSource;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
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

@@ -1,4 +1,4 @@
package j2html_codegen.model;
package com.j2html.codegen.model;
public final class AttrD {
//attribute descriptor

View File

@@ -1,4 +1,4 @@
package j2html_codegen.model;
package com.j2html.codegen.model;
import java.util.ArrayList;
import java.util.Arrays;
@@ -80,7 +80,7 @@ public final class AttributesList {
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","textarea"),
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"),
@@ -174,7 +174,7 @@ public final class AttributesList {
//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","input","li","option","meter","progress","param"),
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 com.j2html.codegen.wattsi;
public interface AttributeDefinition {
String name();
boolean appliesTo(ElementDefinition element);
boolean isObsolete();
}

View File

@@ -0,0 +1,11 @@
package com.j2html.codegen.wattsi;
public interface ElementDefinition {
String name();
boolean isSelfClosing();
boolean isObsolete();
}

View File

@@ -0,0 +1,209 @@
package com.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 isSelfClosing() {
return false;
}
@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

@@ -1,4 +1,4 @@
package j2html_codegen;
package com.j2html.codegen;
import static org.junit.Assert.assertTrue;

View File

@@ -0,0 +1,77 @@
package com.j2html.codegen;
import com.j2html.codegen.generators.TagCreatorCodeGenerator;
import com.j2html.codegen.wattsi.ElementDefinition;
import com.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);
}
}

View File

@@ -0,0 +1,69 @@
package com.j2html.codegen;
import org.junit.Test;
import org.mockito.InOrder;
import java.util.function.Consumer;
import static org.mockito.Mockito.*;
public class ParserTest {
private void verifyParsing(String txt, Consumer<Parser.Listener> checks) {
Parser.Listener listener = mock(Parser.Listener.class);
Parser.parse(txt, listener);
checks.accept(listener);
}
@Test
public void an_empty_input_has_no_events() {
verifyParsing("", listener -> {
verifyNoInteractions(listener);
});
}
@Test
public void whitespace_has_no_events() {
verifyParsing(" \t\t\t\t", listener -> {
verifyNoInteractions(listener);
});
}
@Test
public void commented_lines_are_signaled() {
verifyParsing("#Comment 1.\n# Comment B?", listener -> {
InOrder order = inOrder(listener);
order.verify(listener).lineCommented(1, "#Comment 1.");
order.verify(listener).lineCommented(2, "# Comment B?");
});
}
@Test
public void node_definitions_are_signaled() {
verifyParsing("ELEMENT[a]\nEMPTY-ELEMENT[b]\nBOOLEAN[c]\nONOFF[d]\nSTRING[e]", listener -> {
InOrder order = inOrder(listener);
order.verify(listener).elementDefined(1, "a");
order.verify(listener).emptyElementDefined(2, "b");
order.verify(listener).booleanDefined(3, "c");
order.verify(listener).onOffDefined(4, "d");
order.verify(listener).stringDefined(5, "e");
});
}
@Test
public void attribute_definitions_are_signaled() {
verifyParsing("ATTRIBUTE[a:b]", listener -> {
InOrder order = inOrder(listener);
order.verify(listener).attributeDefined(1, "a", "b");
});
}
@Test
public void invalid_lines_are_signaled() {
verifyParsing("lol, I dunno!\nIt Broke...", listener -> {
InOrder order = inOrder(listener);
order.verify(listener).invalidLine(1, "lol, I dunno!");
order.verify(listener).invalidLine(2, "It Broke...");
});
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,622 @@
EMPTY-ELEMENT[area]
EMPTY-ELEMENT[base]
EMPTY-ELEMENT[br]
EMPTY-ELEMENT[col]
EMPTY-ELEMENT[embed]
EMPTY-ELEMENT[hr]
EMPTY-ELEMENT[img]
EMPTY-ELEMENT[input]
EMPTY-ELEMENT[keygen]
EMPTY-ELEMENT[link]
EMPTY-ELEMENT[meta]
EMPTY-ELEMENT[param]
EMPTY-ELEMENT[source]
EMPTY-ELEMENT[track]
EMPTY-ELEMENT[wbr]
ELEMENT[a]
ELEMENT[abbr]
ELEMENT[address]
ELEMENT[article]
ELEMENT[aside]
ELEMENT[audio]
ELEMENT[b]
ELEMENT[bdi]
ELEMENT[bdo]
ELEMENT[blockquote]
ELEMENT[body]
ELEMENT[button]
ELEMENT[canvas]
ELEMENT[caption]
ELEMENT[cite]
ELEMENT[code]
ELEMENT[colgroup]
ELEMENT[data]
ELEMENT[datalist]
ELEMENT[dd]
ELEMENT[del]
ELEMENT[details]
ELEMENT[dfn]
ELEMENT[dialog]
ELEMENT[div]
ELEMENT[dl]
ELEMENT[dt]
ELEMENT[em]
ELEMENT[fieldset]
ELEMENT[figcaption]
ELEMENT[figure]
ELEMENT[footer]
ELEMENT[form]
ELEMENT[h1]
ELEMENT[h2]
ELEMENT[h3]
ELEMENT[h4]
ELEMENT[h5]
ELEMENT[h6]
ELEMENT[head]
ELEMENT[header]
ELEMENT[html]
ELEMENT[i]
ELEMENT[iframe]
ELEMENT[ins]
ELEMENT[kbd]
ELEMENT[label]
ELEMENT[legend]
ELEMENT[li]
ELEMENT[main]
ELEMENT[map]
ELEMENT[mark]
ELEMENT[menu]
ELEMENT[menuitem]
ELEMENT[meter]
ELEMENT[nav]
ELEMENT[noscript]
ELEMENT[object]
ELEMENT[ol]
ELEMENT[optgroup]
ELEMENT[option]
ELEMENT[output]
ELEMENT[p]
ELEMENT[picture]
ELEMENT[pre]
ELEMENT[progress]
ELEMENT[q]
ELEMENT[rp]
ELEMENT[rt]
ELEMENT[ruby]
ELEMENT[s]
ELEMENT[samp]
ELEMENT[script]
ELEMENT[section]
ELEMENT[select]
ELEMENT[slot]
ELEMENT[small]
ELEMENT[span]
ELEMENT[strong]
ELEMENT[style]
ELEMENT[sub]
ELEMENT[summary]
ELEMENT[sup]
ELEMENT[table]
ELEMENT[tbody]
ELEMENT[td]
ELEMENT[template]
ELEMENT[textarea]
ELEMENT[tfoot]
ELEMENT[th]
ELEMENT[thead]
ELEMENT[time]
ELEMENT[title]
ELEMENT[tr]
ELEMENT[u]
ELEMENT[ul]
ELEMENT[var]
ELEMENT[video]
STRING[accept]
ATTRIBUTE[input:accept]
STRING[action]
ATTRIBUTE[form:action]
STRING[alt]
ATTRIBUTE[area:alt]
ATTRIBUTE[img:alt]
ATTRIBUTE[input:alt]
BOOLEAN[async]
ATTRIBUTE[script:async]
ONOFF[autocomplete]
ATTRIBUTE[form:autocomplete]
ATTRIBUTE[input:autocomplete]
BOOLEAN[autofocus]
ATTRIBUTE[button:autofocus]
ATTRIBUTE[input:autofocus]
ATTRIBUTE[select:autofocus]
ATTRIBUTE[textarea:autofocus]
BOOLEAN[autoplay]
ATTRIBUTE[audio:autoplay]
ATTRIBUTE[video:autoplay]
STRING[charset]
ATTRIBUTE[meta:charset]
ATTRIBUTE[script:charset]
BOOLEAN[checked]
ATTRIBUTE[input:checked]
STRING[cite]
ATTRIBUTE[blockquote:cite]
ATTRIBUTE[del:cite]
ATTRIBUTE[ins:cite]
ATTRIBUTE[q:cite]
STRING[cols]
ATTRIBUTE[textarea:cols]
STRING[colspan]
ATTRIBUTE[td:colspan]
ATTRIBUTE[th:colspan]
STRING[content]
ATTRIBUTE[meta:content]
BOOLEAN[controls]
ATTRIBUTE[audio:controls]
ATTRIBUTE[video:controls]
STRING[coords]
ATTRIBUTE[area:coords]
STRING[data]
ATTRIBUTE[object:data]
STRING[datetime]
ATTRIBUTE[del:datetime]
ATTRIBUTE[ins:datetime]
ATTRIBUTE[time:datetime]
BOOLEAN[default]
ATTRIBUTE[track:default]
BOOLEAN[defer]
ATTRIBUTE[script:defer]
STRING[dirname]
ATTRIBUTE[input:dirname]
ATTRIBUTE[textarea:dirname]
BOOLEAN[disabled]
ATTRIBUTE[button:disabled]
ATTRIBUTE[fieldset:disabled]
ATTRIBUTE[input:disabled]
ATTRIBUTE[optgroup:disabled]
ATTRIBUTE[option:disabled]
ATTRIBUTE[select:disabled]
ATTRIBUTE[textarea:disabled]
BOOLEAN[download]
ATTRIBUTE[a:download]
ATTRIBUTE[area:download]
STRING[enctype]
ATTRIBUTE[form:enctype]
STRING[for]
ATTRIBUTE[label:for]
ATTRIBUTE[output:for]
STRING[form]
ATTRIBUTE[button:form]
ATTRIBUTE[fieldset:form]
ATTRIBUTE[input:form]
ATTRIBUTE[label:form]
ATTRIBUTE[meter:form]
ATTRIBUTE[object:form]
ATTRIBUTE[output:form]
ATTRIBUTE[select:form]
ATTRIBUTE[textarea:form]
STRING[formaction]
ATTRIBUTE[button:formaction]
ATTRIBUTE[input:formaction]
STRING[headers]
ATTRIBUTE[td:headers]
ATTRIBUTE[th:headers]
STRING[height]
ATTRIBUTE[canvas:height]
ATTRIBUTE[embed:height]
ATTRIBUTE[iframe:height]
ATTRIBUTE[img:height]
ATTRIBUTE[input:height]
ATTRIBUTE[object:height]
ATTRIBUTE[video:height]
STRING[high]
ATTRIBUTE[meter:high]
STRING[href]
ATTRIBUTE[a:href]
ATTRIBUTE[area:href]
ATTRIBUTE[base:href]
ATTRIBUTE[link:href]
STRING[hreflang]
ATTRIBUTE[a:hreflang]
ATTRIBUTE[area:hreflang]
ATTRIBUTE[link:hreflang]
BOOLEAN[ismap]
ATTRIBUTE[img:ismap]
STRING[kind]
ATTRIBUTE[track:kind]
STRING[label]
ATTRIBUTE[track:label]
ATTRIBUTE[option:label]
ATTRIBUTE[optgroup:label]
STRING[list]
ATTRIBUTE[input:list]
BOOLEAN[loop]
ATTRIBUTE[audio:loop]
ATTRIBUTE[video:loop]
STRING[low]
ATTRIBUTE[meter:low]
STRING[max]
ATTRIBUTE[input:max]
ATTRIBUTE[meter:max]
ATTRIBUTE[progress:max]
STRING[maxlength]
ATTRIBUTE[input:maxlength]
ATTRIBUTE[textarea:maxlength]
STRING[media]
ATTRIBUTE[a:media]
ATTRIBUTE[area:media]
ATTRIBUTE[link:media]
ATTRIBUTE[source:media]
ATTRIBUTE[style:media]
STRING[method]
ATTRIBUTE[form:method]
STRING[min]
ATTRIBUTE[input:min]
ATTRIBUTE[meter:min]
BOOLEAN[multiple]
ATTRIBUTE[input:multiple]
ATTRIBUTE[select:multiple]
BOOLEAN[muted]
ATTRIBUTE[video:muted]
ATTRIBUTE[audio:muted]
STRING[name]
ATTRIBUTE[button:name]
ATTRIBUTE[fieldset:name]
ATTRIBUTE[form:name]
ATTRIBUTE[iframe:name]
ATTRIBUTE[input:name]
ATTRIBUTE[map:name]
ATTRIBUTE[meta:name]
ATTRIBUTE[object:name]
ATTRIBUTE[output:name]
ATTRIBUTE[param:name]
ATTRIBUTE[select:name]
ATTRIBUTE[slot:name]
ATTRIBUTE[textarea:name]
BOOLEAN[novalidate]
ATTRIBUTE[form:novalidate]
STRING[onabort]
ATTRIBUTE[audio:onabort]
ATTRIBUTE[embed:onabort]
ATTRIBUTE[img:onabort]
ATTRIBUTE[object:onabort]
ATTRIBUTE[video:onabort]
STRING[onafterprint]
ATTRIBUTE[body:onafterprint]
STRING[onbeforeprint]
ATTRIBUTE[body:onbeforeprint]
STRING[onbeforeunload]
ATTRIBUTE[body:onbeforeunload]
STRING[oncanplay]
ATTRIBUTE[audio:oncanplay]
ATTRIBUTE[embed:oncanplay]
ATTRIBUTE[object:oncanplay]
ATTRIBUTE[video:oncanplay]
STRING[oncanplaythrough]
ATTRIBUTE[audio:oncanplaythrough]
ATTRIBUTE[video:oncanplaythrough]
STRING[oncuechange]
ATTRIBUTE[track:oncuechange]
STRING[ondurationchange]
ATTRIBUTE[audio:ondurationchange]
ATTRIBUTE[video:ondurationchange]
STRING[onemptied]
ATTRIBUTE[audio:onemptied]
ATTRIBUTE[video:onemptied]
STRING[onended]
ATTRIBUTE[audio:onended]
ATTRIBUTE[video:onended]
STRING[onerror]
ATTRIBUTE[audio:onerror]
ATTRIBUTE[body:onerror]
ATTRIBUTE[embed:onerror]
ATTRIBUTE[img:onerror]
ATTRIBUTE[object:onerror]
ATTRIBUTE[script:onerror]
ATTRIBUTE[style:onerror]
ATTRIBUTE[video:onerror]
STRING[onhashchange]
ATTRIBUTE[body:onhashchange]
STRING[onload]
ATTRIBUTE[body:onload]
ATTRIBUTE[iframe:onload]
ATTRIBUTE[img:onload]
ATTRIBUTE[input:onload]
ATTRIBUTE[link:onload]
ATTRIBUTE[script:onload]
ATTRIBUTE[style:onload]
STRING[onloadeddata]
ATTRIBUTE[audio:onloadeddata]
ATTRIBUTE[video:onloadeddata]
STRING[onloadedmetadata]
ATTRIBUTE[audio:onloadedmetadata]
ATTRIBUTE[video:onloadedmetadata]
STRING[onloadstart]
ATTRIBUTE[audio:onloadstart]
ATTRIBUTE[video:onloadstart]
STRING[onoffline]
ATTRIBUTE[body:onoffline]
STRING[ononline]
ATTRIBUTE[body:ononline]
STRING[onpagehide]
ATTRIBUTE[body:onpagehide]
STRING[onpageshow]
ATTRIBUTE[body:onpageshow]
STRING[onpause]
ATTRIBUTE[audio:onpause]
ATTRIBUTE[video:onpause]
STRING[onplay]
ATTRIBUTE[audio:onplay]
ATTRIBUTE[video:onplay]
STRING[onplaying]
ATTRIBUTE[audio:onplaying]
ATTRIBUTE[video:onplaying]
STRING[onpopstate]
ATTRIBUTE[body:onpopstate]
STRING[onprogress]
ATTRIBUTE[audio:onprogress]
ATTRIBUTE[video:onprogress]
STRING[onratechange]
ATTRIBUTE[audio:onratechange]
ATTRIBUTE[video:onratechange]
STRING[onreset]
ATTRIBUTE[form:onreset]
STRING[onresize]
ATTRIBUTE[body:onresize]
STRING[onsearch]
ATTRIBUTE[input:onsearch]
STRING[onseeked]
ATTRIBUTE[audio:onseeked]
ATTRIBUTE[video:onseeked]
STRING[onseeking]
ATTRIBUTE[audio:onseeking]
ATTRIBUTE[video:onseeking]
STRING[onstalled]
ATTRIBUTE[audio:onstalled]
ATTRIBUTE[video:onstalled]
STRING[onstorage]
ATTRIBUTE[body:onstorage]
STRING[onsubmit]
ATTRIBUTE[form:onsubmit]
STRING[onsuspend]
ATTRIBUTE[audio:onsuspend]
ATTRIBUTE[video:onsuspend]
STRING[ontimeupdate]
ATTRIBUTE[audio:ontimeupdate]
ATTRIBUTE[video:ontimeupdate]
STRING[ontoggle]
ATTRIBUTE[details:ontoggle]
STRING[onunload]
ATTRIBUTE[body:onunload]
STRING[onvolumechanged]
ATTRIBUTE[audio:onvolumechanged]
ATTRIBUTE[video:onvolumechanged]
STRING[onwaiting]
ATTRIBUTE[audio:onwaiting]
ATTRIBUTE[video:onwaiting]
BOOLEAN[open]
ATTRIBUTE[details:open]
STRING[optimum]
ATTRIBUTE[meter:optimum]
STRING[pattern]
ATTRIBUTE[input:pattern]
STRING[placeholder]
ATTRIBUTE[input:placeholder]
ATTRIBUTE[textarea:placeholder]
STRING[poster]
ATTRIBUTE[video:poster]
STRING[preload]
ATTRIBUTE[audio:preload]
ATTRIBUTE[video:preload]
BOOLEAN[readonly]
ATTRIBUTE[input:readonly]
ATTRIBUTE[textarea:readonly]
STRING[rel]
ATTRIBUTE[a:rel]
ATTRIBUTE[area:rel]
ATTRIBUTE[form:rel]
ATTRIBUTE[link:rel]
BOOLEAN[required]
ATTRIBUTE[input:required]
ATTRIBUTE[select:required]
ATTRIBUTE[textarea:required]
BOOLEAN[reversed]
ATTRIBUTE[ol:reversed]
STRING[rows]
ATTRIBUTE[textarea:rows]
STRING[rowspan]
ATTRIBUTE[td:rowspan]
ATTRIBUTE[th:rowspan]
BOOLEAN[sandbox]
ATTRIBUTE[iframe:sandbox]
STRING[scope]
ATTRIBUTE[th:scope]
BOOLEAN[selected]
ATTRIBUTE[option:selected]
STRING[shape]
ATTRIBUTE[area:shape]
STRING[size]
ATTRIBUTE[input:size]
ATTRIBUTE[select:size]
STRING[sizes]
ATTRIBUTE[img:sizes]
ATTRIBUTE[link:sizes]
ATTRIBUTE[source:sizes]
STRING[span]
ATTRIBUTE[col:span]
ATTRIBUTE[colgroup:span]
STRING[src]
ATTRIBUTE[audio:src]
ATTRIBUTE[embed:src]
ATTRIBUTE[iframe:src]
ATTRIBUTE[img:src]
ATTRIBUTE[input:src]
ATTRIBUTE[script:src]
ATTRIBUTE[source:src]
ATTRIBUTE[track:src]
ATTRIBUTE[video:src]
STRING[srcdoc]
ATTRIBUTE[iframe:srcdoc]
STRING[srclang]
ATTRIBUTE[track:srclang]
STRING[srcset]
ATTRIBUTE[img:srcset]
ATTRIBUTE[source:srcset]
STRING[start]
ATTRIBUTE[ol:start]
STRING[step]
ATTRIBUTE[input:step]
STRING[target]
ATTRIBUTE[a:target]
ATTRIBUTE[area:target]
ATTRIBUTE[base:target]
ATTRIBUTE[form:target]
STRING[type]
ATTRIBUTE[a:type]
ATTRIBUTE[button:type]
ATTRIBUTE[embed:type]
ATTRIBUTE[input:type]
ATTRIBUTE[link:type]
ATTRIBUTE[menu:type]
ATTRIBUTE[object:type]
ATTRIBUTE[script:type]
ATTRIBUTE[source:type]
ATTRIBUTE[style:type]
STRING[usemap]
ATTRIBUTE[img:usemap]
ATTRIBUTE[object:usemap]
STRING[value]
ATTRIBUTE[button:value]
ATTRIBUTE[data:value]
ATTRIBUTE[input:value]
ATTRIBUTE[li:value]
ATTRIBUTE[option:value]
ATTRIBUTE[meter:value]
ATTRIBUTE[progress:value]
ATTRIBUTE[param:value]
STRING[width]
ATTRIBUTE[canvas:width]
ATTRIBUTE[embed:width]
ATTRIBUTE[iframe:width]
ATTRIBUTE[img:width]
ATTRIBUTE[input:width]
ATTRIBUTE[object:width]
ATTRIBUTE[video:width]
STRING[wrap]
ATTRIBUTE[textarea:wrap]

130
j2html-ext-mathml/pom.xml Normal file
View File

@@ -0,0 +1,130 @@
<?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>com.j2html</groupId>
<artifactId>j2html-parent</artifactId>
<version>1.6.1-SNAPSHOT</version>
</parent>
<name>j2html-ext-mathml</name>
<artifactId>j2html-ext-mathml</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.6.1-SNAPSHOT</version>
</dependency>
</dependencies>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>com.j2html</groupId>
<artifactId>j2html-codegen-maven-plugin</artifactId>
<version>1.6.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>generate-source-files</goal>
</goals>
</execution>
</executions>
<configuration>
<modelFile>${project.basedir}/src/main/models/mathml.model</modelFile>
<attributePackage>com.j2html.mathml.attributes</attributePackage>
<tagPackage>com.j2html.mathml.tags</tagPackage>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<goals>
<goal>perform</goal>
</goals>
<configuration>
<pomFileName>pom.xml</pomFileName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<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>
<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>
<configuration>
<oldArtifacts>
<artifact>com.j2html:j2html-ext-mathml:1.6.0</artifact>
</oldArtifacts>
<analysisConfiguration>
<revapi.differences>
<differences>
</differences>
</revapi.differences>
</analysisConfiguration>
</configuration>
</plugin-->
</plugins>
</build>
</project>

View File

@@ -0,0 +1,247 @@
package com.j2html.mathml;
import com.j2html.mathml.tags.*;
import j2html.tags.DomContent;
public class MathML {
public static AnnotationTag annotation(String text) {
return new AnnotationTag().withText(text);
}
public static AnnotationTag annotation(DomContent... dc) {
return new AnnotationTag().with(dc);
}
public static MactionTag maction(String text) {
return new MactionTag().withText(text);
}
public static MactionTag maction(DomContent... dc) {
return new MactionTag().with(dc);
}
public static MathTag math(String text) {
return new MathTag().withText(text);
}
public static MathTag math(DomContent... dc) {
return new MathTag().with(dc);
}
public static MerrorTag merror(String text) {
return new MerrorTag().withText(text);
}
public static MerrorTag merror(DomContent... dc) {
return new MerrorTag().with(dc);
}
public static MfracTag mfrac(String text) {
return new MfracTag().withText(text);
}
public static MfracTag mfrac(DomContent... dc) {
return new MfracTag().with(dc);
}
public static MiTag mi(String text) {
return new MiTag().withText(text);
}
public static MiTag mi(DomContent... dc) {
return new MiTag().with(dc);
}
public static MmultiscriptsTag mmultiscripts(String text) {
return new MmultiscriptsTag().withText(text);
}
public static MmultiscriptsTag mmultiscripts(DomContent... dc) {
return new MmultiscriptsTag().with(dc);
}
public static MnTag mn(String text) {
return new MnTag().withText(text);
}
public static MnTag mn(DomContent... dc) {
return new MnTag().with(dc);
}
public static MoTag mo(String text) {
return new MoTag().withText(text);
}
public static MoTag mo(DomContent... dc) {
return new MoTag().with(dc);
}
public static MoverTag mover(String text) {
return new MoverTag().withText(text);
}
public static MoverTag mover(DomContent... dc) {
return new MoverTag().with(dc);
}
public static MpaddedTag mpadded(String text) {
return new MpaddedTag().withText(text);
}
public static MpaddedTag mpadded(DomContent... dc) {
return new MpaddedTag().with(dc);
}
public static MphantomTag mphantom(String text) {
return new MphantomTag().withText(text);
}
public static MphantomTag mphantom(DomContent... dc) {
return new MphantomTag().with(dc);
}
public static MprescriptsTag mprescripts(String text) {
return new MprescriptsTag().withText(text);
}
public static MprescriptsTag mprescripts(DomContent... dc) {
return new MprescriptsTag().with(dc);
}
public static MrootTag mroot(String text) {
return new MrootTag().withText(text);
}
public static MrootTag mroot(DomContent... dc) {
return new MrootTag().with(dc);
}
public static MrowTag mrow(String text) {
return new MrowTag().withText(text);
}
public static MrowTag mrow(DomContent... dc) {
return new MrowTag().with(dc);
}
public static MsTag ms(String text) {
return new MsTag().withText(text);
}
public static MsTag ms(DomContent... dc) {
return new MsTag().with(dc);
}
public static MspaceTag mspace(String text) {
return new MspaceTag().withText(text);
}
public static MspaceTag mspace(DomContent... dc) {
return new MspaceTag().with(dc);
}
public static MsqrtTag msqrt(String text) {
return new MsqrtTag().withText(text);
}
public static MsqrtTag msqrt(DomContent... dc) {
return new MsqrtTag().with(dc);
}
public static MstyleTag mstyle(String text) {
return new MstyleTag().withText(text);
}
public static MstyleTag mstyle(DomContent... dc) {
return new MstyleTag().with(dc);
}
public static MsubTag msub(String text) {
return new MsubTag().withText(text);
}
public static MsubTag msub(DomContent... dc) {
return new MsubTag().with(dc);
}
public static MsubsupTag msubsup(String text) {
return new MsubsupTag().withText(text);
}
public static MsubsupTag msubsup(DomContent... dc) {
return new MsubsupTag().with(dc);
}
public static MsupTag msup(String text) {
return new MsupTag().withText(text);
}
public static MsupTag msup(DomContent... dc) {
return new MsupTag().with(dc);
}
public static MtableTag mtable(String text) {
return new MtableTag().withText(text);
}
public static MtableTag mtable(DomContent... dc) {
return new MtableTag().with(dc);
}
public static MtdTag mtd(String text) {
return new MtdTag().withText(text);
}
public static MtdTag mtd(DomContent... dc) {
return new MtdTag().with(dc);
}
public static MtextTag mtext(String text) {
return new MtextTag().withText(text);
}
public static MtextTag mtext(DomContent... dc) {
return new MtextTag().with(dc);
}
public static MtrTag mtr(String text) {
return new MtrTag().withText(text);
}
public static MtrTag mtr(DomContent... dc) {
return new MtrTag().with(dc);
}
public static MunderTag munder(String text) {
return new MunderTag().withText(text);
}
public static MunderTag munder(DomContent... dc) {
return new MunderTag().with(dc);
}
public static MunderoverTag munderover(String text) {
return new MunderoverTag().withText(text);
}
public static MunderoverTag munderover(DomContent... dc) {
return new MunderoverTag().with(dc);
}
public static NoneTag none(String text) {
return new NoneTag().withText(text);
}
public static NoneTag none(DomContent... dc) {
return new NoneTag().with(dc);
}
public static SemanticsTag semantics(String text) {
return new SemanticsTag().withText(text);
}
public static SemanticsTag semantics(DomContent... dc) {
return new SemanticsTag().with(dc);
}
}

View File

@@ -0,0 +1,254 @@
ELEMENT[annotation]
ELEMENT[maction]
ELEMENT[math]
ELEMENT[merror]
ELEMENT[mfrac]
ELEMENT[mi]
ELEMENT[mmultiscripts]
ELEMENT[mn]
ELEMENT[mo]
ELEMENT[mover]
ELEMENT[mpadded]
ELEMENT[mphantom]
ELEMENT[mprescripts]
ELEMENT[mroot]
ELEMENT[mrow]
ELEMENT[ms]
ELEMENT[mspace]
ELEMENT[msqrt]
ELEMENT[mstyle]
ELEMENT[msub]
ELEMENT[msubsup]
ELEMENT[msup]
ELEMENT[mtable]
ELEMENT[mtd]
ELEMENT[mtext]
ELEMENT[mtr]
ELEMENT[munder]
ELEMENT[munderover]
ELEMENT[none]
ELEMENT[semantics]
BOOLEAN[displaystyle]
ATTRIBUTE[annotation:displaystyle]
ATTRIBUTE[maction:displaystyle]
ATTRIBUTE[math:displaystyle]
ATTRIBUTE[merror:displaystyle]
ATTRIBUTE[mfrac:displaystyle]
ATTRIBUTE[mi:displaystyle]
ATTRIBUTE[mmultiscripts:displaystyle]
ATTRIBUTE[mn:displaystyle]
ATTRIBUTE[mo:displaystyle]
ATTRIBUTE[mover:displaystyle]
ATTRIBUTE[mpadded:displaystyle]
ATTRIBUTE[mphantom:displaystyle]
ATTRIBUTE[mprescripts:displaystyle]
ATTRIBUTE[mroot:displaystyle]
ATTRIBUTE[mrow:displaystyle]
ATTRIBUTE[ms:displaystyle]
ATTRIBUTE[mspace:displaystyle]
ATTRIBUTE[msqrt:displaystyle]
ATTRIBUTE[mstyle:displaystyle]
ATTRIBUTE[msub:displaystyle]
ATTRIBUTE[msubsup:displaystyle]
ATTRIBUTE[msup:displaystyle]
ATTRIBUTE[mtable:displaystyle]
ATTRIBUTE[mtd:displaystyle]
ATTRIBUTE[mtext:displaystyle]
ATTRIBUTE[mtr:displaystyle]
ATTRIBUTE[munder:displaystyle]
ATTRIBUTE[munderover:displaystyle]
ATTRIBUTE[none:displaystyle]
ATTRIBUTE[semantics:displaystyle]
BOOLEAN[mathbackground]
ATTRIBUTE[annotation:mathbackground]
ATTRIBUTE[maction:mathbackground]
ATTRIBUTE[math:mathbackground]
ATTRIBUTE[merror:mathbackground]
ATTRIBUTE[mfrac:mathbackground]
ATTRIBUTE[mi:mathbackground]
ATTRIBUTE[mmultiscripts:mathbackground]
ATTRIBUTE[mn:mathbackground]
ATTRIBUTE[mo:mathbackground]
ATTRIBUTE[mover:mathbackground]
ATTRIBUTE[mpadded:mathbackground]
ATTRIBUTE[mphantom:mathbackground]
ATTRIBUTE[mprescripts:mathbackground]
ATTRIBUTE[mroot:mathbackground]
ATTRIBUTE[mrow:mathbackground]
ATTRIBUTE[ms:mathbackground]
ATTRIBUTE[mspace:mathbackground]
ATTRIBUTE[msqrt:mathbackground]
ATTRIBUTE[mstyle:mathbackground]
ATTRIBUTE[msub:mathbackground]
ATTRIBUTE[msubsup:mathbackground]
ATTRIBUTE[msup:mathbackground]
ATTRIBUTE[mtable:mathbackground]
ATTRIBUTE[mtd:mathbackground]
ATTRIBUTE[mtext:mathbackground]
ATTRIBUTE[mtr:mathbackground]
ATTRIBUTE[munder:mathbackground]
ATTRIBUTE[munderover:mathbackground]
ATTRIBUTE[none:mathbackground]
ATTRIBUTE[semantics:mathbackground]
BOOLEAN[mathcolor]
ATTRIBUTE[annotation:mathcolor]
ATTRIBUTE[maction:mathcolor]
ATTRIBUTE[math:mathcolor]
ATTRIBUTE[merror:mathcolor]
ATTRIBUTE[mfrac:mathcolor]
ATTRIBUTE[mi:mathcolor]
ATTRIBUTE[mmultiscripts:mathcolor]
ATTRIBUTE[mn:mathcolor]
ATTRIBUTE[mo:mathcolor]
ATTRIBUTE[mover:mathcolor]
ATTRIBUTE[mpadded:mathcolor]
ATTRIBUTE[mphantom:mathcolor]
ATTRIBUTE[mprescripts:mathcolor]
ATTRIBUTE[mroot:mathcolor]
ATTRIBUTE[mrow:mathcolor]
ATTRIBUTE[ms:mathcolor]
ATTRIBUTE[mspace:mathcolor]
ATTRIBUTE[msqrt:mathcolor]
ATTRIBUTE[mstyle:mathcolor]
ATTRIBUTE[msub:mathcolor]
ATTRIBUTE[msubsup:mathcolor]
ATTRIBUTE[msup:mathcolor]
ATTRIBUTE[mtable:mathcolor]
ATTRIBUTE[mtd:mathcolor]
ATTRIBUTE[mtext:mathcolor]
ATTRIBUTE[mtr:mathcolor]
ATTRIBUTE[munder:mathcolor]
ATTRIBUTE[munderover:mathcolor]
ATTRIBUTE[none:mathcolor]
ATTRIBUTE[semantics:mathcolor]
BOOLEAN[mathsize]
ATTRIBUTE[annotation:mathsize]
ATTRIBUTE[maction:mathsize]
ATTRIBUTE[math:mathsize]
ATTRIBUTE[merror:mathsize]
ATTRIBUTE[mfrac:mathsize]
ATTRIBUTE[mi:mathsize]
ATTRIBUTE[mmultiscripts:mathsize]
ATTRIBUTE[mn:mathsize]
ATTRIBUTE[mo:mathsize]
ATTRIBUTE[mover:mathsize]
ATTRIBUTE[mpadded:mathsize]
ATTRIBUTE[mphantom:mathsize]
ATTRIBUTE[mprescripts:mathsize]
ATTRIBUTE[mroot:mathsize]
ATTRIBUTE[mrow:mathsize]
ATTRIBUTE[ms:mathsize]
ATTRIBUTE[mspace:mathsize]
ATTRIBUTE[msqrt:mathsize]
ATTRIBUTE[mstyle:mathsize]
ATTRIBUTE[msub:mathsize]
ATTRIBUTE[msubsup:mathsize]
ATTRIBUTE[msup:mathsize]
ATTRIBUTE[mtable:mathsize]
ATTRIBUTE[mtd:mathsize]
ATTRIBUTE[mtext:mathsize]
ATTRIBUTE[mtr:mathsize]
ATTRIBUTE[munder:mathsize]
ATTRIBUTE[munderover:mathsize]
ATTRIBUTE[none:mathsize]
ATTRIBUTE[semantics:mathsize]
BOOLEAN[mathvariant]
ATTRIBUTE[annotation:mathvariant]
ATTRIBUTE[maction:mathvariant]
ATTRIBUTE[math:mathvariant]
ATTRIBUTE[merror:mathvariant]
ATTRIBUTE[mfrac:mathvariant]
ATTRIBUTE[mi:mathvariant]
ATTRIBUTE[mmultiscripts:mathvariant]
ATTRIBUTE[mn:mathvariant]
ATTRIBUTE[mo:mathvariant]
ATTRIBUTE[mover:mathvariant]
ATTRIBUTE[mpadded:mathvariant]
ATTRIBUTE[mphantom:mathvariant]
ATTRIBUTE[mprescripts:mathvariant]
ATTRIBUTE[mroot:mathvariant]
ATTRIBUTE[mrow:mathvariant]
ATTRIBUTE[ms:mathvariant]
ATTRIBUTE[mspace:mathvariant]
ATTRIBUTE[msqrt:mathvariant]
ATTRIBUTE[mstyle:mathvariant]
ATTRIBUTE[msub:mathvariant]
ATTRIBUTE[msubsup:mathvariant]
ATTRIBUTE[msup:mathvariant]
ATTRIBUTE[mtable:mathvariant]
ATTRIBUTE[mtd:mathvariant]
ATTRIBUTE[mtext:mathvariant]
ATTRIBUTE[mtr:mathvariant]
ATTRIBUTE[munder:mathvariant]
ATTRIBUTE[munderover:mathvariant]
ATTRIBUTE[none:mathvariant]
ATTRIBUTE[semantics:mathvariant]
BOOLEAN[nonce]
ATTRIBUTE[annotation:nonce]
ATTRIBUTE[maction:nonce]
ATTRIBUTE[math:nonce]
ATTRIBUTE[merror:nonce]
ATTRIBUTE[mfrac:nonce]
ATTRIBUTE[mi:nonce]
ATTRIBUTE[mmultiscripts:nonce]
ATTRIBUTE[mn:nonce]
ATTRIBUTE[mo:nonce]
ATTRIBUTE[mover:nonce]
ATTRIBUTE[mpadded:nonce]
ATTRIBUTE[mphantom:nonce]
ATTRIBUTE[mprescripts:nonce]
ATTRIBUTE[mroot:nonce]
ATTRIBUTE[mrow:nonce]
ATTRIBUTE[ms:nonce]
ATTRIBUTE[mspace:nonce]
ATTRIBUTE[msqrt:nonce]
ATTRIBUTE[mstyle:nonce]
ATTRIBUTE[msub:nonce]
ATTRIBUTE[msubsup:nonce]
ATTRIBUTE[msup:nonce]
ATTRIBUTE[mtable:nonce]
ATTRIBUTE[mtd:nonce]
ATTRIBUTE[mtext:nonce]
ATTRIBUTE[mtr:nonce]
ATTRIBUTE[munder:nonce]
ATTRIBUTE[munderover:nonce]
ATTRIBUTE[none:nonce]
ATTRIBUTE[semantics:nonce]
BOOLEAN[scriptlevel]
ATTRIBUTE[annotation:scriptlevel]
ATTRIBUTE[maction:scriptlevel]
ATTRIBUTE[math:scriptlevel]
ATTRIBUTE[merror:scriptlevel]
ATTRIBUTE[mfrac:scriptlevel]
ATTRIBUTE[mi:scriptlevel]
ATTRIBUTE[mmultiscripts:scriptlevel]
ATTRIBUTE[mn:scriptlevel]
ATTRIBUTE[mo:scriptlevel]
ATTRIBUTE[mover:scriptlevel]
ATTRIBUTE[mpadded:scriptlevel]
ATTRIBUTE[mphantom:scriptlevel]
ATTRIBUTE[mprescripts:scriptlevel]
ATTRIBUTE[mroot:scriptlevel]
ATTRIBUTE[mrow:scriptlevel]
ATTRIBUTE[ms:scriptlevel]
ATTRIBUTE[mspace:scriptlevel]
ATTRIBUTE[msqrt:scriptlevel]
ATTRIBUTE[mstyle:scriptlevel]
ATTRIBUTE[msub:scriptlevel]
ATTRIBUTE[msubsup:scriptlevel]
ATTRIBUTE[msup:scriptlevel]
ATTRIBUTE[mtable:scriptlevel]
ATTRIBUTE[mtd:scriptlevel]
ATTRIBUTE[mtext:scriptlevel]
ATTRIBUTE[mtr:scriptlevel]
ATTRIBUTE[munder:scriptlevel]
ATTRIBUTE[munderover:scriptlevel]
ATTRIBUTE[none:scriptlevel]
ATTRIBUTE[semantics:scriptlevel]

View File

@@ -0,0 +1,42 @@
import org.junit.Test;
import static com.j2html.mathml.MathML.*;
import static org.junit.Assert.assertEquals;
public class MathMLTests {
@Test
public void all_tags_render_containers(){
assertEquals("<annotation></annotation>", annotation().render());
assertEquals("<maction></maction>", maction().render());
assertEquals("<math></math>", math().render());
assertEquals("<merror></merror>", merror().render());
assertEquals("<mfrac></mfrac>", mfrac().render());
assertEquals("<mi></mi>", mi().render());
assertEquals("<mmultiscripts></mmultiscripts>", mmultiscripts().render());
assertEquals("<mn></mn>", mn().render());
assertEquals("<mo></mo>", mo().render());
assertEquals("<mover></mover>", mover().render());
assertEquals("<mpadded></mpadded>", mpadded().render());
assertEquals("<mphantom></mphantom>", mphantom().render());
assertEquals("<mprescripts></mprescripts>", mprescripts().render());
assertEquals("<mroot></mroot>", mroot().render());
assertEquals("<mrow></mrow>", mrow().render());
assertEquals("<ms></ms>", ms().render());
assertEquals("<mspace></mspace>", mspace().render());
assertEquals("<msqrt></msqrt>", msqrt().render());
assertEquals("<mstyle></mstyle>", mstyle().render());
assertEquals("<msub></msub>", msub().render());
assertEquals("<msubsup></msubsup>", msubsup().render());
assertEquals("<msup></msup>", msup().render());
assertEquals("<mtable></mtable>", mtable().render());
assertEquals("<mtd></mtd>", mtd().render());
assertEquals("<mtext></mtext>", mtext().render());
assertEquals("<mtr></mtr>", mtr().render());
assertEquals("<munder></munder>", munder().render());
assertEquals("<munderover></munderover>", munderover().render());
assertEquals("<none></none>", none().render());
assertEquals("<semantics></semantics>", semantics().render());
}
}

View File

@@ -10,7 +10,7 @@ Website is available on http://localhost:8888/.
In order to "deploy" the website, the static files in the `j2html/docs` must be updated.
You can either download the files manually from your browser, or use curl:
```
```sh
curl "http://localhost:8888/" > index.html
curl "http://localhost:8888/download.html" > download.html
curl "http://localhost:8888/examples.html" > examples.html

View File

@@ -3,9 +3,13 @@
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>j2html-webpage</groupId>
<artifactId>j2html-webpage</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>com.j2html</groupId>
<artifactId>j2html-parent</artifactId>
<version>1.6.1-SNAPSHOT</version>
</parent>
<artifactId>j2html-website</artifactId>
<dependencies>
<dependency>
@@ -13,26 +17,33 @@
<artifactId>javalin</artifactId>
<version>4.0.0.ALPHA2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.4.0</version>
<version>1.6.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>j2html-webpage</finalName>
<finalName>j2html-website</finalName>
<archive>
<manifest>
<addClasspath>true</addClasspath>
@@ -42,15 +53,7 @@
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
@@ -73,6 +76,7 @@
</archive>
</configuration>
</plugin>
</plugins>
</build>

View File

@@ -7,9 +7,8 @@ import io.javalin.http.staticfiles.Location;
public class Main {
public static void main(String[] args) {
Javalin app = Javalin.create(config ->
config.addStaticFiles("src/main/resources/public", Location.EXTERNAL)
config.addStaticFiles("website/src/main/resources/public", Location.EXTERNAL)
).start(8888);
app.get("/", PageController::serveIndex);

View File

@@ -0,0 +1,43 @@
package app.views.pages;
import app.views.MainView;
import static app.views.Partials.codeSnippet;
import static j2html.TagCreator.*;
public class DownloadView {
public static String render() {
return MainView.render(
"Download j2html",
"Maven and GitHub",
section(attrs("#download"),
h2("Maven dependency"),
p("To experience the joy of generating HTML with a Java HTML builder, add the j2html dependency to your POM:"),
codeSnippet("markup", fileAsEscapedString("/codeExamples/mavenDep.xml")),
a().withId("upgrade"),
h2("Steps for upgrading"),
p("From 1.4.0 to 1.5.0"),
ul(
li(
join("Change return types from", code("Tag"), ",", code("ContainerTag"), "or", code("EmptyTag"), "to the specific tag being returned.")
),
li(
join("Change missing method calls on tags, such as", code("withRole(\"value\")"), "to", code(".attr(\"role\", \"value\")"), ".")
),
li(
join("Method parameters of", code("Tag"), ",", code("ContainerTag"), "or", code("EmptyTag"), "should have a wildcard (&lt;?&gt;) added, or be changed to a specific tag.")
),
li(
join("Replace ambiguous method references like ", code("each(list, TagCreator::li)"), " with lambdas such as", code("each(list, str -> li(str))"), ".")
)
),
h2("Clone the repo on GitHub"),
p(join(
"Please clone and/or fork the repo on",
a("GitHub").withHref("https://github.com/tipsy/j2html").withTarget("_blank"),
", make changes, and create pull requests! We will go through pull requests every sunday, so don't be shy."
))
)
);
}
}

View File

@@ -2,39 +2,35 @@ package app.views.pages;
import app.views.MainView;
import j2html.TagCreator;
import j2html.tags.ContainerTag;
import j2html.tags.DomContent;
import j2html.tags.specialized.ArticleTag;
import java.util.Arrays;
import java.util.List;
import static app.views.Partials.mavenLink;
import static j2html.TagCreator.a;
import static j2html.TagCreator.article;
import static j2html.TagCreator.attrs;
import static j2html.TagCreator.br;
import static j2html.TagCreator.code;
import static j2html.TagCreator.dd;
import static j2html.TagCreator.dl;
import static j2html.TagCreator.dt;
import static j2html.TagCreator.each;
import static j2html.TagCreator.em;
import static j2html.TagCreator.h2;
import static j2html.TagCreator.join;
import static j2html.TagCreator.li;
import static j2html.TagCreator.p;
import static j2html.TagCreator.section;
import static j2html.TagCreator.text;
import static j2html.TagCreator.ul;
import static j2html.TagCreator.*;
public class NewsView {
private static ContainerTag newsPost(String title, String version, DomContent... listItems) {
private static ArticleTag newsPost(
String title,
String version,
boolean breaking,
DomContent... listItems
) {
List<DomContent> list = Arrays.asList(listItems);
return article(
h2(title).withId("j2html-" + version + "-released"),
mavenLink(version),
iff(breaking,
p(
a("This version contains breaking changes. Please view the upgrade guide.").withHref("download.html#upgrade")
)
),
p("Changes:"),
ul(
each(list, TagCreator::li)
each(list, el -> TagCreator.li(el))
));
}
@@ -45,13 +41,45 @@ public class NewsView {
section(attrs("#news"),
newsPost(
"j2html 1.4.0 adds a couple of convenient methods (Jan 2019)", "1.4.0",
"j2html 1.6.0 adds support for web components and newer HTML elements. (Jun 2022)",
"1.6.0",
false,
join("Added", code("TagCreator::data"), "to provide machine-readable translations."),
join("Added", code("TagCreator::picture"), "to provide alternative versions of an image for different display/device scenarios."),
join("Added", code("TagCreator::slot"), "to provide placeholders for web components."),
join("Added", code("TagCreator::template"), "to provide templating of content fragments for web components."),
join("Added global attributes used for web components.")
),
newsPost(
"j2html 1.5.0 enhances factory methods and class types, overhauls HTML rendering, introduces support for Java modules and fixes several bugs (Jun 2021)",
"1.5.0",
true,
join("Added", code("Automatic-Module-Name"), "to manifest to support JDK 9+"),
join("Added", code("TagCreator::each(DomContent...)")),
join("Added", code("TagCreator::each(Collection, BiFunction)")),
join("Added", code("HtmlBuilder"), "interface, with implementations for ", code("FlatHtml"), "and", code("IndentedHtml")),
join("Added", code("Config.defaults()"), "for customizable configuration instances and", code("Config.global()"), "for (backwards-compatible) static global configuration"),
join("Deprecated old rendering methods. Libraries that use custom Tag implementations should switch to using ", code("HtmlBuilder")),
join("Fixed the use of", code("rawHtml()"), "when constructing the Tag tree"),
join("Fixed text escaping for", code("style()"), "and", code("script()")),
join("Fixed formatting of children for", code("textarea()"), "and", code("pre()")),
join("Fixed appending an unnecessary delimiter to the end of text with", code("join()")),
join("Thanks to", a("Oliver Becker").withHref("https://github.com/obecker"), "for many code improvements")
),
newsPost(
"j2html 1.4.0 adds a couple of convenient methods (Jan 2019)",
"1.4.0",
false,
join("Added", code("TagCreator::each(Map, BiFunction)")),
join("Added", code("Stream<DomContent>"), "variants of", code("each"), "and", code("with"))
),
newsPost(
"j2html 1.3.0 has a couple of features and fixes (May 2018)", "1.3.0",
"j2html 1.3.0 has a couple of features and fixes (May 2018)",
"1.3.0",
false,
join("Added support for", code("Map"), "in", code("each()")),
join("Added osgi metadata"),
join("Added support for", code("Optional"), "in", code("iff()")),
@@ -59,19 +87,25 @@ public class NewsView {
),
newsPost(
"j2html 1.2.2 has performance improvements (Dec 2017)", "1.2.2",
"j2html 1.2.2 has performance improvements (Dec 2017)",
"1.2.2",
false,
join("There have been some massive performance improvements. Big thanks to", a("kicktipp").withHref("https://github.com/kicktipp"), ".")
),
newsPost(
"j2html 1.2.1 fixes some bugs (Nov 2017)", "1.2.1",
"j2html 1.2.1 fixes some bugs (Nov 2017)",
"1.2.1",
false,
join("Fix", em("\"bad closing tag (<!DOCTYPE html/>) when closeEmptyTags is true\""), "bug"),
join("Fix", em("\"can't load static resources from jar\""), "bug"),
join("Fix", em("\"CSSMin stripping last character of CSS rule if rule doesn't end in semi-colon\""), "bug")
),
newsPost(
"j2html 1.2.0 already? (Sep 2017)", "1.2.0",
"j2html 1.2.0 already? (Sep 2017)",
"1.2.0",
false,
join("Added option to render formatted HTML, ex", code("body(...).renderFormatted()")),
join("Added option to configure HTML-formatting-indent via", code("Config.indenter = (int, string) -> {...}")),
join("Added option to configure CSS-minification via", code("Config.cssMinifier = string -> {...}")),
@@ -81,12 +115,16 @@ public class NewsView {
),
newsPost(
"j2html 1.1.0 is out! (Aug 2017)", "1.1.0",
"j2html 1.1.0 is out! (Aug 2017)",
"1.1.0",
false,
join("Added a option to customize TextEscaper via", code("Config.textEscaper = text -> {}"))
),
newsPost(
"j2html 1.0.0 is here! (May 2017)", "1.0.0",
"j2html 1.0.0 is here! (May 2017)",
"1.0.0",
false,
join("v1 is officially done. We will be doing", a("semantic versioning").withHref("http://semver.org/").withTarget("_blank"), "from now on."),
join("All tag methods (", code("div()"), ",", code("p()"), "etc ) can now accept an arbitrary number of", code("DomContent"), "as arguments, eliminating the need for", code("with()"), "in most cases."),
join("Added a shorthand-attribute overloads to all TagCreator methods:", br(), code("div(attrs(\"#id.class\")"), "becomes", code("<div id=\"id\" class=\"class\"></div>")),
@@ -96,7 +134,9 @@ public class NewsView {
),
newsPost(
"j2html 0.99 released! (Apr 2017)", "0.99",
"j2html 0.99 released! (Apr 2017)",
"0.99",
false,
join("Added generic", code("iff()"), "/", code("iffElse()"), "methods for performing if's in method calls."),
join("Added", code("withClasses()"), "to add multiple classes to element. Works well with", code("iff()"), "."),
join("HTML-escaping is now a lot faster (and a lot faster than StringUtils)"),
@@ -104,7 +144,9 @@ public class NewsView {
),
newsPost(
"j2html 0.88 released! (Jan 2017)", "0.88",
"j2html 0.88 released! (Jan 2017)",
"0.88",
false,
text("Closure and StringUtils dependencies removed in favor of custom implementations. Most users seem interested in a very lightweight library."),
code("unsafeHtml()"), text(" is now "), code("rawHtml()"),
text("Added "), code(".equals()"), text(" to Tag-class. Two Tags are equal if they render the same HTML")

View File

@@ -0,0 +1,38 @@
TagCreator.class // Static utility class for creating all tags
import static j2html.TagCreator.*; // Use static star import
Config.class // Holds all configuration. Offers global configuration or customizable instances
Config.closeEmptyTags = true // Global options are public, static and mutable.
Config.global() // Copy all static Config fields into an instance. Instances are immutable
Config.defaults() // A Config with defaults that are independent of global options
Config.global().withEmptyTagsClosed(true) // A Config that is different from the global options
Config.defaults().withEmptyTagsClosed(true) // A Config that is different from the default options
TagCreator.join() // Method for joining small snippets, like:
p(join("This paragraph has", b("bold"), "and", i("italic"), "text."))
TagCreator.iff(boolean condition, T ifValue) // If-expression for use in method calls
div().withClasses("menu-element", iff(isActive, "active"))
TagCreator.iffElse(boolean condition, T ifValue, T elseValue) // If/else-expression for use in method calls
div().withClasses("menu-element", iffElse(isActive, "active", "not-active"))
Tag.class // Is extended by ContainerTag (ex <div></div> and EmptyTag (ex <br>)
Tag.attr(String attribute, Object value) // Set an attribute on the tag
Tag.withXyz(String value) // Calls attr with predefined attribute (ex .withId, .withClass, etc.)
Tag.render(HtmlBuilder builder) // Render HTML using the given builder.
Tag.render() // Shortcut for rendering flat HTML into a string using global Config.
ContainerTag.renderFormatted() // Shortcut for rendering indented HTML into a string using global Config.
HtmlBuilder.class // Interface for composing HTML. Implemented by FlatHtml and IndentedHtml
FlatHtml.into(Appendable) // Render into a stream, file, etc. without indentation or line breaks
FlatHtml.into(Appendable appendable, Config config) // Customize rendering of flat html
IndentedHtml.into(Appendable) // Render human-readable HTML into an stream, file, etc.
IndentedHtml.into(Appendable appendable, Config config) // Customize rendering of intended html
ul(li("one"), li("two")).render(IndentedHtml.inMemory()).toString() // Similar to renderFormatted()
ul(li("one"), li("two")).render(IndentedHtml.into(filewriter)) // Write HTML into a file

View File

@@ -1,5 +1,5 @@
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.4.0</version>
<version>1.6.0</version>
</dependency>

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 240 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

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

View File

@@ -1,88 +1,79 @@
<?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">
<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>
<groupId>com.j2html</groupId>
<artifactId>j2html-parent</artifactId>
<version>1.6.1-SNAPSHOT</version>
</parent>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.5.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.5.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>
<artifactId>j2html</artifactId>
<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>com.j2html</groupId>
<artifactId>j2html-codegen-maven-plugin</artifactId>
<version>1.6.1-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>generate-source-files</goal>
</goals>
</execution>
</executions>
<configuration>
<modelFile>${project.basedir}/src/main/models/html.model</modelFile>
<attributePackage>j2html.tags.attributes</attributePackage>
<tagPackage>j2html.tags.specialized</tagPackage>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<executions>
<execution>
<id>default</id>
@@ -90,55 +81,25 @@
<goal>perform</goal>
</goals>
<configuration>
<pomFileName>library/pom.xml</pomFileName>
<pomFileName>pom.xml</pomFileName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</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>1.4</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>2.10.3</version>
<configuration>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
@@ -151,10 +112,10 @@
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>bundle-manifest</id>
@@ -165,37 +126,31 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.revapi</groupId>
<artifactId>revapi-maven-plugin</artifactId>
<configuration>
<oldArtifacts>
<artifact>com.j2html:j2html:1.6.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>
</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>1.6</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

@@ -461,6 +461,13 @@ public class TagCreator {
public static ColgroupTag colgroup (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new ColgroupTag().withText(text), shortAttr); }
public static ColgroupTag colgroup (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new ColgroupTag().with(dc), shortAttr); }
public static DataTag data () { return new DataTag(); }
public static DataTag data (String text) { return new DataTag().withText(text); }
public static DataTag data (DomContent... dc) { return new DataTag().with(dc); }
public static DataTag data (Attr.ShortForm shortAttr) { return Attr.addTo( new DataTag(), shortAttr); }
public static DataTag data (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new DataTag().withText(text), shortAttr); }
public static DataTag data (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new DataTag().with(dc), shortAttr); }
public static DatalistTag datalist () { return new DatalistTag(); }
public static DatalistTag datalist (String text) { return new DatalistTag().withText(text); }
public static DatalistTag datalist (DomContent... dc) { return new DatalistTag().with(dc); }
@@ -762,6 +769,13 @@ public class TagCreator {
public static PTag p (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new PTag().withText(text), shortAttr); }
public static PTag p (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new PTag().with(dc), shortAttr); }
public static PictureTag picture () { return new PictureTag(); }
public static PictureTag picture (String text) { return new PictureTag().withText(text); }
public static PictureTag picture (DomContent... dc) { return new PictureTag().with(dc); }
public static PictureTag picture (Attr.ShortForm shortAttr) { return Attr.addTo( new PictureTag(), shortAttr); }
public static PictureTag picture (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new PictureTag().withText(text), shortAttr); }
public static PictureTag picture (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new PictureTag().with(dc), shortAttr); }
public static PreTag pre () { return new PreTag(); }
public static PreTag pre (String text) { return new PreTag().withText(text); }
public static PreTag pre (DomContent... dc) { return new PreTag().with(dc); }
@@ -839,6 +853,13 @@ public class TagCreator {
public static SelectTag select (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new SelectTag().withText(text), shortAttr); }
public static SelectTag select (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new SelectTag().with(dc), shortAttr); }
public static SlotTag slot () { return new SlotTag(); }
public static SlotTag slot (String text) { return new SlotTag().withText(text); }
public static SlotTag slot (DomContent... dc) { return new SlotTag().with(dc); }
public static SlotTag slot (Attr.ShortForm shortAttr) { return Attr.addTo( new SlotTag(), shortAttr); }
public static SlotTag slot (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new SlotTag().withText(text), shortAttr); }
public static SlotTag slot (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new SlotTag().with(dc), shortAttr); }
public static SmallTag small () { return new SmallTag(); }
public static SmallTag small (String text) { return new SmallTag().withText(text); }
public static SmallTag small (DomContent... dc) { return new SmallTag().with(dc); }
@@ -909,6 +930,13 @@ public class TagCreator {
public static TdTag td (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new TdTag().withText(text), shortAttr); }
public static TdTag td (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new TdTag().with(dc), shortAttr); }
public static TemplateTag template () { return new TemplateTag(); }
public static TemplateTag template (String text) { return new TemplateTag().withText(text); }
public static TemplateTag template (DomContent... dc) { return new TemplateTag().with(dc); }
public static TemplateTag template (Attr.ShortForm shortAttr) { return Attr.addTo( new TemplateTag(), shortAttr); }
public static TemplateTag template (Attr.ShortForm shortAttr, String text) { return Attr.addTo( new TemplateTag().withText(text), shortAttr); }
public static TemplateTag template (Attr.ShortForm shortAttr, DomContent... dc) { return Attr.addTo( new TemplateTag().with(dc), shortAttr); }
public static TextareaTag textarea () { return new TextareaTag(); }
public static TextareaTag textarea (String text) { return new TextareaTag().withText(text); }
public static TextareaTag textarea (DomContent... dc) { return new TextareaTag().with(dc); }

View File

@@ -53,6 +53,7 @@ public abstract class Attr {
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";
@@ -96,6 +97,7 @@ public abstract class Attr {
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";

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