sw/qa/extras/htmlexport/htmlexport.cxx | 41 ++++++++++++++++++++++++++++++++ sw/source/filter/html/htmlatr.cxx | 12 +++++++-- sw/source/filter/html/htmlnumwriter.cxx | 4 ++- sw/source/filter/html/wrthtml.hxx | 3 +- 4 files changed, 56 insertions(+), 4 deletions(-)
New commits: commit eb0cd13590ae93410d831e689922c263ea75face Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Jun 16 15:55:23 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Jun 17 08:50:48 2022 +0200 sw HTML export, XHTML mode: fix lost <li> with a list header + item There is a general mismatch between XHTML and Writer lists: XHTML can only contain list items (for ordered or unordered lists), while Writer can contain list headers and list items. List headers have no bullet or number at the start, list items are the normal text nodes. Commit 8c2607ae3ce143586e623532b8ae5288277ec3ac (sw HTML export, XHTML mode: fix lost </li> when last list item is not numbered, 2022-02-21) fixed the list item end side of this problem: if all text nodes in a list are headers, then don't write ul/ol at all, otherwise end list headers with </li> as well to make sure the output XML is valid. However, this created a mis-match, the starting <li> for list headers in a list which have non-header text nodes at as was not adapted. Fix the problem by extending OutHTML_SwFormat() so list headers in a list with non-header text nodes always have a <li> and </li>, and this condition is the same on the start/end side. Calculating if at least one text node is non-header in a list may not be cheap, so reuse the already calculated info from OutHTML_NumberBulletListStart() in OutHTML_SwFormat(). (cherry picked from commit b2bee5a4db5552c4d408800908ca717b4ea2564a) Change-Id: I3817a489f16166fc5b4c33ee64e2283c41a4402c diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 7b9128e8d32a..1d03d107fd09 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -1512,6 +1512,47 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testPartiallyNumberedList) "/reqif-xhtml:html/reqif-xhtml:div/reqif-xhtml:ol/reqif-xhtml:li/reqif-xhtml:p", 2); } +CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testListHeaderAndItem) +{ + // Given a document with a list, first para is not numbered, but the second is: + loadURL("private:factory/swriter", nullptr); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell(); + pWrtShell->Insert("not numbered"); + 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())); + rTextNode.SetCountedInList(false); + } + pWrtShell->SplitNode(); + pWrtShell->Insert2("numbered"); + { + SwNode& rNode = pWrtShell->GetCursor()->GetPoint()->nNode.GetNode(); + SwTextNode& rTextNode = *rNode.GetTextNode(); + rTextNode.SetAttr(SwNumRuleItem(pNumRule->GetName())); + } + + // When exporting to ReqIF: + ExportToReqif(); + + // Then make sure the output is well-formed xhtml: + SvMemoryStream aStream; + HtmlExportTest::wrapFragment(maTempFile, aStream); + xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); + // Without the accompanying fix in place, this test would have failed: + // Entity: line 3: parser error : Opening and ending tag mismatch: ol line 3 and li + // <reqif-xhtml:ol><reqif-xhtml:p>not numbered</reqif-xhtml:p></reqif-xhtml:li> + CPPUNIT_ASSERT(pXmlDoc); + // Make sure that in case the list has a header and an item, then both are wrapped in an <li> + // element. + 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/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx index 8f8d0c1fa080..24ae4cbc1713 100644 --- a/sw/source/filter/html/htmlatr.cxx +++ b/sw/source/filter/html/htmlatr.cxx @@ -686,11 +686,12 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, if( nNewDefListLvl != rHWrt.m_nDefListLvl ) rHWrt.OutAndSetDefList( nNewDefListLvl ); + bool bAtLeastOneNumbered = false; // if necessary, start a bulleted or numbered list if( rInfo.bInNumberBulletList ) { OSL_ENSURE( !rHWrt.m_nDefListLvl, "DL cannot be inside OL!" ); - OutHTML_NumberBulletListStart( rHWrt, aNumInfo ); + OutHTML_NumberBulletListStart( rHWrt, aNumInfo, bAtLeastOneNumbered ); if( bNumbered ) { @@ -759,7 +760,14 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, bool bXhtmlBlockQuote = rHWrt.mbXHTML && rInfo.aToken == OOO_STRING_SVTOOLS_HTML_blockquote; // if necessary, start a new list item - if( rInfo.bInNumberBulletList && bNumbered ) + bool bNumberedForListItem = bNumbered; + if (!bNumberedForListItem && rHWrt.mbXHTML && bAtLeastOneNumbered) + { + // OutHTML_NumberBulletListEnd() will end a list item if at least one text node is numbered + // in the list, so open the list item with the same condition here. + bNumberedForListItem = true; + } + if( rInfo.bInNumberBulletList && bNumberedForListItem ) { HtmlWriter html(rWrt.Strm(), rHWrt.maNamespace); html.start(OOO_STRING_SVTOOLS_HTML_li); diff --git a/sw/source/filter/html/htmlnumwriter.cxx b/sw/source/filter/html/htmlnumwriter.cxx index f338251c0211..fdc579a65d3d 100644 --- a/sw/source/filter/html/htmlnumwriter.cxx +++ b/sw/source/filter/html/htmlnumwriter.cxx @@ -84,7 +84,8 @@ void SwHTMLWriter::SetNextNumInfo( std::unique_ptr<SwHTMLNumRuleInfo> pNxt ) } Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, - const SwHTMLNumRuleInfo& rInfo ) + const SwHTMLNumRuleInfo& rInfo, + bool& rAtLeastOneNumbered ) { SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo(); bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule(); @@ -124,6 +125,7 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, ++nPos; } + rAtLeastOneNumbered = bAtLeastOneNumbered; if (!bAtLeastOneNumbered) { return rWrt; diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx index 52ab53205165..723fa03ab950 100644 --- a/sw/source/filter/html/wrthtml.hxx +++ b/sw/source/filter/html/wrthtml.hxx @@ -721,7 +721,8 @@ Writer& OutCSS1_NumberBulletListStyleOpt( Writer& rWrt, const SwNumRule& rNumRul sal_uInt8 nLevel ); Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, - const SwHTMLNumRuleInfo& rInfo ); + const SwHTMLNumRuleInfo& rInfo, + bool& rAtLeastOneNumbered ); Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, const SwHTMLNumRuleInfo& rNextInfo );