Markdown importer: keep entities in HTML blocks with the HTML

If an entity occurs directly in markdown, we parse and insert it
directly; but if it occurs in an HTML block, it has to be added to the
HTML accumulator string for deferred parsing when the HTML block ends.

Pick-to: 6.2
Fixes: QTBUG-91222
Fixes: QTBUG-94245
Change-Id: I0cf586d68d6751892ca035a98f77cd67950d3bc4
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Shawn Rutledge 2021-10-14 07:53:36 +02:00
parent 848e3855f9
commit 362e56b520
2 changed files with 70 additions and 1 deletions

View File

@ -490,6 +490,9 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
break; break;
#if QT_CONFIG(texthtmlparser) #if QT_CONFIG(texthtmlparser)
case MD_TEXT_ENTITY: case MD_TEXT_ENTITY:
if (m_htmlTagDepth)
m_htmlAccumulator += s;
else
m_cursor->insertHtml(s); m_cursor->insertHtml(s);
s = QString(); s = QString();
break; break;

View File

@ -62,6 +62,8 @@ private slots:
void nestedSpans(); void nestedSpans();
void avoidBlankLineAtBeginning_data(); void avoidBlankLineAtBeginning_data();
void avoidBlankLineAtBeginning(); void avoidBlankLineAtBeginning();
void fragmentsAndProperties_data();
void fragmentsAndProperties();
void pathological_data(); void pathological_data();
void pathological(); void pathological();
@ -378,6 +380,70 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning() // QTBUG-81060
QCOMPARE(i, expectedNumberOfParagraphs); QCOMPARE(i, expectedNumberOfParagraphs);
} }
void tst_QTextMarkdownImporter::fragmentsAndProperties_data()
{
QTest::addColumn<QString>("input");
QTest::addColumn<int>("fragmentToCheck");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QTextFormat::Property>("propertyToCheck");
QTest::addColumn<QVariant>("expectedPropertyValue");
QTest::addColumn<int>("expectedNumberOfBlocks");
QTest::addColumn<int>("expectedNumberOfFragments");
QTest::newRow("entitiesInHtmlFontBlock") // QTBUG-94245
<< QString("<font color='red'>&lt;123 test&gt;</font>&nbsp;test")
<< 0 << "<123 test>" << QTextFormat::ForegroundBrush << QVariant(QBrush(QColor("red")))
<< 1 << 2;
QTest::newRow("entitiesInHtmlBoldBlock") // QTBUG-91222
<< QString("<b>x&amp;lt;</b>")
<< 0 << "x&lt;" << QTextFormat::FontWeight << QVariant(700)
<< 1 << 1;
}
void tst_QTextMarkdownImporter::fragmentsAndProperties()
{
QFETCH(QString, input);
QFETCH(int, fragmentToCheck);
QFETCH(QString, expectedText);
QFETCH(QTextFormat::Property, propertyToCheck);
QFETCH(QVariant, expectedPropertyValue);
QFETCH(int, expectedNumberOfBlocks);
QFETCH(int, expectedNumberOfFragments);
QTextDocument doc;
QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, input);
#ifdef DEBUG_WRITE_HTML
{
QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".html");
out.open(QFile::WriteOnly);
out.write(doc.toHtml().toLatin1());
out.close();
}
#endif
QTextFrame::iterator blockIter = doc.rootFrame()->begin();
int blockCount = 0;
int fragCount = 0;
while (!blockIter.atEnd()) {
QTextBlock block = blockIter.currentBlock();
auto fragIter = block.begin();
while (!fragIter.atEnd()) {
auto frag = fragIter.fragment();
qCDebug(lcTests) << "fragment" << fragCount << ':' << frag.text() << Qt::hex << frag.charFormat().properties();
if (fragCount == fragmentToCheck) {
QVariant prop = frag.charFormat().property(propertyToCheck);
QCOMPARE(prop, expectedPropertyValue);
QCOMPARE(frag.text(), expectedText);
}
++fragIter;
++fragCount;
}
++blockIter;
++blockCount;
}
QCOMPARE(blockCount, expectedNumberOfBlocks);
QCOMPARE(fragCount, expectedNumberOfFragments);
}
void tst_QTextMarkdownImporter::pathological_data() void tst_QTextMarkdownImporter::pathological_data()
{ {
QTest::addColumn<QString>("warning"); QTest::addColumn<QString>("warning");