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 846079db0cf519c396125a8dfedd86ad560c26dd
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jun 16 15:55:23 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jun 20 09:49:33 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 472a40b022ef685610faa663421a00cfe6121c24)
    
    Change-Id: I3817a489f16166fc5b4c33ee64e2283c41a4402c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136136
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index c1e7d945dedb..21feaa0b5e73 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -1535,6 +1535,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 e50a5f06d6c1..51f059d5a2cc 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 df15619cd85e..f41ac73929f9 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 8986c3e1cc9a..22a386bcee7c 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -719,7 +719,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 );
 

Reply via email to