From: Thibaut Cuvelier Date: Fri, 1 Apr 2022 19:15:13 +0000 (+0200) Subject: XHTML tables: fix borders and implement booktabs. X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=544adb065b89afa27002dc8b391ee7c907e200ac;p=features.git XHTML tables: fix borders and implement booktabs. https://www.lyx.org/trac/ticket/10154 Contributed by raccoon. --- diff --git a/autotests/export/xhtml/table_borders.lyx b/autotests/export/xhtml/table_borders.lyx new file mode 100644 index 0000000000..7b59f5fe11 --- /dev/null +++ b/autotests/export/xhtml/table_borders.lyx @@ -0,0 +1,235 @@ +#LyX 2.4 created this file. For more info see https://www.lyx.org/ +\lyxformat 609 +\begin_document +\begin_header +\save_transient_properties true +\origin unavailable +\textclass scrbook +\begin_preamble +% Added by lyx2lyx +\setlength{\parskip}{\medskipamount} +\setlength{\parindent}{0pt} +\end_preamble +\use_default_options true +\maintain_unincluded_children no +\language ngerman +\language_package default +\inputencoding auto-legacy +\fontencoding auto +\font_roman "lmodern" "default" +\font_sans "lmss" "default" +\font_typewriter "lmtt" "default" +\font_math "auto" "auto" +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_roman_osf false +\font_sans_osf false +\font_typewriter_osf false +\font_sf_scale 100 100 +\font_tt_scale 100 100 +\use_microtype false +\use_dash_ligatures true +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\spacing single +\use_hyperref false +\papersize default +\use_geometry false +\use_package amsmath 1 +\use_package amssymb 1 +\use_package cancel 1 +\use_package esint 1 +\use_package mathdots 0 +\use_package mathtools 0 +\use_package mhchem 1 +\use_package stackrel 1 +\use_package stmaryrd 1 +\use_package undertilde 0 +\cite_engine basic +\cite_engine_type default +\biblio_style plain +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\justification true +\use_refstyle 0 +\use_minted 0 +\use_lineno 0 +\branch Test +\selected 1 +\filename_suffix 0 +\color #e9c792 #16386d +\end_branch +\index Stichwortverzeichnis +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\is_math_indent 0 +\math_numbering_side default +\quotes_style english +\dynamic_quotes 0 +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tablestyle default +\tracking_changes false +\output_changes false +\change_bars false +\postpone_fragile_content false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\docbook_table_output 0 +\docbook_mathml_prefix 1 +\html_latex_start +\html_latex_end +\end_header + +\begin_body + +\begin_layout Title +Check HTML export +\end_layout + +\begin_layout Standard +\begin_inset Tabular + + + + + + + +\begin_inset Text + +\begin_layout Plain Layout +a +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +d +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +s +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout + +\end_layout + +\end_inset + + + + +\end_inset + + +\end_layout + +\end_body +\end_document diff --git a/autotests/export/xhtml/table_borders.xhtml b/autotests/export/xhtml/table_borders.xhtml new file mode 100644 index 0000000000..7e0602e22d --- /dev/null +++ b/autotests/export/xhtml/table_borders.xhtml @@ -0,0 +1,91 @@ + + + + + + +Check HTML export + + + +

Check HTML export

+
+

1 here

+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
a
+
d
+
s
+
+ + +
+ + +
+ + +
+
+
+ + diff --git a/lib/layouts/stdinsets.inc b/lib/layouts/stdinsets.inc index 32a0af3996..074b2748d5 100644 --- a/lib/layouts/stdinsets.inc +++ b/lib/layouts/stdinsets.inc @@ -776,7 +776,6 @@ InsetLayout Tabular display: inline-block; } td { - border: 1px solid black; padding: 0.5ex; } EndHTMLStyle diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 0832054bc3..478ecf1fa6 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -3654,6 +3654,77 @@ std::string Tabular::getHAlignAsXmlAttribute(idx_type cell, bool is_xhtml) const } } +Tabular::XmlRowWiseBorders Tabular::computeXmlBorders(row_type row) const +{ + Tabular::XmlRowWiseBorders borders; + + // Determine whether borders are required. + for (col_type c = 0; c < ncols(); ++c) { + if (row < nrows() - 1) { + if (!bottomLine(cellIndex(row, c)) + || !topLine(cellIndex(row + 1, c))) { + borders.completeBorder = false; + } + if (!bottomLine(cellIndex(row, c)) + && !topLine(cellIndex(row + 1, c))) { + borders.completeBorderBelow = false; + } + } else if (row == nrows() - 1 && !bottomLine(cellIndex(row, c))) { + borders.completeBorderBelow = false; + } + + if ((row > 0 && !bottomLine(cellIndex(row - 1, c)) && !topLine(cellIndex(row, c))) || + (row == 0 && !topLine(cellIndex(row, c)))) { + borders.completeBorderAbove = false; + } + } + + // Size of booktabs borders. + if (use_booktabs) { + if (borders.completeBorderAbove) + borders.borderTopWidth = row == 0 ? 2 : 1.5; + if (borders.completeBorderBelow) { + borders.borderBottomWidth = row == nrows() - 1 ? 2 : 1.5; + borders.borderBottomWidthComplete = 3 * borders.borderBottomWidth; + } + } + + return borders; +} + + +std::vector Tabular::computeCssStylePerCell(row_type row, col_type col, idx_type cell) const +{ + std::vector styles; + + // Fixed width. + Length const col_width = column_info[col].p_width; + if (!col_width.zero()) + styles.emplace_back("width: " + col_width.asHTMLString()); + + // Borders and booktabs. + const Tabular::XmlRowWiseBorders borders = computeXmlBorders(row); + + if (bottomLine(cell)) { + if (row < nrows() - 1 && borders.completeBorder) + styles.emplace_back("border-bottom: " + to_string(borders.borderBottomWidthComplete) + "px double"); + else + styles.emplace_back("border-bottom: " + to_string(borders.borderBottomWidth) + "px solid"); + } + if (rightLine(cell)) { + if (col < ncols() - 1 && leftLine(cell + 1)) + styles.emplace_back("border-right: 3px double"); + else + styles.emplace_back("border-right: 1px solid"); + } + if (leftLine(cell)) + styles.emplace_back("border-left: 1px solid"); + if (topLine(cell)) + styles.emplace_back("border-top: " + to_string(borders.borderTopWidth) + "px solid"); + + return styles; +} + docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & runparams, bool header, bool is_xhtml, BufferParams::TableOutput docbook_table_output) const @@ -3663,22 +3734,26 @@ docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & run std::string const row_tag = is_xhtml_table ? "tr" : "row"; std::string const cell_tag = is_xhtml_table ? (header ? "th" : "td") : "entry"; + Tabular::XmlRowWiseBorders const borders = computeXmlBorders(row); idx_type cell = getFirstCellInRow(row); xs << xml::StartTag(row_tag); xs << xml::CR(); - for (col_type c = 0; c < ncols(); ++c) { + for (col_type c = 0; c < ncols(); ++c, ++cell) { if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c)) continue; stringstream attr; if (is_xhtml_table) { - Length const cwidth = column_info[c].p_width; - if (!cwidth.zero()) { - string const hwidth = cwidth.asHTMLString(); - attr << "style='width: " << hwidth << ";' "; - } + const std::vector styles = computeCssStylePerCell(row, c, cell); + attr << "style='" ; + for (auto it = styles.begin(); it != styles.end(); ++it) { + attr << *it; + if (it != styles.end() - 1) + attr << "; "; + } + attr << "' "; } attr << getHAlignAsXmlAttribute(cell, false) << " " << getVAlignAsXmlAttribute(cell); @@ -3707,7 +3782,6 @@ docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & run } xs << xml::EndTag(cell_tag); xs << xml::CR(); - ++cell; } xs << xml::EndTag(row_tag); xs << xml::CR(); diff --git a/src/insets/InsetTabular.h b/src/insets/InsetTabular.h index 8a99ef4086..0fbafa8ede 100644 --- a/src/insets/InsetTabular.h +++ b/src/insets/InsetTabular.h @@ -850,6 +850,24 @@ public: /// typedef std::vector column_vector; +private: + // Determines the style of borders, per row. + class XmlRowWiseBorders { + public: + // Whether to draw double bottom line. + bool completeBorder = true; + + // Whether to draw booktabs' thicker lines. + bool completeBorderAbove = true; + bool completeBorderBelow = true; + + // Size of the borders. + double borderBottomWidth = 1.0; + double borderBottomWidthComplete = 3.0; + double borderTopWidth = 1.0; + }; + +public: /// idx_type numberofcells; /// @@ -939,6 +957,8 @@ public: docstring xmlRow(XMLStream & xs, row_type row, OutputParams const &, bool header = false, bool is_xhtml = true, BufferParams::TableOutput docbook_table_output = BufferParams::TableOutput::HTMLTable) const; + XmlRowWiseBorders computeXmlBorders(row_type row) const; + std::vector computeCssStylePerCell(row_type row, col_type col, idx_type cell) const; /// Transforms the vertical alignment of the given cell as a prebaked XML attribute (for HTML and CALS). std::string getHAlignAsXmlAttribute(idx_type cell, bool is_xhtml = true) const;