Support missing white-space:pre-line CSS

A mode that only preserves new lines.

Change-Id: I612347b181c6e6c41dfae0cf60b22a662cba1b7e
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2019-03-26 12:48:36 +01:00
parent a1609d1603
commit d45908e242
7 changed files with 60 additions and 12 deletions

View File

@ -222,6 +222,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "outset", Value_Outset }, { "outset", Value_Outset },
{ "overline", Value_Overline }, { "overline", Value_Overline },
{ "pre", Value_Pre }, { "pre", Value_Pre },
{ "pre-line", Value_PreLine },
{ "pre-wrap", Value_PreWrap }, { "pre-wrap", Value_PreWrap },
{ "ridge", Value_Ridge }, { "ridge", Value_Ridge },
{ "right", Value_Right }, { "right", Value_Right },
@ -248,10 +249,10 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
}; };
//Map id to strings as they appears in the 'values' array above //Map id to strings as they appears in the 'values' array above
static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 54, 35, 26, 70, 71, 25, 43, 5, 63, 47, static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 50, 55, 35, 26, 71, 72, 25, 43, 5, 64, 48,
29, 58, 59, 27, 51, 61, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 50, 24, 46, 67, 37, 3, 2, 40, 62, 16, 29, 59, 60, 27, 52, 62, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 51, 24, 46, 68, 37, 3, 2, 40, 63, 16,
11, 57, 14, 32, 64, 33, 65, 55, 66, 34, 69, 8, 28, 38, 12, 36, 60, 7, 9, 4, 68, 53, 22, 23, 30, 31, 11, 58, 14, 32, 65, 33, 66, 56, 67, 34, 70, 8, 28, 38, 12, 36, 61, 7, 9, 4, 69, 54, 22, 23, 30, 31,
1, 15, 0, 52, 45, 44 }; 1, 15, 0, 53, 45, 44 };
QString Value::toString() const QString Value::toString() const
{ {

View File

@ -205,6 +205,7 @@ enum KnownValue {
Value_Normal, Value_Normal,
Value_Pre, Value_Pre,
Value_NoWrap, Value_NoWrap,
Value_PreLine,
Value_PreWrap, Value_PreWrap,
Value_Small, Value_Small,
Value_Medium, Value_Medium,

View File

@ -576,6 +576,9 @@ bool QTextHtmlImporter::appendNodeText()
&& ch != QChar::Nbsp && ch != QChar::Nbsp
&& ch != QChar::ParagraphSeparator) { && ch != QChar::ParagraphSeparator) {
if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')))
compressNextWhitespace = PreserveWhiteSpace;
if (compressNextWhitespace == CollapseWhiteSpace) if (compressNextWhitespace == CollapseWhiteSpace)
compressNextWhitespace = RemoveWhiteSpace; // allow this one, and remove the ones coming next. compressNextWhitespace = RemoveWhiteSpace; // allow this one, and remove the ones coming next.
else if(compressNextWhitespace == RemoveWhiteSpace) else if(compressNextWhitespace == RemoveWhiteSpace)
@ -592,7 +595,9 @@ bool QTextHtmlImporter::appendNodeText()
} }
} else if (wsm != QTextHtmlParserNode::WhiteSpacePreWrap) { } else if (wsm != QTextHtmlParserNode::WhiteSpacePreWrap) {
compressNextWhitespace = RemoveWhiteSpace; compressNextWhitespace = RemoveWhiteSpace;
if (wsm == QTextHtmlParserNode::WhiteSpaceNoWrap) if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')))
{ }
else if (wsm == QTextHtmlParserNode::WhiteSpaceNoWrap)
ch = QChar::Nbsp; ch = QChar::Nbsp;
else else
ch = QLatin1Char(' '); ch = QLatin1Char(' ');
@ -605,6 +610,8 @@ bool QTextHtmlImporter::appendNodeText()
|| ch == QChar::ParagraphSeparator) { || ch == QChar::ParagraphSeparator) {
if (!textToInsert.isEmpty()) { if (!textToInsert.isEmpty()) {
if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && textToInsert.at(textToInsert.length() - 1) == QChar(' '))
textToInsert = textToInsert.chopped(1);
cursor.insertText(textToInsert, format); cursor.insertText(textToInsert, format);
textToInsert.clear(); textToInsert.clear();
} }

View File

@ -649,7 +649,7 @@ void QTextHtmlParser::parseTag()
parseExclamationTag(); parseExclamationTag();
if (nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePre if (nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePre
&& nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePreWrap && nodes.last().wsm != QTextHtmlParserNode::WhiteSpacePreWrap
&& !textEditMode) && !textEditMode)
eatSpace(); eatSpace();
return; return;
} }
@ -717,7 +717,8 @@ void QTextHtmlParser::parseTag()
// in a white-space preserving environment strip off a initial newline // in a white-space preserving environment strip off a initial newline
// since the element itself already generates a newline // since the element itself already generates a newline
if ((node->wsm == QTextHtmlParserNode::WhiteSpacePre if ((node->wsm == QTextHtmlParserNode::WhiteSpacePre
|| node->wsm == QTextHtmlParserNode::WhiteSpacePreWrap) || node->wsm == QTextHtmlParserNode::WhiteSpacePreWrap
|| node->wsm == QTextHtmlParserNode::WhiteSpacePreLine)
&& node->isBlock()) { && node->isBlock()) {
if (pos < len - 1 && txt.at(pos) == QLatin1Char('\n')) if (pos < len - 1 && txt.at(pos) == QLatin1Char('\n'))
++pos; ++pos;
@ -761,7 +762,8 @@ void QTextHtmlParser::parseCloseTag()
// in a new block for elements following the <pre> // in a new block for elements following the <pre>
// ...foo\n</pre><p>blah -> foo</pre><p>blah // ...foo\n</pre><p>blah -> foo</pre><p>blah
if ((at(p).wsm == QTextHtmlParserNode::WhiteSpacePre if ((at(p).wsm == QTextHtmlParserNode::WhiteSpacePre
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreWrap) || at(p).wsm == QTextHtmlParserNode::WhiteSpacePreWrap
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreLine)
&& at(p).isBlock()) { && at(p).isBlock()) {
if (at(last()).text.endsWith(QLatin1Char('\n'))) if (at(last()).text.endsWith(QLatin1Char('\n')))
nodes[last()].text.chop(1); nodes[last()].text.chop(1);
@ -1278,6 +1280,7 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::Value_Pre: wsm = QTextHtmlParserNode::WhiteSpacePre; break; case QCss::Value_Pre: wsm = QTextHtmlParserNode::WhiteSpacePre; break;
case QCss::Value_NoWrap: wsm = QTextHtmlParserNode::WhiteSpaceNoWrap; break; case QCss::Value_NoWrap: wsm = QTextHtmlParserNode::WhiteSpaceNoWrap; break;
case QCss::Value_PreWrap: wsm = QTextHtmlParserNode::WhiteSpacePreWrap; break; case QCss::Value_PreWrap: wsm = QTextHtmlParserNode::WhiteSpacePreWrap; break;
case QCss::Value_PreLine: wsm = QTextHtmlParserNode::WhiteSpacePreLine; break;
default: break; default: break;
} }
break; break;

View File

@ -158,6 +158,7 @@ struct QTextHtmlParserNode {
WhiteSpacePre, WhiteSpacePre,
WhiteSpaceNoWrap, WhiteSpaceNoWrap,
WhiteSpacePreWrap, WhiteSpacePreWrap,
WhiteSpacePreLine,
WhiteSpaceModeUndefined = -1 WhiteSpaceModeUndefined = -1
}; };

View File

@ -78,6 +78,8 @@ private slots:
void extractBorder(); void extractBorder();
void noTextDecoration(); void noTextDecoration();
void quotedAndUnquotedIdentifiers(); void quotedAndUnquotedIdentifiers();
void whitespaceValues_data();
void whitespaceValues();
}; };
void tst_QCssParser::scanner_data() void tst_QCssParser::scanner_data()
@ -1746,6 +1748,33 @@ void tst_QCssParser::quotedAndUnquotedIdentifiers()
QCOMPARE(decls.at(1).d->values.first().toString(), QLatin1String("bold")); QCOMPARE(decls.at(1).d->values.first().toString(), QLatin1String("bold"));
} }
void tst_QCssParser::whitespaceValues_data()
{
QTest::addColumn<QString>("value");
QTest::newRow("normal") << "normal";
QTest::newRow("inherit") << "inherit";
QTest::newRow("nowrap") << "nowrap";
QTest::newRow("pre") << "pre";
QTest::newRow("pre-wrap") << "pre-wrap";
QTest::newRow("pre-line") << "pre-line";
}
void tst_QCssParser::whitespaceValues()
{
QFETCH(QString, value);
QCss::Parser parser(QString("foo { white-space: %1 }").arg(value));
QCss::StyleSheet sheet;
QVERIFY(parser.parse(&sheet));
QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ?
sheet.styleRules.at(0) : *sheet.nameIndex.begin();
QCOMPARE(rule.declarations.size(), 1);
QCOMPARE(rule.declarations.at(0).d->property, QLatin1String("white-space"));
QCOMPARE(rule.declarations.at(0).d->values.first().toString(), value);
}
QTEST_MAIN(tst_QCssParser) QTEST_MAIN(tst_QCssParser)
#include "tst_qcssparser.moc" #include "tst_qcssparser.moc"

View File

@ -1272,11 +1272,11 @@ void tst_QTextDocumentFragment::html_whitespace_data()
QTest::newRow("2") << QString("<span> </span><span>nowhitespacehereplease</span>") QTest::newRow("2") << QString("<span> </span><span>nowhitespacehereplease</span>")
<< QString::fromLatin1("nowhitespacehereplease"); << QString::fromLatin1("nowhitespacehereplease");
QTest::newRow("3") << QString("<span style=\"white-space: pre;\"> white space here </span>") QTest::newRow("3") << QString("<span style=\"white-space: pre;\"> white space \n\n here </span>")
<< QString::fromLatin1(" white space here "); << QString::fromLatin1(" white space \n\n here ");
QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\"> white space here </span>") QTest::newRow("4") << QString("<span style=\"white-space: pre-wrap;\"> white space \n\n here </span>")
<< QString::fromLatin1(" white space here "); << QString::fromLatin1(" white space \n\n here ");
QTest::newRow("5") << QString("<a href=\"One.html\">One</a> <a href=\"Two.html\">Two</a> <b>Three</b>\n" QTest::newRow("5") << QString("<a href=\"One.html\">One</a> <a href=\"Two.html\">Two</a> <b>Three</b>\n"
"<b>Four</b>") "<b>Four</b>")
@ -1291,6 +1291,12 @@ void tst_QTextDocumentFragment::html_whitespace_data()
QTest::newRow("8") << QString("<table><tr><td><i>Blah</i></td></tr></table> <i>Blub</i>") QTest::newRow("8") << QString("<table><tr><td><i>Blah</i></td></tr></table> <i>Blub</i>")
<< QString("\nBlah\nBlub"); << QString("\nBlah\nBlub");
QTest::newRow("9") << QString("<span style=\"white-space: nowrap;\"> white space \n\n here </span>")
<< QString::fromLatin1("white space here ");
QTest::newRow("10") << QString("<span style=\"white-space: pre-line;\"> white space \n\n here </span>")
<< QString::fromLatin1("white space\n\nhere ");
QTest::newRow("task116492") << QString("<p>a<font=\"Times\"> b </font>c</p>") QTest::newRow("task116492") << QString("<p>a<font=\"Times\"> b </font>c</p>")
<< QString("a b c"); << QString("a b c");