summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/text/qtextformat.h4
-rw-r--r--src/gui/text/qtexthtmlparser.cpp1
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp103
-rw-r--r--src/gui/text/qtextmarkdownimporter_p.h8
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp58
-rw-r--r--src/gui/text/qtextmarkdownwriter_p.h1
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro1
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md39
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro4
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp17
10 files changed, 191 insertions, 45 deletions
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 1eb52a379c..a631309ae0 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -176,7 +176,9 @@ public:
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
HeadingLevel = 0x1070,
- BlockMarker = 0x1080,
+ BlockQuoteLevel = 0x1080,
+ BlockCodeLanguage = 0x1090,
+ BlockMarker = 0x10A0,
// character properties
FirstFontProperty = 0x1FE0,
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 895232e4c7..37051502fa 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1125,6 +1125,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
margin[QTextHtmlParser::MarginBottom] = 12;
margin[QTextHtmlParser::MarginLeft] = 40;
margin[QTextHtmlParser::MarginRight] = 40;
+ blockFormat.setProperty(QTextFormat::BlockQuoteLevel, 1);
break;
case Html_dl:
margin[QTextHtmlParser::MarginTop] = 8;
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 5cee01d932..d8ffec2496 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -55,6 +55,9 @@ Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown")
static const QChar Newline = QLatin1Char('\n');
static const QChar Space = QLatin1Char(' ');
+// TODO maybe eliminate the margins after all views recognize BlockQuoteLevel, CSS can format it, etc.
+static const int BlockQuoteIndent = 40; // pixels, same as in QTextHtmlParserNode::initializeProperties
+
// --------------------------------------------------------
// MD4C callback function wrappers
@@ -131,6 +134,7 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown)
nullptr // syntax
};
m_doc = doc;
+ m_paragraphMargin = m_doc->defaultFont().pointSize() * 2 / 3;
m_cursor = new QTextCursor(doc);
doc->clear();
qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont;
@@ -146,11 +150,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
switch (blockType) {
case MD_BLOCK_P:
if (m_listStack.isEmpty()) {
- QTextBlockFormat blockFmt;
- int margin = m_doc->defaultFont().pointSize() / 2;
- blockFmt.setTopMargin(margin);
- blockFmt.setBottomMargin(margin);
- m_cursor->insertBlock(blockFmt, QTextCharFormat());
+ m_needsInsertBlock = true;
qCDebug(lcMD, "P");
} else {
if (m_emptyListItem) {
@@ -159,18 +159,25 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
m_emptyListItem = false;
} else {
qCDebug(lcMD, "P inside LI at level %d", m_listStack.count());
- QTextBlockFormat blockFmt;
- blockFmt.setIndent(m_listStack.count());
- m_cursor->insertBlock(blockFmt, QTextCharFormat());
+ m_needsInsertBlock = true;
}
}
break;
+ case MD_BLOCK_QUOTE: {
+ ++m_blockQuoteDepth;
+ qCDebug(lcMD, "QUOTE level %d", m_blockQuoteDepth);
+ break;
+ }
case MD_BLOCK_CODE: {
- QTextBlockFormat blockFmt;
- QTextCharFormat charFmt;
- charFmt.setFont(m_monoFont);
- m_cursor->insertBlock(blockFmt, charFmt);
- qCDebug(lcMD, "CODE");
+ MD_BLOCK_CODE_DETAIL *detail = static_cast<MD_BLOCK_CODE_DETAIL *>(det);
+ m_codeBlock = true;
+ m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size));
+ QString info = QLatin1String(detail->info.text, int(detail->info.size));
+ m_needsInsertBlock = true;
+ if (m_blockQuoteDepth)
+ qCDebug(lcMD, "CODE lang '%s' info '%s' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockQuoteDepth);
+ else
+ qCDebug(lcMD, "CODE lang '%s' info '%s'", qPrintable(m_blockCodeLanguage), qPrintable(info));
} break;
case MD_BLOCK_H: {
MD_BLOCK_H_DETAIL *detail = static_cast<MD_BLOCK_H_DETAIL *>(det);
@@ -180,10 +187,12 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
charFmt.setFontWeight(QFont::Bold);
blockFmt.setHeadingLevel(int(detail->level));
+ m_needsInsertBlock = false;
m_cursor->insertBlock(blockFmt, charFmt);
qCDebug(lcMD, "H%d", detail->level);
} break;
case MD_BLOCK_LI: {
+ m_needsInsertBlock = false;
MD_BLOCK_LI_DETAIL *detail = static_cast<MD_BLOCK_LI_DETAIL *>(det);
QTextList *list = m_listStack.top();
QTextBlockFormat bfmt = list->item(list->count() - 1).blockFormat();
@@ -316,9 +325,9 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
}
} break;
case MD_BLOCK_QUOTE: {
- QTextBlockFormat blockFmt = m_cursor->blockFormat();
- blockFmt.setIndent(1);
- m_cursor->setBlockFormat(blockFmt);
+ qCDebug(lcMD, "QUOTE level %d ended", m_blockQuoteDepth);
+ --m_blockQuoteDepth;
+ m_needsInsertBlock = true;
} break;
case MD_BLOCK_TABLE:
qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows";
@@ -329,7 +338,15 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
qCDebug(lcMD, "LI at level %d ended", m_listStack.count());
m_listItem = false;
break;
- case MD_BLOCK_CODE:
+ case MD_BLOCK_CODE: {
+ m_codeBlock = false;
+ m_blockCodeLanguage.clear();
+ if (m_blockQuoteDepth)
+ qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth);
+ else
+ qCDebug(lcMD, "CODE ended");
+ m_needsInsertBlock = true;
+ } break;
case MD_BLOCK_H:
m_cursor->setCharFormat(QTextCharFormat());
break;
@@ -365,6 +382,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
QString title = QString::fromUtf8(detail->title.text, int(detail->title.size));
QTextImageFormat img;
img.setName(src);
+ if (m_needsInsertBlock)
+ insertBlock();
qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl();
m_cursor->insertImage(img);
break;
@@ -377,6 +396,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
break;
}
m_spanFormatStack.push(charFmt);
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight()
+ << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name();
m_cursor->setCharFormat(charFmt);
return 0; // no error
}
@@ -391,6 +412,8 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail)
charFmt = m_spanFormatStack.top();
}
m_cursor->setCharFormat(charFmt);
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight()
+ << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name();
if (spanType == int(MD_SPAN_IMG))
m_imageSpan = false;
return 0; // no error
@@ -400,6 +423,8 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
{
if (m_imageSpan)
return 0; // it's the alt-text
+ if (m_needsInsertBlock)
+ insertBlock();
static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]"));
static const QRegularExpression closingBracket(QStringLiteral("(/>|</)"));
QString s = QString::fromUtf8(text, int(size));
@@ -467,13 +492,51 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
m_cursor->insertText(s);
if (m_cursor->currentList()) {
// The list item will indent the list item's text, so we don't need indentation on the block.
- QTextBlockFormat blockFmt = m_cursor->blockFormat();
- blockFmt.setIndent(0);
- m_cursor->setBlockFormat(blockFmt);
+ QTextBlockFormat bfmt = m_cursor->blockFormat();
+ bfmt.setIndent(0);
+ m_cursor->setBlockFormat(bfmt);
+ }
+ if (lcMD().isEnabled(QtDebugMsg)) {
+ QTextBlockFormat bfmt = m_cursor->blockFormat();
+ QString debugInfo;
+ if (m_cursor->currentList())
+ debugInfo = QLatin1String("in list at depth ") + QString::number(m_cursor->currentList()->format().indent());
+ if (bfmt.hasProperty(QTextFormat::BlockQuoteLevel))
+ debugInfo += QLatin1String("in blockquote at depth ") +
+ QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel));
+ if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage))
+ debugInfo += QLatin1String("in a code block");
+ 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
}
+void QTextMarkdownImporter::insertBlock()
+{
+ QTextCharFormat charFormat;
+ if (!m_spanFormatStack.isEmpty())
+ charFormat = m_spanFormatStack.top();
+ QTextBlockFormat blockFormat;
+ if (m_blockQuoteDepth) {
+ blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
+ blockFormat.setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth);
+ blockFormat.setRightMargin(BlockQuoteIndent);
+ }
+ if (m_listStack.count())
+ blockFormat.setIndent(m_listStack.count());
+ if (m_codeBlock) {
+ blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage);
+ charFormat.setFont(m_monoFont);
+ } else {
+ blockFormat.setTopMargin(m_paragraphMargin);
+ blockFormat.setBottomMargin(m_paragraphMargin);
+ }
+ m_cursor->insertBlock(blockFormat, charFormat);
+ m_needsInsertBlock = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
index 8ab119d051..1716530b1d 100644
--- a/src/gui/text/qtextmarkdownimporter_p.h
+++ b/src/gui/text/qtextmarkdownimporter_p.h
@@ -100,25 +100,33 @@ public:
int cbText(int textType, const char* text, unsigned size);
private:
+ void insertBlock();
+
+private:
QTextDocument *m_doc = nullptr;
QTextCursor *m_cursor = nullptr;
QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work
QString m_htmlAccumulator;
+ QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row
QStack<QTextList *> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont;
QPalette m_palette;
int m_htmlTagDepth = 0;
+ int m_blockQuoteDepth = 0;
int m_tableColumnCount = 0;
int m_tableRowCount = 0;
int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work
+ int m_paragraphMargin = 0;
Features m_features;
int m_blockType = 0;
bool m_emptyList = false; // true when the last thing we did was insertList
bool m_listItem = false;
bool m_emptyListItem = false;
+ bool m_codeBlock = false;
bool m_imageSpan = false;
+ bool m_needsInsertBlock = false;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features)
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index a445ee7e83..f180098db2 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -106,7 +106,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
Q_ASSERT(frame);
const QTextTable *table = qobject_cast<const QTextTable*> (frame);
QTextFrame::iterator iterator = frame->begin();
- QTextFrame *child = 0;
+ QTextFrame *child = nullptr;
int tableRow = -1;
bool lastWasList = false;
QVector<int> tableColumnWidths;
@@ -161,7 +161,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
m_stream << QString(paddingLen, Space);
for (int col = cell.column(); col < spanEndCol; ++col)
m_stream << "|";
- } else if (block.textList()) {
+ } else if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
m_stream << Newline;
} else if (endingCol > 0) {
m_stream << Newline << Newline;
@@ -252,6 +252,8 @@ static void maybeEscapeFirstChar(QString &s)
int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat)
{
int ColumnLimit = 80;
+ QTextBlockFormat blockFmt = block.blockFormat();
+ bool indentedCodeBlock = false;
if (block.textList()) { // it's a list-item
auto fmt = block.textList()->format();
const int listLevel = fmt.indent();
@@ -281,7 +283,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
m_wrappedLineIndent = 4;
break;
}
- switch (block.blockFormat().marker()) {
+ switch (blockFmt.marker()) {
case QTextBlockFormat::Checked:
bullet += " [x]";
break;
@@ -309,21 +311,35 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
prefix += QLatin1String(bullet) + Space;
}
m_stream << prefix;
- } else if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
+ } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading
return 0;
- } else if (!block.blockFormat().indent()) {
+ } else if (!blockFmt.indent()) {
m_wrappedLineIndent = 0;
+ m_linePrefix.clear();
+ if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) {
+ int level = blockFmt.intProperty(QTextFormat::BlockQuoteLevel);
+ QString quoteMarker = QStringLiteral("> ");
+ m_linePrefix.reserve(level * 2);
+ for (int i = 0; i < level; ++i)
+ m_linePrefix += quoteMarker;
+ }
+ if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) {
+ // A block quote can contain an indented code block, but not vice-versa.
+ m_linePrefix += QString(4, Space);
+ indentedCodeBlock = true;
+ }
}
+ if (blockFmt.headingLevel())
+ m_stream << QByteArray(blockFmt.headingLevel(), '#') << ' ';
+ else
+ m_stream << m_linePrefix;
- if (block.blockFormat().headingLevel())
- m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' ';
-
- QString wrapIndentString(m_wrappedLineIndent, Space);
+ QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, Space);
// It would be convenient if QTextStream had a lineCharPos() accessor,
// to keep track of how many characters (not bytes) have been written on the current line,
// but it doesn't. So we have to keep track with this col variable.
- int col = m_wrappedLineIndent;
+ int col = wrapIndentString.length();
bool mono = false;
bool startsOrEndsWithBacktick = false;
bool bold = false;
@@ -338,7 +354,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
if (block.textList()) { // <li>first line</br>continuation</li>
QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space);
fragmentText.replace(QString(LineBreak), newlineIndent);
- } else if (block.blockFormat().indent() > 0) { // <li>first line<p>continuation</p></li>
+ } else if (blockFmt.indent() > 0) { // <li>first line<p>continuation</p></li>
m_stream << QString(m_wrappedLineIndent, Space);
} else {
fragmentText.replace(LineBreak, Newline);
@@ -368,7 +384,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
bool monoFrag = fontInfo.fixedPitch();
QString markers;
if (!ignoreFormat) {
- if (monoFrag != mono) {
+ if (monoFrag != mono && !indentedCodeBlock) {
if (monoFrag)
backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick);
markers += backticks;
@@ -376,25 +392,25 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
markers += Space;
mono = monoFrag;
}
- if (!block.blockFormat().headingLevel() && !mono) {
- if (fmt.font().bold() != bold) {
+ if (!blockFmt.headingLevel() && !mono) {
+ if (fontInfo.bold() != bold) {
markers += QLatin1String("**");
- bold = fmt.font().bold();
+ bold = fontInfo.bold();
}
- if (fmt.font().italic() != italic) {
+ if (fontInfo.italic() != italic) {
markers += QLatin1Char('*');
- italic = fmt.font().italic();
+ italic = fontInfo.italic();
}
- if (fmt.font().strikeOut() != strikeOut) {
+ if (fontInfo.strikeOut() != strikeOut) {
markers += QLatin1String("~~");
- strikeOut = fmt.font().strikeOut();
+ strikeOut = fontInfo.strikeOut();
}
- if (fmt.font().underline() != underline) {
+ if (fontInfo.underline() != underline) {
// Markdown doesn't support underline, but the parser will treat a single underline
// the same as a single asterisk, and the marked fragment will be rendered in italics.
// That will have to do.
markers += QLatin1Char('_');
- underline = fmt.font().underline();
+ underline = fontInfo.underline();
}
}
}
diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h
index 4c07bad2e7..96ceb445cd 100644
--- a/src/gui/text/qtextmarkdownwriter_p.h
+++ b/src/gui/text/qtextmarkdownwriter_p.h
@@ -81,6 +81,7 @@ private:
QTextStream &m_stream;
QTextDocument::MarkdownFeatures m_features;
QMap<QTextList *, ListInfo> m_listInfo;
+ QString m_linePrefix;
int m_wrappedLineIndent = 0;
int m_lastListIndent = 1;
bool m_doubleNewlineWritten = false;
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
index 7afc807c9b..7b7fb61244 100644
--- a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
+++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
@@ -4,5 +4,6 @@ QT += core-private gui-private testlib
SOURCES += tst_qtextmarkdownimporter.cpp
TESTDATA += \
data/thematicBreaks.md \
+ data/headingBulletsContinuations.md \
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
new file mode 100644
index 0000000000..f429fcc21b
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
@@ -0,0 +1,39 @@
+In 1958, Mahatma Gandhi was quoted as follows:
+
+> The Earth provides enough to satisfy every man's need but not for every man's
+> greed.
+
+In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John
+MacFarlane writes:
+
+> What distinguishes Markdown from many other lightweight markup syntaxes,
+> which are often easier to write, is its readability. As Gruber writes:
+
+> > The overriding design goal for Markdown's formatting syntax is to make it
+> > as readable as possible. The idea is that a Markdown-formatted document should
+> > be publishable as-is, as plain text, without looking like it's been marked up
+> > with tags or formatting instructions. (
+> > [http://daringfireball.net/projects/markdown/](http://daringfireball.net/projects/markdown/))
+
+> The point can be illustrated by comparing a sample of AsciiDoc with an
+> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
+> manual:
+
+> 1. List item one.
+> +
+> List item one continued with a second paragraph followed by an
+> Indented block.
+> +
+> .................
+> $ ls *.sh
+> $ mv *.sh ~/tmp
+> .................
+> +
+> List item continued with a third paragraph.
+>
+> 2. List item two continued with an open block.
+> ...
+>
+The quotation includes an embedded quotation and a code quotation and ends with
+an ellipsis due to being incomplete.
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
index 04cf7ef5dd..6144710b99 100644
--- a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
+++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
@@ -2,6 +2,8 @@ CONFIG += testcase
TARGET = tst_qtextmarkdownwriter
QT += core-private gui-private testlib
SOURCES += tst_qtextmarkdownwriter.cpp
-TESTDATA += data/example.md
+TESTDATA += \
+ data/example.md \
+ data/blockquotes.md \
DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
index 3d77ccd9d8..9998794762 100644
--- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
+++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
@@ -54,6 +54,7 @@ private slots:
void testWriteNestedBulletLists();
void testWriteNestedNumericLists();
void testWriteTable();
+ void rewriteDocument_data();
void rewriteDocument();
void fromHtml_data();
void fromHtml();
@@ -350,10 +351,19 @@ void tst_QTextMarkdownWriter::testWriteTable()
QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n"));
}
+void tst_QTextMarkdownWriter::rewriteDocument_data()
+{
+ QTest::addColumn<QString>("inputFile");
+
+ QTest::newRow("block quotes") << "blockquotes.md";
+ QTest::newRow("example") << "example.md";
+}
+
void tst_QTextMarkdownWriter::rewriteDocument()
{
+ QFETCH(QString, inputFile);
QTextDocument doc;
- QFile f(QFINDTESTDATA("data/example.md"));
+ QFile f(QFINDTESTDATA("data/" + inputFile));
QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
QString orig = QString::fromUtf8(f.readAll());
f.close();
@@ -361,7 +371,7 @@ void tst_QTextMarkdownWriter::rewriteDocument()
QString md = doc.toMarkdown();
#ifdef DEBUG_WRITE_OUTPUT
- QFile out("/tmp/rewrite.md");
+ QFile out("/tmp/rewrite-" + inputFile);
out.open(QFile::WriteOnly);
out.write(md.toUtf8());
out.close();
@@ -401,6 +411,9 @@ void tst_QTextMarkdownWriter::fromHtml_data()
QTest::newRow("thematic break") <<
"something<hr/>something else" <<
"something\n\n- - -\nsomething else\n\n";
+ QTest::newRow("block quote") <<
+ "<p>In 1958, Mahatma Gandhi was quoted as follows:</p><blockquote>The Earth provides enough to satisfy every man's need but not for every man's greed.</blockquote>" <<
+ "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n";
// TODO
// QTest::newRow("escaped number and paren after double newline") <<
// "<p>(The first sentence of this paragraph is a line, the next paragraph has a number</p>13) but that's not part of an ordered list" <<