data/MailHtmlWriter.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "MailHtmlWriter.h" | ||
| 2 | |||
| 3 | #include "ComposeDocumentFormat.h" | ||
| 4 | |||
| 5 | #include <QTextBlock> | ||
| 6 | #include <QTextCharFormat> | ||
| 7 | #include <QTextDocument> | ||
| 8 | #include <QTextFrame> | ||
| 9 | #include <QTextImageFormat> | ||
| 10 | #include <QTextList> | ||
| 11 | #include <QTextTable> | ||
| 12 | #include <QVector> | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | using namespace ComposeDocumentFormat; | ||
| 17 | |||
| 18 | // A paragraph's attributes; consecutive plain blocks with equal attributes | ||
| 19 | // share one <p> (lines joined by <br>, an empty block ends the paragraph). | ||
| 20 | struct ParagraphStyle { | ||
| 21 | QString align; // "", "left", "right", "center", "justify" | ||
| 22 | bool rtl = false; | ||
| 23 | int indent = 0; | ||
| 24 | 585 | bool operator==(const ParagraphStyle &other) const { | |
| 25 |
4/6✓ Branch 3 → 4 taken 582 times.
✓ Branch 3 → 7 taken 3 times.
✓ Branch 4 → 5 taken 582 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 582 times.
✗ Branch 5 → 7 not taken.
|
585 | return align == other.align && rtl == other.rtl && indent == other.indent; |
| 26 | } | ||
| 27 | }; | ||
| 28 | |||
| 29 | 4800 | QString physicalAlignment(const QTextBlockFormat &format, bool rtl) { | |
| 30 |
3/3✓ Branch 2 → 3 taken 4800 times.
✓ Branch 3 → 4 taken 4783 times.
✓ Branch 3 → 5 taken 17 times.
|
4800 | if (!format.hasProperty(QTextFormat::BlockAlignment)) return {}; |
| 31 |
1/1✓ Branch 5 → 6 taken 17 times.
|
17 | const Qt::Alignment alignment = format.alignment(); |
| 32 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 14 taken 17 times.
|
17 | if (alignment & Qt::AlignJustify) return QStringLiteral("justify"); |
| 33 |
2/2✓ Branch 16 → 17 taken 9 times.
✓ Branch 16 → 22 taken 8 times.
|
26 | if (alignment & Qt::AlignHCenter) return QStringLiteral("center"); |
| 34 | 8 | const bool absolute = alignment & Qt::AlignAbsolute; | |
| 35 |
1/2✓ Branch 26 → 27 taken 8 times.
✗ Branch 26 → 41 not taken.
|
8 | if (alignment & Qt::AlignRight) |
| 36 |
4/8✓ Branch 27 → 28 taken 8 times.
✗ Branch 27 → 29 not taken.
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 32 not taken.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 8 times.
✓ Branch 38 → 39 taken 8 times.
✗ Branch 38 → 40 not taken.
|
24 | return (absolute || !rtl) ? QStringLiteral("right") : QStringLiteral("left"); |
| 37 | ✗ | if (alignment & Qt::AlignLeft) { | |
| 38 | // Logical start is the default: written only when it differs (absolute | ||
| 39 | // left in a right-to-left paragraph). | ||
| 40 | ✗ | if (absolute && rtl) return QStringLiteral("left"); | |
| 41 | ✗ | return {}; | |
| 42 | } | ||
| 43 | ✗ | return {}; | |
| 44 | } | ||
| 45 | |||
| 46 | 4800 | ParagraphStyle paragraphStyle(const QTextBlock &block) { | |
| 47 | 4800 | ParagraphStyle style; | |
| 48 |
1/1✓ Branch 2 → 3 taken 4800 times.
|
4800 | style.rtl = block.textDirection() == Qt::RightToLeft; |
| 49 |
2/2✓ Branch 3 → 4 taken 4800 times.
✓ Branch 4 → 5 taken 4800 times.
|
4800 | style.align = physicalAlignment(block.blockFormat(), style.rtl); |
| 50 |
2/2✓ Branch 8 → 9 taken 4800 times.
✓ Branch 9 → 10 taken 4800 times.
|
4800 | style.indent = qBound(0, block.blockFormat().indent(), 8); |
| 51 | 4800 | return style; | |
| 52 | ✗ | } | |
| 53 | |||
| 54 | 4218 | QString blockAttributes(const ParagraphStyle &style, const QString &baseStyle) { | |
| 55 | 4218 | QStringList declarations; | |
| 56 |
3/3✓ Branch 3 → 4 taken 3471 times.
✓ Branch 3 → 5 taken 747 times.
✓ Branch 4 → 5 taken 3471 times.
|
4218 | if (!baseStyle.isEmpty()) declarations.append(baseStyle); |
| 57 |
4/4✓ Branch 6 → 7 taken 17 times.
✓ Branch 6 → 16 taken 4201 times.
✓ Branch 10 → 11 taken 17 times.
✓ Branch 11 → 12 taken 17 times.
|
4235 | if (!style.align.isEmpty()) declarations.append(QStringLiteral("text-align:") + style.align); |
| 58 |
1/2✗ Branch 16 → 17 not taken.
✓ Branch 16 → 42 taken 4218 times.
|
4218 | if (style.indent > 0) |
| 59 | ✗ | declarations.append((style.rtl ? QStringLiteral("margin-right:") : QStringLiteral("margin-left:")) + | |
| 60 | ✗ | QString::number(style.indent * 40) + QStringLiteral("px")); | |
| 61 | 4218 | QString attributes; | |
| 62 |
3/3✓ Branch 42 → 43 taken 26 times.
✓ Branch 42 → 50 taken 4192 times.
✓ Branch 46 → 47 taken 26 times.
|
4244 | if (style.rtl) attributes += QStringLiteral(" dir=\"rtl\""); |
| 63 |
6/6✓ Branch 51 → 52 taken 3471 times.
✓ Branch 51 → 69 taken 747 times.
✓ Branch 56 → 57 taken 3471 times.
✓ Branch 60 → 61 taken 3471 times.
✓ Branch 61 → 62 taken 3471 times.
✓ Branch 62 → 63 taken 3471 times.
|
7689 | if (!declarations.isEmpty()) attributes += QStringLiteral(" style=\"") + declarations.join(QLatin1Char(';')) + QLatin1Char('"'); |
| 64 | 4218 | return attributes; | |
| 65 | 4218 | } | |
| 66 | |||
| 67 | // `previousSpace` carries the space run across the fragments of one block. | ||
| 68 | 11580 | QString escapedText(const QString &text, bool &previousSpace) { | |
| 69 | 11580 | QString out; | |
| 70 |
1/1✓ Branch 3 → 4 taken 11580 times.
|
11580 | out.reserve(text.size() + 16); |
| 71 |
2/2✓ Branch 78 → 6 taken 304961 times.
✓ Branch 78 → 79 taken 11580 times.
|
316541 | for (const QChar c : text) { |
| 72 |
7/10✓ Branch 7 → 8 taken 33 times.
✓ Branch 7 → 15 taken 39 times.
✓ Branch 7 → 22 taken 17 times.
✓ Branch 7 → 29 taken 4 times.
✗ Branch 7 → 36 not taken.
✗ Branch 7 → 43 not taken.
✓ Branch 7 → 50 taken 2 times.
✗ Branch 7 → 57 not taken.
✓ Branch 7 → 58 taken 71456 times.
✓ Branch 7 → 72 taken 233410 times.
|
304961 | switch (c.unicode()) { |
| 73 |
1/1✓ Branch 11 → 12 taken 33 times.
|
66 | case '<': out += QStringLiteral("<"); break; |
| 74 |
1/1✓ Branch 18 → 19 taken 39 times.
|
78 | case '>': out += QStringLiteral(">"); break; |
| 75 |
1/1✓ Branch 25 → 26 taken 17 times.
|
34 | case '&': out += QStringLiteral("&"); break; |
| 76 |
1/1✓ Branch 32 → 33 taken 4 times.
|
8 | case '"': out += QStringLiteral("""); break; |
| 77 | ✗ | case 0x2028: out += QStringLiteral("<br>"); break; // Shift+Enter line break | |
| 78 | ✗ | case 0x00A0: out += QStringLiteral(" "); break; | |
| 79 |
1/1✓ Branch 53 → 54 taken 2 times.
|
4 | case '\t': out += QStringLiteral(" "); break; |
| 80 | ✗ | case 0xFFFC: break; // object without image format | |
| 81 | 71456 | case ' ': | |
| 82 | // Runs of spaces keep their width: every second one is non-breaking. | ||
| 83 |
4/11✗ Branch 58 → 59 not taken.
✓ Branch 58 → 62 taken 71456 times.
✓ Branch 65 → 66 taken 71456 times.
✓ Branch 67 → 68 taken 71456 times.
✗ Branch 67 → 69 not taken.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 71456 times.
✗ Branch 125 → 126 not taken.
✗ Branch 125 → 127 not taken.
✗ Branch 129 → 130 not taken.
✗ Branch 129 → 131 not taken.
|
142912 | out += previousSpace ? QStringLiteral(" ") : QStringLiteral(" "); |
| 84 | 71456 | previousSpace = !previousSpace; | |
| 85 | 71456 | continue; | |
| 86 | 233410 | default: | |
| 87 |
2/2✓ Branch 73 → 74 taken 2 times.
✓ Branch 73 → 75 taken 233408 times.
|
233410 | if (c.unicode() < 0x20) break; // control characters never leave |
| 88 |
1/1✓ Branch 75 → 76 taken 233408 times.
|
233408 | out += c; |
| 89 | } | ||
| 90 | 233505 | previousSpace = false; | |
| 91 | } | ||
| 92 | 11580 | return out; | |
| 93 | ✗ | } | |
| 94 | |||
| 95 | 16 | QString escapedText(const QString &text) { | |
| 96 | 16 | bool previousSpace = false; | |
| 97 |
1/1✓ Branch 2 → 3 taken 16 times.
|
32 | return escapedText(text, previousSpace); |
| 98 | } | ||
| 99 | |||
| 100 | 11564 | QString spanStyle(const QTextCharFormat &format) { | |
| 101 | 11564 | QStringList declarations; | |
| 102 |
6/6✓ Branch 2 → 3 taken 11564 times.
✓ Branch 3 → 4 taken 11564 times.
✓ Branch 4 → 5 taken 11564 times.
✓ Branch 5 → 6 taken 11564 times.
✓ Branch 9 → 10 taken 59 times.
✓ Branch 9 → 19 taken 11505 times.
|
11564 | if (const FontFamily *family = fontFamilyFor(format.fontFamilies().toStringList().value(0))) |
| 103 |
2/2✓ Branch 13 → 14 taken 59 times.
✓ Branch 14 → 15 taken 59 times.
|
118 | declarations.append(QStringLiteral("font-family:") + family->stack); |
| 104 |
3/3✓ Branch 19 → 20 taken 11564 times.
✓ Branch 20 → 21 taken 58 times.
✓ Branch 20 → 34 taken 11506 times.
|
11564 | if (format.hasProperty(QTextFormat::FontPointSize)) { |
| 105 |
1/1✓ Branch 21 → 22 taken 58 times.
|
58 | const int points = qBound(FontPointSizeMin, qRound(format.fontPointSize()), FontPointSizeMax); |
| 106 |
2/2✓ Branch 28 → 29 taken 58 times.
✓ Branch 29 → 30 taken 58 times.
|
116 | declarations.append(QStringLiteral("font-size:%1pt").arg(points)); |
| 107 | } | ||
| 108 |
7/8✓ Branch 34 → 35 taken 11564 times.
✓ Branch 35 → 36 taken 9667 times.
✓ Branch 35 → 42 taken 1897 times.
✓ Branch 36 → 37 taken 9667 times.
✓ Branch 37 → 38 taken 41 times.
✓ Branch 37 → 42 taken 9626 times.
✓ Branch 40 → 41 taken 41 times.
✗ Branch 40 → 42 not taken.
|
11605 | if (!format.isAnchor() && format.hasProperty(QTextFormat::ForegroundBrush) && |
| 109 |
5/7✓ Branch 38 → 39 taken 41 times.
✓ Branch 43 → 44 taken 41 times.
✓ Branch 43 → 45 taken 11523 times.
✓ Branch 45 → 46 taken 41 times.
✓ Branch 45 → 60 taken 11523 times.
✗ Branch 126 → 127 not taken.
✗ Branch 126 → 128 not taken.
|
11605 | format.foreground().style() != Qt::NoBrush) |
| 110 |
4/4✓ Branch 46 → 47 taken 41 times.
✓ Branch 48 → 49 taken 41 times.
✓ Branch 52 → 53 taken 41 times.
✓ Branch 53 → 54 taken 41 times.
|
82 | declarations.append(QStringLiteral("color:") + cssColor(format.foreground().color())); |
| 111 |
8/12✓ Branch 60 → 61 taken 11564 times.
✓ Branch 61 → 62 taken 14 times.
✓ Branch 61 → 70 taken 11550 times.
✓ Branch 62 → 63 taken 14 times.
✓ Branch 64 → 65 taken 14 times.
✗ Branch 64 → 70 not taken.
✓ Branch 68 → 69 taken 14 times.
✗ Branch 68 → 70 not taken.
✓ Branch 75 → 76 taken 14 times.
✓ Branch 75 → 90 taken 11550 times.
✗ Branch 149 → 150 not taken.
✗ Branch 149 → 151 not taken.
|
23142 | if (format.hasProperty(QTextFormat::BackgroundBrush) && format.background().style() != Qt::NoBrush && |
| 112 |
5/7✓ Branch 65 → 66 taken 14 times.
✓ Branch 71 → 72 taken 14 times.
✓ Branch 71 → 73 taken 11550 times.
✓ Branch 73 → 74 taken 14 times.
✓ Branch 73 → 75 taken 11550 times.
✗ Branch 145 → 146 not taken.
✗ Branch 145 → 147 not taken.
|
11578 | format.background().color().alpha() > 0) |
| 113 |
4/4✓ Branch 76 → 77 taken 14 times.
✓ Branch 78 → 79 taken 14 times.
✓ Branch 82 → 83 taken 14 times.
✓ Branch 83 → 84 taken 14 times.
|
28 | declarations.append(QStringLiteral("background-color:") + cssColor(format.background().color())); |
| 114 |
1/1✓ Branch 92 → 93 taken 11564 times.
|
23128 | return declarations.join(QLatin1Char(';')); |
| 115 | 11564 | } | |
| 116 | |||
| 117 | class Writer { | ||
| 118 | public: | ||
| 119 | 521 | explicit Writer(const MailHtmlWriter::Options &options) : m_options(options) {} | |
| 120 | |||
| 121 | 521 | MailHtmlWriter::Result run(const QTextDocument &document) { | |
| 122 | 521 | writeFrame(document.rootFrame()); | |
| 123 | 521 | closeAll(); | |
| 124 | 521 | closeRegion(); | |
| 125 | 2084 | return {m_out, m_contentIds}; | |
| 126 | 521 | } | |
| 127 | |||
| 128 | private: | ||
| 129 | struct OpenList { | ||
| 130 | QTextList *list = nullptr; | ||
| 131 | int level = 0; | ||
| 132 | QString tag; | ||
| 133 | }; | ||
| 134 | const MailHtmlWriter::Options &m_options; | ||
| 135 | QString m_out; | ||
| 136 | QStringList m_contentIds; | ||
| 137 | QVector<OpenList> m_lists; | ||
| 138 | bool m_paragraphOpen = false; | ||
| 139 | ParagraphStyle m_paragraphStyle; | ||
| 140 | bool m_preOpen = false; | ||
| 141 | bool m_afterFrame = false; | ||
| 142 | int m_quoteDepth = 0; | ||
| 143 | int m_region = NoRegion; | ||
| 144 | |||
| 145 | 521 | void writeFrame(QTextFrame *frame) { | |
| 146 |
4/4✓ Branch 2 → 3 taken 521 times.
✓ Branch 24 → 25 taken 4938 times.
✓ Branch 26 → 4 taken 4938 times.
✓ Branch 26 → 27 taken 521 times.
|
5459 | for (auto it = frame->begin(); !it.atEnd(); ++it) { |
| 147 |
2/2✓ Branch 5 → 6 taken 55 times.
✓ Branch 5 → 12 taken 4883 times.
|
4938 | if (QTextFrame *child = it.currentFrame()) { |
| 148 |
1/1✓ Branch 6 → 7 taken 55 times.
|
55 | closeAll(); |
| 149 |
3/4✓ Branch 7 → 8 taken 55 times.
✓ Branch 8 → 9 taken 55 times.
✗ Branch 8 → 10 not taken.
✓ Branch 9 → 11 taken 55 times.
|
55 | if (auto *table = qobject_cast<QTextTable *>(child)) writeTable(table); |
| 150 | ✗ | else writeFrame(child); | |
| 151 | 55 | m_afterFrame = true; | |
| 152 | 55 | continue; | |
| 153 | 55 | } | |
| 154 | // QTextDocument always keeps a block after a table; an empty one is | ||
| 155 | // structure, not a line the user typed. | ||
| 156 |
1/1✓ Branch 12 → 13 taken 4883 times.
|
4883 | const QTextBlock block = it.currentBlock(); |
| 157 |
7/8✓ Branch 13 → 14 taken 55 times.
✓ Branch 13 → 19 taken 4828 times.
✓ Branch 14 → 15 taken 55 times.
✓ Branch 15 → 16 taken 53 times.
✓ Branch 15 → 19 taken 2 times.
✓ Branch 16 → 17 taken 53 times.
✓ Branch 17 → 18 taken 53 times.
✗ Branch 17 → 19 not taken.
|
4883 | const bool structural = m_afterFrame && block.length() <= 1 && !block.textList(); |
| 158 | 4883 | m_afterFrame = false; | |
| 159 |
3/3✓ Branch 20 → 21 taken 4830 times.
✓ Branch 20 → 22 taken 53 times.
✓ Branch 21 → 22 taken 4830 times.
|
4883 | if (!structural) writeBlock(block); |
| 160 | } | ||
| 161 | 521 | } | |
| 162 | |||
| 163 | 4908 | void closeParagraph() { | |
| 164 |
3/3✓ Branch 2 → 3 taken 1858 times.
✓ Branch 2 → 10 taken 3050 times.
✓ Branch 6 → 7 taken 1858 times.
|
6766 | if (m_paragraphOpen) m_out += QStringLiteral("</p>"); |
| 165 | 4908 | m_paragraphOpen = false; | |
| 166 | 4908 | } | |
| 167 | 5462 | void closePre() { | |
| 168 |
3/3✓ Branch 2 → 3 taken 15 times.
✓ Branch 2 → 10 taken 5447 times.
✓ Branch 6 → 7 taken 15 times.
|
5477 | if (m_preOpen) m_out += QStringLiteral("</pre>"); |
| 169 | 5462 | m_preOpen = false; | |
| 170 | 5462 | } | |
| 171 | 5496 | void closeLists(int downToLevel = 0) { | |
| 172 |
6/6✓ Branch 18 → 19 taken 694 times.
✓ Branch 18 → 22 taken 4898 times.
✓ Branch 20 → 21 taken 96 times.
✓ Branch 20 → 22 taken 598 times.
✓ Branch 23 → 3 taken 96 times.
✓ Branch 23 → 24 taken 5496 times.
|
5592 | while (!m_lists.isEmpty() && m_lists.last().level > downToLevel) { |
| 173 |
4/4✓ Branch 5 → 6 taken 96 times.
✓ Branch 9 → 10 taken 96 times.
✓ Branch 10 → 11 taken 96 times.
✓ Branch 11 → 12 taken 96 times.
|
192 | m_out += QStringLiteral("</li></") + m_lists.last().tag + QLatin1Char('>'); |
| 174 | 96 | m_lists.removeLast(); | |
| 175 | } | ||
| 176 | 5496 | } | |
| 177 | 660 | void setQuoteDepth(int depth) { | |
| 178 |
2/2✓ Branch 10 → 3 taken 32 times.
✓ Branch 10 → 11 taken 660 times.
|
692 | while (m_quoteDepth > depth) { |
| 179 |
1/1✓ Branch 6 → 7 taken 32 times.
|
32 | m_out += QStringLiteral("</blockquote>"); |
| 180 | 32 | --m_quoteDepth; | |
| 181 | } | ||
| 182 |
2/2✓ Branch 19 → 12 taken 32 times.
✓ Branch 19 → 20 taken 660 times.
|
692 | while (m_quoteDepth < depth) { |
| 183 |
1/1✓ Branch 15 → 16 taken 32 times.
|
32 | m_out += QStringLiteral("<blockquote style=\"margin:0 0 0 0.8ex;border-left:1px solid #cccccc;" |
| 184 | "padding-left:1ex\">"); | ||
| 185 | 32 | ++m_quoteDepth; | |
| 186 | } | ||
| 187 | 660 | } | |
| 188 | 620 | void closeAll() { | |
| 189 | 620 | closeParagraph(); | |
| 190 | 620 | closePre(); | |
| 191 | 620 | closeLists(); | |
| 192 | 620 | setQuoteDepth(0); | |
| 193 | 620 | } | |
| 194 | 565 | void closeRegion() { | |
| 195 |
3/3✓ Branch 2 → 3 taken 42 times.
✓ Branch 2 → 10 taken 523 times.
✓ Branch 6 → 7 taken 42 times.
|
607 | if (m_region != NoRegion) m_out += QStringLiteral("</div>"); |
| 196 | 565 | m_region = NoRegion; | |
| 197 | 565 | } | |
| 198 | 4830 | void enterRegion(int region) { | |
| 199 |
2/2✓ Branch 2 → 3 taken 4786 times.
✓ Branch 2 → 4 taken 44 times.
|
4830 | if (region == m_region) return; |
| 200 | 44 | closeAll(); | |
| 201 | 44 | closeRegion(); | |
| 202 | // The only class values MailJD writes: fixed region markers that no CSS | ||
| 203 | // refers to (as Thunderbird's moz-signature); the import reads them back. | ||
| 204 |
3/3✓ Branch 6 → 7 taken 35 times.
✓ Branch 6 → 14 taken 9 times.
✓ Branch 10 → 11 taken 35 times.
|
79 | if (region == SignatureRegion) m_out += QStringLiteral("<div class=\"mailjd-signature\">"); |
| 205 |
3/3✓ Branch 14 → 15 taken 7 times.
✓ Branch 14 → 22 taken 2 times.
✓ Branch 18 → 19 taken 7 times.
|
16 | else if (region == QuoteRegion) m_out += QStringLiteral("<div class=\"mailjd-quote\">"); |
| 206 |
4/4✓ Branch 22 → 23 taken 9 times.
✓ Branch 22 → 24 taken 35 times.
✓ Branch 23 → 24 taken 7 times.
✓ Branch 23 → 25 taken 2 times.
|
44 | m_region = (region == SignatureRegion || region == QuoteRegion) ? region : NoRegion; |
| 207 | } | ||
| 208 | |||
| 209 | 4830 | void writeBlock(const QTextBlock &block) { | |
| 210 |
2/2✓ Branch 2 → 3 taken 4830 times.
✓ Branch 3 → 4 taken 4830 times.
|
4830 | enterRegion(ComposeDocumentFormat::region(block)); |
| 211 |
1/1✓ Branch 4 → 5 taken 4830 times.
|
4830 | const int depth = qBound(0, quoteLevel(block), 8); |
| 212 |
2/2✓ Branch 6 → 7 taken 40 times.
✓ Branch 6 → 11 taken 4790 times.
|
4830 | if (depth != m_quoteDepth) { |
| 213 |
1/1✓ Branch 7 → 8 taken 40 times.
|
40 | closeParagraph(); |
| 214 |
1/1✓ Branch 8 → 9 taken 40 times.
|
40 | closePre(); |
| 215 |
1/1✓ Branch 9 → 10 taken 40 times.
|
40 | closeLists(); |
| 216 |
1/1✓ Branch 10 → 11 taken 40 times.
|
40 | setQuoteDepth(depth); |
| 217 | } | ||
| 218 |
3/3✓ Branch 11 → 12 taken 4830 times.
✓ Branch 12 → 13 taken 28 times.
✓ Branch 12 → 37 taken 4802 times.
|
4830 | if (isCodeBlock(block)) { |
| 219 |
1/1✓ Branch 13 → 14 taken 28 times.
|
28 | closeParagraph(); |
| 220 |
1/1✓ Branch 14 → 15 taken 28 times.
|
28 | closeLists(); |
| 221 |
3/3✓ Branch 15 → 16 taken 15 times.
✓ Branch 15 → 23 taken 13 times.
✓ Branch 19 → 20 taken 15 times.
|
43 | if (!m_preOpen) m_out += QStringLiteral("<pre>"); |
| 222 |
1/1✓ Branch 25 → 26 taken 13 times.
|
13 | else m_out += QLatin1Char('\n'); |
| 223 | 28 | m_preOpen = true; | |
| 224 |
1/1✓ Branch 27 → 28 taken 28 times.
|
28 | QString text = block.text(); |
| 225 |
1/1✓ Branch 31 → 32 taken 28 times.
|
28 | text.replace(QChar(0x2028), QLatin1Char('\n')); |
| 226 |
2/2✓ Branch 32 → 33 taken 28 times.
✓ Branch 33 → 34 taken 28 times.
|
28 | m_out += text.toHtmlEscaped(); |
| 227 | 28 | return; | |
| 228 | 28 | } | |
| 229 |
1/1✓ Branch 37 → 38 taken 4802 times.
|
4802 | closePre(); |
| 230 |
9/12✓ Branch 38 → 39 taken 4802 times.
✓ Branch 39 → 40 taken 2 times.
✓ Branch 39 → 44 taken 4800 times.
✓ Branch 40 → 41 taken 2 times.
✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 44 not taken.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 47 taken 4800 times.
✓ Branch 47 → 48 taken 2 times.
✓ Branch 47 → 57 taken 4800 times.
✗ Branch 204 → 205 not taken.
✗ Branch 204 → 206 not taken.
|
4802 | if (isHorizontalRule(block) && block.text().isEmpty()) { |
| 231 |
1/1✓ Branch 48 → 49 taken 2 times.
|
2 | closeParagraph(); |
| 232 |
1/1✓ Branch 49 → 50 taken 2 times.
|
2 | closeLists(); |
| 233 |
1/1✓ Branch 53 → 54 taken 2 times.
|
2 | m_out += QStringLiteral("<hr>"); |
| 234 | 2 | return; | |
| 235 | } | ||
| 236 |
3/3✓ Branch 57 → 58 taken 4800 times.
✓ Branch 58 → 59 taken 680 times.
✓ Branch 58 → 61 taken 4120 times.
|
4800 | if (QTextList *list = block.textList()) { |
| 237 |
1/1✓ Branch 59 → 60 taken 680 times.
|
680 | writeListItem(block, list); |
| 238 | 680 | return; | |
| 239 | } | ||
| 240 |
1/1✓ Branch 61 → 62 taken 4120 times.
|
4120 | closeLists(); |
| 241 |
2/2✓ Branch 62 → 63 taken 4120 times.
✓ Branch 63 → 64 taken 4120 times.
|
4120 | const int heading = qBound(0, block.blockFormat().headingLevel(), MaxHeadingLevel); |
| 242 |
1/1✓ Branch 66 → 67 taken 4120 times.
|
4120 | const ParagraphStyle style = paragraphStyle(block); |
| 243 |
2/2✓ Branch 67 → 68 taken 67 times.
✓ Branch 67 → 110 taken 4053 times.
|
4120 | if (heading > 0) { |
| 244 |
1/1✓ Branch 68 → 69 taken 67 times.
|
67 | closeParagraph(); |
| 245 |
1/1✓ Branch 73 → 74 taken 67 times.
|
134 | const QString tag = QStringLiteral("h%1").arg(heading + 1); |
| 246 |
4/4✓ Branch 85 → 86 taken 67 times.
✓ Branch 88 → 89 taken 67 times.
✓ Branch 89 → 90 taken 67 times.
✓ Branch 90 → 91 taken 67 times.
|
134 | m_out += QLatin1Char('<') + tag + blockAttributes(style, {}) + QLatin1Char('>') + |
| 247 |
6/6✓ Branch 81 → 82 taken 67 times.
✓ Branch 91 → 92 taken 67 times.
✓ Branch 92 → 93 taken 67 times.
✓ Branch 93 → 94 taken 67 times.
✓ Branch 94 → 95 taken 67 times.
✓ Branch 95 → 96 taken 67 times.
|
268 | inlineContent(block) + QStringLiteral("</") + tag + QLatin1Char('>'); |
| 248 | 67 | return; | |
| 249 | 67 | } | |
| 250 |
3/3✓ Branch 110 → 111 taken 4053 times.
✓ Branch 111 → 112 taken 1613 times.
✓ Branch 111 → 136 taken 2440 times.
|
4053 | if (block.length() <= 1) { |
| 251 | // An empty block is an empty line of its own: paragraphs carry no | ||
| 252 | // margins, so what the receiver sees is what was typed. | ||
| 253 |
1/1✓ Branch 112 → 113 taken 1613 times.
|
1613 | closeParagraph(); |
| 254 |
4/4✓ Branch 119 → 120 taken 1613 times.
✓ Branch 123 → 124 taken 1613 times.
✓ Branch 124 → 125 taken 1613 times.
✓ Branch 125 → 126 taken 1613 times.
|
4839 | m_out += QStringLiteral("<p") + blockAttributes(style, QStringLiteral("margin:0")) + QStringLiteral("><br></p>"); |
| 255 | 1613 | return; | |
| 256 | } | ||
| 257 |
6/6✓ Branch 136 → 137 taken 585 times.
✓ Branch 136 → 140 taken 1855 times.
✓ Branch 138 → 139 taken 582 times.
✓ Branch 138 → 140 taken 3 times.
✓ Branch 141 → 142 taken 582 times.
✓ Branch 141 → 153 taken 1858 times.
|
2440 | if (m_paragraphOpen && m_paragraphStyle == style) { |
| 258 |
3/3✓ Branch 142 → 143 taken 582 times.
✓ Branch 146 → 147 taken 582 times.
✓ Branch 147 → 148 taken 582 times.
|
1164 | m_out += QStringLiteral("<br>") + inlineContent(block); |
| 259 | 582 | return; | |
| 260 | } | ||
| 261 |
1/1✓ Branch 153 → 154 taken 1858 times.
|
1858 | closeParagraph(); |
| 262 |
2/2✓ Branch 160 → 161 taken 1858 times.
✓ Branch 164 → 165 taken 1858 times.
|
5574 | m_out += QStringLiteral("<p") + blockAttributes(style, QStringLiteral("margin:0")) + |
| 263 |
4/4✓ Branch 154 → 155 taken 1858 times.
✓ Branch 165 → 166 taken 1858 times.
✓ Branch 166 → 167 taken 1858 times.
✓ Branch 167 → 168 taken 1858 times.
|
5574 | QLatin1Char('>') + inlineContent(block); |
| 264 | 1858 | m_paragraphOpen = true; | |
| 265 | 1858 | m_paragraphStyle = style; | |
| 266 | 4120 | } | |
| 267 | |||
| 268 | 96 | static QString listTag(const QTextListFormat &format, QString &styleType) { | |
| 269 |
2/8✗ Branch 3 → 4 not taken.
✗ Branch 3 → 15 not taken.
✓ Branch 3 → 26 taken 62 times.
✗ Branch 3 → 37 not taken.
✗ Branch 3 → 48 not taken.
✗ Branch 3 → 59 not taken.
✗ Branch 3 → 70 not taken.
✓ Branch 3 → 81 taken 34 times.
|
96 | switch (format.style()) { |
| 270 | ✗ | case QTextListFormat::ListCircle: styleType = QStringLiteral("circle"); return QStringLiteral("ul"); | |
| 271 | ✗ | case QTextListFormat::ListSquare: styleType = QStringLiteral("square"); return QStringLiteral("ul"); | |
| 272 | 186 | case QTextListFormat::ListDecimal: styleType = QStringLiteral("decimal"); return QStringLiteral("ol"); | |
| 273 | ✗ | case QTextListFormat::ListLowerAlpha: styleType = QStringLiteral("lower-alpha"); return QStringLiteral("ol"); | |
| 274 | ✗ | case QTextListFormat::ListUpperAlpha: styleType = QStringLiteral("upper-alpha"); return QStringLiteral("ol"); | |
| 275 | ✗ | case QTextListFormat::ListLowerRoman: styleType = QStringLiteral("lower-roman"); return QStringLiteral("ol"); | |
| 276 | ✗ | case QTextListFormat::ListUpperRoman: styleType = QStringLiteral("upper-roman"); return QStringLiteral("ol"); | |
| 277 | 102 | default: styleType = QStringLiteral("disc"); return QStringLiteral("ul"); | |
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | 680 | void writeListItem(const QTextBlock &block, QTextList *list) { | |
| 282 |
1/1✓ Branch 2 → 3 taken 680 times.
|
680 | closeParagraph(); |
| 283 |
2/2✓ Branch 3 → 4 taken 680 times.
✓ Branch 4 → 5 taken 680 times.
|
680 | const int level = qBound(1, list->format().indent(), MaxListLevel); |
| 284 |
1/1✓ Branch 7 → 8 taken 680 times.
|
680 | closeLists(level); |
| 285 |
10/10✓ Branch 9 → 10 taken 598 times.
✓ Branch 9 → 15 taken 82 times.
✓ Branch 10 → 11 taken 598 times.
✓ Branch 11 → 12 taken 590 times.
✓ Branch 11 → 15 taken 8 times.
✓ Branch 12 → 13 taken 590 times.
✓ Branch 13 → 14 taken 6 times.
✓ Branch 13 → 15 taken 584 times.
✓ Branch 16 → 17 taken 6 times.
✓ Branch 16 → 18 taken 674 times.
|
680 | if (!m_lists.isEmpty() && m_lists.last().level == level && m_lists.last().list != list) |
| 286 |
1/1✓ Branch 17 → 18 taken 6 times.
|
6 | closeLists(level - 1); |
| 287 |
7/7✓ Branch 19 → 20 taken 592 times.
✓ Branch 19 → 22 taken 88 times.
✓ Branch 20 → 21 taken 592 times.
✓ Branch 21 → 22 taken 8 times.
✓ Branch 21 → 23 taken 584 times.
✓ Branch 24 → 25 taken 96 times.
✓ Branch 24 → 55 taken 584 times.
|
680 | if (m_lists.isEmpty() || m_lists.last().level < level) { |
| 288 | 96 | QString styleType; | |
| 289 |
2/2✓ Branch 25 → 26 taken 96 times.
✓ Branch 26 → 27 taken 96 times.
|
96 | const QString tag = listTag(list->format(), styleType); |
| 290 | // A deeper list opens inside the open item; a list without a parent | ||
| 291 | // item at a deeper level starts at its own level. | ||
| 292 |
3/3✓ Branch 36 → 37 taken 96 times.
✓ Branch 37 → 38 taken 96 times.
✓ Branch 38 → 39 taken 96 times.
|
192 | m_out += QLatin1Char('<') + tag + QStringLiteral(" style=\"list-style-type:") + styleType + |
| 293 |
2/2✓ Branch 39 → 40 taken 96 times.
✓ Branch 40 → 41 taken 96 times.
|
288 | QStringLiteral(";margin-top:0;margin-bottom:0\">"); |
| 294 |
1/1✓ Branch 50 → 51 taken 96 times.
|
96 | m_lists.append({list, level, tag}); |
| 295 | 96 | } else { | |
| 296 |
1/1✓ Branch 58 → 59 taken 584 times.
|
584 | m_out += QStringLiteral("</li>"); |
| 297 | } | ||
| 298 |
1/1✓ Branch 62 → 63 taken 680 times.
|
680 | const ParagraphStyle style = paragraphStyle(block); |
| 299 |
6/6✓ Branch 63 → 64 taken 680 times.
✓ Branch 67 → 68 taken 680 times.
✓ Branch 71 → 72 taken 680 times.
✓ Branch 72 → 73 taken 680 times.
✓ Branch 73 → 74 taken 680 times.
✓ Branch 74 → 75 taken 680 times.
|
1360 | m_out += QStringLiteral("<li") + blockAttributes(style, {}) + QLatin1Char('>') + inlineContent(block); |
| 300 | 776 | } | |
| 301 | |||
| 302 | 55 | void writeTable(QTextTable *table) { | |
| 303 |
1/1✓ Branch 2 → 3 taken 55 times.
|
55 | const QTextTableFormat format = table->format(); |
| 304 |
2/2✓ Branch 3 → 4 taken 55 times.
✓ Branch 4 → 5 taken 55 times.
|
55 | const int headerRows = qBound(0, format.headerRowCount(), table->rows()); |
| 305 |
1/1✓ Branch 6 → 7 taken 55 times.
|
55 | const bool border = format.border() > 0; |
| 306 | 110 | m_out += QStringLiteral("<table cellpadding=\"4\" cellspacing=\"0\" border=\"%1\" style=\"border-collapse:" | |
| 307 | "collapse%2\">") | ||
| 308 |
3/3✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 53 times.
✓ Branch 14 → 15 taken 55 times.
|
110 | .arg(border ? 1 : 0) |
| 309 |
6/8✓ Branch 16 → 17 taken 2 times.
✓ Branch 16 → 20 taken 53 times.
✓ Branch 21 → 22 taken 55 times.
✓ Branch 22 → 23 taken 55 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 27 taken 53 times.
✗ Branch 237 → 238 not taken.
✗ Branch 237 → 239 not taken.
|
57 | .arg(border ? QStringLiteral(";border:1px solid #c8c8c8") : QString()); |
| 310 |
1/1✓ Branch 30 → 31 taken 55 times.
|
55 | const auto widths = format.columnWidthConstraints(); |
| 311 |
3/3✓ Branch 211 → 212 taken 189 times.
✓ Branch 212 → 32 taken 134 times.
✓ Branch 212 → 213 taken 55 times.
|
189 | for (int row = 0; row < table->rows(); ++row) { |
| 312 |
9/13✓ Branch 32 → 33 taken 55 times.
✓ Branch 32 → 47 taken 79 times.
✓ Branch 33 → 34 taken 2 times.
✓ Branch 33 → 37 taken 53 times.
✓ Branch 40 → 41 taken 55 times.
✓ Branch 42 → 43 taken 53 times.
✓ Branch 42 → 44 taken 2 times.
✓ Branch 44 → 45 taken 2 times.
✓ Branch 44 → 46 taken 53 times.
✗ Branch 256 → 257 not taken.
✗ Branch 256 → 258 not taken.
✗ Branch 260 → 261 not taken.
✗ Branch 260 → 262 not taken.
|
189 | if (row == 0) m_out += headerRows > 0 ? QStringLiteral("<thead>") : QStringLiteral("<tbody>"); |
| 313 |
5/5✓ Branch 47 → 48 taken 55 times.
✓ Branch 47 → 56 taken 79 times.
✓ Branch 48 → 49 taken 2 times.
✓ Branch 48 → 56 taken 53 times.
✓ Branch 52 → 53 taken 2 times.
|
136 | if (row == headerRows && headerRows > 0) m_out += QStringLiteral("</thead><tbody>"); |
| 314 |
1/1✓ Branch 59 → 60 taken 134 times.
|
134 | m_out += QStringLiteral("<tr>"); |
| 315 |
3/3✓ Branch 202 → 203 taken 386 times.
✓ Branch 203 → 63 taken 252 times.
✓ Branch 203 → 204 taken 134 times.
|
386 | for (int column = 0; column < table->columns(); ++column) { |
| 316 |
1/1✓ Branch 63 → 64 taken 252 times.
|
252 | const QTextTableCell cell = table->cellAt(row, column); |
| 317 | // A merged cell is written once, where it starts (pasted tables). | ||
| 318 |
8/10✓ Branch 65 → 66 taken 252 times.
✗ Branch 65 → 70 not taken.
✓ Branch 66 → 67 taken 252 times.
✓ Branch 67 → 68 taken 251 times.
✓ Branch 67 → 70 taken 1 time.
✓ Branch 68 → 69 taken 251 times.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 251 times.
✓ Branch 72 → 73 taken 1 time.
✓ Branch 72 → 74 taken 251 times.
|
252 | if (!cell.isValid() || cell.row() != row || cell.column() != column) continue; |
| 319 |
6/6✓ Branch 74 → 75 taken 4 times.
✓ Branch 74 → 78 taken 247 times.
✓ Branch 81 → 82 taken 247 times.
✓ Branch 81 → 83 taken 4 times.
✓ Branch 83 → 84 taken 4 times.
✓ Branch 83 → 85 taken 247 times.
|
502 | const QString tag = row < headerRows ? QStringLiteral("th") : QStringLiteral("td"); |
| 320 | 251 | QString attributes; | |
| 321 |
2/6✓ Branch 85 → 86 taken 251 times.
✗ Branch 86 → 87 not taken.
✓ Branch 86 → 99 taken 251 times.
✗ Branch 91 → 92 not taken.
✗ Branch 93 → 94 not taken.
✗ Branch 94 → 95 not taken.
|
251 | if (cell.columnSpan() > 1) attributes += QStringLiteral(" colspan=\"%1\"").arg(qMin(cell.columnSpan(), 64)); |
| 322 |
2/6✓ Branch 99 → 100 taken 251 times.
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 113 taken 251 times.
✗ Branch 105 → 106 not taken.
✗ Branch 107 → 108 not taken.
✗ Branch 108 → 109 not taken.
|
251 | if (cell.rowSpan() > 1) attributes += QStringLiteral(" rowspan=\"%1\"").arg(qMin(cell.rowSpan(), 64)); |
| 323 |
7/8✓ Branch 113 → 114 taken 99 times.
✓ Branch 113 → 120 taken 152 times.
✓ Branch 115 → 116 taken 99 times.
✗ Branch 115 → 120 not taken.
✓ Branch 118 → 119 taken 4 times.
✓ Branch 118 → 120 taken 95 times.
✓ Branch 121 → 122 taken 4 times.
✓ Branch 121 → 136 taken 247 times.
|
251 | if (row == 0 && column < widths.size() && widths.at(column).type() == QTextLength::PercentageLength) |
| 324 |
2/2✓ Branch 130 → 131 taken 4 times.
✓ Branch 131 → 132 taken 4 times.
|
8 | attributes += QStringLiteral(" width=\"%1%\"").arg(qBound(1, qRound(widths.at(column).rawValue()), 100)); |
| 325 |
3/3✓ Branch 136 → 137 taken 8 times.
✓ Branch 136 → 144 taken 243 times.
✓ Branch 140 → 141 taken 8 times.
|
259 | if (border) attributes += QStringLiteral(" style=\"border:1px solid #c8c8c8\""); |
| 326 |
4/4✓ Branch 148 → 149 taken 251 times.
✓ Branch 149 → 150 taken 251 times.
✓ Branch 150 → 151 taken 251 times.
✓ Branch 151 → 152 taken 251 times.
|
251 | m_out += QLatin1Char('<') + tag + attributes + QLatin1Char('>'); |
| 327 | // The cell's blocks by position: a nested table's frame iterator did | ||
| 328 | // not end inside a merged cell (fuzz_compose_html_import). Nested | ||
| 329 | // tables are not offered (D-6); their lines join the cell. | ||
| 330 | 251 | bool first = true; | |
| 331 |
1/1✓ Branch 155 → 156 taken 251 times.
|
251 | const QTextDocument *document = table->document(); |
| 332 |
2/2✓ Branch 156 → 157 taken 251 times.
✓ Branch 157 → 158 taken 251 times.
|
251 | for (QTextBlock block = document->findBlock(cell.firstPosition()); |
| 333 |
8/9✓ Branch 173 → 174 taken 514 times.
✓ Branch 174 → 175 taken 514 times.
✗ Branch 174 → 179 not taken.
✓ Branch 175 → 176 taken 514 times.
✓ Branch 176 → 177 taken 514 times.
✓ Branch 177 → 178 taken 263 times.
✓ Branch 177 → 179 taken 251 times.
✓ Branch 180 → 159 taken 263 times.
✓ Branch 180 → 181 taken 251 times.
|
514 | block.isValid() && block.position() <= cell.lastPosition(); block = block.next()) { |
| 334 |
3/3✓ Branch 159 → 160 taken 12 times.
✓ Branch 159 → 167 taken 251 times.
✓ Branch 163 → 164 taken 12 times.
|
275 | if (!first) m_out += QStringLiteral("<br>"); |
| 335 |
2/2✓ Branch 167 → 168 taken 263 times.
✓ Branch 168 → 169 taken 263 times.
|
263 | m_out += inlineContent(block); |
| 336 |
1/1✓ Branch 170 → 171 taken 263 times.
|
263 | first = false; |
| 337 | } | ||
| 338 |
3/3✓ Branch 186 → 187 taken 251 times.
✓ Branch 187 → 188 taken 251 times.
✓ Branch 188 → 189 taken 251 times.
|
502 | m_out += QStringLiteral("</") + tag + QLatin1Char('>'); |
| 339 | 252 | } | |
| 340 |
1/1✓ Branch 207 → 208 taken 134 times.
|
134 | m_out += QStringLiteral("</tr>"); |
| 341 | } | ||
| 342 |
2/7✓ Branch 213 → 214 taken 55 times.
✗ Branch 214 → 215 not taken.
✓ Branch 214 → 219 taken 55 times.
✗ Branch 215 → 216 not taken.
✗ Branch 215 → 219 not taken.
✗ Branch 377 → 378 not taken.
✗ Branch 377 → 379 not taken.
|
165 | m_out += (headerRows >= table->rows() && headerRows > 0) ? QStringLiteral("</thead></table>") |
| 343 |
3/7✓ Branch 222 → 223 taken 55 times.
✓ Branch 224 → 225 taken 55 times.
✗ Branch 224 → 226 not taken.
✗ Branch 226 → 227 not taken.
✓ Branch 226 → 228 taken 55 times.
✗ Branch 373 → 374 not taken.
✗ Branch 373 → 375 not taken.
|
110 | : QStringLiteral("</tbody></table>"); |
| 344 | 55 | } | |
| 345 | |||
| 346 | 30 | QString imageHtml(const QTextImageFormat &image) { | |
| 347 |
6/8✓ Branch 3 → 4 taken 28 times.
✓ Branch 3 → 6 taken 2 times.
✓ Branch 4 → 5 taken 28 times.
✓ Branch 5 → 7 taken 28 times.
✓ Branch 7 → 8 taken 28 times.
✓ Branch 7 → 9 taken 2 times.
✗ Branch 123 → 124 not taken.
✗ Branch 123 → 125 not taken.
|
30 | const QString contentId = m_options.contentIdFor ? m_options.contentIdFor(image.name()) : QString(); |
| 348 |
5/5✓ Branch 9 → 10 taken 30 times.
✓ Branch 10 → 11 taken 30 times.
✓ Branch 11 → 12 taken 28 times.
✓ Branch 11 → 13 taken 2 times.
✓ Branch 13 → 14 taken 2 times.
|
30 | QString alt = image.name().startsWith(ImageScheme) ? QString() : image.name(); |
| 349 |
4/4✓ Branch 15 → 16 taken 30 times.
✓ Branch 16 → 17 taken 28 times.
✓ Branch 16 → 21 taken 2 times.
✓ Branch 17 → 18 taken 28 times.
|
30 | if (image.hasProperty(ImageAltProperty)) alt = image.stringProperty(ImageAltProperty); |
| 350 |
8/10✓ Branch 22 → 23 taken 26 times.
✓ Branch 22 → 31 taken 4 times.
✓ Branch 25 → 26 taken 26 times.
✓ Branch 26 → 27 taken 26 times.
✗ Branch 26 → 31 not taken.
✓ Branch 29 → 30 taken 26 times.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 26 times.
✓ Branch 33 → 34 taken 4 times.
✓ Branch 33 → 59 taken 26 times.
|
30 | if (contentId.isEmpty() || contentId.contains(QLatin1Char('"')) || contentId.contains(QLatin1Char('>'))) |
| 351 |
9/25✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 4 times.
✓ Branch 43 → 44 taken 4 times.
✓ Branch 44 → 45 taken 4 times.
✓ Branch 45 → 46 taken 4 times.
✓ Branch 48 → 49 taken 4 times.
✗ Branch 48 → 50 not taken.
✓ Branch 50 → 51 taken 4 times.
✗ Branch 50 → 52 not taken.
✓ Branch 52 → 53 taken 4 times.
✗ Branch 52 → 54 not taken.
✓ Branch 54 → 55 taken 4 times.
✗ Branch 54 → 56 not taken.
✓ Branch 56 → 57 taken 4 times.
✗ Branch 56 → 58 not taken.
✗ Branch 137 → 138 not taken.
✗ Branch 137 → 139 not taken.
✗ Branch 141 → 142 not taken.
✗ Branch 141 → 143 not taken.
✗ Branch 145 → 146 not taken.
✗ Branch 145 → 147 not taken.
✗ Branch 149 → 150 not taken.
✗ Branch 149 → 151 not taken.
✗ Branch 153 → 154 not taken.
✗ Branch 153 → 155 not taken.
|
12 | return escapedText(alt.isEmpty() ? QString() : QStringLiteral("[") + alt + QStringLiteral("]")); |
| 352 |
2/3✓ Branch 60 → 61 taken 26 times.
✗ Branch 60 → 62 not taken.
✓ Branch 61 → 62 taken 26 times.
|
26 | if (!m_contentIds.contains(contentId)) m_contentIds.append(contentId); |
| 353 |
3/3✓ Branch 68 → 69 taken 26 times.
✓ Branch 72 → 73 taken 26 times.
✓ Branch 73 → 74 taken 26 times.
|
78 | QString html = QStringLiteral("<img src=\"cid:") + contentId.toHtmlEscaped() + QStringLiteral("\" alt=\"") + |
| 354 |
3/3✓ Branch 64 → 65 taken 26 times.
✓ Branch 74 → 75 taken 26 times.
✓ Branch 75 → 76 taken 26 times.
|
78 | alt.toHtmlEscaped() + QLatin1Char('"'); |
| 355 |
6/6✓ Branch 85 → 86 taken 26 times.
✓ Branch 86 → 87 taken 18 times.
✓ Branch 86 → 100 taken 8 times.
✓ Branch 91 → 92 taken 18 times.
✓ Branch 94 → 95 taken 18 times.
✓ Branch 95 → 96 taken 18 times.
|
62 | if (image.width() > 0) html += QStringLiteral(" width=\"%1\"").arg(qBound(1, qRound(image.width()), 4096)); |
| 356 |
2/6✓ Branch 100 → 101 taken 26 times.
✗ Branch 101 → 102 not taken.
✓ Branch 101 → 115 taken 26 times.
✗ Branch 106 → 107 not taken.
✗ Branch 109 → 110 not taken.
✗ Branch 110 → 111 not taken.
|
26 | if (image.height() > 0) html += QStringLiteral(" height=\"%1\"").arg(qBound(1, qRound(image.height()), 4096)); |
| 357 |
1/1✓ Branch 117 → 118 taken 26 times.
|
26 | return html + QLatin1Char('>'); |
| 358 | 30 | } | |
| 359 | |||
| 360 | // Headings are bold by themselves; their bold is not repeated. | ||
| 361 | 3450 | QString inlineContent(const QTextBlock &block) { | |
| 362 |
2/2✓ Branch 2 → 3 taken 3450 times.
✓ Branch 3 → 4 taken 3450 times.
|
3450 | const bool heading = block.blockFormat().headingLevel() > 0; |
| 363 | 3450 | bool previousSpace = false; | |
| 364 | 3450 | QString out; | |
| 365 |
4/4✓ Branch 5 → 6 taken 3450 times.
✓ Branch 246 → 247 taken 11594 times.
✓ Branch 248 → 7 taken 11594 times.
✓ Branch 248 → 249 taken 3450 times.
|
15044 | for (auto it = block.begin(); !it.atEnd(); ++it) { |
| 366 |
1/1✓ Branch 7 → 8 taken 11594 times.
|
11594 | const QTextFragment fragment = it.fragment(); |
| 367 |
1/2✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 11594 times.
|
11624 | if (!fragment.isValid()) continue; |
| 368 |
1/1✓ Branch 11 → 12 taken 11594 times.
|
11594 | const QTextCharFormat format = fragment.charFormat(); |
| 369 |
3/3✓ Branch 12 → 13 taken 11594 times.
✓ Branch 13 → 14 taken 30 times.
✓ Branch 13 → 26 taken 11564 times.
|
11594 | if (format.isImageFormat()) { |
| 370 | // One object character per image; a fragment can hold several. | ||
| 371 |
6/6✓ Branch 15 → 16 taken 30 times.
✓ Branch 16 → 17 taken 30 times.
✓ Branch 17 → 18 taken 30 times.
✓ Branch 21 → 22 taken 60 times.
✓ Branch 24 → 15 taken 30 times.
✓ Branch 24 → 25 taken 30 times.
|
60 | for (int i = 0; i < fragment.text().size(); ++i) out += imageHtml(format.toImageFormat()); |
| 372 | 30 | previousSpace = false; | |
| 373 | 30 | continue; | |
| 374 | 30 | } | |
| 375 |
2/2✓ Branch 26 → 27 taken 11564 times.
✓ Branch 27 → 28 taken 11564 times.
|
11564 | QString text = escapedText(fragment.text(), previousSpace); |
| 376 |
1/2✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 11564 times.
|
11564 | if (text.isEmpty()) continue; |
| 377 |
5/5✓ Branch 32 → 33 taken 11564 times.
✓ Branch 33 → 34 taken 16 times.
✓ Branch 33 → 50 taken 11548 times.
✓ Branch 40 → 41 taken 16 times.
✓ Branch 41 → 42 taken 16 times.
|
11596 | if (isInlineCode(format)) text = QStringLiteral("<code>") + text + QStringLiteral("</code>"); |
| 378 |
3/3✓ Branch 50 → 51 taken 11564 times.
✓ Branch 51 → 52 taken 4 times.
✓ Branch 51 → 68 taken 11560 times.
|
11564 | if (format.verticalAlignment() == QTextCharFormat::AlignSuperScript) |
| 379 |
2/2✓ Branch 58 → 59 taken 4 times.
✓ Branch 59 → 60 taken 4 times.
|
8 | text = QStringLiteral("<sup>") + text + QStringLiteral("</sup>"); |
| 380 |
2/3✓ Branch 68 → 69 taken 11560 times.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 86 taken 11560 times.
|
11560 | else if (format.verticalAlignment() == QTextCharFormat::AlignSubScript) |
| 381 | ✗ | text = QStringLiteral("<sub>") + text + QStringLiteral("</sub>"); | |
| 382 |
5/5✓ Branch 86 → 87 taken 11564 times.
✓ Branch 87 → 88 taken 9 times.
✓ Branch 87 → 104 taken 11555 times.
✓ Branch 94 → 95 taken 9 times.
✓ Branch 95 → 96 taken 9 times.
|
11582 | if (format.fontStrikeOut()) text = QStringLiteral("<s>") + text + QStringLiteral("</s>"); |
| 383 |
10/10✓ Branch 104 → 105 taken 11564 times.
✓ Branch 105 → 106 taken 12 times.
✓ Branch 105 → 109 taken 11552 times.
✓ Branch 106 → 107 taken 12 times.
✓ Branch 107 → 108 taken 10 times.
✓ Branch 107 → 109 taken 2 times.
✓ Branch 110 → 111 taken 10 times.
✓ Branch 110 → 127 taken 11554 times.
✓ Branch 117 → 118 taken 10 times.
✓ Branch 118 → 119 taken 10 times.
|
11584 | if (format.fontUnderline() && !format.isAnchor()) text = QStringLiteral("<u>") + text + QStringLiteral("</u>"); |
| 384 |
5/5✓ Branch 127 → 128 taken 11564 times.
✓ Branch 128 → 129 taken 1210 times.
✓ Branch 128 → 145 taken 10354 times.
✓ Branch 135 → 136 taken 1210 times.
✓ Branch 136 → 137 taken 1210 times.
|
13984 | if (format.fontItalic()) text = QStringLiteral("<em>") + text + QStringLiteral("</em>"); |
| 385 |
7/7✓ Branch 145 → 146 taken 11564 times.
✓ Branch 146 → 147 taken 1374 times.
✓ Branch 146 → 149 taken 10190 times.
✓ Branch 147 → 148 taken 1372 times.
✓ Branch 147 → 149 taken 2 times.
✓ Branch 150 → 151 taken 1372 times.
✓ Branch 150 → 167 taken 10192 times.
|
11564 | if (format.fontWeight() >= QFont::Bold && !heading) |
| 386 |
2/2✓ Branch 157 → 158 taken 1372 times.
✓ Branch 158 → 159 taken 1372 times.
|
2744 | text = QStringLiteral("<strong>") + text + QStringLiteral("</strong>"); |
| 387 |
1/1✓ Branch 167 → 168 taken 11564 times.
|
11564 | const QString style = spanStyle(format); |
| 388 |
6/6✓ Branch 169 → 170 taken 123 times.
✓ Branch 169 → 195 taken 11441 times.
✓ Branch 179 → 180 taken 123 times.
✓ Branch 180 → 181 taken 123 times.
✓ Branch 181 → 182 taken 123 times.
✓ Branch 182 → 183 taken 123 times.
|
11933 | if (!style.isEmpty()) text = QStringLiteral("<span style=\"") + style + QStringLiteral("\">") + text + QStringLiteral("</span>"); |
| 389 |
11/13✓ Branch 195 → 196 taken 11564 times.
✓ Branch 196 → 197 taken 1897 times.
✓ Branch 196 → 201 taken 9667 times.
✓ Branch 197 → 198 taken 1897 times.
✓ Branch 198 → 199 taken 1897 times.
✓ Branch 199 → 200 taken 1895 times.
✓ Branch 199 → 201 taken 2 times.
✓ Branch 202 → 203 taken 1897 times.
✓ Branch 202 → 204 taken 9667 times.
✓ Branch 204 → 205 taken 1895 times.
✓ Branch 204 → 234 taken 9669 times.
✗ Branch 404 → 405 not taken.
✗ Branch 404 → 406 not taken.
|
11564 | if (format.isAnchor() && isAllowedLink(format.anchorHref())) |
| 390 |
5/5✓ Branch 211 → 212 taken 1895 times.
✓ Branch 212 → 213 taken 1895 times.
✓ Branch 216 → 217 taken 1895 times.
✓ Branch 217 → 218 taken 1895 times.
✓ Branch 218 → 219 taken 1895 times.
|
5685 | text = QStringLiteral("<a href=\"") + format.anchorHref().toHtmlEscaped() + QStringLiteral("\">") + text + |
| 391 |
1/1✓ Branch 219 → 220 taken 1895 times.
|
5685 | QStringLiteral("</a>"); |
| 392 |
1/1✓ Branch 234 → 235 taken 11564 times.
|
11564 | out += text; |
| 393 | 11594 | } | |
| 394 | 3450 | return out; | |
| 395 | ✗ | } | |
| 396 | }; | ||
| 397 | |||
| 398 | } // namespace | ||
| 399 | |||
| 400 | 521 | MailHtmlWriter::Result MailHtmlWriter::writeBody(const QTextDocument &document, const Options &options) { | |
| 401 | 521 | Writer writer(options); | |
| 402 |
1/1✓ Branch 3 → 4 taken 521 times.
|
1042 | return writer.run(document); |
| 403 | 521 | } | |
| 404 | |||
| 405 | 497 | QString MailHtmlWriter::wrapDocument(const QString &bodyHtml, bool rightToLeft) { | |
| 406 | 994 | return QStringLiteral("<!DOCTYPE html>\n<html><head><meta charset=\"utf-8\">" | |
| 407 | "<meta name=\"viewport\" content=\"width=device-width\"></head>\n" | ||
| 408 | "<body><div%1 style=\"font-family:system-ui,-apple-system,'Segoe UI',Roboto," | ||
| 409 | "Helvetica,Arial,sans-serif;max-width:44em\">") | ||
| 410 |
5/7✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 13 taken 495 times.
✓ Branch 14 → 15 taken 497 times.
✓ Branch 21 → 22 taken 2 times.
✓ Branch 21 → 23 taken 495 times.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
|
996 | .arg(rightToLeft ? QStringLiteral(" dir=\"rtl\"") : QString()) + |
| 411 |
2/2✓ Branch 15 → 16 taken 497 times.
✓ Branch 16 → 17 taken 497 times.
|
1491 | bodyHtml + QStringLiteral("</div></body></html>\n"); |
| 412 | } | ||
| 413 | |||
| 414 | 12 | QString MailHtmlWriter::quoteContainer(const QString &attributionText, const QString "edBodyHtml) { | |
| 415 |
2/2✓ Branch 8 → 9 taken 12 times.
✓ Branch 12 → 13 taken 12 times.
|
36 | return QStringLiteral("<div class=\"mailjd-quote\"><p style=\"margin:0\">") + escapedText(attributionText) + |
| 416 |
1/1✓ Branch 13 → 14 taken 12 times.
|
36 | QStringLiteral("</p><blockquote style=\"margin:0 0 0 0.8ex;border-left:1px solid #cccccc;" |
| 417 | 12 | "padding-left:1ex\">") + | |
| 418 |
2/2✓ Branch 14 → 15 taken 12 times.
✓ Branch 15 → 16 taken 12 times.
|
36 | quotedBodyHtml + QStringLiteral("</blockquote></div>"); |
| 419 | } | ||
| 420 | |||
| 421 | namespace { | ||
| 422 | 8 | bool fail(QString *problem, const QString &text) { | |
| 423 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 7 times.
|
8 | if (problem) *problem = text; |
| 424 | 8 | return false; | |
| 425 | } | ||
| 426 | } // namespace | ||
| 427 | |||
| 428 | 63 | bool MailHtmlWriter::conforms(const QString &html, QString *problem) { | |
| 429 | 63 | qsizetype position = 0; | |
| 430 | while (true) { | ||
| 431 | 1548 | const qsizetype open = html.indexOf(QLatin1Char('<'), position); | |
| 432 |
2/2✓ Branch 6 → 7 taken 55 times.
✓ Branch 6 → 8 taken 1493 times.
|
1556 | if (open < 0) return true; |
| 433 | 1493 | const qsizetype close = html.indexOf(QLatin1Char('>'), open); | |
| 434 |
1/2✗ Branch 11 → 12 not taken.
✓ Branch 11 → 19 taken 1493 times.
|
1493 | if (close < 0) return fail(problem, QStringLiteral("unterminated tag")); |
| 435 |
1/1✓ Branch 19 → 20 taken 1493 times.
|
1493 | const QString tag = html.mid(open + 1, close - open - 1); |
| 436 | 1493 | position = close + 1; | |
| 437 |
3/3✓ Branch 21 → 22 taken 1493 times.
✓ Branch 22 → 23 taken 54 times.
✓ Branch 22 → 24 taken 1439 times.
|
1493 | if (tag.startsWith(QLatin1String("!DOCTYPE html"))) continue; |
| 438 |
3/3✓ Branch 26 → 27 taken 1439 times.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 27 → 35 taken 1438 times.
|
1440 | if (tag.startsWith(QLatin1Char('!'))) return fail(problem, QStringLiteral("comment or declaration")); |
| 439 | 1438 | QString rest = tag; | |
| 440 |
4/4✓ Branch 38 → 39 taken 1438 times.
✓ Branch 39 → 40 taken 598 times.
✓ Branch 39 → 44 taken 840 times.
✓ Branch 40 → 41 taken 598 times.
|
1438 | if (rest.startsWith(QLatin1Char('/'))) rest = rest.mid(1); |
| 441 | 1438 | qsizetype nameEnd = 0; | |
| 442 |
6/6✓ Branch 47 → 48 taken 4199 times.
✓ Branch 47 → 52 taken 961 times.
✓ Branch 50 → 51 taken 3722 times.
✓ Branch 50 → 52 taken 477 times.
✓ Branch 53 → 45 taken 3722 times.
✓ Branch 53 → 54 taken 1438 times.
|
5160 | while (nameEnd < rest.size() && rest.at(nameEnd).isLetterOrNumber()) ++nameEnd; |
| 443 |
2/2✓ Branch 54 → 55 taken 1438 times.
✓ Branch 55 → 56 taken 1438 times.
|
1438 | const QString name = rest.left(nameEnd).toLower(); |
| 444 |
4/4✓ Branch 57 → 58 taken 1438 times.
✓ Branch 59 → 60 taken 1 time.
✓ Branch 59 → 69 taken 1437 times.
✓ Branch 63 → 64 taken 1 time.
|
1439 | if (!allowedElements().contains(name)) return fail(problem, QStringLiteral("element ") + name); |
| 445 | // Attributes: name="value" pairs only (the writer always quotes). | ||
| 446 | 1437 | qsizetype at = nameEnd; | |
| 447 |
2/2✓ Branch 293 → 70 taken 554 times.
✓ Branch 293 → 294 taken 1431 times.
|
1985 | while (at < rest.size()) { |
| 448 |
5/6✓ Branch 73 → 74 taken 1108 times.
✗ Branch 73 → 78 not taken.
✓ Branch 76 → 77 taken 554 times.
✓ Branch 76 → 78 taken 554 times.
✓ Branch 79 → 71 taken 554 times.
✓ Branch 79 → 80 taken 554 times.
|
1108 | while (at < rest.size() && rest.at(at).isSpace()) ++at; |
| 449 |
1/2✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 554 times.
|
554 | if (at >= rest.size()) break; |
| 450 | 554 | const qsizetype equals = rest.indexOf(QLatin1Char('='), at); | |
| 451 |
4/8✓ Branch 86 → 87 taken 554 times.
✗ Branch 86 → 94 not taken.
✓ Branch 88 → 89 taken 554 times.
✗ Branch 88 → 94 not taken.
✗ Branch 93 → 94 not taken.
✓ Branch 93 → 95 taken 554 times.
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 106 taken 554 times.
|
554 | if (equals < 0 || equals + 1 >= rest.size() || rest.at(equals + 1) != QLatin1Char('"')) |
| 452 | ✗ | return fail(problem, QStringLiteral("unquoted attribute in ") + name); | |
| 453 |
3/3✓ Branch 106 → 107 taken 554 times.
✓ Branch 107 → 108 taken 554 times.
✓ Branch 108 → 109 taken 554 times.
|
554 | const QString attribute = rest.mid(at, equals - at).trimmed().toLower(); |
| 454 | 554 | const qsizetype valueEnd = rest.indexOf(QLatin1Char('"'), equals + 2); | |
| 455 |
1/2✗ Branch 114 → 115 not taken.
✓ Branch 114 → 122 taken 554 times.
|
554 | if (valueEnd < 0) return fail(problem, QStringLiteral("unterminated attribute")); |
| 456 |
1/1✓ Branch 122 → 123 taken 554 times.
|
554 | const QString value = rest.mid(equals + 2, valueEnd - equals - 2); |
| 457 | 554 | at = valueEnd + 1; | |
| 458 |
4/4✓ Branch 123 → 124 taken 554 times.
✓ Branch 125 → 126 taken 1 time.
✓ Branch 125 → 135 taken 553 times.
✓ Branch 129 → 130 taken 1 time.
|
555 | if (!allowedAttributes().contains(attribute)) return fail(problem, QStringLiteral("attribute ") + attribute); |
| 459 |
2/2✓ Branch 137 → 138 taken 140 times.
✓ Branch 137 → 167 taken 413 times.
|
553 | if (attribute == QLatin1String("href")) { |
| 460 | 140 | QString href = value; | |
| 461 |
1/1✓ Branch 145 → 146 taken 140 times.
|
280 | href.replace(QStringLiteral("&"), QStringLiteral("&")); |
| 462 |
4/4✓ Branch 150 → 151 taken 140 times.
✓ Branch 151 → 152 taken 1 time.
✓ Branch 151 → 161 taken 139 times.
✓ Branch 155 → 156 taken 1 time.
|
141 | if (!ComposeDocumentFormat::isAllowedLink(href)) return fail(problem, QStringLiteral("link ") + value); |
| 463 | 140 | } | |
| 464 |
4/4✓ Branch 169 → 170 taken 5 times.
✓ Branch 169 → 177 taken 547 times.
✓ Branch 172 → 173 taken 2 times.
✓ Branch 172 → 177 taken 3 times.
|
554 | if (attribute == QLatin1String("class") && value != QLatin1String("mailjd-signature") && |
| 465 |
4/4✓ Branch 175 → 176 taken 1 time.
✓ Branch 175 → 177 taken 1 time.
✓ Branch 178 → 179 taken 1 time.
✓ Branch 178 → 188 taken 551 times.
|
554 | value != QLatin1String("mailjd-quote")) |
| 466 |
1/1✓ Branch 182 → 183 taken 1 time.
|
1 | return fail(problem, QStringLiteral("class ") + value); |
| 467 |
7/7✓ Branch 190 → 191 taken 3 times.
✓ Branch 190 → 195 taken 548 times.
✓ Branch 192 → 193 taken 3 times.
✓ Branch 193 → 194 taken 1 time.
✓ Branch 193 → 195 taken 2 times.
✓ Branch 196 → 197 taken 1 time.
✓ Branch 196 → 206 taken 550 times.
|
551 | if (attribute == QLatin1String("src") && !value.startsWith(QLatin1String("cid:"))) |
| 468 |
1/1✓ Branch 200 → 201 taken 1 time.
|
1 | return fail(problem, QStringLiteral("image source ") + value); |
| 469 |
2/2✓ Branch 208 → 209 taken 218 times.
✓ Branch 208 → 282 taken 332 times.
|
550 | if (attribute == QLatin1String("style")) { |
| 470 |
1/1✓ Branch 209 → 210 taken 218 times.
|
218 | const QString lower = value.toLower(); |
| 471 |
3/4✓ Branch 211 → 212 taken 218 times.
✓ Branch 214 → 215 taken 217 times.
✓ Branch 215 → 216 taken 217 times.
✗ Branch 215 → 223 not taken.
|
435 | if (lower.contains(QLatin1String("url(")) || lower.contains(QLatin1String("expression")) || |
| 472 |
8/10✓ Branch 212 → 213 taken 217 times.
✓ Branch 212 → 223 taken 1 time.
✓ Branch 218 → 219 taken 217 times.
✓ Branch 219 → 220 taken 217 times.
✗ Branch 219 → 223 not taken.
✓ Branch 221 → 222 taken 217 times.
✗ Branch 222 → 223 not taken.
✓ Branch 222 → 224 taken 217 times.
✓ Branch 225 → 226 taken 1 time.
✓ Branch 225 → 235 taken 217 times.
|
435 | lower.contains(QLatin1Char('\\')) || lower.contains(QLatin1String("@import"))) |
| 473 |
1/1✓ Branch 229 → 230 taken 1 time.
|
1 | return fail(problem, QStringLiteral("style value ") + value); |
| 474 |
5/5✓ Branch 238 → 239 taken 217 times.
✓ Branch 239 → 240 taken 217 times.
✓ Branch 240 → 241 taken 217 times.
✓ Branch 270 → 242 taken 314 times.
✓ Branch 270 → 271 taken 216 times.
|
530 | for (const QString &declaration : value.split(QLatin1Char(';'), Qt::SkipEmptyParts)) { |
| 475 |
3/3✓ Branch 246 → 247 taken 314 times.
✓ Branch 247 → 248 taken 314 times.
✓ Branch 248 → 249 taken 314 times.
|
314 | const QString property = declaration.section(QLatin1Char(':'), 0, 0).trimmed().toLower(); |
| 476 |
3/3✓ Branch 251 → 252 taken 314 times.
✓ Branch 253 → 254 taken 1 time.
✓ Branch 253 → 263 taken 313 times.
|
314 | if (!allowedStyleProperties().contains(property)) |
| 477 |
1/1✓ Branch 257 → 258 taken 1 time.
|
1 | return fail(problem, QStringLiteral("style property ") + property); |
| 478 | 531 | } | |
| 479 | 218 | } | |
| 480 | 560 | } | |
| 481 | 2992 | } | |
| 482 | } | ||
| 483 | |||
| 484 | 1438 | const QSet<QString> &MailHtmlWriter::allowedElements() { | |
| 485 | static const QSet<QString> elements{ | ||
| 486 | 2 | QStringLiteral("html"), QStringLiteral("head"), QStringLiteral("meta"), QStringLiteral("body"), | |
| 487 | 2 | QStringLiteral("p"), QStringLiteral("br"), QStringLiteral("strong"), QStringLiteral("em"), | |
| 488 | 2 | QStringLiteral("u"), QStringLiteral("s"), QStringLiteral("sup"), QStringLiteral("sub"), | |
| 489 | 2 | QStringLiteral("code"), QStringLiteral("pre"), QStringLiteral("h2"), QStringLiteral("h3"), | |
| 490 | 2 | QStringLiteral("h4"), QStringLiteral("blockquote"), QStringLiteral("ul"), QStringLiteral("ol"), | |
| 491 | 2 | QStringLiteral("li"), QStringLiteral("a"), QStringLiteral("img"), QStringLiteral("span"), | |
| 492 | 2 | QStringLiteral("hr"), QStringLiteral("table"), QStringLiteral("thead"), QStringLiteral("tbody"), QStringLiteral("tr"), | |
| 493 |
5/10✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 140 taken 1436 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 140 not taken.
✓ Branch 105 → 106 taken 64 times.
✓ Branch 105 → 107 taken 2 times.
✗ Branch 143 → 144 not taken.
✗ Branch 143 → 145 not taken.
✗ Branch 248 → 249 not taken.
✗ Branch 248 → 250 not taken.
|
1506 | QStringLiteral("th"), QStringLiteral("td"), QStringLiteral("div")}; |
| 494 | 1438 | return elements; | |
| 495 | 66 | } | |
| 496 | |||
| 497 | 554 | const QSet<QString> &MailHtmlWriter::allowedAttributes() { | |
| 498 | static const QSet<QString> attributes{ | ||
| 499 | 2 | QStringLiteral("style"), QStringLiteral("dir"), QStringLiteral("href"), QStringLiteral("src"), | |
| 500 | 2 | QStringLiteral("alt"), QStringLiteral("width"), QStringLiteral("height"), | |
| 501 | 2 | QStringLiteral("cellpadding"), QStringLiteral("cellspacing"), QStringLiteral("border"), | |
| 502 | 2 | QStringLiteral("colspan"), QStringLiteral("rowspan"), | |
| 503 |
5/10✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 76 taken 552 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 76 not taken.
✓ Branch 57 → 58 taken 32 times.
✓ Branch 57 → 59 taken 2 times.
✗ Branch 79 → 80 not taken.
✗ Branch 79 → 81 not taken.
✗ Branch 136 → 137 not taken.
✗ Branch 136 → 138 not taken.
|
590 | QStringLiteral("charset"), QStringLiteral("name"), QStringLiteral("content"), QStringLiteral("class")}; |
| 504 | 554 | return attributes; | |
| 505 | 34 | } | |
| 506 | |||
| 507 | 314 | const QSet<QString> &MailHtmlWriter::allowedStyleProperties() { | |
| 508 | static const QSet<QString> properties{ | ||
| 509 | 2 | QStringLiteral("font-family"), QStringLiteral("font-size"), QStringLiteral("color"), | |
| 510 | 2 | QStringLiteral("background-color"), QStringLiteral("text-align"), QStringLiteral("margin"), | |
| 511 | 2 | QStringLiteral("margin-left"), QStringLiteral("margin-right"), QStringLiteral("margin-top"), | |
| 512 | 2 | QStringLiteral("margin-bottom"), QStringLiteral("list-style-type"), | |
| 513 | 2 | QStringLiteral("border"), QStringLiteral("border-left"), QStringLiteral("border-collapse"), | |
| 514 | 2 | QStringLiteral("width"), QStringLiteral("padding"), QStringLiteral("padding-left"), | |
| 515 |
5/10✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 84 taken 312 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 84 not taken.
✓ Branch 63 → 64 taken 36 times.
✓ Branch 63 → 65 taken 2 times.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
✗ Branch 150 → 151 not taken.
✗ Branch 150 → 152 not taken.
|
354 | QStringLiteral("max-width")}; |
| 516 | 314 | return properties; | |
| 517 | 38 | } | |
| 518 |