From ff153d9874f728c9ec3ab40b87f55ccf0239e538 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 16 May 2022 13:32:44 +0200 Subject: [PATCH] Avoid ending Markdown fenced code blocks with gratuitous blank lines This caused unnecessary empty
 blocks when converting markdown to
HTML, made code blocks too large using QSyntaxHighlighter to highlight
the whole block, and caused assymmetry when rewriting markdown.

Pick-to: 6.3
Fixes: QTBUG-101031
Change-Id: I08016577ccb92edb4afae31d7df3259cb011d5c8
Reviewed-by: Qt CI Bot 
Reviewed-by: Allan Sandfeld Jensen 
---
 src/gui/text/qtextmarkdownimporter.cpp               | 12 ++++++++++--
 src/gui/text/qtextmarkdownwriter.cpp                 |  4 ++--
 .../tst_qtextmarkdownimporter.cpp                    |  9 ++++-----
 .../gui/text/qtextmarkdownwriter/data/blockquotes.md |  1 +
 .../qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp  |  2 +-
 5 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index c434bf859aa..1b6222761f0 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -498,6 +498,14 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
     case MD_BLOCK_TD:
         m_nonEmptyTableCells.append(m_tableCol);
         break;
+    case MD_BLOCK_CODE:
+        if (s == Newline) {
+            // defer a blank line until we see something else in the code block,
+            // to avoid ending every code block with a gratuitous blank line
+            m_needsInsertBlock = true;
+            s = QString();
+        }
+        break;
     default:
         break;
     }
@@ -531,12 +539,12 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
                     QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel));
         if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage))
             debugInfo += "in a code block"_L1;
+        if (m_cursor->currentList())
+            debugInfo += "in a list"_L1;
         qCDebug(lcMD) << textType << "in block" << m_blockType << s << qPrintable(debugInfo)
                       << "bindent" << bfmt.indent() << "tindent" << bfmt.textIndent()
                       << "margins" << bfmt.leftMargin() << bfmt.topMargin() << bfmt.bottomMargin() << bfmt.rightMargin();
     }
-    qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList()
-                  << "indent" << m_cursor->blockFormat().indent();
     return 0; // no error
 }
 
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index fe772d3944e..9f651a04fd7 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -156,11 +156,11 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                 for (int col = cell.column(); col < spanEndCol; ++col)
                     m_stream << "|";
             } else if (m_fencedCodeBlock && ending) {
-                m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
+                m_stream << Newline << m_linePrefix << QString(m_wrappedLineIndent, Space)
                          << m_codeBlockFence << Newline << Newline;
                 m_codeBlockFence.clear();
             } else if (m_indentedCodeBlock && nextIsDifferent) {
-                m_stream << Newline;
+                m_stream << Newline << Newline;
             } else if (endingCol > 0) {
                 if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
                     m_stream << Newline;
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
index b8d53ca194e..686187cc777 100644
--- a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
+++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
@@ -380,7 +380,7 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning_data()
 
     QTest::newRow("Text block") << QString("Markdown text") << 1;
     QTest::newRow("Headline") << QString("Markdown text\n============") << 1;
-    QTest::newRow("Code block") << QString("    Markdown text") << 2;
+    QTest::newRow("Code block") << QString("    Markdown text") << 1;
     QTest::newRow("Unordered list") << QString("* Markdown text") << 1;
     QTest::newRow("Ordered list") << QString("1. Markdown text") << 1;
     QTest::newRow("Blockquote") << QString("> Markdown text") << 1;
@@ -501,18 +501,17 @@ void tst_QTextMarkdownImporter::fencedCodeBlocks_data()
     QTest::addColumn("expectedFenceChar");
     QTest::addColumn("rewrite");
 
-    // TODO shouldn't add empty blocks: QTBUG-101031
     QTest::newRow("backtick fence with language")
             << "```pseudocode\nprint('hello world\\n')\n```\n"
-            << 2 << 0 << "pseudocode" << "`"
+            << 1 << 0 << "pseudocode" << "`"
             << "```pseudocode\nprint('hello world\\n')\n```\n\n";
     QTest::newRow("tilde fence with language")
             << "~~~pseudocode\nprint('hello world\\n')\n~~~\n"
-            << 2 << 0 << "pseudocode" << "~"
+            << 1 << 0 << "pseudocode" << "~"
             << "~~~pseudocode\nprint('hello world\\n')\n~~~\n\n";
     QTest::newRow("embedded backticks")
             << "```\nnone `one` ``two``\n```\nplain\n```\n```three``` ````four````\n```\nplain\n"
-            << 4 << 2 << QString() << "`"
+            << 2 << 2 << QString() << "`"
             << "```\nnone `one` ``two``\n```\nplain\n\n```\n```three``` ````four````\n```\nplain\n\n";
 }
 
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
index 702ccef1346..b29b53651b6 100644
--- a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
@@ -50,6 +50,7 @@ Now let's have an indented code block:
     }
 
 and end with a fenced code block:
+
 ~~~pseudocode
 #include 
 #include 
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
index c5e48295330..b258869dfd5 100644
--- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
+++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
@@ -494,7 +494,7 @@ void tst_QTextMarkdownWriter::fromHtml_data()
         "![foo](/url \"title\")\n\n";
     QTest::newRow("code") <<
         "
\n#include \"foo.h\"\n\nblock {\n    statement();\n}\n\n
" << - "```pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n```\n\n"; + "```pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n```\n\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

(The first sentence of this paragraph is a line, the next paragraph has a number

13) but that's not part of an ordered list" <<