sw/qa/extras/odfexport/data/ruby+hyperlink.fodt |   22 ++++++++++++++++++++++
 sw/qa/extras/odfexport/odfexport4.cxx           |   17 +++++++++++++++++
 xmloff/source/text/txtparae.cxx                 |    9 +++++++++
 3 files changed, 48 insertions(+)

New commits:
commit e8bb0ffb658b8f2567a6eb93dfbca2670b18a673
Author:     Mike Kaganski <[email protected]>
AuthorDate: Sun Oct 12 16:55:00 2025 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sun Oct 12 20:15:11 2025 +0200

    tdf#168817: don't emit hyperlink markup for Ruby portions
    
    It produced incorrect markup like
    
    <text:a ...><text:ruby 
...><text:ruby-base>...</text:a></text:ruby-base><text:ruby-text>...</text:ruby-text></text:ruby>
    
    after commit c50fbdceafdd4b857954f098e38cae03e8bc6064 (tdf#148198: merge
    identical hyperlinks of adjacent text ranges on ODF export, 2022-07-18).
    
    Only the inner Text portions need an 'a' element.
    
    Change-Id: Ia5a0b671b5d454b0e9d4dab0295b57249db9f4dd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192249
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sw/qa/extras/odfexport/data/ruby+hyperlink.fodt 
b/sw/qa/extras/odfexport/data/ruby+hyperlink.fodt
new file mode 100644
index 000000000000..88048e97c6f1
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/ruby+hyperlink.fodt
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+  <style:style style:name="Rubies" style:family="text">
+   <style:text-properties fo:font-size="6pt" style:text-underline-style="none" 
style:font-size-asian="6pt" style:font-size-complex="6pt" 
style:text-emphasize="none"/>
+  </style:style>
+  <style:style style:name="Internet_20_link" style:display-name="Internet 
link" style:family="text">
+   <style:text-properties fo:color="#000080" 
style:text-underline-style="solid" style:text-underline-width="auto" 
style:text-underline-color="font-color"/>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="Ru1" style:family="ruby">
+   <style:ruby-properties style:ruby-align="left" style:ruby-position="above"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <text:p><text:ruby text:style-name="Ru1"><text:ruby-base><text:a 
xlink:type="simple" xlink:href="https://en.wiktionary.org/wiki/一日#Japanese"; 
text:style-name="Internet_20_link" 
text:visited-style-name="Visited_20_Internet_20_Link">一日</text:a></text:ruby-base><text:ruby-text>ついたち</text:ruby-text></text:ruby></text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/odfexport/odfexport4.cxx 
b/sw/qa/extras/odfexport/odfexport4.cxx
index 98c607cad9f6..a978447b0914 100644
--- a/sw/qa/extras/odfexport/odfexport4.cxx
+++ b/sw/qa/extras/odfexport/odfexport4.cxx
@@ -1556,6 +1556,23 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf166011ee)
                 u"latin");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf168817)
+{
+    // A ruby text with a hyperlink
+    // Without the fix, it failed an assertion on save, and produced invalid 
XML that couldn't load
+    loadAndReload("ruby+hyperlink.fodt");
+    xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
+    // Check that only one instance of respective elements are produced
+    assertXPath(pXmlDoc, "//text:p", 1);
+    assertXPath(pXmlDoc, "//text:ruby", 1);
+    assertXPath(pXmlDoc, "//text:a", 1);
+    // Check the generated markup
+    assertXPath(pXmlDoc, "//text:p/text:ruby/text:ruby-base/text:a", "href",
+                u"https://en.wiktionary.org/wiki/一日#Japanese";);
+    assertXPathContent(pXmlDoc, "//text:p/text:ruby/text:ruby-base/text:a", 
u"一日");
+    assertXPathContent(pXmlDoc, "//text:p/text:ruby/text:ruby-text", u"ついたち");
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index 331fb6aba408..28295dbce90e 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -300,6 +300,15 @@ namespace
     {
         const css::uno::Reference<css::beans::XPropertyState> 
xPropState(rPropSet, UNO_QUERY);
         const auto xPropSetInfo(rPropSet->getPropertySetInfo());
+
+        if (xPropSetInfo->hasPropertyByName(gsTextPortionType))
+        {
+            // No hyperlink for Ruby portions; the hyperlink will be added for 
their inner Text
+            if (OUString type;
+                (rPropSet->getPropertyValue(gsTextPortionType) >>= type) && 
type == gsRuby)
+                return;
+        }
+
         if (xPropSetInfo->hasPropertyByName(gsHyperLinkURL)
             && (!xPropState.is()
                 || PropertyState_DIRECT_VALUE == 
xPropState->getPropertyState(gsHyperLinkURL)))

Reply via email to