Template Customization
As written in the README file the core module is using Handlebars as the templating engine. With that we are able to create smaller files, and we can render them together.
If you would like to use your own templates as inputs you should first read through the following section to know which parameters you can use in your template.
Handlebars template compiler
By default, the tool depends on the Handlebars 3rd party library to put life into the templates.
With that said, Handlerbars supports custom helpers, and there are a few helpers, those can be used in any custom template.
Helpers:
-
as_env
- (org.rodnansol.core.generator.template.handlebars.EnvironmentVariableHelper
) - Renders the parameter property to its environment variable form. -
is_included
- (org.rodnansol.core.generator.template.handlebars.IsIncludedHelper
) - Checks if a given property can be rendred into the document or not. -
is_compact_mode
- (org.rodnansol.core.generator.template.handlebars.IsCompactModeHelper
) - Shows if the template mode is set to COMPACT or not.-
These can be configured with this object - Keys it can handle:
-
class
-
key
-
type
-
description
-
defaultValue
-
deprecation
-
envFormat
-
-
Default templates
The provided/packaged templates can be found here:
-
spring-configuration-property-documenter-core/src/main/resources/templates/single
-
Contains the basic templates for a single module
-
-
spring-configuration-property-documenter-core/src/main/resources/templates/aggregated
-
Contains templates that could be used for multiple document aggregation
-
-
spring-configuration-property-documenter-core/src/main/resources/templates/partials
-
Contains the templates for the content, and for the HTML a few helper templates
-
Template modes
With the template mode setting you can set how your template should look like, right now this customization option just selects different template for the different sections.
Available modes:
-
Standard - Default mode where the property group based properties are separated by the groups, and they are listed in different tables.
-
Compact - All the properties from the available property groups are shown in one just one table, no grouping by property groups.
-
In this case the keys will be shown with their fully qualified name.
-
Check the template customizations for the setting.
Examples
Standard
AsciiDoc
Random name for the Unknown group
Class: Unknown
Key | Type | Description | Default value | Deprecation | Environment variable |
---|
this.is.your
Class: org.rodnansol.YourProperties
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
property |
java.lang.String |
This is YOUR property. |
|
this.is.a.bean.configuration
Class: org.rodnansol.PropertiesForConfiguration
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
configuration-value |
java.lang.String |
A field inside a class that is not property by default by within a Configuration class. |
|
this.is.my.nested
Class: org.rodnansol.TopLevelClassNestedProperty
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
nested-value |
java.lang.String |
Nested value. |
|
this.is.my.first-level-nested-property.second-level-nested-class
Class: org.rodnansol.FirstLevelNestedProperty$SecondLevelNestedClass
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
second-level-value |
java.lang.String |
Custom nested |
|
this.is.my
Class: org.rodnansol.MyProperties
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
another-variable |
java.lang.String |
with default value |
Reason: null, use for replacement: null |
|
|
date |
java.time.LocalDate |
|
|||
date-time |
java.time.LocalDateTime |
|
|||
duration |
java.time.Duration |
A duration. |
2d |
Reason: Because it is deprecated, use for replacement: instant |
|
instant |
java.time.Instant |
123 |
|
||
variable |
java.lang.String |
This is my variable. |
|
this.is.my.first-level-nested-property
Class: org.rodnansol.FirstLevelNestedProperty
Key | Type | Description | Default value | Deprecation | Environment variable |
---|---|---|---|---|---|
desc |
java.lang.String |
Description of this thing. |
123 |
|
|
name |
java.lang.String |
Name of the custom property. |
ABC |
|
Markdown
Compact
AsciiDoc
Key | Type | Description | Default value | Deprecation |
---|---|---|---|---|
this.is.your.property |
java.lang.String |
This is YOUR property. |
||
this.is.a.bean.configuration.configuration-value |
java.lang.String |
A field inside a class that is not property by default by within a Configuration class. |
||
this.is.my.nested.nested-value |
java.lang.String |
Nested value. |
||
this.is.my.first-level-nested-property.second-level-nested-class.second-level-value |
java.lang.String |
Custom nested |
||
this.is.my.another-variable |
java.lang.String |
with default value |
Reason: null, use for replacement: null |
|
this.is.my.date |
java.time.LocalDate |
|||
this.is.my.date-time |
java.time.LocalDateTime |
|||
this.is.my.duration |
java.time.Duration |
A duration. |
2d |
Reason: Because it is deprecated, use for replacement: instant |
this.is.my.instant |
java.time.Instant |
123 |
||
this.is.my.variable |
java.lang.String |
This is my variable. |
||
this.is.my.first-level-nested-property.desc |
java.lang.String |
Description of this thing. |
123 |
|
this.is.my.first-level-nested-property.name |
java.lang.String |
Name of the custom property. |
ABC |
Markdown
AsciiDoc customizations
The final AsciiDoc files when they are being included, the rendered files are utilizing the following AsciiDoc related features:
Tag filtering
Every configuration property key is wrapped in a tag, and on include any tag can be ignored, or a specific list of configuration property keys can be set to include in the main documentation
// tag::this.is.module.a[]
=== this.is.module.a
*Class:* `com.example.multimodulea.ModuleAProperty`
[cols="2,1,3,1,1"]
|===
|Key |Type |Description |Default value |Deprecation
|variable-a
|java.lang.String
|This is my variable from module A.
|Default value for module A
|
|===
// end::this.is.module.a[]
include::file.adoc[tags=my.property.key.a;my.property.key.b]
include::file.adoc[tags=!my.property.key.a;my.property.key.b]
ifdef and ifndef Directives
With the ifdef
and ifndef
directives the content of the document can be manipulated and the tool gives you the following directives to play with:
-
property-group-simple-title
- Define this attribute to have the included document’s header style just a simple text and not a header-
It can be good if the configuration documentation is being included in a collapsible section
-
-
property-group-discrete-heading
- Define this attribute if the included document’s headers should be rendered as discrete headings-
It can be good if the configuration documentation is being included in a collapsible section
-
-
If none of the attributes are configured, the typical (= based) headings will be used.
=== this.is.module.a +
*Class:* `com.example.multimodulea.ModuleAProperty`
[cols="2,1,3,1,1"]
|===
|Key |Type |Description |Default value |Deprecation
|variable-a
|java.lang.String
|This is my variable from module A.
|Default value for module A
|
|===
:property-group-simple-title: (1)
include::file.adoc[]
:property-group-simple-title!: (2)
:property-group-discrete-heading: (3)
include::file.adoc[]
:property-group-discrete-heading!:(4)
1 | Enable the simple titles |
2 | Disabled the simple titles to make sure another included files are not inheriting the attributes |
3 | Enable the discrete headings |
4 | Disabled the discrete headings to make sure another included files are not inheriting the attributes |
Custom templates
You are not forced to use our templates, we can understand it is not your taste and maybe the customization options for the provided ones are not that flexible for your (for example the HTML format).
By default, as written above Handlebars is being used as the primary templating engine, and we are using the default settings, so if you create a template for yourself make sure you know the basic syntax and for all the templates the .hbs
extension should be used, please check the provided templates for more information.
For a single document only one template is being used, but for the aggregated documents the tool is using multiple templates to render the final template, it is because we are compiling the header, footer and the content section after each other, and we are merging them in the end. |
The custom templates can be provided with the Maven and Gradle plugins as well or with JBang if this is your preference.
Make sure you use your custom template file names with the .hbs extension, because Handlebars will put it to the end of the file.
|
Custom template compiler
By default, as written above Handlebars is being used as the primary templating engine, but it is fully understood if this tool does not suit your requirements, there are a lot of out there, and you might want to use that as the templating engine.
It is doable!
The tool is coming with an SPI (Service Provider Interface) extension where you can use your own org.rodnansol.core.generator.template.TemplateCompiler
implementation and from the Maven or Gradle plugin you can set the compiler’s name.
It has been available since the 0.2.0 version. |
You only have to implement one method for now:
package org.rodnansol.core.generator.template;
import edu.umd.cs.findbugs.annotations.NonNull;
import org.rodnansol.core.generator.DocumentGenerationException;
/**
* Class that handles the template compiling.
*
* @author nandorholozsnyak
* @since 0.2.0
*/
public interface TemplateCompiler {
/**
* Compiles the template with the given template data.
* <p>
* If the template is not found an exception must be raised.
*
* @param templatePath path to the template that the compiler can understand and work with.
* @param templateData template data.
* @return templated populated and compiled with the given template data.
* @throws DocumentGenerationException when the template compiler occurs an error.
*/
String compileTemplate(String templatePath, TemplateData templateData) throws DocumentGenerationException;
/**
* Returns the associated memory store.
*
* @since 0.6.0
*/
@NonNull
default TemplateCompilerMemoryStore getMemoryStore() {
return ThreadLocalTemplateCompilerStore.INSTANCE;
}
}
-
templatePath
variable is that what you can set for yourself from the Maven and Gradle plugin which should be the path to the template that must be compiled. -
templateData
variable is an object that is holding the converted data from thespring-configuration-metadata.json
file. Check below for the available fields
Register custom template compiler
To register your service create a file named org.rodnansol.core.generator.template.TemplateCompiler
under the META-INF/services
directory and put your class’s fully qualified name into the file.
To make sure you have the necessary classes, at least for now, you have to add the following dependency to your project:
<dependency>
<groupId>org.rodnansol</groupId>
<artifactId>spring-configuration-property-documenter-core</artifactId>
<version>${project.version}</version>
</dependency>
If this feature is going to get more visibility we will create an API module that would contain only the necessary classes to make sure your project is not polluted with a plugin dependency. |
The template variables are going to be the same, but if there is any compatibility issue with your compiling engine please let us know about the problem and open an issue to make sure we can handle these problems as well. |
Registration example
<plugin>
<groupId>org.rodnansol</groupId>
<artifactId>spring-configuration-property-documenter-maven-plugin</artifactId>
<version>999-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.rodnansol.example</groupId>
<artifactId>custom-template-compiler</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>generate-markdown-custom-template-compiler</id>
<phase>process-classes</phase>
<goals>
<goal>generate-property-document</goal>
</goals>
<configuration>
<type>MARKDOWN</type>
<templateCompilerName>com.example.custom.CustomTemplateCompiler</templateCompilerName>
<outputFile>target/custom-compiler-document.md</outputFile>
</configuration>
</execution>
</executions>
</plugin>
Make sure you add the Maven module that contains the service registration (with the META-INF/services folder) to the plugin’s dependency list, unless it will not recognize it. |
For a working example please check the samples/multi-module directory’s multi-module-c and custom-template-compiler module. |
Template variables
There are few Java classes to be discovered if you wish:
-
org.rodnansol.core.generator.MainTemplateData
-
org.rodnansol.core.generator.SubTemplateData
-
org.rodnansol.core.generator.PropertyGroup
-
org.rodnansol.core.generator.Property
-
org.rodnansol.core.generator.PropertyDeprecation
Variable | Type | Description | Since |
---|---|---|---|
mainName |
String |
Main header name, this can be configured, most times it is the name of the project or module |
0.1.0 |
propertyGroups |
List<PropertyGroup> |
List of the property groups that has been read and converted from the |
0.1.0 |
subTemplateDataList |
List<SubTemplateData> |
If multiple file aggregation is happening than this is going to contain all the incoming module data. |
0.1.0 |
mainDescription |
String |
Main description that is customizable |
0.1.0 |
generationDate |
LocalDateTime |
The date time of the template generation |
0.1.0 |
templateCustomization |
TemplateCustomization |
An object that can be used to customize a given template (see here) |
0.2.0 |
Variable | Type | Description | Since |
---|---|---|---|
moduleName |
String |
Name of the module, in case of aggregation it can be a module name |
0.1.0 |
propertyGroups |
List<PropertyGroup> |
List of the property groups that has been read and converted from the |
0.1.0 |
moduleDescription |
String |
Module description that is customizable |
0.1.0 |
generationDate |
LocalDateTime |
The date time of the template generation |
0.1.0 |
Variable | Type | Description | Since |
---|---|---|---|
groupName |
String |
Name of the group, this is basically the prefix you set in the |
0.1.0 |
type |
String |
The name of the class, if it is a nested class it will be the name of that class |
0.1.0 |
sourceType |
String |
The name of the class, if it is a nested class it will be the name of that parent class |
0.1.0 |
properties |
List<Property> |
List of the properties |
0.1.0 |
parentGroup |
PropertyGroup |
Parent property group |
0.1.0 |
childrenGroups |
List<PropertyGroup> |
Children property groups, in case of parent and nester class associations |
0.1.0 |
Variable | Type | Description | Since |
---|---|---|---|
fqName |
String |
Fully qualified name |
0.1.0 |
type |
String |
The Java type |
0.1.0 |
key |
String |
Property key |
0.1.0 |
description |
String |
Description of the property, read from the JavaDoc |
0.1.0 |
defaultValue |
String |
Default value if specified |
0.1.0 |
propertyDeprecation |
PropertyDeprecation |
If the property is marked as deprecated data about that |
0.1.0 |
Variable | Type | Description | Since |
---|---|---|---|
reason |
String |
Reason of the deprecation |
0.1.0 |
replacement |
String |
The replacement of the specific key |
0.1.0 |
TemplateCustomization subclasses
Variable | Type | Description | Default value | Since |
---|---|---|---|---|
headerEnabled |
boolean |
Controls if the header section (main module name and main module description) should be enabled/visible or not |
true |
0.2.0 |
tableOfContentsEnabled |
boolean |
Controls if the "Table of Contents" sections should be enabled or not |
true |
0.2.0 |
includeUnknownGroup |
boolean |
Controls if the properties without any known group should be included or not. It can happen if the input metadata JSON file is missing the group association with its properties. |
true |
0.3.0 |
unknownGroupLocalization |
String |
Overwrites the name of the |
Unknown group |
0.4.0 |
includeGenerationDate |
boolean |
Controls if the generation date should be rendered to the final document or not. |
true |
0.4.0 |
removeEmptyGroups |
boolean |
Controls if the empty property groups should be removed from the final document or not. |
false |
0.4.0 |
tocTitle |
String |
'Table of Contents' section’s title. By default, it is coming from the |
0.4.0 |
|
locale |
String |
Set’s the locale of the final document. - It will be converted to Locale with the |
JVM’s default locale. |
0.4.0 |
contentCustomization |
Configures the customization for the content (tables, property groups and properties) |
Check defaults below. |
0.6.0 |
|
templateMode |
STANDARD or COMPACT |
Sets the template mode. Read more about here |
STANDARD |
0.6.0 |
Variable | Type | Description | Default value | Since |
---|---|---|---|---|
includeClass |
boolean |
Controls if the property group’s class should be rendered or not in the final document. |
true |
0.6.0 |
includeKey |
boolean |
Controls if the property’s key should be rendered or not in the final document. |
true |
0.6.0 |
includeType |
boolean |
Controls if the property’s type should be rendered or not in the final document. |
true |
0.6.0 |
includeDescription |
String |
Controls if the property’s description should be rendered or not in the final document. |
true |
0.6.0 |
includeDefaultValue |
boolean |
Controls if the property’s default value should be rendered or not in the final document. |
true |
0.6.0 |
includeDeprecation |
boolean |
Controls if the property’s deprecation should be rendered or not in the final document. |
true |
0.6.0 |
includeEnvFormat |
boolean |
Controls if the environment variable form of the properties should be rendered into the final document or not. |
false |
0.6.0 |
Variable | Type | Description | Default value | Since |
---|
Variable | Type | Description | Default value | Since |
---|
Variable | Type | Description | Default value | Since |
---|---|---|---|---|
tocPlacement |
TocPlacement (AUTO, LEFT, RIGHT) |
"Table of Contents" placement |
AUTO |
0.2.0 |
tocLevels |
int |
"Table of Contents" level/depth |
4 |
0.2.0 |
Variable | Type | Description | Default value | Since |
---|---|---|---|---|
backgroundColor |
String |
Table and associated elements background color |
#7db04b |
0.2.0 |
linkColor |
String |
Link (<a>) text color |
black |
0.2.0 |
collapsibleHoverColor |
String |
Table of content based collapsible block hover color |
#96d95c |
0.2.0 |
codeColor |
String |
<code> section color |
#eeeeee |
0.2.0 |
evenTableRowColor |
String |
Even table row’s color |
#f3f3f3 |
0.2.0 |
lastTableRowColor |
String |
Last table row’s color |
#009879 |
0.2.0 |
tableRowColor |
String |
Table row color |
#ffffff |
0.2.0 |
tableRowBorderColor |
String |
Border color of the table rows |
#dddddd |
0.2.0 |
textColor |
String |
Text color |
white |
0.2.0 |
The full stylesheet can be found here in this file: https://github.com/rodnansol/spring-configuration-property-documenter/blob/master/spring-configuration-property-documenter-core/src/main/resources/templates/partials/html/header.html.hbs |
i18n resources
The following languages are supported, feel free to open new pull requests for additional languages.
-
English
-
Hungarian
-
German
-
Dutch
-
French
-
Italian
-
Romanian
The default file can be found here: spring-configuration-property-documenter-core/src/main/resources/messages.properties
Key | Description | Since |
---|---|---|
toc |
Title for the |
0.4.0 |
generationDate |
Localization for the generation date footer value |
0.4.0 |
backToTop |
Localization for the back to top section in the HTML template |
0.4.0 |
class |
Localization for the class field |
0.4.0 |
key |
Localization for the key field |
0.4.0 |
type |
Localization for the type field |
0.4.0 |
description |
Localization for the description field |
0.4.0 |
defaultValue |
Localization for the default value field |
0.4.0 |
deprecation |
Localization for the deprecation field |
0.4.0 |
environmentVariable |
Localization for the environmentVariable field |
0.4.0 |
It’s the default content:
template.toc=Table of Contents
template.generationDate=This is a generated file, generated at:
template.backToTop=Back to Top
template.class=Class
template.key=Key
template.type=Type
template.description=Description
template.defaultValue=Default value
template.deprecation=Deprecation
template.environmentVariable=Environment variable