diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
index e619acc..bc3cac8 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
@@ -25,6 +25,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
@@ -489,7 +491,7 @@ public class PluginXdocGenerator
tidy.setMakeClean( true );
tidy.setQuiet( true );
tidy.setShowWarnings( false );
- tidy.parse( new StringInputStream( description ), out );
+ tidy.parse( new StringInputStream( decodeJavadocTags( description ) ), out );
// strip the header/body stuff
String LS = System.getProperty( "line.separator" );
@@ -503,4 +505,116 @@ public class PluginXdocGenerator
return commentCleaned.substring( startPos, endPos );
}
+
+ /**
+ * Decodes javadoc inline tags into equivalent HTML tags. For instance, the inline tag "{@code }" should be
+ * rendered as "<A&B>".
+ *
+ * @param description The javadoc description to decode, may be null.
+ * @return The decoded description, never null.
+ */
+ protected static String decodeJavadocTags( String description )
+ {
+ if ( StringUtils.isEmpty( description ) )
+ {
+ return "";
+ }
+
+ StringBuffer decoded = new StringBuffer( description.length() + 1024 );
+
+ Matcher matcher = Pattern.compile( "\\{@(\\w+)\\s*([^\\}]*)\\}" ).matcher( description );
+ while ( matcher.find() )
+ {
+ String tag = matcher.group( 1 );
+ String text = matcher.group( 2 );
+ text = StringUtils.replace( text, "&", "&" );
+ text = StringUtils.replace( text, "<", "<" );
+ text = StringUtils.replace( text, ">", ">" );
+ if ( "code".equals( tag ) )
+ {
+ text = "" + text + "";
+ }
+ else if ( "link".equals( tag ) || "linkplain".equals( tag ) || "value".equals( tag ) )
+ {
+ String pattern = "(([^#\\.\\s]+\\.)*([^#\\.\\s]+))?" + "(#([^\\(\\s]*)(\\([^\\)]*\\))?\\s*(\\S.*)?)?";
+ final int LABEL = 7;
+ final int CLASS = 3;
+ final int MEMBER = 5;
+ final int ARGS = 6;
+ Matcher link = Pattern.compile( pattern ).matcher( text );
+ if ( link.matches() )
+ {
+ text = link.group( LABEL );
+ if ( StringUtils.isEmpty( text ) )
+ {
+ text = link.group( CLASS );
+ if ( StringUtils.isEmpty( text ) )
+ {
+ text = "";
+ }
+ if ( StringUtils.isNotEmpty( link.group( MEMBER ) ) )
+ {
+ if ( StringUtils.isNotEmpty( text ) )
+ {
+ text += '.';
+ }
+ text += link.group( MEMBER );
+ if ( StringUtils.isNotEmpty( link.group( ARGS ) ) )
+ {
+ text += "()";
+ }
+ }
+ }
+ }
+ if ( !"linkplain".equals( tag ) )
+ {
+ text = "" + text + "";
+ }
+ }
+ matcher.appendReplacement( decoded, ( text != null ) ? quoteReplacement( text ) : "" );
+ }
+ matcher.appendTail( decoded );
+
+ return decoded.toString();
+ }
+
+ /**
+ * Returns a literal replacement String for the specified String. This method
+ * produces a String that will work as a literal replacement s in the
+ * appendReplacement method of the {@link Matcher} class. The String produced will
+ * match the sequence of characters in s treated as a literal sequence. Slashes ('\') and dollar
+ * signs ('$') will be given no special meaning.
+ *
+ * TODO: copied from Matcher class of Java 1.5, remove once target platform can be upgraded
+ * @see
+ * http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Matcher.html
+ *
+ * @param s The string to be literalized
+ * @return A literal string replacement
+ */
+ private static String quoteReplacement( String s )
+ {
+ if ( ( s.indexOf( '\\' ) == -1 ) && ( s.indexOf( '$' ) == -1 ) )
+ return s;
+ StringBuffer sb = new StringBuffer();
+ for ( int i = 0; i < s.length(); i++ )
+ {
+ char c = s.charAt( i );
+ if ( c == '\\' )
+ {
+ sb.append( '\\' );
+ sb.append( '\\' );
+ }
+ else if ( c == '$' )
+ {
+ sb.append( '\\' );
+ sb.append( '$' );
+ }
+ else
+ {
+ sb.append( c );
+ }
+ }
+ return sb.toString();
+ }
}
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
index 41f6b5c..3c4c99f 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
@@ -41,4 +41,58 @@ public class PluginXdocGeneratorTest
assertEquals( "Generates something for the project.", PluginXdocGenerator
.makeHtmlValid( javadoc ) );
}
-}
\ No newline at end of file
+
+ public void testDecodeJavadocTags()
+ {
+ String javadoc = null;
+ assertEquals( "", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "";
+ assertEquals( "", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@code text}";
+ assertEquals( "text", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@code }";
+ assertEquals( "<A&B>", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@literal text}";
+ assertEquals( "text", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@literal text} {@literal text}";
+ assertEquals( "text text", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@literal }";
+ assertEquals( "<A&B>", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@link Class}";
+ assertEquals( "Class", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain Class}";
+ assertEquals( "Class", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain #field}";
+ assertEquals( "field", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain Class#field}";
+ assertEquals( "Class.field", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain #method()}";
+ assertEquals( "method()", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain #method(Object arg)}";
+ assertEquals( "method()", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain #method(Object, String)}";
+ assertEquals( "method()", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain #method(Object, String) label}";
+ assertEquals( "label", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain Class#method(Object, String)}";
+ assertEquals( "Class.method()", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+
+ javadoc = "{@linkplain Class#method(Object, String) label}";
+ assertEquals( "label", PluginXdocGenerator.decodeJavadocTags( javadoc ) );
+ }
+}