diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-01-12 13:57:16 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2023-01-13 07:36:45 +0000 |
commit | ddf4ff31f075e00ca4cbb623b596eabf62ab4758 (patch) | |
tree | f90e66b7e2af79922a4219f77c7a076941b1b855 /sw/source | |
parent | c8851caa9bc3fe7965cbf4a19662d14e9f61eb42 (diff) |
sw HTML export: fix invalid HTML when all cells of a row have the same rowspan
The bugdoc has a table with 2 columns and 2 rows, but both the A1 and
the A2 cell has rowspan=2, so there are only covered cells in the second
row. It seems there is no valid HTML markup to express this Writer doc
model.
What HTML seems to suggest instead is to simply decrease the amount of
rowspan attribute values and then the empty <tr> elements can be simply
skipped.
This fixes the
Row 2 of a row group established by a tbody element has no cells beginning on it.
from the w3c HTML validator.
Note that you can't create such problematic tables on the UI: the UI
will delete the row only containing covered cells for you when the last
cell gets merged. Such documents can be created by importers, though.
Change-Id: Ice4fa3636e8b780d374f3d319b198aaaada9f5e0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145402
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
(cherry picked from commit a2fb3a135425bbc14375e1edfcc1e09a41d760f9)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145434
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'sw/source')
-rw-r--r-- | sw/source/filter/html/htmltabw.cxx | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/sw/source/filter/html/htmltabw.cxx b/sw/source/filter/html/htmltabw.cxx index 43e9ebf97328..ddb8c8eb5f10 100644 --- a/sw/source/filter/html/htmltabw.cxx +++ b/sw/source/filter/html/htmltabw.cxx @@ -63,12 +63,20 @@ class SwHTMLWrtTable : public SwWriteTable static void Pixelize( sal_uInt16& rValue ); void PixelizeBorders(); + /// Writes a single table cell. + /// + /// bCellRowSpan decides if the cell's row span should be written or not. void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const; + bool bOutVAlign, + bool bCellRowSpan ) const; + /// Writes a single table row. + /// + /// rSkipRows decides if the next N rows should be skipped or written. void OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const; + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const; virtual bool ShouldExpandSub( const SwTableBox *pBox, bool bExpandedBefore, sal_uInt16 nDepth ) const override; @@ -254,7 +262,8 @@ bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox, // Write a box as single cell void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const + bool bOutVAlign, + bool bCellRowSpan ) const { const SwTableBox *pBox = pCell->GetBox(); sal_uInt16 nRow = pCell->GetRow(); @@ -307,7 +316,7 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, sOut.append(rWrt.GetNamespace() + aTag); // output ROW- and COLSPAN - if( nRowSpan>1 ) + if (nRowSpan > 1 && bCellRowSpan) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan "=\"" + OString::number(nRowSpan) + "\""); @@ -505,7 +514,8 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, // output a line as lines void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const { // If the line contains more the one cell and all cells have the same // alignment, then output the VALIGN at the line instead of the cell. @@ -556,9 +566,26 @@ void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, rWrt.IncIndentLevel(); // indent content of <TR>...</TR> + bool bCellRowSpan = true; + if (!rCells.empty() && rCells[0]->GetRowSpan() > 1) + { + // Skip the rowspan attrs of <td> elements if they are the same for every cell of this row. + bCellRowSpan = std::adjacent_find(rCells.begin(), rCells.end(), + [](const std::unique_ptr<SwWriteTableCell>& pA, + const std::unique_ptr<SwWriteTableCell>& pB) + { return pA->GetRowSpan() != pB->GetRowSpan(); }) + != rCells.end(); + if (!bCellRowSpan) + { + // If no rowspan is written, then skip rows which would only contain covered cells, but + // not the current row. + rSkipRows = rCells[0]->GetRowSpan() - 1; + } + } + for (const auto &rpCell : rCells) { - OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri); + OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri, bCellRowSpan); } rWrt.DecIndentLevel(); // indent content of <TR>...</TR> @@ -824,11 +851,19 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA> } + sal_uInt16 nSkipRows = 0; for( SwWriteTableRows::size_type nRow = 0; nRow < m_aRows.size(); ++nRow ) { const SwWriteTableRow *pRow2 = m_aRows[nRow].get(); - OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() ); + if (nSkipRows == 0) + { + OutTableCells(rWrt, pRow2->GetCells(), pRow2->GetBackground(), nSkipRows); + } + else + { + --nSkipRows; + } if( !m_nCellSpacing && nRow < m_aRows.size()-1 && pRow2->m_bBottomBorder && pRow2->m_nBottomBorder > SvxBorderLineWidth::Thin ) { |