diff --git a/modello-plugins/modello-plugin-xdoc/src/main/java/org/codehaus/modello/plugin/xdoc/XdocGenerator.java b/modello-plugins/modello-plugin-xdoc/src/main/java/org/codehaus/modello/plugin/xdoc/XdocGenerator.java index 9fceef8d6..289b6c9a6 100644 --- a/modello-plugins/modello-plugin-xdoc/src/main/java/org/codehaus/modello/plugin/xdoc/XdocGenerator.java +++ b/modello-plugins/modello-plugin-xdoc/src/main/java/org/codehaus/modello/plugin/xdoc/XdocGenerator.java @@ -29,6 +29,8 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import com.github.chhorz.javadoc.JavaDoc; @@ -685,6 +687,43 @@ private static void writeMarkupElement(XMLWriter w, String name, String markup) w.endElement(); } + /** + * Pattern matching {@code {@code ...}} and {@code {@literal ...}} inline tags, + * including nested braces. + */ + private static final Pattern INLINE_CODE_TAG_PATTERN = + Pattern.compile("\\{@(?:code|literal)\\s+((?:[^{}]|\\{[^{}]*\\})*)\\}"); + + /** + * HTML-escapes {@code <}, {@code >} and {@code &} in {@code s}. + * Handles both raw characters and pre-existing HTML entities (e.g. {@code <} from + * CDATA-wrapped .mdo descriptions) so that the result is always a clean, once-escaped + * HTML string. + */ + private static String escapeHtml(String s) { + // Normalise any pre-escaped entities first so we never double-escape + String unescaped = s.replace("<", "<").replace(">", ">").replace("&", "&"); + return unescaped.replace("&", "&").replace("<", "<").replace(">", ">"); + } + + /** + * Pre-processes Javadoc {@code {@code}} and {@code {@literal}} inline tags so that + * their content is HTML-escaped before being fed into the HTML/Jsoup pipeline. + * + *
Without this step, content such as {@code {@code } HTML element
+ * without escaping; Jsoup would then silently drop the unknown {@code
" + escapeHtml(m.group(1)) + ""));
+ }
+ m.appendTail(sb);
+ return sb.toString();
+ }
+
/**
* Ensures that text will have balanced tags
*
@@ -692,10 +731,14 @@ private static void writeMarkupElement(XMLWriter w, String name, String markup)
* @return valid XML string
*/
private static String rewrite(String text) {
+ // Pre-process {@code} / {@literal} tags to HTML-escape their content before the
+ // Javadoc parser and Jsoup pipeline see it; otherwise angle brackets inside those
+ // tags are treated as HTML elements and silently dropped by Jsoup.
+ String preprocessed = preprocessInlineCodeTags(text);
JavaDoc javaDoc = JavaDocParserBuilder.withStandardJavadocTags()
.withOutputType(OutputType.HTML)
.build()
- .parse(text);
+ .parse(preprocessed);
String html = javaDoc.getDescription()
+ javaDoc.getTags().stream()
.map(XdocGenerator::renderJavaDocTag)
diff --git a/modello-plugins/modello-plugin-xdoc/src/test/resources/html4.expected.xml b/modello-plugins/modello-plugin-xdoc/src/test/resources/html4.expected.xml
index a629a5bf3..15410f53c 100644
--- a/modello-plugins/modello-plugin-xdoc/src/test/resources/html4.expected.xml
+++ b/modello-plugins/modello-plugin-xdoc/src/test/resources/html4.expected.xml
@@ -13,6 +13,7 @@
properties
+ String
+ <name>value</name>.