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 release of the 0.6.0 version the tool now supports different templates modes, the default and fallback option is called STANDARD

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_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_A_BEAN_CONFIGURATION_CONFIGURATIONVALUE

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_NESTED_NESTEDVALUE

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_FIRSTLEVELNESTEDPROPERTY_SECONDLEVELNESTEDCLASS_SECONDLEVELVALUE

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

THIS_IS_MY_ANOTHERVARIABLE

date

java.time.LocalDate

THIS_IS_MY_DATE

date-time

java.time.LocalDateTime

THIS_IS_MY_DATETIME

duration

java.time.Duration

A duration.

2d

Reason: Because it is deprecated, use for replacement: instant

THIS_IS_MY_DURATION

instant

java.time.Instant

123

THIS_IS_MY_INSTANT

variable

java.lang.String

This is my variable.

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

THIS_IS_MY_FIRSTLEVELNESTEDPROPERTY_DESC

name

java.lang.String

Name of the custom property.

ABC

THIS_IS_MY_FIRSTLEVELNESTEDPROPERTY_NAME

Markdown
image$standard document md
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
image$compact document md

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

Example
// 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[]
Example include
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.

Example file
=== 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
|


|===
Example include
: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 the spring-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:

pom.xml
<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
pom.xml
<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

Table 1. Template variables (MainTemplateData)
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 spring-configuration-metadata.json

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

Table 2. Template variables (SubTemplateData)
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 spring-configuration-metadata.json

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

Table 3. Template variables (PropertyGroup)
Variable Type Description Since

groupName

String

Name of the group, this is basically the prefix you set in the @ConfigurationProperties annotation

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

Table 4. Template variables (Property)
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

Table 5. Template variables (PropertyDeprecation)
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

Table 6. org.rodnansol.core.generator.template.customization.AbstractTemplateCustomization
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

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 messages.properties

0.4.0

locale

String

Set’s the locale of the final document. - It will be converted to Locale with the Locale.forLanguageTag method.

JVM’s default locale.

0.4.0

contentCustomization

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

Table 7. org.rodnansol.core.generator.template.customization.ContentCustomization
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

Table 8. org.rodnansol.core.generator.template.customization.MarkdownTemplateCustomization
Variable Type Description Default value Since
Table 9. org.rodnansol.core.generator.template.customization.XmlTemplateCustomization
Variable Type Description Default value Since
Table 10. org.rodnansol.core.generator.template.customization.AsciiDocTemplateCustomization
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

Table 11. org.rodnansol.core.generator.template.customization.HtmlTemplateCustomization
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

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

Table 12. The following keys are available in your custom templates
Key Description Since

toc

Title for the Table of Contents section

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