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 356a0fe6 [DOXIA-731] Simplify HTML markup emitted from Sink.verbatim 
(#202)
356a0fe6 is described below

commit 356a0fe63fe6789f001518455514e513c1a40647
Author: Konrad Windszus <k...@apache.org>
AuthorDate: Sat Mar 16 12:33:33 2024 +0100

    [DOXIA-731] Simplify HTML markup emitted from Sink.verbatim (#202)
    
    Emit either <pre> or <pre><code>.
    Add parser tests for verbatim text/code (for all parsers)
---
 .../maven/doxia/sink/impl/Xhtml5BaseSink.java      |  82 +++++++------
 .../maven/doxia/parser/AbstractParserTest.java     | 127 ++++++++++++++++++++-
 .../maven/doxia/parser/Xhtml5BaseParserTest.java   |  12 +-
 .../maven/doxia/sink/impl/SinkTestDocument.java    |   8 +-
 .../maven/doxia/sink/impl/Xhtml5BaseSinkTest.java  |  15 ++-
 .../maven/doxia/module/apt/AptParserTest.java      |  25 +++-
 .../maven/doxia/module/fml/FmlParserTest.java      |  63 +++++++++-
 .../doxia/module/markdown/MarkdownParserTest.java  |  36 +++++-
 .../apache/maven/doxia/module/xdoc/XdocSink.java   |  21 ++--
 .../maven/doxia/module/xdoc/XdocParserTest.java    |  14 ++-
 .../doxia/module/xhtml5/Xhtml5ParserTest.java      |  14 ++-
 .../maven/doxia/module/xhtml5/Xhtml5SinkTest.java  |   2 +-
 12 files changed, 344 insertions(+), 75 deletions(-)

diff --git 
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSink.java 
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSink.java
index cdb7d7b8..bbe3107e 100644
--- 
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSink.java
+++ 
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSink.java
@@ -40,6 +40,7 @@ import org.apache.maven.doxia.markup.HtmlMarkup;
 import org.apache.maven.doxia.markup.Markup;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkEventAttributes;
+import org.apache.maven.doxia.sink.impl.Xhtml5BaseSink.VerbatimMode;
 import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.doxia.util.HtmlTools;
 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
@@ -77,8 +78,16 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
     /** An indication on if we're inside a paragraph flag. */
     private boolean paragraphFlag;
 
-    /** An indication on if we're in verbatim mode. */
-    private boolean verbatimFlag;
+    protected enum VerbatimMode {
+        /** not in verbatim mode */
+        OFF,
+        /** Inside {@code <pre>} */
+        ON,
+        /** Inside {@code <pre><code>} */
+        ON_WITH_CODE
+    }
+    /** An indication on if we're in verbatim mode and if so, surrounded by 
which tags. */
+    private VerbatimMode verbatimMode;
 
     /** Stack of alignment int[] of table cells. */
     private final LinkedList<int[]> cellJustifStack;
@@ -160,21 +169,28 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
     }
 
     /**
-     * <p>Setter for the field <code>verbatimFlag</code>.</p>
      *
-     * @param verb a verbatim flag.
+     * @return the current verbatim mode.
+     */
+    protected VerbatimMode getVerbatimMode() {
+        return this.verbatimMode;
+    }
+
+    /**
+     * <p>Setter for the field <code>verbatimMode</code>.</p>
+     *
+     * @param mode a verbatim mode.
      */
-    protected void setVerbatimFlag(boolean verb) {
-        this.verbatimFlag = verb;
+    protected void setVerbatimMode(VerbatimMode mode) {
+        this.verbatimMode = mode;
     }
 
     /**
-     * <p>isVerbatimFlag.</p>
      *
-     * @return the current verbatim flag.
+     * @return {@code true} if inside verbatim section, {@code false} otherwise
      */
-    protected boolean isVerbatimFlag() {
-        return this.verbatimFlag;
+    protected boolean isVerbatim() {
+        return this.verbatimMode != VerbatimMode.OFF;
     }
 
     /**
@@ -232,7 +248,7 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
 
         this.headFlag = false;
         this.paragraphFlag = false;
-        this.verbatimFlag = false;
+        this.verbatimMode = VerbatimMode.OFF;
 
         this.evenTableRow = true;
         this.tableAttributes = null;
@@ -825,11 +841,13 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
     }
 
     /**
-     * The default class style is <code>verbatim</code>, for source is {@code 
verbatim source}.
+     * Depending on whether the decoration attribute is "source" or not, this 
leads
+     * to either emitting {@code <pre><code>} or just {@code <pre>}.
+     * No default classes are emitted but the given attributes are always 
added to the {@code pre} element only.
      *
      * {@inheritDoc}
-     * @see javax.swing.text.html.HTML.Tag#DIV
      * @see javax.swing.text.html.HTML.Tag#PRE
+     * @see javax.swing.text.html.HTML.Tag#CODE
      */
     @Override
     public void verbatim(SinkEventAttributes attributes) {
@@ -840,47 +858,41 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
             paragraph_();
         }
 
-        verbatimFlag = true;
-
         MutableAttributeSet atts = SinkUtils.filterAttributes(attributes, 
SinkUtils.SINK_VERBATIM_ATTRIBUTES);
 
         if (atts == null) {
             atts = new SinkEventAttributeSet();
         }
 
-        boolean source = false;
-
+        verbatimMode = VerbatimMode.ON;
         if (atts.isDefined(SinkEventAttributes.DECORATION)) {
-            source = "source"
-                    
.equals(atts.getAttribute(SinkEventAttributes.DECORATION).toString());
-        }
-
-        SinkEventAttributes divAtts = null;
-        String divClass = "verbatim";
-
-        if (source) {
-            divClass += " source";
+            if ("source"
+                    
.equals(atts.getAttribute(SinkEventAttributes.DECORATION).toString())) {
+                verbatimMode = VerbatimMode.ON_WITH_CODE;
+            }
         }
 
-        divAtts = new 
SinkEventAttributeSet(SinkEventAttributes.CLASS.toString(), divClass);
-
         atts.removeAttribute(SinkEventAttributes.DECORATION);
 
-        writeStartTag(HtmlMarkup.DIV, divAtts);
         writeStartTag(HtmlMarkup.PRE, atts);
+        if (verbatimMode == VerbatimMode.ON_WITH_CODE) {
+            writeStartTag(HtmlMarkup.CODE);
+        }
     }
 
     /**
      * {@inheritDoc}
-     * @see javax.swing.text.html.HTML.Tag#DIV
+     * @see javax.swing.text.html.HTML.Tag#CODE
      * @see javax.swing.text.html.HTML.Tag#PRE
      */
     @Override
     public void verbatim_() {
+        if (verbatimMode == VerbatimMode.ON_WITH_CODE) {
+            writeEndTag(HtmlMarkup.CODE);
+        }
         writeEndTag(HtmlMarkup.PRE);
-        writeEndTag(HtmlMarkup.DIV);
 
-        verbatimFlag = false;
+        verbatimMode = VerbatimMode.OFF;
     }
 
     /**
@@ -1369,7 +1381,7 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
      */
     @Override
     public void lineBreak(SinkEventAttributes attributes) {
-        if (headFlag || isVerbatimFlag()) {
+        if (headFlag || isVerbatim()) {
             getTextBuffer().append(EOL);
         } else {
             MutableAttributeSet atts = SinkUtils.filterAttributes(attributes, 
SinkUtils.SINK_BR_ATTRIBUTES);
@@ -1381,7 +1393,7 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
     /** {@inheritDoc} */
     @Override
     public void lineBreakOpportunity(SinkEventAttributes attributes) {
-        if (!headFlag && !isVerbatimFlag()) {
+        if (!headFlag && !isVerbatim()) {
             MutableAttributeSet atts = SinkUtils.filterAttributes(attributes, 
SinkUtils.SINK_BR_ATTRIBUTES);
 
             writeSimpleTag(HtmlMarkup.WBR, atts);
@@ -1412,7 +1424,7 @@ public class Xhtml5BaseSink extends AbstractXmlSink 
implements HtmlMarkup {
         }
         if (headFlag) {
             getTextBuffer().append(text);
-        } else if (verbatimFlag) {
+        } else if (isVerbatim()) {
             verbatimContent(text);
         } else {
             content(text);
diff --git 
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
 
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
index 59e0e9c3..285d9c0a 100644
--- 
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
+++ 
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
@@ -23,12 +23,14 @@ import java.io.Reader;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Iterator;
+import java.util.ListIterator;
 
 import org.apache.maven.doxia.AbstractModuleTest;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkEventAttributes;
 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
+import org.apache.maven.doxia.sink.impl.SinkEventTestingSink;
 import org.apache.maven.doxia.sink.impl.SinkWrapper;
 import org.apache.maven.doxia.sink.impl.SinkWrapperFactory;
 import org.apache.maven.doxia.sink.impl.TextSink;
@@ -36,7 +38,10 @@ import 
org.apache.maven.doxia.sink.impl.WellformednessCheckingSink;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
 /**
  * Test the parsing of sample input files.
@@ -46,12 +51,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
  * @since 1.0
  */
 public abstract class AbstractParserTest extends AbstractModuleTest {
+    /**
+     * Example text which usually requires escaping in different markup 
languages as they have special meaning there
+     */
+    public static final String TEXT_WITH_SPECIAL_CHARS = "<>{}=#*";
+
     /**
      * Create a new instance of the parser to test.
      *
      * @return the parser to test.
      */
-    protected abstract Parser createParser();
+    protected abstract AbstractParser createParser();
 
     /**
      * Returns the directory where all parser test output will go.
@@ -146,6 +156,91 @@ public abstract class AbstractParserTest extends 
AbstractModuleTest {
         }
     }
 
+    /**
+     * Override this method if the parser always emits some static prefix for 
incomplete documents
+     * and consume the prefix related events from the given {@link Iterator}.
+     * @param eventIterator the iterator
+     */
+    protected void assertEventPrefix(Iterator<SinkEventElement> eventIterator) 
{
+        // do nothing by default, i.e. assume no prefix
+    }
+
+    /**
+     * Override this method if the parser always emits some static suffix for 
incomplete documents
+     * and consume the suffix related events from the given {@link Iterator}.
+     * @param eventIterator the iterator
+     */
+    protected void assertEventSuffix(Iterator<SinkEventElement> eventIterator) 
{
+        assertFalse(eventIterator.hasNext(), "didn't expect any further events 
but got at least one");
+    }
+
+    /**
+     * @return markup representing the verbatim text {@value 
#TEXT_WITH_SPECIAL_CHARS} (needs to be properly escaped).
+     * {@code null} can be returned to skip the test for a particular parser.
+     */
+    protected abstract String getVerbatimSource();
+
+    /**
+     * Test a verbatim block (no code) given through {@link 
#getVerbatimSource()}
+     * @throws ParseException
+     */
+    @Test
+    public void testVerbatim() throws ParseException {
+        String source = getVerbatimSource();
+        assumeTrue(source != null, "parser does not support simple verbatim 
text");
+        AbstractParser parser = createParser();
+        SinkEventTestingSink sink = new SinkEventTestingSink();
+
+        parser.parse(source, sink);
+        ListIterator<SinkEventElement> it = sink.getEventList().listIterator();
+        assertEventPrefix(it);
+        assertEquals("verbatim", it.next().getName());
+        assertConcatenatedTextEquals(it, TEXT_WITH_SPECIAL_CHARS, true);
+        assertEquals("verbatim_", it.next().getName());
+        assertEventSuffix(it);
+    }
+
+    /**
+     * @return markup representing the verbatim code block {@value 
#TEXT_WITH_SPECIAL_CHARS} (needs to be properly escaped).
+     * {@code null} can be returned to skip the test for a particular parser.
+     */
+    protected abstract String getVerbatimCodeSource();
+
+    /**
+     * Test a verbatim code block given through {@link 
#getVerbatimCodeSource()}
+     * @throws ParseException
+     */
+    @Test
+    public void testVerbatimCode() throws ParseException {
+        String source = getVerbatimCodeSource();
+        assumeTrue(source != null, "parser does not support verbatim code");
+        AbstractParser parser = createParser();
+        SinkEventTestingSink sink = new SinkEventTestingSink();
+
+        parser.parse(source, sink);
+        ListIterator<SinkEventElement> it = sink.getEventList().listIterator();
+        assertEventPrefix(it);
+        SinkEventElement verbatimEvt = it.next();
+        assertEquals("verbatim", verbatimEvt.getName());
+        SinkEventAttributeSet atts = (SinkEventAttributeSet) 
verbatimEvt.getArgs()[0];
+
+        // either verbatim event has attribute "source" or additional "inline" 
event
+        boolean isInlineCode;
+        if (atts.isEmpty()) {
+            isInlineCode = true;
+            assertSinkAttributesEqual(it.next(), "inline", 
SinkEventAttributeSet.Semantics.CODE);
+        } else {
+            isInlineCode = false;
+            assertEquals(SinkEventAttributeSet.SOURCE, atts);
+        }
+        assertConcatenatedTextEquals(it, TEXT_WITH_SPECIAL_CHARS, true);
+        if (isInlineCode) {
+            assertEquals("inline_", it.next().getName());
+        }
+        assertEquals("verbatim_", it.next().getName());
+        assertEventSuffix(it);
+    }
+
     public static void assertSinkEquals(SinkEventElement element, String name, 
Object... args) {
         Assertions.assertEquals(name, element.getName(), "Name of element 
doesn't match");
         Assertions.assertArrayEquals(args, element.getArgs(), "Arguments don't 
match");
@@ -157,6 +252,36 @@ public abstract class AbstractParserTest extends 
AbstractModuleTest {
         Assertions.assertEquals(value, atts.getAttribute(attr));
     }
 
+    public static void assertSinkAttributesEqual(
+            SinkEventElement element, String name, SinkEventAttributes 
expectedAttributes) {
+        Assertions.assertEquals(name, element.getName());
+        SinkEventAttributeSet atts = (SinkEventAttributeSet) 
element.getArgs()[0];
+        Assertions.assertEquals(expectedAttributes, atts);
+    }
+
+    /**
+     * Consumes all consecutive text events from the given {@link 
ListIterator} and compares the concatenated text with the expected text
+     * @param it the iterator to traverse, is positioned to the last text 
event once this method finishes
+     * @param expectedText the expected text which is compared with the 
concatenated text of all text events
+     * @param trimText {@code true} to trim the actual text before comparing 
with the expected one, otherwise compare without trimming
+     */
+    void assertConcatenatedTextEquals(ListIterator<SinkEventElement> it, 
String expectedText, boolean trimText) {
+        StringBuilder builder = new StringBuilder();
+        while (it.hasNext()) {
+            SinkEventElement currentEvent = it.next();
+            if (currentEvent.getName() != "text") {
+                it.previous();
+                break;
+            }
+            builder.append(currentEvent.getArgs()[0]);
+        }
+        String actualValue = builder.toString();
+        if (trimText) {
+            actualValue = actualValue.trim();
+        }
+        assertEquals(expectedText, actualValue);
+    }
+
     public static void assertSinkEquals(Iterator<SinkEventElement> it, 
String... names) {
         StringBuilder expected = new StringBuilder();
         StringBuilder actual = new StringBuilder();
diff --git 
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
 
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
index dadc9122..084b03f6 100644
--- 
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
+++ 
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
@@ -36,7 +36,7 @@ public class Xhtml5BaseParserTest extends AbstractParserTest {
     private final SinkEventTestingSink sink = new SinkEventTestingSink();
 
     @Override
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         parser = new Xhtml5BaseParser();
         return parser;
     }
@@ -931,4 +931,14 @@ public class Xhtml5BaseParserTest extends 
AbstractParserTest {
                 "definitionListItem_",
                 "definitionList_");
     }
+
+    @Override
+    protected String getVerbatimSource() {
+        return "<pre>&lt;&gt;{}=#*</pre>";
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return "<pre><code>&lt;&gt;{}=#*</code></pre>";
+    }
 }
diff --git 
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkTestDocument.java
 
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkTestDocument.java
index c4d5d676..35220f2a 100644
--- 
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkTestDocument.java
+++ 
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkTestDocument.java
@@ -81,8 +81,10 @@ public class SinkTestDocument {
 
         generateList(sink);
 
-        sink.verbatim(SinkEventAttributeSet.SOURCE);
+        sink.verbatim();
+        sink.inline(SinkEventAttributeSet.Semantics.CODE);
         sink.text("Verbatim source text not contained in list item 3");
+        sink.inline_();
         sink.verbatim_();
 
         generateNumberedList(sink);
@@ -258,8 +260,10 @@ public class SinkTestDocument {
         sink.definedTerm_();
         sink.definition();
         sink.text("of definition list.");
-        sink.verbatim(SinkEventAttributeSet.SOURCE);
+        sink.verbatim();
+        sink.inline(SinkEventAttributeSet.Semantics.CODE);
         sink.text("Verbatim source text" + eol + "                        in a 
box        ");
+        sink.inline_();
         sink.verbatim_();
         sink.definition_();
         sink.definitionListItem_();
diff --git 
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSinkTest.java
 
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSinkTest.java
index 43b6af06..63c6e436 100644
--- 
a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSinkTest.java
+++ 
b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/Xhtml5BaseSinkTest.java
@@ -651,28 +651,27 @@ public class Xhtml5BaseSinkTest {
      * Test of verbatim method, of class Xhtml5BaseSink.
      */
     @Test
-    public void testVerbatimSource() {
+    public void testVerbatim() {
         try (Xhtml5BaseSink sink = new Xhtml5BaseSink(writer)) {
             sink.verbatim(SinkEventAttributeSet.SOURCE);
             sink.verbatim_();
         }
 
-        assertEquals("<div class=\"verbatim source\">" + LS + 
"<pre></pre></div>", writer.toString());
+        assertEquals("<pre><code></code></pre>", writer.toString());
 
-        checkVerbatimAttributes(attributes, "<div class=\"verbatim\">" + LS + 
"<pre style=\"bold\"></pre></div>");
+        checkVerbatimAttributes(attributes, "<pre style=\"bold\"></pre>");
 
         final SinkEventAttributes att = new 
SinkEventAttributeSet(SinkEventAttributes.ID, "id");
-        checkVerbatimAttributes(att, "<div class=\"verbatim\">" + LS + "<pre 
id=\"id\"></pre></div>");
+        checkVerbatimAttributes(att, "<pre id=\"id\"></pre>");
 
         att.addAttribute(Attribute.CLASS, "class");
-        checkVerbatimAttributes(att, "<div class=\"verbatim\">" + LS + "<pre 
id=\"id\" class=\"class\"></pre></div>");
+        checkVerbatimAttributes(att, "<pre id=\"id\" class=\"class\"></pre>");
 
         att.addAttribute(SinkEventAttributes.DECORATION, "source");
-        checkVerbatimAttributes(
-                att, "<div class=\"verbatim source\">" + LS + "<pre id=\"id\" 
class=\"class\"></pre></div>");
+        checkVerbatimAttributes(att, "<pre id=\"id\" 
class=\"class\"><code></code></pre>");
 
         att.removeAttribute(Attribute.CLASS.toString());
-        checkVerbatimAttributes(att, "<div class=\"verbatim source\">" + LS + 
"<pre id=\"id\"></pre></div>");
+        checkVerbatimAttributes(att, "<pre id=\"id\"><code></code></pre>");
     }
 
     private void checkVerbatimAttributes(final SinkEventAttributes att, final 
String expected) {
diff --git 
a/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptParserTest.java
 
b/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptParserTest.java
index b4a69df2..c6a6a501 100644
--- 
a/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptParserTest.java
+++ 
b/doxia-modules/doxia-module-apt/src/test/java/org/apache/maven/doxia/module/apt/AptParserTest.java
@@ -26,9 +26,9 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.util.Iterator;
 
+import org.apache.maven.doxia.parser.AbstractParser;
 import org.apache.maven.doxia.parser.AbstractParserTest;
 import org.apache.maven.doxia.parser.ParseException;
-import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
@@ -47,7 +47,7 @@ public class AptParserTest extends AbstractParserTest {
     @Inject
     private AptParser parser;
 
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         return parser;
     }
 
@@ -522,7 +522,28 @@ public class AptParserTest extends AbstractParserTest {
         assertSinkEquals(sink.getEventList().get(8), "text", "Another author", 
null);
     }
 
+    @Override
     protected String outputExtension() {
         return "apt";
     }
+
+    @Override
+    protected void assertEventPrefix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkStartsWith(eventIterator, "head", "head_", "body");
+    }
+
+    @Override
+    protected void assertEventSuffix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkEquals(eventIterator, "body_");
+    }
+
+    @Override
+    protected String getVerbatimSource() {
+        return "---" + EOL + "<>{}=#*" + EOL + "---" + EOL;
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return "+--" + EOL + "<>{}=#*" + EOL + "+--" + EOL;
+    }
 }
diff --git 
a/doxia-modules/doxia-module-fml/src/test/java/org/apache/maven/doxia/module/fml/FmlParserTest.java
 
b/doxia-modules/doxia-module-fml/src/test/java/org/apache/maven/doxia/module/fml/FmlParserTest.java
index 7eaad969..fb89d26b 100644
--- 
a/doxia-modules/doxia-module-fml/src/test/java/org/apache/maven/doxia/module/fml/FmlParserTest.java
+++ 
b/doxia-modules/doxia-module-fml/src/test/java/org/apache/maven/doxia/module/fml/FmlParserTest.java
@@ -29,8 +29,8 @@ import java.util.Iterator;
 import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.maven.doxia.parser.AbstractParser;
 import org.apache.maven.doxia.parser.AbstractParserTest;
-import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
 import org.apache.maven.doxia.sink.impl.SinkEventTestingSink;
@@ -73,7 +73,7 @@ public class FmlParserTest extends AbstractParserTest {
     }
 
     /** {@inheritDoc} */
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         return parser;
     }
 
@@ -272,6 +272,65 @@ public class FmlParserTest extends AbstractParserTest {
         assertTrue(content.contains("<a id=\"macro-definition\"></a>" + EOL + 
"<dt>Macro Question</dt>"));
     }
 
+    @Override
+    protected void assertEventPrefix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkStartsWith(
+                eventIterator,
+                "head",
+                "title",
+                "text",
+                "title_",
+                "head_",
+                "body",
+                "section1",
+                "anchor",
+                "anchor_",
+                "sectionTitle1",
+                "text",
+                "sectionTitle1_",
+                "numberedList",
+                "numberedListItem",
+                "link",
+                "link_",
+                "numberedListItem_",
+                "numberedList_",
+                "section1_",
+                "definitionList",
+                "anchor",
+                "anchor_",
+                "definedTerm",
+                "definedTerm_",
+                "definition");
+    }
+
+    @Override
+    protected void assertEventSuffix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkEquals(
+                eventIterator,
+                "paragraph",
+                "link",
+                "text",
+                "link_",
+                "paragraph_",
+                "definition_",
+                "definitionList_",
+                "body_");
+    }
+
+    @Override
+    protected String getVerbatimSource() {
+        return "<faqs title=\"title\"><part id=\"general\"><faq 
id=\"first\"><question></question><answer>"
+                + "<pre>&lt;&gt;{}=#*</pre>"
+                + "</answer></faq></part></faqs>";
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return "<faqs title=\"title\"><part id=\"general\"><faq 
id=\"first\"><question></question><answer>"
+                + "<source>&lt;&gt;{}=#*</source>"
+                + "</answer></faq></part></faqs>";
+    }
+
     private void assertTextEvent(SinkEventElement textEvt, String string) {
         assertEquals("text", textEvt.getName());
         assertEquals(string, textEvt.getArgs()[0]);
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 9d716de0..4308f051 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
@@ -25,9 +25,9 @@ import java.io.Reader;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.maven.doxia.parser.AbstractParser;
 import org.apache.maven.doxia.parser.AbstractParserTest;
 import org.apache.maven.doxia.parser.ParseException;
-import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.SinkEventAttributes;
 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
@@ -56,7 +56,7 @@ public class MarkdownParserTest extends AbstractParserTest {
      * {@inheritDoc}
      */
     @Override
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         return parser;
     }
 
@@ -205,12 +205,12 @@ public class MarkdownParserTest extends 
AbstractParserTest {
 
         assertFalse(it.hasNext());
 
-        // PRE element must be a "verbatim" Sink event that specifies
-        // SOURCE = true
+        // PRE element must be a "verbatim" Sink event
         SinkEventElement pre = eventList.get(7);
         assertEquals("verbatim", pre.getName());
         SinkEventAttributeSet preAtts = (SinkEventAttributeSet) 
pre.getArgs()[0];
-        assertFalse(preAtts.containsAttribute(SinkEventAttributes.DECORATION, 
"source"));
+        // instead of using a decoration tag on the verbatim event and 
additional inline event is used
+        assertTrue(preAtts.isEmpty());
 
         // * CODE element must be an "inline" Sink event that specifies:
         // * SEMANTICS = "code" and CLASS = "language-java"
@@ -778,12 +778,14 @@ public class MarkdownParserTest extends 
AbstractParserTest {
     }
 
     // test fix for https://github.com/vsch/flexmark-java/issues/384
+    @Test
     public void testFlexIssue384() throws Exception {
         parseFileToEventTestingSink("flex-384");
     }
 
     // Apostrophe versus single quotes
     // Simple apostrophes (like in Sophie's Choice) must not be replaced with 
a single quote
+    @Test
     public void testQuoteVsApostrophe() throws Exception {
         List<SinkEventElement> eventList =
                 
parseFileToEventTestingSink("quote-vs-apostrophe").getEventList();
@@ -798,4 +800,28 @@ public class MarkdownParserTest extends AbstractParserTest 
{
                 "This apostrophe isn't a quote." + "This \u2018quoted 
text\u2019 isn't surrounded by apostrophes.",
                 content.toString());
     }
+
+    @Override
+    protected void assertEventPrefix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkStartsWith(eventIterator, "head", "head_", "body");
+    }
+
+    @Override
+    protected void assertEventSuffix(Iterator<SinkEventElement> eventIterator) 
{
+        assertSinkEquals(eventIterator, "body_");
+    }
+
+    @Override
+    protected String getVerbatimSource() {
+        /**
+         * Markdown doesn't support verbatim text which is not code:
+         * https://spec.commonmark.org/0.31.2/#fenced-code-blocks and 
https://spec.commonmark.org/0.31.2/#indented-code-blocks
+         */
+        return null;
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return "```" + EOL + "<>{}=#*" + EOL + "```";
+    }
 }
diff --git 
a/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocSink.java
 
b/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocSink.java
index f4e55b96..c90e9024 100644
--- 
a/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocSink.java
+++ 
b/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocSink.java
@@ -44,9 +44,6 @@ public class XdocSink extends Xhtml5BaseSink implements 
XdocMarkup {
     // Instance fields
     // ----------------------------------------------------------------------
 
-    /** An indication on if we're inside verbatim source. */
-    private boolean sourceFlag;
-
     private String encoding;
 
     private String languageId;
@@ -104,8 +101,6 @@ public class XdocSink extends Xhtml5BaseSink implements 
XdocMarkup {
      */
     protected void init() {
         super.init();
-
-        sourceFlag = false;
     }
 
     /**
@@ -340,7 +335,6 @@ public class XdocSink extends Xhtml5BaseSink implements 
XdocMarkup {
      * @param attributes a {@link 
org.apache.maven.doxia.sink.SinkEventAttributes} object.
      */
     public void verbatim(SinkEventAttributes attributes) {
-        setVerbatimFlag(true);
 
         MutableAttributeSet atts = SinkUtils.filterAttributes(attributes, 
SinkUtils.SINK_VERBATIM_ATTRIBUTES);
 
@@ -348,15 +342,16 @@ public class XdocSink extends Xhtml5BaseSink implements 
XdocMarkup {
             atts = new SinkEventAttributeSet();
         }
 
-        boolean source = false;
-
+        this.setVerbatimMode(VerbatimMode.ON);
         if (atts.isDefined(SinkEventAttributes.DECORATION)) {
-            sourceFlag = source = 
"source".equals(atts.getAttribute(SinkEventAttributes.DECORATION));
+            if 
("source".equals(atts.getAttribute(SinkEventAttributes.DECORATION))) {
+                this.setVerbatimMode(VerbatimMode.ON_WITH_CODE);
+            }
         }
 
         atts.removeAttribute(SinkEventAttributes.DECORATION);
 
-        if (source) {
+        if (getVerbatimMode() == VerbatimMode.ON_WITH_CODE) {
             writeStartTag(SOURCE_TAG, atts);
         } else {
             writeStartTag(PRE, atts);
@@ -370,15 +365,13 @@ public class XdocSink extends Xhtml5BaseSink implements 
XdocMarkup {
      * @see javax.swing.text.html.HTML.Tag#PRE
      */
     public void verbatim_() {
-        if (sourceFlag) {
+        if (getVerbatimMode() == VerbatimMode.ON_WITH_CODE) {
             writeEndTag(SOURCE_TAG);
         } else {
             writeEndTag(PRE);
         }
 
-        setVerbatimFlag(false);
-
-        sourceFlag = false;
+        this.setVerbatimMode(VerbatimMode.OFF);
     }
 
     /**
diff --git 
a/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
 
b/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
index 2fb5c5d4..eb953355 100644
--- 
a/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
+++ 
b/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java
@@ -29,9 +29,9 @@ import java.util.Iterator;
 import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.maven.doxia.parser.AbstractParser;
 import org.apache.maven.doxia.parser.AbstractParserTest;
 import org.apache.maven.doxia.parser.ParseException;
-import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
@@ -91,7 +91,7 @@ public class XdocParserTest extends AbstractParserTest {
     }
 
     /** {@inheritDoc} */
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         return parser;
     }
 
@@ -430,4 +430,14 @@ public class XdocParserTest extends AbstractParserTest {
         assertEquals("style", styleElm_.getArgs()[0]);
         assertFalse(it.hasNext());
     }
+
+    @Override
+    protected String getVerbatimSource() {
+        return "<pre><![CDATA[<>{}=#*]]></pre>";
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return "<source><![CDATA[<>{}=#*]]></source>";
+    }
 }
diff --git 
a/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5ParserTest.java
 
b/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5ParserTest.java
index 60cfc9f6..b939f3d5 100644
--- 
a/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5ParserTest.java
+++ 
b/doxia-modules/doxia-module-xhtml5/src/test/java/org/apache/maven/doxia/module/xhtml5/Xhtml5ParserTest.java
@@ -25,8 +25,8 @@ import java.io.FileFilter;
 import java.util.Iterator;
 import java.util.regex.Pattern;
 
+import org.apache.maven.doxia.parser.AbstractParser;
 import org.apache.maven.doxia.parser.AbstractParserTest;
-import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.impl.SinkEventElement;
 import org.apache.maven.doxia.sink.impl.SinkEventTestingSink;
 import org.junit.jupiter.api.BeforeEach;
@@ -63,7 +63,7 @@ public class Xhtml5ParserTest extends AbstractParserTest {
     }
 
     /** {@inheritDoc} */
-    protected Parser createParser() {
+    protected AbstractParser createParser() {
         return parser;
     }
 
@@ -181,4 +181,14 @@ public class Xhtml5ParserTest extends AbstractParserTest {
         assertEquals("listItem_", it.next().getName());
         assertEquals("list_", it.next().getName());
     }
+
+    @Override
+    protected String getVerbatimSource() {
+        return null; // already tested in Xhtml5BaseParserTest
+    }
+
+    @Override
+    protected String getVerbatimCodeSource() {
+        return null; // already tested in Xhtml5BaseParserTest
+    }
 }
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 8d262e0a..875c246a 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,7 +259,7 @@ public class Xhtml5SinkTest extends AbstractSinkTest {
 
     /** {@inheritDoc} */
     protected String getVerbatimSourceBlock(String text) {
-        return "<div class=\"verbatim source\">\n<pre>" + text + 
"</pre></div>";
+        return "<pre><code>" + text + "</code></pre>";
     }
 
     /** {@inheritDoc} */


Reply via email to