This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-doxia.git
The following commit(s) were added to refs/heads/master by this push:
new 074f7843 Support strikethrough for Markdown sink (#1033)
074f7843 is described below
commit 074f7843ed2fec3e9843f4bce29e3c36d959bf80
Author: Konrad Windszus <[email protected]>
AuthorDate: Tue Feb 24 10:41:54 2026 +0100
Support strikethrough for Markdown sink (#1033)
Properly support inline attributes not natively supported in Markdown.
Add tests for strikethrough/del to all Sinks.
Remove unused methods from Sink tests.
This closes #872
---
.../maven/doxia/sink/impl/AbstractSinkTest.java | 32 +++++++++-
.../apache/maven/doxia/module/apt/AptSinkTest.java | 12 +---
.../doxia/module/markdown/MarkdownMarkup.java | 6 ++
.../maven/doxia/module/markdown/MarkdownSink.java | 71 ++++++++++++++++------
.../doxia/module/markdown/MarkdownParserTest.java | 13 ++++
.../doxia/module/markdown/MarkdownSinkTest.java | 8 +--
.../maven/doxia/module/xdoc/XdocSinkTest.java | 4 ++
.../maven/doxia/module/xhtml5/Xhtml5SinkTest.java | 12 +---
8 files changed, 114 insertions(+), 44 deletions(-)
diff --git
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
index 5e5cc0c2..022f80d0 100644
---
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
+++
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/AbstractSinkTest.java
@@ -1009,7 +1009,7 @@ public abstract class AbstractSinkTest extends
AbstractModuleTest {
/**
* Checks that the sequence <code>[inline(italic), text(text),
inline_()]</code>,
* invoked on the current sink, produces the same result as
- * {@link #getInlineBoldBlock getInlineBoldBlock}(text).
+ * {@link #getInlineItalicBlock}.
*/
@Test
public void inlineItalic() {
@@ -1029,7 +1029,7 @@ public abstract class AbstractSinkTest extends
AbstractModuleTest {
/**
* Checks that the sequence <code>[inline(code), text(text),
inline_()]</code>,
* invoked on the current sink, produces the same result as
- * {@link #getInlineBoldBlock getInlineBoldBlock}(text).
+ * {@link #getInlineCodeBlock}.
*/
@Test
public void inlineCode() {
@@ -1046,6 +1046,26 @@ public abstract class AbstractSinkTest extends
AbstractModuleTest {
assertEquals(expected, actual, "Wrong inline code!");
}
+ /**
+ * Checks that the sequence <code>[inline(code), text(text),
inline_()]</code>,
+ * invoked on the current sink, produces the same result as
+ * {@link #getInlineDeleteBlock}.
+ */
+ @Test
+ public void inlineDelete() {
+ String text = "InlineDelete";
+ sink.inline(SinkEventAttributeSet.Semantics.DELETE);
+ sink.text(text);
+ sink.inline_();
+ sink.flush();
+ sink.close();
+
+ String actual = testWriter.toString();
+ String expected = getInlineDeleteBlock(text);
+
+ assertEquals(expected, actual, "Wrong inline code!");
+ }
+
/**
* Checks that the sequence <code>[lineBreak()]</code>,
* invoked on the current sink, produces the same result as
@@ -1565,6 +1585,14 @@ public abstract class AbstractSinkTest extends
AbstractModuleTest {
*/
protected abstract String getInlineCodeBlock(String text);
+ /**
+ * Returns an Inline code block generated by this sink.
+ * @param text The text to use.
+ * @return The result of invoking a Inline cdldgd block on the current
sink.
+ * @see #inlineBold()
+ */
+ protected abstract String getInlineDeleteBlock(String text);
+
/**
* Returns a LineBreak block generated by this sink.
* @return The result of invoking a LineBreak block on the current sink.
diff --git
a/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptSinkTest.java
b/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptSinkTest.java
index 2ff3b72b..bbad9639 100644
---
a/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptSinkTest.java
+++
b/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptSinkTest.java
@@ -256,15 +256,9 @@ class AptSinkTest extends AbstractSinkTest {
return AptMarkup.MONOSPACED_START_MARKUP + text +
AptMarkup.MONOSPACED_END_MARKUP;
}
- protected String getItalicBlock(String text) {
- return AptMarkup.ITALIC_START_MARKUP + text +
AptMarkup.ITALIC_END_MARKUP;
- }
-
- protected String getBoldBlock(String text) {
- return AptMarkup.BOLD_START_MARKUP + text + AptMarkup.BOLD_END_MARKUP;
- }
-
- protected String getMonospacedBlock(String text) {
+ @Override
+ protected String getInlineDeleteBlock(String text) {
+ // delete/strikethrough is not supported in APT, so we just return the
text without any markup
return text;
}
diff --git
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownMarkup.java
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownMarkup.java
index b7bbccd2..9d7b0f55 100644
---
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownMarkup.java
+++
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownMarkup.java
@@ -68,6 +68,12 @@ public interface MarkdownMarkup extends TextMarkup {
/** Syntax for the italic style start: "_" */
String ITALIC_START_MARKUP = "_";
+ /** Syntax for the strikethrough style end: "~~",
https://github.github.com/gfm/#strikethrough-extension- */
+ String STRIKETHROUGH_END_MARKUP = "~~";
+
+ /** Syntax for the strikethrough style start: "~~",
https://github.github.com/gfm/#strikethrough-extension- */
+ String STRIKETHROUGH_START_MARKUP = "~~";
+
/** Syntax for the link end: ")" */
String LINK_END_MARKUP = ")";
diff --git
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
index e40d59dd..88c987a0 100644
---
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
+++
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownSink.java
@@ -18,6 +18,9 @@
*/
package org.apache.maven.doxia.module.markdown;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.MutableAttributeSet;
+
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
@@ -88,7 +91,9 @@ public class MarkdownSink extends Xhtml5BaseSink implements
MarkdownMarkup {
/** A temporary writer used to buffer the last two lines */
private final LastTwoLinesBufferingWriter bufferingWriter;
- /** Keep track of end markup for inline events. */
+ private static final String USE_XHTML_SINK = "XhtmlSink";
+
+ /** Keep track of end markup for inline events. Special value {@link
#USE_XHTML_SINK} is used to indicate usage of the Xhtml5BaseSink.inline_()*/
protected Queue<Queue<String>> inlineStack;
/** The context of the surrounding elements as stack (LIFO) */
@@ -1074,19 +1079,19 @@ public class MarkdownSink extends Xhtml5BaseSink
implements MarkdownMarkup {
@Override
public void inline(SinkEventAttributes attributes) {
+ Queue<String> endMarkups = Collections.asLifoQueue(new LinkedList<>());
if (elementContextStack.element().isHtml()) {
super.inline(attributes);
+ endMarkups.add(USE_XHTML_SINK);
} else {
- Queue<String> endMarkups = Collections.asLifoQueue(new
LinkedList<>());
-
boolean requiresHtml = elementContextStack.element() ==
ElementContext.HTML_BLOCK;
if (attributes != null
&& elementContextStack.element() !=
ElementContext.CODE_BLOCK
&& elementContextStack.element() !=
ElementContext.CODE_SPAN) {
// code excludes other styles in markdown
- if
(attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "code")
- ||
attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "monospaced")
- ||
attributes.containsAttribute(SinkEventAttributes.STYLE, "monospaced")) {
+ if
(attributes.containsAttributes(SinkEventAttributeSet.Semantics.CODE)
+ ||
attributes.containsAttributes(SinkEventAttributeSet.Semantics.MONOSPACED)
+ ||
attributes.containsAttributes(SinkEventAttributeSet.MONOSPACED)) {
if (requiresHtml) {
writeUnescaped("<code>");
endMarkups.add("</code>");
@@ -1096,10 +1101,13 @@ public class MarkdownSink extends Xhtml5BaseSink
implements MarkdownMarkup {
endMarkups.add(MONOSPACED_END_MARKUP);
}
} else {
+ SinkEventAttributeSet remainingAttributes = new
SinkEventAttributeSet(attributes);
// in XHTML "<em>" is used, but some tests still rely on
the outdated "<italic>"
- if
(attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "emphasis")
- ||
attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "italic")
- ||
attributes.containsAttribute(SinkEventAttributes.STYLE, "italic")) {
+ if (filterAttributes(
+ remainingAttributes,
+ SinkEventAttributeSet.Semantics.EMPHASIS,
+ SinkEventAttributeSet.Semantics.ITALIC,
+ SinkEventAttributeSet.ITALIC)) {
if (requiresHtml) {
writeUnescaped("<em>");
endMarkups.add("</em>");
@@ -1109,9 +1117,11 @@ public class MarkdownSink extends Xhtml5BaseSink
implements MarkdownMarkup {
}
}
// in XHTML "<strong>" is used, but some tests still rely
on the outdated "<bold>"
- if
(attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "strong")
- ||
attributes.containsAttribute(SinkEventAttributes.SEMANTICS, "bold")
- ||
attributes.containsAttribute(SinkEventAttributes.STYLE, "bold")) {
+ if (filterAttributes(
+ remainingAttributes,
+ SinkEventAttributeSet.Semantics.STRONG,
+ SinkEventAttributeSet.Semantics.BOLD,
+ SinkEventAttributeSet.BOLD)) {
if (requiresHtml) {
writeUnescaped("<strong>");
endMarkups.add("</strong>");
@@ -1120,18 +1130,45 @@ public class MarkdownSink extends Xhtml5BaseSink
implements MarkdownMarkup {
endMarkups.add(BOLD_END_MARKUP);
}
}
+ // <del> is supported via GFM strikethrough extension
+ if (filterAttributes(remainingAttributes,
SinkEventAttributeSet.Semantics.DELETE)) {
+ if (requiresHtml) {
+ writeUnescaped("<del>");
+ endMarkups.add("</del>");
+ } else {
+ writeUnescaped(STRIKETHROUGH_START_MARKUP);
+ endMarkups.add(STRIKETHROUGH_END_MARKUP);
+ }
+ }
+ if (!remainingAttributes.isEmpty()) {
+ // use HTML for other inline semantics which are not
natively supported in Markdown (e.g.
+ // subscript, superscript, small, etc.)
+ super.inline(remainingAttributes);
+ endMarkups.add(USE_XHTML_SINK);
+ }
}
}
- inlineStack.add(endMarkups);
}
+ inlineStack.add(endMarkups);
+ }
+
+ private static boolean filterAttributes(MutableAttributeSet attributes,
AttributeSet... attributesToFilter) {
+ boolean hasAny = false;
+ for (AttributeSet attributeSet : attributesToFilter) {
+ if (attributes.containsAttributes(attributeSet)) {
+ hasAny = true;
+ attributes.removeAttributes(attributeSet);
+ }
+ }
+ return hasAny;
}
@Override
public void inline_() {
- if (elementContextStack.element().isHtml()) {
- super.inline_();
- } else {
- for (String endMarkup : inlineStack.remove()) {
+ for (String endMarkup : inlineStack.remove()) {
+ if (USE_XHTML_SINK.equals(endMarkup)) {
+ super.inline_();
+ } else {
if (endMarkup.equals(MONOSPACED_END_MARKUP)) {
String buffer = getCurrentBuffer().toString();
endContext(ElementContext.CODE_SPAN);
diff --git
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
index 1fad1a69..4b9b66e4 100644
---
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
+++
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
@@ -888,4 +888,17 @@ class MarkdownParserTest extends AbstractParserTest {
assertSinkStartsWith(eventIterator, "paragraph", "anchor", "text",
"anchor_", "paragraph_");
assertEventSuffix(eventIterator);
}
+
+ @Test
+ void strikeThrough() throws ParseException {
+ Iterator<SinkEventElement> eventIterator =
parseSourceToEventTestingSink("~~strikethrough~~")
+ .getEventList()
+ .iterator();
+ assertEventPrefix(eventIterator);
+ assertSinkStartsWith(eventIterator, "paragraph");
+ // https://github.github.com/gfm/#strikethrough-extension- uses "del"
element (not "s")
+ assertSinkEquals(eventIterator.next(), "inline",
SinkEventAttributeSet.Semantics.DELETE);
+ assertSinkStartsWith(eventIterator, "text", "inline_", "paragraph_");
+ assertEventSuffix(eventIterator);
+ }
}
diff --git
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
index 81cd43dc..95c06f95 100644
---
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
+++
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownSinkTest.java
@@ -259,12 +259,8 @@ class MarkdownSinkTest extends AbstractSinkTest {
return MarkdownMarkup.MONOSPACED_START_MARKUP + text +
MarkdownMarkup.MONOSPACED_END_MARKUP;
}
- protected String getItalicBlock(String text) {
- return MarkdownMarkup.ITALIC_START_MARKUP + text +
MarkdownMarkup.ITALIC_END_MARKUP;
- }
-
- protected String getBoldBlock(String text) {
- return MarkdownMarkup.BOLD_START_MARKUP + text +
MarkdownMarkup.BOLD_END_MARKUP;
+ protected String getInlineDeleteBlock(String text) {
+ return MarkdownMarkup.STRIKETHROUGH_START_MARKUP + text +
MarkdownMarkup.STRIKETHROUGH_END_MARKUP;
}
protected String getMonospacedBlock(String text) {
diff --git
a/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java
b/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java
index ea39ea35..c664c872 100644
---
a/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java
+++
b/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java
@@ -261,6 +261,10 @@ public class XdocSinkTest extends AbstractSinkTest {
return "<code>" + text + "</code>";
}
+ protected String getInlineDeleteBlock(String text) {
+ return "<del>" + text + "</del>";
+ }
+
protected String getLineBreakBlock() {
return "<br />";
}
diff --git
a/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5SinkTest.java
b/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5SinkTest.java
index d0e0c75c..87da4b18 100644
---
a/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5SinkTest.java
+++
b/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5SinkTest.java
@@ -259,16 +259,8 @@ public class Xhtml5SinkTest extends AbstractSinkTest {
return "<code>" + text + "</code>";
}
- protected String getItalicBlock(String text) {
- return "<i>" + text + "</i>";
- }
-
- protected String getBoldBlock(String text) {
- return "<b>" + text + "</b>";
- }
-
- protected String getMonospacedBlock(String text) {
- return "<code>" + text + "</code>";
+ protected String getInlineDeleteBlock(String text) {
+ return "<del>" + text + "</del>";
}
protected String getLineBreakBlock() {