diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-02-21 16:38:51 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-02-23 11:07:45 +0100 |
commit | 2466b9fcf20ee61f6fc621298011c0efaa55e7c6 (patch) | |
tree | 09c050c75d28c8cf0377482979f78ff606a4ee0a /sw | |
parent | 74d57d107cf6fc797170f3c381622b6c7bc87287 (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.cxx | 42 | ||||
-rw-r--r-- | sw/source/filter/html/htmlnumwriter.cxx | 46 |
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; } |