Skip to content

Commit

Permalink
Introduce log4j-docgen-type-target-template argument to ApirefMacro
Browse files Browse the repository at this point in the history
  • Loading branch information
vy committed Mar 21, 2024
1 parent 982e613 commit cb98f92
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 24 deletions.
5 changes: 5 additions & 0 deletions log4j-docgen-asciidoctor-extension/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
<artifactId>log4j-docgen</artifactId>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-tools-internal-freemarker-util</artifactId>
</dependency>

<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package org.apache.logging.log4j.docgen.asciidoctor;

import static java.util.Collections.singletonMap;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.FileSystems;
Expand All @@ -36,6 +38,7 @@
import org.apache.logging.log4j.docgen.generator.internal.ArtifactSourcedType;
import org.apache.logging.log4j.docgen.generator.internal.TypeLookup;
import org.apache.logging.log4j.docgen.io.stax.PluginBundleStaxReader;
import org.apache.logging.log4j.tools.internal.freemarker.util.FreeMarkerUtils;
import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.extension.Format;
Expand All @@ -59,7 +62,7 @@ public final class ApirefMacro extends InlineMacroProcessor {

private TypeLookup lookup;

private String typeTemplateTarget;
private String typeTargetTemplate;

private boolean packageNameStripped;

Expand Down Expand Up @@ -97,14 +100,8 @@ private PhraseNode createPhraseNode(
}

private String createTypeTemplateTargetPath(final ArtifactSourcedType sourcedType) {
final String groupId = or(sourcedType.groupId, "unknown-groupId");
final String artifactId = or(sourcedType.artifactId, "unknown-artifactId");
final String version = or(sourcedType.version, "unknown-version");
return typeTemplateTarget
.replaceAll("%g", groupId)
.replaceAll("%a", artifactId)
.replaceAll("%v", version)
.replaceAll("%c", sourcedType.type.getClassName());
final Map<String, ArtifactSourcedType> templateData = singletonMap("sourcedType", sourcedType);
return FreeMarkerUtils.renderString(typeTargetTemplate, templateData);
}

private static String or(@Nullable final String value, final String fallback) {
Expand All @@ -116,7 +113,7 @@ private void initialize(final StructuralNode node) {
LOGGER.fine("Initializing...");
lookup = createTypeLookup(node);
final Map<String, Object> documentAttributes = node.getDocument().getAttributes();
typeTemplateTarget = getStringAttribute(documentAttributes, attributeName("type-template-target"), null);
typeTargetTemplate = getStringAttribute(documentAttributes, attributeName("type-target-template"), null);
packageNameStripped =
isBooleanAttributeProvided(documentAttributes, attributeName("package-name-stripped"));
initialized = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class ApirefMacroTest {

private final AttributesBuilder attributesBuilder = Attributes.builder()
.attribute("log4j-docgen-descriptor-directory", "src/test/resources/" + TEST_NAME + "/plugins.xml")
.attribute("log4j-docgen-type-template-target", "%g/%a/%c.html");
.attribute(
"log4j-docgen-type-target-template",
"#${sourcedType.groupId?replace('.', '-')}_${sourcedType.artifactId?replace('.', '-')}_${sourcedType.type.className?replace('.', '-')}");

@Test
void unlabeled_unknown_class() {
Expand All @@ -53,7 +55,7 @@ void labeled_unknown_class() {
void unlabeled_known_class() {
assertConversion(
"apiref:example.MyAppender[]",
"<a href=\"com.example.groupId/example-artifactId/example.MyAppender.html\">MyAppender</a>");
"<a href=\"#com-example-groupId_example-artifactId_example-MyAppender\">MyAppender</a>");
}

@Test
Expand All @@ -66,7 +68,7 @@ void unlabeled_known_excluded_class() {
void labeled_known_class() {
assertConversion(
"apiref:example.MyAppender[foo]",
"<a href=\"com.example.groupId/example-artifactId/example.MyAppender.html\">foo</a>");
"<a href=\"#com-example-groupId_example-artifactId_example-MyAppender\">foo</a>");
}

private void assertConversion(final String asciiDoc, final String expectedOutput) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
import freemarker.template.Version;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
Expand All @@ -39,20 +42,21 @@ public final class FreeMarkerUtils {

private static final String CHARSET_NAME = CHARSET.name();

private static final Version CONFIGURATION_VERSION = Configuration.VERSION_2_3_29;

private FreeMarkerUtils() {}

@SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
private static Configuration createConfiguration(final Path templateDirectory) {
final Version configurationVersion = Configuration.VERSION_2_3_29;
final Configuration configuration = new Configuration(configurationVersion);
final Configuration configuration = new Configuration(CONFIGURATION_VERSION);
configuration.setDefaultEncoding(CHARSET_NAME);
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
try {
configuration.setTemplateLoader(new FileTemplateLoader(templateDirectory.toFile()));
} catch (final IOException error) {
throw new UncheckedIOException(error);
}
final DefaultObjectWrapperBuilder objectWrapperBuilder = new DefaultObjectWrapperBuilder(configurationVersion);
final DefaultObjectWrapperBuilder objectWrapperBuilder = new DefaultObjectWrapperBuilder(CONFIGURATION_VERSION);
objectWrapperBuilder.setExposeFields(true);
final DefaultObjectWrapper objectWrapper = objectWrapperBuilder.build();
configuration.setObjectWrapper(objectWrapper);
Expand Down Expand Up @@ -83,4 +87,23 @@ public static void render(
throw new RuntimeException(message, error);
}
}

@SuppressFBWarnings("TEMPLATE_INJECTION_FREEMARKER")
public static String renderString(final String templateString, final Object templateData) {
final Configuration configuration = new Configuration(CONFIGURATION_VERSION);
final DefaultObjectWrapperBuilder objectWrapperBuilder = new DefaultObjectWrapperBuilder(CONFIGURATION_VERSION);
objectWrapperBuilder.setExposeFields(true);
final DefaultObjectWrapper objectWrapper = objectWrapperBuilder.build();
configuration.setObjectWrapper(objectWrapper);
try {
final Template template =
new Template("ephemeralInlineTemplate", new StringReader(templateString), configuration);
final Writer templateWriter = new StringWriter();
template.process(templateData, templateWriter);
return templateWriter.toString();
} catch (final Exception error) {
final String message = String.format("failed rendering template `%s`", templateString);
throw new RuntimeException(message, error);
}
}
}
15 changes: 7 additions & 8 deletions src/site/_log4j-docgen-asciidoctor-extension.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,13 @@ That is, if `true`, `apiref:some.unknown.Class[]` will be converted to `<code>Cl
Note that this only applies to types where the label is not provided.
This flag is disabled by default.
`log4j-docgen-type-template-target`::
The target file path of individual types documented, e.g., `../../%g/%a/%c.html`.
Certain directives are subject to substitution:
* `%a` – artifact ID, if the type is provided with an artifact origin; `unknown-artifactId`, otherwise
* `%c` – class name
* `%g` – group ID, if the type is provided with an artifact origin; `unknown-groupId`, otherwise
* `%v` – version, if the type is provided with an artifact origin; `unknown-version`, otherwise
`log4j-docgen-type-target-template`::
The FreeMarker template to produce the link target for individual types documented, for instance:
+
[source]
----
#${sourcedType.groupId?replace('.', '-')}_${sourcedType.artifactId?replace('.', '-')}_${sourcedType.type.className?replace('.', '-')
----
+
This attribute is *required*.

0 comments on commit cb98f92

Please sign in to comment.