sw/qa/extras/htmlexport/htmlexport.cxx |   82 +++++++++++++++++++++++----------
 sw/source/filter/html/htmlatr.cxx      |   18 ++++---
 sw/source/filter/html/htmltab.cxx      |    6 ++
 3 files changed, 76 insertions(+), 30 deletions(-)

New commits:
commit fb035e08ff759c06bab9839d41be89de6ba61ad2
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Feb 11 16:18:26 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Feb 14 15:23:16 2022 +0100

    sw XHTML / ReqIF filter: avoid adding and removing <br>s for trailing <br>s
    
    The sw/ HTML export writes two <br>s for a <br> in the doc model at the
    end of a paragraph, because the last <br> would be ignored by browsers.
    But then the import ignores all <br>s at the end of paragraphs, so the
    import and the export are not a 1:1 mapping; but at least the layout of
    the exported HTML is close to the Writer layout.
    
    ReqIF focuses on the preserving the semantics of the doc model instead:
    it already doesn't open the document in "web view", and it's not
    expected that the number of <br>s change on import or export.
    
    Fix the problem by disabling both the import and the export tweaks in
    the ReqIF case.
    
    It would perhaps make sense to do this in general, but for users who
    only care about the export layout (and never import the result again),
    that would be probably a regression, so don't change this
    unconditionally for now.
    
    (cherry picked from commit b86679ea6bd2bb053c3822c4642a62a49e381909)
    
    Conflicts:
            sw/qa/extras/htmlexport/htmlexport.cxx
    
    Change-Id: Iabd4a462185493c1ece0352069077e04c293816b

diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index f95884620b55..eff7bda22037 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -268,6 +268,8 @@ public:
     void ParseOle1FromRtfUrl(const OUString& rRtfUrl, SvMemoryStream& rOle1);
     /// Export using the C++ HTML export filter, with xhtmlns=reqif-xhtml.
     void ExportToReqif();
+    /// Import using the C++ HTML import filter, with xhtmlns=reqif-xhtml.
+    void ImportFromReqif(const OUString& rUrl);
 };
 
 OUString SwHtmlDomExportTest::GetOlePath()
@@ -322,6 +324,15 @@ void SwHtmlDomExportTest::ExportToReqif()
     xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
 }
 
+void SwHtmlDomExportTest::ImportFromReqif(const OUString& rUrl)
+{
+    uno::Sequence<beans::PropertyValue> aLoadProperties = {
+        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
+        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
+    };
+    mxComponent = loadFromDesktop(rUrl, "com.sun.star.text.TextDocument", 
aLoadProperties);
+}
+
 char const DATA_DIRECTORY[] = "/sw/qa/extras/htmlexport/data/";
 
 DECLARE_HTMLEXPORT_ROUNDTRIP_TEST(testFdo81276, "fdo81276.html")
@@ -700,11 +711,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfPngImg)
     };
 
     OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"reqif-png-img.xhtml";
-    uno::Sequence<beans::PropertyValue> aLoadProperties = {
-        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
-        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
-    };
-    mxComponent = loadFromDesktop(aURL, "com.sun.star.text.TextDocument", 
aLoadProperties);
+    ImportFromReqif(aURL);
     verify(/*bExported=*/false);
     uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
     uno::Sequence<beans::PropertyValue> aStoreProperties = {
@@ -714,8 +721,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIfPngImg)
     };
     xStorable->storeToURL(maTempFile.GetURL(), aStoreProperties);
     mxComponent->dispose();
-    mxComponent
-        = loadFromDesktop(maTempFile.GetURL(), 
"com.sun.star.text.TextDocument", aLoadProperties);
+    ImportFromReqif(maTempFile.GetURL());
     verify(/*bExported=*/true);
 }
 
@@ -1011,12 +1017,8 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testRTFOLEMimeType)
 {
     // Import a document with an embedded object.
     OUString aType("test/rtf");
-    uno::Sequence<beans::PropertyValue> aLoadProperties = {
-        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
-        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
-    };
     OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"reqif-ole-data.xhtml";
-    mxComponent = loadFromDesktop(aURL, "com.sun.star.text.TextDocument", 
aLoadProperties);
+    ImportFromReqif(aURL);
 
     // Export it.
     uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
@@ -1185,12 +1187,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqifOle1PDF)
     // Now import this back and check the ODT result.
     mxComponent->dispose();
     mxComponent.clear();
-    uno::Sequence<beans::PropertyValue> aLoadProperties = {
-        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
-        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
-    };
-    mxComponent
-        = loadFromDesktop(maTempFile.GetURL(), 
"com.sun.star.text.TextDocument", aLoadProperties);
+    ImportFromReqif(maTempFile.GetURL());
     xStorable.set(mxComponent, uno::UNO_QUERY);
     utl::TempFile aTempFile;
     aStoreProperties = {
@@ -1217,12 +1214,7 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqifOle1Paint)
 {
     // Load the bug document, which has OLE1 data in it, which is not a 
wrapper around OLE2 data.
     OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"paint-ole.xhtml";
-    uno::Sequence<beans::PropertyValue> aLoadProperties = {
-        comphelper::makePropertyValue("FilterName", OUString("HTML 
(StarWriter)")),
-        comphelper::makePropertyValue("FilterOptions", 
OUString("xhtmlns=reqif-xhtml")),
-    };
-    mxComponent
-        = loadFromDesktop(aURL, "com.sun.star.text.TextDocument", 
aLoadProperties);
+    ImportFromReqif(aURL);
 
     // Save it as ODT to inspect the result of the OLE1 -> OLE2 conversion.
     uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
@@ -2025,6 +2017,48 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testNestedBullets)
         "second");
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testTrailingLineBreak)
+{
+    // Given a document with a trailing line-break:
+    loadURL("private:factory/swriter", nullptr);
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->Insert("test\n");
+
+    // When exporting to reqif-xhtml:
+    ExportToReqif();
+
+    // Then make sure that we still have a single line-break:
+    SvMemoryStream aStream;
+    HtmlExportTest::wrapFragment(maTempFile, aStream);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+    CPPUNIT_ASSERT(pDoc);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 2
+    // - XPath '//reqif-xhtml:br' number of nodes is incorrect
+    assertXPath(pXmlDoc, "//reqif-xhtml:br", 1);
+
+    // Then test the import side:
+
+    // Given an empty document:
+    mxComponent->dispose();
+
+    // When importing a <br> from reqif-xhtml:
+    ImportFromReqif(maTempFile.GetURL());
+
+    // Then make sure that line-break is not lost:
+    pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    pDoc = pTextDoc->GetDocShell()->GetDoc();
+    pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    OUString aActual = 
pWrtShell->GetCursor()->GetNode().GetTextNode()->GetText();
+    // Without the accompanying fix in place, this test would have failed, as 
the trailing
+    // line-break was lost.
+    CPPUNIT_ASSERT_EQUAL(OUString("test\n"), aActual);
+}
+
 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 46abffd664a9..80f1b7d2ddea 100644
--- a/sw/source/filter/html/htmlatr.cxx
+++ b/sw/source/filter/html/htmlatr.cxx
@@ -2352,8 +2352,11 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
     }
 
     bool bWriteBreak = (HtmlTokenId::PREFORMTXT_ON != 
rHTMLWrt.m_nLastParaToken);
-    if( bWriteBreak && pNd->GetNumRule()  )
+    if (bWriteBreak && (pNd->GetNumRule() || rHTMLWrt.mbReqIF))
+    {
+        // One line-break is exactly one <br> in the ReqIF case.
         bWriteBreak = false;
+    }
 
     {
         HTMLOutContext aContext( rHTMLWrt.m_eDestEnc );
@@ -2493,11 +2496,14 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const 
SwContentNode& rNode )
                     else
                         HTMLOutFuncs::Out_Char( rWrt.Strm(), c, aContext, 
&rHTMLWrt.m_aNonConvertableCharacters );
 
-                    // if a paragraph's last character is a hard line break
-                    // then we need to add an extra <br>
-                    // because browsers like Mozilla wouldn't add a line for 
the next paragraph
-                    bWriteBreak = (0x0a == c) &&
-                                  (HtmlTokenId::PREFORMTXT_ON != 
rHTMLWrt.m_nLastParaToken);
+                    if (!rHTMLWrt.mbReqIF)
+                    {
+                        // if a paragraph's last character is a hard line break
+                        // then we need to add an extra <br>
+                        // because browsers like Mozilla wouldn't add a line 
for the next paragraph
+                        bWriteBreak = (0x0a == c) &&
+                                      (HtmlTokenId::PREFORMTXT_ON != 
rHTMLWrt.m_nLastParaToken);
+                    }
                 }
             }
         }
diff --git a/sw/source/filter/html/htmltab.cxx 
b/sw/source/filter/html/htmltab.cxx
index 9104497ccd2e..21a387fdc80f 100644
--- a/sw/source/filter/html/htmltab.cxx
+++ b/sw/source/filter/html/htmltab.cxx
@@ -2661,6 +2661,12 @@ sal_Int32 SwHTMLParser::StripTrailingLF()
 {
     sal_Int32 nStripped = 0;
 
+    if (IsReqIF())
+    {
+        // One <br> is exactly one line-break in the ReqIF case.
+        return nStripped;
+    }
+
     const sal_Int32 nLen = m_pPam->GetPoint()->nContent.GetIndex();
     if( nLen )
     {

Reply via email to