Skip to content

Commit

Permalink
Inject maven properties in asciidoctor mojo (#459)
Browse files Browse the repository at this point in the history
* inject Maven properties as attributes in Mojo same as site module

* updates README

* adds unit test

* updates CHANGELOG
  • Loading branch information
abelsromero committed Jul 14, 2020
1 parent 30379a5 commit b7f4c34
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 32 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Expand Up @@ -13,6 +13,10 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/master[

== Unreleased

Improvements::

* Inject Maven properties as attributes in `process-asciidoc` mojo (#459)

Bug Fixes::

* Remove Maven components from plugin descriptor (#450)
Expand Down
33 changes: 13 additions & 20 deletions README.adoc
Expand Up @@ -216,6 +216,18 @@ Refer to the http://asciidoctor.org/docs/user-manual/#attribute-catalog[catalog
<source-highlighter>coderay</source-highlighter>
</attributes>
----
In addition to those attributes found in this section, any Maven property is also passed as attribute (replacing . by -).
+
[source,xml]
----
<properties>
<my-site.version>2.3.0</my-site.version> <.>
</properties>
----
<.> Will be passed as `my-site-version` to the converter.
+
Note that when defining a build with multiple executions, shared attributes can be set in the global `<configuration>` section of the plugin.

embedAssets:: embeds the CSS file and images into the output, defaults to `false`
gemPaths:: enables to specify the location to one or more gem installation directories (same as GEM_PATH environment var), `empty` by default
requires:: a `List<String>` to specify additional Ruby libraries not packaged in AsciidoctorJ, `empty` by default
Expand Down Expand Up @@ -306,25 +318,6 @@ Since version 1.5.8 of AsciidoctorJ set `enableVerbose` to `true` option to vali
See https://github.com/asciidoctor/asciidoctor/issues/2722[#2722] if your are interested in the details.
====

==== Passing POM properties

It is possible to pass properties defined in the POM to the Asciidoctor processor.
This is handy for example to include in the generated document the POM artifact version number.

This is done by creating a custom AsciiDoc property in the `attributes` section of the `configuration`.
The AsciiDoc property value is defined in the usual Maven way: `${property.name}`.

[source,xml]
----
<attributes>
<project-version>${project.version}</project-version>
</attributes>
----

The custom AsciiDoc property can then be used in the document like this:

The latest version of the project is {project-version}.

==== Setting boolean values

Boolean attributes in asciidoctor, such as `sectnums`, `linkcss` or `copycss` can be set with a value of `true` and unset with a value of `false`.
Expand Down Expand Up @@ -558,7 +551,7 @@ Specifies additional Ruby libraries not packaged in AsciidoctorJ, `empty` by def
attributes::
Similar to the plugin's `attributes`. +
Allows defining a set of Asciidoctor attributes to be passed to the conversion. +
In addition to those attributes found in this section, any maven property is also passed as attribute (replacing . by -).
In addition to those attributes found in this section, any Maven property is also passed as attribute (replacing . by -).
+
[source,xml]
----
Expand Down
1 change: 1 addition & 0 deletions src/it/inject-attributes-from-maven-pom/invoker.properties
@@ -0,0 +1 @@
invoker.goals=clean generate-resources
45 changes: 45 additions & 0 deletions src/it/inject-attributes-from-maven-pom/pom.xml
@@ -0,0 +1,45 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.asciidoctor</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>

<name>Converts Asciidoctor Article to Html</name>
<description>Processes attributes from different sections in the Maven pom</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.property.attribute>project property configuration</project.property.attribute>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>@project.version@</version>
<configuration>
<attributes>
<plugin-configuration-attribute>plugin configuration</plugin-configuration-attribute>
</attributes>
</configuration>
<executions>
<execution>
<id>asciidoc-to-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<attributes>
<execution-attribute>execution configuration</execution-attribute>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
Document Title
==============
Doc Writer <thedoc@asciidoctor.org>
:execution.attribute: cosa
:idprefix: id_

Preamble paragraph.

NOTE: This is test, only a test.

== Section A

* This attribute is set in the plugin configuration: {plugin-configuration-attribute}
* This attribute is set in the execution configuration: {execution-attribute}
* This attribute is set in the project's properties: {project-property-attribute}
19 changes: 19 additions & 0 deletions src/it/inject-attributes-from-maven-pom/validate.groovy
@@ -0,0 +1,19 @@
final File outputDir = new File(basedir, "target/generated-docs");
final File expectedFile = new File(outputDir, 'attributes-example.html')

if (!expectedFile.exists()) {
throw new Exception("Missing file " + expectedFile)
}

expectedFile.text.with { outputContent ->
assertContains(outputContent, 'This attribute is set in the plugin configuration: plugin configuration')
assertContains(outputContent, 'This attribute is set in the execution configuration: execution configuration')
assertContains(outputContent, 'This attribute is set in the project&#8217;s properties: project property configuration')
}

void assertContains(String text, String expectedValueToContain) {
if (!text.contains(expectedValueToContain))
throw new Exception("Expected value '$expectedValueToContain' not found")
}

return true
16 changes: 16 additions & 0 deletions src/main/java/org/asciidoctor/maven/AsciidoctorHelper.java
Expand Up @@ -12,6 +12,7 @@

package org.asciidoctor.maven;

import org.apache.maven.project.MavenProject;
import org.asciidoctor.Attributes;
import org.asciidoctor.AttributesBuilder;

Expand All @@ -36,6 +37,21 @@ public static void addAttributes(final Map<String, Object> attributes, Attribute
}
}

/**
* Adds properties from the {@link MavenProject} into a {@link AttributesBuilder} taking care of Maven's XML parsing special
* cases like toggles, nulls, etc.
*
* @param project Maven project
* @param attributesBuilder AsciidoctorJ AttributesBuilder
*/
public static void addMavenProperties(MavenProject project, AttributesBuilder attributesBuilder) {
if (project.getProperties() != null) {
for (Map.Entry<Object, Object> entry : project.getProperties().entrySet()) {
attributesBuilder.attribute(((String) entry.getKey()).replaceAll("\\.", "-"), entry.getValue());
}
}
}

/**
* Adds an attribute into a {@link AttributesBuilder} taking care of Maven's XML parsing special cases like
* toggles toggles, nulls, etc.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/asciidoctor/maven/AsciidoctorMojo.java
Expand Up @@ -517,12 +517,13 @@ protected void setOptionsOnBuilder(OptionsBuilder optionsBuilder) {
optionsBuilder.templateDirs(templateDirs.toArray(new File[]{}));
}

protected void setAttributesOnBuilder(AttributesBuilder attributesBuilder) throws MojoExecutionException {
protected void setAttributesOnBuilder(AttributesBuilder attributesBuilder) {
if (embedAssets) {
attributesBuilder.linkCss(false);
attributesBuilder.dataUri(true);
}

AsciidoctorHelper.addMavenProperties(project, attributesBuilder);
AsciidoctorHelper.addAttributes(attributes, attributesBuilder);

if (!attributesChain.isEmpty()) {
Expand Down
Expand Up @@ -37,11 +37,7 @@ SiteConversionConfiguration processAsciiDocConfig(Xpp3Dom siteConfig,
return new SiteConversionConfiguration(options.get(), Collections.emptyList());
}

if (project.getProperties() != null) {
for (Map.Entry<Object, Object> entry : project.getProperties().entrySet()) {
presetAttributes.attribute(((String) entry.getKey()).replaceAll("\\.", "-"), entry.getValue());
}
}
AsciidoctorHelper.addMavenProperties(project, presetAttributes);

final List<String> gemsToRequire = new ArrayList<>();
for (Xpp3Dom asciidocOpt : asciidocConfig.getChildren()) {
Expand Down
Expand Up @@ -439,7 +439,7 @@ class AsciidoctorMojoTest extends Specification {
}

// Test for Issue 62
def 'setting_boolean_values'() {
def 'setting boolean attributes values'() {
given:
File srcDir = new File(DEFAULT_SOURCE_DIRECTORY)
File outputDir = new File('target/asciidoctor-output-issue-62')
Expand All @@ -460,11 +460,39 @@ class AsciidoctorMojoTest extends Specification {
File sampleOutput = new File(outputDir, 'sample.html')
String text = sampleOutput.getText()
text.contains('class="toc2"')
}

def 'should inject attributes from maven property, plugin and execution'() {
given:
MockPlexusContainer.initializeMockContext(AsciidoctorMojo,
['project.property.attribute': 'project property configuration'])
File srcDir = new File(DEFAULT_SOURCE_DIRECTORY)
File outputDir = new File('target/unit-tests/attributes')

if (!outputDir.exists())
outputDir.mkdir()
when:
AsciidoctorMojo mojo = new AsciidoctorMojo()
mojo.outputDirectory = outputDir
mojo.sourceDirectory = srcDir
mojo.sourceDocumentName = 'attributes-example.adoc'
mojo.backend = 'html5'
mojo.attributes = [
'plugin-configuration-attribute': 'plugin configuration',
'execution-attribute': 'execution configuration'
]
mojo.resources = [new Resource(directory: '.', excludes: ['**/**'])]
mojo.execute()
then:
File sampleOutput = new File(outputDir, 'attributes-example.html')
String text = sampleOutput.getText()
text.contains('This attribute is set in the project&#8217;s properties: project property configuration')
text.contains('This attribute is set in the plugin configuration: plugin configuration')
text.contains('This attribute is set in the execution configuration: execution configuration')
}

// Test for Issue 62 (unset)
def 'unsetting_boolean_values'() {
def 'unsetting boolean attributes values'() {
given:
File srcDir = new File(DEFAULT_SOURCE_DIRECTORY)
File outputDir = new File('target/asciidoctor-output-issue-62-unset')
Expand Down
Expand Up @@ -23,12 +23,14 @@ class MockPlexusContainer {
Log logger = new SystemStreamLog()
}

private void initializeMojoContext(AsciidoctorMojo mojo) {
private void initializeMojoContext(AsciidoctorMojo mojo, Map<String, String> properties) {

mojo.@project = [
getBasedir: {
getBasedir : {
return new File('.')
}] as MavenProject
},
getProperties: properties as Properties
] as MavenProject

mojo.@buildContext = new DefaultBuildContext()

Expand All @@ -51,12 +53,16 @@ class MockPlexusContainer {
* Intercept Asciidoctor mojo constructor to mock and inject required plexus objects.
*/
static MockPlexusContainer initializeMockContext(Class<?> clazz) {
initializeMockContext(clazz, Collections.emptyMap())
}

static MockPlexusContainer initializeMockContext(Class<?> clazz, Map<String, String> mavenProperties) {
final MockPlexusContainer mockPlexusContainer = new MockPlexusContainer()
def oldConstructor = clazz.constructors[0]

clazz.metaClass.constructor = {
def mojo = oldConstructor.newInstance()
mockPlexusContainer.initializeMojoContext(mojo)
mockPlexusContainer.initializeMojoContext(mojo, mavenProperties)
return mojo
}
mockPlexusContainer
Expand Down
15 changes: 15 additions & 0 deletions src/test/resources/src/asciidoctor/attributes-example.adoc
@@ -0,0 +1,15 @@
Document Title
==============
Doc Writer <thedoc@asciidoctor.org>
:execution.attribute: cosa
:idprefix: id_

Preamble paragraph.

NOTE: This is test, only a test.

== Section A

* This attribute is set in the plugin configuration: {plugin-configuration-attribute}
* This attribute is set in the execution configuration: {execution-attribute}
* This attribute is set in the project's properties: {project-property-attribute}

0 comments on commit b7f4c34

Please sign in to comment.