You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2023/02/13 11:30:21 UTC

[maven-doxia] branch bugfix/newlines updated (f7290137 -> e413e306)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a change to branch bugfix/newlines
in repository https://gitbox.apache.org/repos/asf/maven-doxia.git


 discard f7290137 [DOXIA-694] Too many line separators
     new e413e306 [DOXIA-694] Too many line separators

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (f7290137)
            \
             N -- N -- N   refs/heads/bugfix/newlines (e413e306)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/maven/doxia/sink/impl/SinkEventElement.java  | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)


[maven-doxia] 01/01: [DOXIA-694] Too many line separators

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch bugfix/newlines
in repository https://gitbox.apache.org/repos/asf/maven-doxia.git

commit e413e3069cc43a00981634167502720cf88b6f20
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Mon Feb 13 12:29:52 2023 +0100

    [DOXIA-694] Too many line separators
---
 .../maven/doxia/sink/impl/SinkEventElement.java    |   9 +-
 .../doxia/module/markdown/MarkdownMarkup.java      |  12 +-
 .../maven/doxia/module/markdown/MarkdownSink.java  | 409 +++++++--------------
 .../doxia/module/markdown/MarkdownSinkTest.java    |  40 +-
 .../src/test/resources/test.md                     |   5 +
 5 files changed, 163 insertions(+), 312 deletions(-)

diff --git a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkEventElement.java b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkEventElement.java
index c8439d05..1a1e54d9 100644
--- a/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkEventElement.java
+++ b/doxia-core/src/test/java/org/apache/maven/doxia/sink/impl/SinkEventElement.java
@@ -92,12 +92,9 @@ public class SinkEventElement {
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
         SinkEventElement other = (SinkEventElement) obj;
         return Arrays.deepEquals(args, other.args) && Objects.equals(methodName, other.methodName);
     }
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 854bfa2e..91b56cf0 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
@@ -36,8 +36,7 @@ public interface MarkdownMarkup extends TextMarkup {
     String COMMENT_START = "<!-- ";
     String COMMENT_END = " -->";
 
-    /** page break markup char: '\f' */
-    char PAGE_BREAK = '\f';
+    String BLANK_LINE = EOL + EOL;
 
     // ----------------------------------------------------------------------
     // Markup syntax
@@ -58,8 +57,8 @@ public interface MarkdownMarkup extends TextMarkup {
     /** Syntax for the header start: "---" */
     String METADATA_MARKUP = StringUtils.repeat(String.valueOf(MINUS), 3);
 
-    /** Syntax for the horizontal rule: "========" */
-    String HORIZONTAL_RULE_MARKUP = StringUtils.repeat(String.valueOf(EQUAL), 8);
+    /** Syntax for the horizontal rule: "***" */
+    String HORIZONTAL_RULE_MARKUP = "***";
 
     /** Syntax for the italic style end: "_" */
     String ITALIC_END_MARKUP = "_";
@@ -92,10 +91,7 @@ public interface MarkdownMarkup extends TextMarkup {
     String VERBATIM_START_MARKUP = "```";
 
     /** Syntax for the non breaking space: "\ " */
-    String NON_BREAKING_SPACE_MARKUP = String.valueOf(BACKSLASH) + SPACE;
-
-    /** Syntax for the page break: "\f" */
-    String PAGE_BREAK_MARKUP = String.valueOf(PAGE_BREAK);
+    String NON_BREAKING_SPACE_MARKUP = "&npsp;";
 
     /** Syntax for the section title start: "#" */
     String SECTION_TITLE_START_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 821c1bc4..acc15158 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
@@ -93,6 +93,9 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
     /**  The writer to use. */
     private final PrintWriter writer;
 
+    /** {@code true} when last written character in {@link #writer} was a line separator, or writer is still at the beginning */
+    private boolean isWriterAtStartOfNewLine;
+
     /**  justification of table cells. */
     private int[] cellJustif;
 
@@ -102,8 +105,8 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
     /**  is header row */
     private boolean headerRow;
 
-    /**  listNestingIndent. */
-    private String listNestingIndent;
+    /**  listNestingLevel, 0 outside the list, 1 for the top-level list, 2 for a nested list, 3 for a list nested inside a nested list, .... */
+    private int listNestingLevel;
 
     /**  listStyles. */
     private final Stack<String> listStyles;
@@ -122,6 +125,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
      */
     protected MarkdownSink(Writer writer) {
         this.writer = new PrintWriter(writer);
+        isWriterAtStartOfNewLine = true;
         this.listStyles = new Stack<>();
 
         init();
@@ -145,16 +149,14 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         this.headerFlag = headFlag;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     protected void init() {
         super.init();
 
         resetBuffer();
 
         this.tableCaptionBuffer = new StringBuilder();
-        this.listNestingIndent = "";
+        this.listNestingLevel = 0;
 
         this.authors = new LinkedList<>();
         this.title = null;
@@ -189,9 +191,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         tableCaptionBuffer = new StringBuilder();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void head() {
         boolean startFlag = this.startFlag;
 
@@ -201,9 +201,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         this.startFlag = startFlag;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void head_() {
         headerFlag = false;
 
@@ -224,12 +222,10 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         if (date != null) {
             write("date: " + date + EOL);
         }
-        write(METADATA_MARKUP + EOL);
+        write(METADATA_MARKUP + BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void title_() {
         if (buffer.length() > 0) {
             title = buffer.toString();
@@ -237,9 +233,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void author_() {
         if (buffer.length() > 0) {
             authors.add(buffer.toString());
@@ -247,9 +241,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void date_() {
         if (buffer.length() > 0) {
             date = buffer.toString();
@@ -257,154 +249,90 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void section1_() {
-        write(EOL);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void section2_() {
-        write(EOL);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void section3_() {
-        write(EOL);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void section4_() {
-        write(EOL);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void section5_() {
-        write(EOL);
-    }
-
     private void sectionTitle(int level) {
-        write(EOL + StringUtils.repeat(SECTION_TITLE_START_MARKUP, level) + SPACE);
+        write(StringUtils.repeat(SECTION_TITLE_START_MARKUP, level) + SPACE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle1() {
         sectionTitle(1);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle1_() {
-        write(EOL + EOL);
+        write(BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle2() {
         sectionTitle(2);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle2_() {
-        write(EOL + EOL);
+        write(BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle3() {
         sectionTitle(3);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle3_() {
-        write(EOL + EOL);
+        write(BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle4() {
         sectionTitle(4);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle4_() {
-        write(EOL + EOL);
+        write(BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle5() {
         sectionTitle(5);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void sectionTitle5_() {
-        write(EOL + EOL);
+        write(BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void list() {
-        listNestingIndent += " ";
+        listNestingLevel++;
         listStyles.push(LIST_UNORDERED_ITEM_START_MARKUP);
-        write(EOL);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void list_() {
-        write(EOL);
-        listNestingIndent = StringUtils.chomp(listNestingIndent, " ");
+        listNestingLevel--;
+        if (listNestingLevel == 0) {
+            write(EOL); // end add blank line (together with the preceding EOL of the item) only in case this was not
+            // nested
+        }
         listStyles.pop();
         itemFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void listItem() {
         orderedOrUnorderedListItem();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void listItem_() {
         orderedOrUnorderedListItem_();
     }
 
     /** {@inheritDoc} */
     public void numberedList(int numbering) {
-        listNestingIndent += " ";
-        //write(EOL);
-
+        listNestingLevel++;
         // markdown only supports decimal numbering
         if (numbering != NUMBERING_DECIMAL) {
             LOGGER.warn(
@@ -416,117 +344,94 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         listStyles.push(style);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void numberedList_() {
-        write(EOL);
-        listNestingIndent = StringUtils.chomp(listNestingIndent, " ");
+        listNestingLevel--;
+        if (listNestingLevel == 0) {
+            write(EOL); // end add blank line (together with the preceding EOL of the item) only in case this was not
+            // nested
+        }
         listStyles.pop();
         itemFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void numberedListItem() {
         orderedOrUnorderedListItem();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void numberedListItem_() {
         orderedOrUnorderedListItem_();
     }
 
     private void orderedOrUnorderedListItem() {
-        String style = listStyles.peek();
-        write(EOL + listNestingIndent + style + SPACE);
+        write(getListPrefix());
         itemFlag = true;
     }
 
     private void orderedOrUnorderedListItem_() {
-        write(EOL);
+        ensureBeginningOfLine();
         itemFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    private String getListPrefix() {
+        StringBuilder prefix = new StringBuilder();
+        for (int indent = 1; indent < listNestingLevel; indent++) {
+            prefix.append("    "); // 4 spaces per indentation level
+        }
+        prefix.append(listStyles.peek());
+        prefix.append(SPACE);
+        return prefix.toString();
+    }
+
+    @Override
     public void definitionList() {
-        listNestingIndent += " ";
-        listStyles.push("");
-        write(EOL);
+        LOGGER.warn("Definition list not natively supported in Markdown, rendering HTML instead");
+        write("<dl>" + EOL);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public void definitionList_() {
-        write(EOL);
-        listNestingIndent = StringUtils.chomp(listNestingIndent, " ");
-        listStyles.pop();
-        itemFlag = false;
+        verbatimFlag = true;
+        write("</dl>" + BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public void definedTerm() {
-        write(EOL + " [");
+        write("<dt>");
+        verbatimFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void definedTerm_() {
-        write("] ");
+        write("</dt>" + EOL);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void definition() {
-        itemFlag = true;
+        write("<dd>");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void definition_() {
-        write(EOL);
-        itemFlag = false;
+        write("</dd>" + EOL);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void pageBreak() {
-        write(EOL + PAGE_BREAK + EOL);
+        LOGGER.warn("Ignoring unsupported page break in Markdown");
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void paragraph() {
-        if (tableCellFlag) {
-            // ignore paragraphs in table cells
-        } else if (itemFlag) {
-            write(EOL + EOL + "  " + listNestingIndent);
-        } else {
-            write(EOL + " ");
-        }
+        ensureBeginningOfLine();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void paragraph_() {
-        if (tableCellFlag) {
-            // ignore paragraphs in table cells
+        if (tableCellFlag || listNestingLevel > 0) {
+            // ignore paragraphs in table cells or lists
         } else {
-            write(EOL + EOL);
+            write(BLANK_LINE);
         }
     }
 
@@ -538,36 +443,30 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
 
     /** {@inheritDoc} */
     public void verbatim(SinkEventAttributes attributes) {
-        write(EOL);
+        ensureBeginningOfLine();
         verbatimFlag = true;
-        write(EOL + VERBATIM_START_MARKUP + EOL);
+        write(VERBATIM_START_MARKUP + EOL);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void verbatim_() {
-        write(EOL + VERBATIM_END_MARKUP + EOL);
+        ensureBeginningOfLine();
+        write(VERBATIM_END_MARKUP + BLANK_LINE);
         verbatimFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void horizontalRule() {
-        write(EOL + HORIZONTAL_RULE_MARKUP + EOL);
+        ensureBeginningOfLine();
+        write(HORIZONTAL_RULE_MARKUP + BLANK_LINE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void table() {
-        write(EOL);
+        ensureBeginningOfLine();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void table_() {
         if (tableCaptionBuffer.length() > 0) {
             text(tableCaptionBuffer.toString() + EOL);
@@ -583,25 +482,19 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         headerRow = true;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableRows_() {
         cellJustif = null;
         gridFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableRow() {
         bufferFlag = true;
         cellCount = 0;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableRow_() {
         bufferFlag = false;
 
@@ -650,16 +543,12 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         this.rowLine = rLine.toString();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableCell() {
         tableCell(false);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableHeaderCell() {
         tableCell(true);
     }
@@ -673,16 +562,12 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         tableCellFlag = true;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableCell_() {
         endTableCell();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableHeaderCell_() {
         endTableCell();
     }
@@ -696,23 +581,17 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         cellCount++;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableCaption() {
         tableCaptionFlag = true;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void tableCaption_() {
         tableCaptionFlag = false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void figureCaption_() {
         write(EOL);
     }
@@ -728,9 +607,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         // TODO get implementation from Xhtml5 base sink
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void anchor_() {
         // write(ANCHOR_END_MARKUP);
     }
@@ -743,9 +620,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void link_() {
         if (!headerFlag) {
             write(LINK_START_2_MARKUP);
@@ -767,16 +642,14 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void inline() {
         inline(null);
     }
 
     /** {@inheritDoc} */
     public void inline(SinkEventAttributes attributes) {
-        if (!headerFlag) {
+        if (!headerFlag && !verbatimFlag) {
             List<String> tags = new ArrayList<>();
 
             if (attributes != null) {
@@ -801,75 +674,57 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void inline_() {
-        if (!headerFlag) {
+        if (!headerFlag && !verbatimFlag) {
             for (String tag : inlineStack.pop()) {
                 write(tag);
             }
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void italic() {
         inline(SinkEventAttributeSet.Semantics.ITALIC);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void italic_() {
         inline_();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void bold() {
         inline(SinkEventAttributeSet.Semantics.BOLD);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void bold_() {
         inline_();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void monospaced() {
         inline(SinkEventAttributeSet.Semantics.CODE);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void monospaced_() {
         inline_();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void lineBreak() {
         if (headerFlag || bufferFlag) {
             buffer.append(EOL);
         } else if (verbatimFlag) {
             write(EOL);
         } else {
-            write(BACKSLASH + EOL);
+            write("" + SPACE + SPACE + EOL);
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void nonBreakingSpace() {
         if (headerFlag || bufferFlag) {
             buffer.append(NON_BREAKING_SPACE_MARKUP);
@@ -878,7 +733,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void text(String text) {
         if (tableCaptionFlag) {
             tableCaptionBuffer.append(text);
@@ -891,12 +746,12 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void rawText(String text) {
         write(text);
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void comment(String comment) {
         rawText((startFlag ? "" : EOL) + COMMENT_START + comment + COMMENT_END);
     }
@@ -907,6 +762,7 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
      * Unkown events just log a warning message but are ignored otherwise.
      * @see org.apache.maven.doxia.sink.Sink#unknown(String,Object[],SinkEventAttributes)
      */
+    @Override
     public void unknown(String name, Object[] requiredParams, SinkEventAttributes attributes) {
         LOGGER.warn("Unknown Sink event '" + name + "', ignoring!");
     }
@@ -921,7 +777,9 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         if (tableCellFlag) {
             buffer.append(text);
         } else {
-            writer.write(unifyEOLs(text));
+            String unifiedText = unifyEOLs(text);
+            isWriterAtStartOfNewLine = unifiedText.endsWith(EOL);
+            writer.write(unifiedText);
         }
     }
 
@@ -943,16 +801,12 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
         write(text);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void flush() {
         writer.flush();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void close() {
         writer.close();
 
@@ -1010,4 +864,15 @@ public class MarkdownSink extends AbstractTextSink implements MarkdownMarkup {
 
         return buffer.toString();
     }
+
+    /**
+     * Ensures that the {@link #writer} is currently at the beginning of a new line.
+     * Optionally writes a line separator to ensure that.
+     */
+    private void ensureBeginningOfLine() {
+        // make sure that we are at the start of a line without adding unnecessary blank lines
+        if (!isWriterAtStartOfNewLine) {
+            write(EOL);
+        }
+    }
 }
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 1ade0028..d11a6973 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
@@ -32,10 +32,8 @@ import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.impl.AbstractSinkTest;
 import org.apache.maven.doxia.sink.impl.SinkEventTestingSink;
 import org.codehaus.plexus.util.StringUtils;
-import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Test;
 
-import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
@@ -106,13 +104,7 @@ public class MarkdownSinkTest extends AbstractSinkTest {
     }
 
     protected String getSectionBlock(String title, int level) {
-        return EOL
-                + StringUtils.repeat(MarkdownMarkup.SECTION_TITLE_START_MARKUP, level)
-                + SPACE
-                + title
-                + EOL
-                + EOL
-                + EOL;
+        return StringUtils.repeat(MarkdownMarkup.SECTION_TITLE_START_MARKUP, level) + SPACE + title + EOL + EOL;
     }
 
     /** {@inheritDoc} */
@@ -157,21 +149,18 @@ public class MarkdownSinkTest extends AbstractSinkTest {
 
     /** {@inheritDoc} */
     protected String getListBlock(String item) {
-        return EOL + EOL + Markup.SPACE + "" + MarkdownMarkup.LIST_UNORDERED_ITEM_START_MARKUP + "" + Markup.SPACE
-                + getEscapedText(item) + EOL + EOL;
+        return MarkdownMarkup.LIST_UNORDERED_ITEM_START_MARKUP + "" + Markup.SPACE + getEscapedText(item) + EOL + EOL;
     }
 
     /** {@inheritDoc} */
     protected String getNumberedListBlock(String item) {
-        return EOL + EOL + Markup.SPACE + ""
-                + MarkdownMarkup.LIST_ORDERED_ITEM_START_MARKUP + ""
-                + Markup.SPACE + getEscapedText(item) + EOL + EOL;
+        return MarkdownMarkup.LIST_ORDERED_ITEM_START_MARKUP + "" + Markup.SPACE + getEscapedText(item) + EOL + EOL;
     }
 
     /** {@inheritDoc} */
     protected String getDefinitionListBlock(String definum, String definition) {
-        return EOL + EOL + Markup.SPACE + "" + Markup.LEFT_SQUARE_BRACKET + definum + Markup.RIGHT_SQUARE_BRACKET + ""
-                + Markup.SPACE + definition + EOL + EOL;
+        return "<dl>" + EOL + "<dt>" + getEscapedText(definum) + "</dt>" + EOL + "<dd>" + getEscapedText(definition)
+                + "</dd>" + EOL + "</dl>" + EOL + EOL;
     }
 
     /** {@inheritDoc} */
@@ -195,7 +184,7 @@ public class MarkdownSinkTest extends AbstractSinkTest {
 
     /** {@inheritDoc} */
     protected String getParagraphBlock(String text) {
-        return EOL + Markup.SPACE + text + EOL + EOL;
+        return text + EOL + EOL;
     }
 
     /** {@inheritDoc} */
@@ -225,24 +214,23 @@ public class MarkdownSinkTest extends AbstractSinkTest {
 
     /** {@inheritDoc} */
     protected String getVerbatimSourceBlock(String text) {
-        return EOL
-                + EOL
-                + MarkdownMarkup.VERBATIM_START_MARKUP
+        return MarkdownMarkup.VERBATIM_START_MARKUP
                 + EOL
                 + text
                 + EOL
                 + MarkdownMarkup.VERBATIM_START_MARKUP
+                + EOL
                 + EOL;
     }
 
     /** {@inheritDoc} */
     protected String getHorizontalRuleBlock() {
-        return EOL + MarkdownMarkup.HORIZONTAL_RULE_MARKUP + EOL;
+        return MarkdownMarkup.HORIZONTAL_RULE_MARKUP + EOL + EOL;
     }
 
     /** {@inheritDoc} */
     protected String getPageBreakBlock() {
-        return EOL + MarkdownMarkup.PAGE_BREAK_MARKUP + EOL;
+        return "";
     }
 
     /** {@inheritDoc} */
@@ -297,7 +285,7 @@ public class MarkdownSinkTest extends AbstractSinkTest {
 
     /** {@inheritDoc} */
     protected String getLineBreakBlock() {
-        return MarkdownMarkup.BACKSLASH + EOL;
+        return "" + SPACE + SPACE + EOL;
     }
 
     /** {@inheritDoc} */
@@ -362,7 +350,7 @@ public class MarkdownSinkTest extends AbstractSinkTest {
                 + "author: " + EOL
                 + "  - first author" + EOL
                 + "  - second author" + EOL
-                + MarkdownMarkup.METADATA_MARKUP + EOL;
+                + MarkdownMarkup.METADATA_MARKUP + EOL + EOL;
 
         assertEquals(expected, getSinkContent(), "Wrong metadata section");
     }
@@ -380,8 +368,8 @@ public class MarkdownSinkTest extends AbstractSinkTest {
         final SinkEventTestingSink originalSink = new SinkEventTestingSink();
         parseFile(parser, "test", originalSink);
 
-        // compare sink events from parsing original markdown with sink events from regenerated markdown
-        assertThat(regeneratedSink.getEventList(), Matchers.contains(originalSink.getEventList().toArray()));
+        // compare sink events from parsing original markdown with sink events from re-generated markdown
+        assertEquals(originalSink.getEventList(), regeneratedSink.getEventList());
     }
 
     private void parseFile(Parser parser, String file, Sink sink) throws ParseException, IOException {
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/test.md b/doxia-modules/doxia-module-markdown/src/test/resources/test.md
index c9c7ae3d..885d1696 100644
--- a/doxia-modules/doxia-module-markdown/src/test/resources/test.md
+++ b/doxia-modules/doxia-module-markdown/src/test/resources/test.md
@@ -6,3 +6,8 @@ Placeholder for future expansion.
 - item1
 - item2
 - item3
+    - item31
+
+```
+code
+```
\ No newline at end of file