diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-02-06 13:54:00 -0700 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2024-02-13 21:37:43 -0700 |
commit | 908fc2e72b34073dc42ce0f2d6f7cc5adc9651d9 (patch) | |
tree | bd984be49776744bab8905b691ff047fa372cf67 /src/gui/text | |
parent | f3e528b97f6836b497953935e1dd27fee134e68a (diff) |
QTextMarkdownWriter: Avoid omitting or misplacing ending indicators
If we need to word-wrap a paragraph after a long formatted span,
write any ending markers before the newline (amends
280d679c556ab8ead4748a627d7cd4c1950027fb ).
Break before a fragment if the whole thing is past the column limit;
in that case, write out any ending format markers before the newline.
And now we have test coverage: prepend characters one-at-a-time to a
line that already has a two-word formatted span at the end, and watch
it successively break after the span, in the middle, and then before,
while never putting a newline before the ending markers or failing to
write them.
Fixes: QTBUG-116927
Change-Id: I140e10d19a491cb599bf7ecf8514af866b5383f3
Pick-to: 6.5 6.6 6.7
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qtextmarkdownwriter.cpp | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 5d6c673179..8cce9df0dd 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -495,6 +495,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign bool italic = false; bool underline = false; bool strikeOut = false; + bool endingMarkers = false; QString backticks(qtmw_Backtick); for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) { missedBlankCodeBlockLine = false; @@ -562,19 +563,27 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign if (startsOrEndsWithBacktick) markers += qtmw_Space; mono = monoFrag; + if (!mono) + endingMarkers = true; } if (!blockFmt.headingLevel() && !mono) { if (fontInfo.bold() != bold) { markers += "**"_L1; bold = fontInfo.bold(); + if (!bold) + endingMarkers = true; } if (fontInfo.italic() != italic) { markers += u'*'; italic = fontInfo.italic(); + if (!italic) + endingMarkers = true; } if (fontInfo.strikeOut() != strikeOut) { markers += "~~"_L1; strikeOut = fontInfo.strikeOut(); + if (!strikeOut) + endingMarkers = true; } if (fontInfo.underline() != underline) { // Markdown doesn't support underline, but the parser will treat a single underline @@ -582,6 +591,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign // That will have to do. markers += u'_'; underline = fontInfo.underline(); + if (!underline) + endingMarkers = true; } } } @@ -591,7 +602,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign bool breakingLine = false; while (i < fragLen) { if (col >= ColumnLimit) { - m_stream << qtmw_Newline << wrapIndentString; + m_stream << markers << qtmw_Newline << wrapIndentString; + markers.clear(); col = m_wrappedLineIndent; while (i < fragLen && fragmentText[i].isSpace()) ++i; @@ -601,6 +613,13 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign int wi = nearestWordWrapIndex(fragmentText, j); if (wi < 0) { j = fragLen; + // can't break within the fragment: we need to break already _before_ it + if (endingMarkers) { + m_stream << markers; + markers.clear(); + } + m_stream << qtmw_Newline << wrapIndentString; + col = m_wrappedLineIndent; } else if (wi >= i) { j = wi; breakingLine = true; @@ -624,7 +643,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign col += subfrag.size(); } i = j + 1; - } + } // loop over fragment characters (we know we need to break somewhere) } else { if (!m_linePrefixWritten && col == wrapIndentString.size()) { m_stream << m_linePrefix; |