summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-05-21 11:05:30 +0200
committerMiklos Vajna <vmiklos@collabora.com>2020-05-21 17:52:37 +0200
commitfad37294ec76178f6987ef8d381663c95581d8ef (patch)
tree94e584c4ad144ab08d30099bd24bb9c4b8f5b672
parent2059ea2a92f73cc8ea4bcf9bad833132c8f4c39c (diff)
sw XHTML export: properly write <li>...</li> around multiple paragraphs
Writer just has a list of text nodes, but ODF and HTML can have multiple paragraphs inside <li>, in case the non-first text nodes have their RES_PARATR_LIST_ISCOUNTED set to false. Improve b6f7a4908d1c3fc610440a1cbbbc1673a53da8b6 (sw XHTML export: properly write <li>...</li> around paragraphs, 2018-04-11) to make the decision around when to write </li> based on not only the current but also the next text node. This way we omit </li> for non-first paragraphs inside <li>, but keep writing it in other cases. (cherry picked from commit 119b6876c92e4cdae44583c4b1b1419d3533e3ee) Conflicts: sw/CppunitTest_sw_htmlexport.mk sw/source/filter/html/htmlatr.cxx Change-Id: I994855961aeea92050268dba5f19f125c7ad2b7f
-rw-r--r--sw/CppunitTest_sw_htmlexport.mk1
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx53
-rw-r--r--sw/source/filter/html/htmlatr.cxx17
-rw-r--r--sw/source/filter/html/htmlnumwriter.cxx14
4 files changed, 69 insertions, 16 deletions
diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index 0d8cd44f4619..1b7c560121b4 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -24,6 +24,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_htmlexport, \
sal \
sfx \
sot \
+ svl \
svt \
sw \
test \
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index b19a6bf3ad19..bddee029ec77 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -24,6 +24,9 @@
#include <swmodule.hxx>
#include <swdll.hxx>
#include <usrpref.hxx>
+#include <wrtsh.hxx>
+#include <ndtxt.hxx>
+#include <paratr.hxx>
#include <test/htmltesttools.hxx>
#include <tools/urlobj.hxx>
@@ -35,6 +38,7 @@
#include <svtools/rtftoken.h>
#include <filter/msfilter/rtfutil.hxx>
#include <sot/storage.hxx>
+#include <svl/eitem.hxx>
class HtmlExportTest : public SwModelTestBase, public HtmlTestTools
{
@@ -1078,6 +1082,55 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifOle1PDF)
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(39409), pOleNative->GetSize());
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testMultiParaListItem)
+{
+ // Create a document with 3 list items: A, B&C and D.
+ loadURL("private:factory/swriter", nullptr);
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+ SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+ pWrtShell->Insert("A");
+ SwDoc* pDoc = pWrtShell->GetDoc();
+ {
+ // Enable numbering.
+ 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->SplitNode();
+ pWrtShell->Insert("B");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("C");
+ {
+ // C is in the same list item as B.
+ SwNode& rNode = pWrtShell->GetCursor()->GetPoint()->nNode.GetNode();
+ SwTextNode& rTextNode = *rNode.GetTextNode();
+ rTextNode.SetCountedInList(false);
+ }
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("D");
+
+ uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aStoreProperties = {
+ comphelper::makePropertyValue("FilterName", OUString("HTML (StarWriter)")),
+ comphelper::makePropertyValue("FilterOptions", OUString("xhtmlns=reqif-xhtml")),
+ };
+ xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
+
+ SvMemoryStream aStream;
+ HtmlExportTest::wrapFragment(maTempFile, aStream);
+ xmlDocPtr pXmlDoc = parseXmlStream(&aStream);
+ CPPUNIT_ASSERT(pDoc);
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li[1]/reqif-xhtml:p", "A");
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li[2]/reqif-xhtml:p[1]", "B");
+ // Without the accompanying fix in place, this test would have failed with:
+ // XPath '//reqif-xhtml:ol/reqif-xhtml:li[2]/reqif-xhtml:p[2]' not found
+ // i.e. </li> was writen before "C", not after "C", so "C" was not in the 2nd list item.
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li[2]/reqif-xhtml:p[2]", "C");
+ assertXPathContent(pXmlDoc, "//reqif-xhtml:ol/reqif-xhtml:li[3]/reqif-xhtml:p", "D");
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx
index ffadbfff3636..dda69d7c7f6a 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -207,7 +207,6 @@ struct SwHTMLTextCollOutputInfo
bool bParaPossible; // a </P> may be output additionally
bool bOutPara; // a </P> is supposed to be output
bool bOutDiv; // write a </DIV>
- bool bOutLi = false; // write a </li>
SwHTMLTextCollOutputInfo() :
bInNumBulList( false ),
@@ -763,14 +762,8 @@ void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat,
html.start(OOO_STRING_SVTOOLS_HTML_li);
if( USHRT_MAX != nNumStart )
html.attribute(OOO_STRING_SVTOOLS_HTML_O_value, OString::number(nNumStart));
- if (rHWrt.mbXHTML)
- {
- rWrt.Strm().WriteCharPtr(">");
- rInfo.bOutLi = true;
- }
- else
- // Finish the opening element, but don't close it.
- html.characters(OString());
+ // Finish the opening element, but don't close it.
+ html.characters(OString());
}
if( rHWrt.m_nDefListLvl > 0 && !bForceDL )
@@ -1023,11 +1016,7 @@ void OutHTML_SwFormatOff( Writer& rWrt, const SwHTMLTextCollOutputInfo& rInfo )
rHWrt.m_bLFPossible = true;
}
- if (rInfo.bOutLi)
- HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rHWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li,
- false);
-
- // if necessary, close a bulleted or numbered list
+ // if necessary, close the list item, then close a bulleted or numbered list
if( rInfo.bInNumBulList )
{
rHWrt.FillNextNumInfo();
diff --git a/sw/source/filter/html/htmlnumwriter.cxx b/sw/source/filter/html/htmlnumwriter.cxx
index 5ee8044f1b4f..8943a2d4d0bf 100644
--- a/sw/source/filter/html/htmlnumwriter.cxx
+++ b/sw/source/filter/html/htmlnumwriter.cxx
@@ -286,8 +286,18 @@ Writer& OutHTML_NumBulListEnd( SwHTMLWriter& rWrt,
{
SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo();
bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
- if( bSameRule && rNextInfo.GetDepth() >= rInfo.GetDepth() &&
- !rNextInfo.IsRestart() )
+ bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart();
+
+ if (rWrt.mbXHTML)
+ {
+ if (bListEnd || (!bListEnd && rNextInfo.IsNumbered()))
+ {
+ HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(),
+ rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li, false);
+ }
+ }
+
+ if (!bListEnd)
{
return rWrt;
}