summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-02-21 16:38:51 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-02-23 11:07:45 +0100
commit2466b9fcf20ee61f6fc621298011c0efaa55e7c6 (patch)
tree09c050c75d28c8cf0377482979f78ff606a4ee0a /sw
parent74d57d107cf6fc797170f3c381622b6c7bc87287 (diff)
sw HTML export, XHTML mode: fix lost </li> when last list item is not numbered
This went wrong in 013a4f1f5c9ea5fb511568c53a7e76d1b365a65d (sw XHTML export: fix handling of list labels, 2021-05-13), where we started to assume that in case the last paragraph of a list is not numbered, then the entire list is not numbered. This lead to loosing the </li> for an <li> in case the list starts with a numbered paragraph, but ends with a non-numbered one. Fix the problem by (if necessary) looking back till the start of the list to see if any paragraph is numbered: that ensures that the <li> and </li> is always in sync. This fixes the new problem and keeps the old problem fixed at the same time. Change-Id: I7d347b37a40dcc727c2080bf8279e33c3ad147e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130287 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins (cherry picked from commit 8c2607ae3ce143586e623532b8ae5288277ec3ac) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130310 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> (cherry picked from commit 81f90d4ab51ec7528fa2a9b14c0426a634971580)
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx42
-rw-r--r--sw/source/filter/html/htmlnumwriter.cxx46
2 files changed, 69 insertions, 19 deletions
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index fa40c8d7d04c..7f64c835ce2d 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -1491,6 +1491,48 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testListHeading)
assertXPathContent(pXmlDoc, "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:p", "list header");
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testPartiallyNumberedList)
+{
+ // Given a document with a list, first para is numbered, second is not:
+ loadURL("private:factory/swriter", nullptr);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("list header");
+ SwDoc* pDoc = pWrtShell->GetDoc();
+ sal_uInt16 nPos = pDoc->MakeNumRule(pDoc->GetUniqueNumRuleName());
+ SwNumRule* pNumRule = pDoc->GetNumRuleTable()[nPos];
+ {
+ SwNode& rNode = pWrtShell->GetCursor()->GetPoint()->nNode.GetNode();
+ SwTextNode& rTextNode = *rNode.GetTextNode();
+ rTextNode.SetAttr(SwNumRuleItem(pNumRule->GetName()));
+ }
+ pWrtShell->Insert2("numbered");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert2("not numbered");
+ {
+ SwNode& rNode = pWrtShell->GetCursor()->GetPoint()->nNode.GetNode();
+ SwTextNode& rTextNode = *rNode.GetTextNode();
+ rTextNode.SetAttr(SwNumRuleItem(pNumRule->GetName()));
+ rTextNode.SetCountedInList(false);
+ }
+
+ // When exporting to ReqIF:
+ ExportToReqif();
+
+ // Then make sure the output is well-formed xhtml:
+ SvMemoryStream aStream;
+ HtmlExportTest::wrapFragment(maTempFile, aStream);
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ CPPUNIT_ASSERT(pXmlDoc);
+ // Without the accompanying fix in place, this test would have failed:
+ // - expected: <li><p>...</p><p>...</p></li>
+ // - actual : <li><p>...</p><p>...</p>
+ // because a <li> without a matching </li> is not well-formed, and the </li> was omitted because
+ // the second para was not numbered.
+ assertXPath(pXmlDoc,
+ "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:p", 2);
+}
+
CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testBlockQuoteNoMargin)
{
// Given a document with some text, para style set to Quotations, no bottom margin:
diff --git a/sw/source/filter/html/htmlnumwriter.cxx b/sw/source/filter/html/htmlnumwriter.cxx
index 7df3402dda35..df15619cd85e 100644
--- a/sw/source/filter/html/htmlnumwriter.cxx
+++ b/sw/source/filter/html/htmlnumwriter.cxx
@@ -321,25 +321,10 @@ Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt,
bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart();
- if (rWrt.mbXHTML)
- {
- // XHTML </li> for the list item content.
- if ((bListEnd && rInfo.IsNumbered()) || (!bListEnd && rNextInfo.IsNumbered()))
- {
- HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(),
- OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li), false);
- }
- }
-
- if (!bListEnd)
- {
- return rWrt;
- }
-
+ std::optional<bool> oAtLeastOneNumbered;
if (rWrt.mbXHTML && !rInfo.IsNumbered())
{
- // If the list only consisted of non-numbered text nodes, then don't end the list.
- bool bAtLeastOneNumbered = false;
+ oAtLeastOneNumbered = false;
SwNodeOffset nPos = rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() - 1;
SwNumRule* pNumRule = nullptr;
while (true)
@@ -360,13 +345,36 @@ Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt,
pNumRule = pTextNode->GetNumRule();
if (pTextNode->IsNumbered())
{
- bAtLeastOneNumbered = true;
+ oAtLeastOneNumbered = true;
break;
}
--nPos;
}
+ }
- if (!bAtLeastOneNumbered)
+ if (rWrt.mbXHTML)
+ {
+ // The list is numbered if the previous text node is numbered or any other previous text
+ // node is numbered.
+ bool bPrevIsNumbered = rInfo.IsNumbered() || *oAtLeastOneNumbered;
+ // XHTML </li> for the list item content, if there is an open <li>.
+ if ((bListEnd && bPrevIsNumbered) || (!bListEnd && rNextInfo.IsNumbered()))
+ {
+ HTMLOutFuncs::Out_AsciiTag(
+ rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
+ false);
+ }
+ }
+
+ if (!bListEnd)
+ {
+ return rWrt;
+ }
+
+ if (rWrt.mbXHTML && !rInfo.IsNumbered())
+ {
+ // If the list only consisted of non-numbered text nodes, then don't end the list.
+ if (!*oAtLeastOneNumbered)
{
return rWrt;
}