Skip to content

Commit 8968d7b

Browse files
committed
Handle Comment-Only Titles
1 parent d2df7f6 commit 8968d7b

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertHtmlNodeRenderer.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import org.commonmark.ext.gfm.alerts.Alert;
44
import org.commonmark.ext.gfm.alerts.AlertTitle;
5+
import org.commonmark.node.HtmlInline;
56
import org.commonmark.node.Node;
7+
import org.commonmark.node.Text;
68
import org.commonmark.renderer.html.HtmlNodeRendererContext;
79
import org.commonmark.renderer.html.HtmlWriter;
810

@@ -38,6 +40,21 @@ protected void renderAlert(Alert alert) {
3840
htmlWriter.tag("p", context.extendAttributes(alert, "p", Map.of("class", "markdown-alert-title")));
3941
var first = alert.getFirstChild();
4042
if (first instanceof AlertTitle) {
43+
/*
44+
* If the alert title only contains HTML comments like this:
45+
*
46+
* > [!TIP] <!-- This won't appear --> <!---> <!-- Neither will this -->
47+
* > Body text
48+
*
49+
* Then the reader will see a blank title. In this case, it's better
50+
* to render the default title (but keep the comments for accuracy).
51+
*
52+
* These comments will be visible when rendered to other formats like
53+
* Markdown, so this is only relevant for the HTML renderer.
54+
*/
55+
if (isCommentOnlyTitle(first)) {
56+
htmlWriter.text(getAlertTitle(type));
57+
}
4158
renderChildren(first);
4259
} else {
4360
htmlWriter.text(getAlertTitle(type));
@@ -73,6 +90,38 @@ private String getAlertTitle(String type) {
7390
}
7491
}
7592

93+
private boolean isCommentOnlyTitle(Node title) {
94+
var node = title.getFirstChild();
95+
if (node == null) {
96+
return false;
97+
}
98+
while (node != null) {
99+
if (node instanceof HtmlInline) {
100+
if (!isHtmlComment((HtmlInline) node)) {
101+
return false;
102+
}
103+
} else if (node instanceof Text) {
104+
if (!((Text) node).getLiteral().trim().isEmpty()) {
105+
return false;
106+
}
107+
} else {
108+
return false;
109+
}
110+
node = node.getNext();
111+
}
112+
return true;
113+
}
114+
115+
private boolean isHtmlComment(HtmlInline htmlInline) {
116+
String literal = htmlInline.getLiteral();
117+
if (literal == null || !literal.startsWith("<!--")) {
118+
return false;
119+
}
120+
return literal.equals("<!-->")
121+
|| literal.equals("<!--->")
122+
|| literal.endsWith("-->");
123+
}
124+
76125
private void renderChildren(Node parent) {
77126
var node = parent.getFirstChild();
78127
while (node != null) {

commonmark-ext-gfm-alerts/src/test/java/org/commonmark/ext/gfm/alerts/AlertsTest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public void customTitleWithComment() {
162162
public void customTitleWithOnlyCommentFallsBackToDefaultTitle() {
163163
assertRenderingCustomTitles("> [!TIP] <!-- This won't appear --> <!-- This won't either -->\n> Body text",
164164
"<div class=\"markdown-alert markdown-alert-tip\" data-alert-type=\"tip\">\n" +
165-
"<p class=\"markdown-alert-title\">Tip <!-- This won't appear --> <!-- This won't either --></p>\n" +
165+
"<p class=\"markdown-alert-title\">Tip<!-- This won't appear --> <!-- This won't either --></p>\n" +
166166
"<p>Body text</p>\n" +
167167
"</div>\n");
168168
}
@@ -238,6 +238,15 @@ public void onlyTrailingWhitespaceIsNotCustomTitle() {
238238
"</div>\n");
239239
}
240240

241+
@Test
242+
public void onlyHtmlCommentsInTitleUseDefaultTitle() {
243+
assertRenderingCustomTitles("> [!NOTE] <!-- This won't appear --> <!---> <!-- Neither will this -->\n> Body text",
244+
"<div class=\"markdown-alert markdown-alert-note\" data-alert-type=\"note\">\n" +
245+
"<p class=\"markdown-alert-title\">Note<!-- This won't appear --> <!---> <!-- Neither will this --></p>\n" +
246+
"<p>Body text</p>\n" +
247+
"</div>\n");
248+
}
249+
241250
// Lazy continuation
242251

243252
@Test

0 commit comments

Comments
 (0)