From e7c088199206d3815670e2f92a1ff069ddabb0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20B?= <2589111+jfbu@users.noreply.github.com> Date: Wed, 12 Oct 2022 17:15:40 +0200 Subject: [PATCH] LaTeX: support for booktabs-style and zebra-striped tables (#10759) This is a combination of 2 + 28 + 7 + and some more commits... * Cherry-pick: Add support for booktabs-style tables to LaTeX builder * Cherry-pick: Add support for zebra-striped tables to LaTeX builder Co-authored-by: Stefan Wiehler Above work originally initiated by @sephalon (thanks!) Development refactored and continued by @jfbu * latex_table_style configuration, support booktabs, colorrows, borderless Some details: - Simplify a bit a conditional in the longtable template This also puts the target for a longtable with a label but no caption above the toprule for better hyperlinking (testing shows hyperlink target can not end up alone at bottom of previous page). - Extend allowed syntax for colour assignments via 'sphinxsetup' - latex_table_style new configuration value and coloured rows For the user interface I tried to look for inspiration in https://docutils.sourceforge.io/docs/user/config.html#table-style which mentions booktabs and borderless. They also mention captionbelow which we can implement later, now that architecture is here. They don't mention coloured rows. - Test on our own document... looks fine! - Work-around an incompatibility of \cline with row colours - Reverse priority of classes to allow overruling booktabs by standard after parsing source but before letting LaTeX writer act - Closes #8220 Commit https://github.com/sphinx-doc/sphinx/commit/bb859c669679baebd8cc8d10c99382478c0d1647 already improved a bit, this finishes it (as :rst:dir:`rst-class` was actually not linking to anywhere). - Let booktabs style defaults to *not* using \cmidrule. They actually don't make much sense there, as all \hline's are removed. - Add \sphinxnorowcolor which allows construct such as this one in a tabularcolumns directive: >{\columncolor{blue}\sphinxnorowcolor} else LaTeX always overrides column colour by row colour - Add TableMergeColorHeader, TableMergeColorOdd, TableMergeColorEven so single-row merged cells can be styled especially - Extend row colours to all header rows not only the first one (all header rows will share same colour settings) - Auto-adjust to a no '|'-colspec for optimal handling of merged cell - Add \sphinxcolorblend - Workaround LaTeX's \cline features and other grid tables matters - Add \sphinxbuildwarning for important warnings - Fix some white gaps in merged cells of tables with vlines and colorrows - Work around LaTeX's \cline serious deficiencies for complex grid tables This commit corrects \cline badly impacting vertical spacing and making tables look even more cramped as they usually are in LaTeX (although one sees it clearly only with \arrarrulewidth a bit more than the LaTeX default of 0.4pt). Most importantly this commit solves the problem that \cline's got masked by colour panels from the row below. - Update CHANGES for PR #10759 - Improve documentation of new latex_table_style regarding colours --- CHANGES | 2 + doc/conf.py | 3 +- doc/extdev/deprecated.rst | 4 +- doc/latex.rst | 70 +- doc/usage/configuration.rst | 95 ++ doc/usage/restructuredtext/basics.rst | 17 +- doc/usage/restructuredtext/directives.rst | 147 ++- doc/usage/theming.rst | 2 +- sphinx/builders/latex/__init__.py | 4 + sphinx/templates/latex/latex.tex_t | 9 + sphinx/templates/latex/longtable.tex_t | 64 +- sphinx/templates/latex/tabular.tex_t | 35 +- sphinx/templates/latex/tabulary.tex_t | 35 +- sphinx/texinputs/sphinx.sty | 152 +++- sphinx/texinputs/sphinxlatexstyleheadings.sty | 3 +- sphinx/texinputs/sphinxlatextables.sty | 835 +++++++++++++++++- sphinx/texinputs/sphinxpackagefootnote.sty | 3 +- sphinx/writers/latex.py | 96 +- tests/roots/test-latex-table/complex.rst | 23 + .../expects/complex_spanning_cell.tex | 14 +- .../test-latex-table/expects/gridtable.tex | 19 +- .../expects/gridtable_with_tabularcolumn.tex | 73 ++ .../test-latex-table/expects/longtable.tex | 37 +- .../expects/longtable_having_align.tex | 36 +- .../expects/longtable_having_caption.tex | 36 +- .../longtable_having_problematic_cell.tex | 36 +- ...ving_stub_columns_and_problematic_cell.tex | 34 +- .../expects/longtable_having_verbatim.tex | 36 +- .../expects/longtable_having_widths.tex | 37 +- ...ble_having_widths_and_problematic_cell.tex | 36 +- .../expects/longtable_with_tabularcolumn.tex | 37 +- .../test-latex-table/expects/simple_table.tex | 14 +- .../expects/table_having_caption.tex | 14 +- .../expects/table_having_problematic_cell.tex | 14 +- ...ving_stub_columns_and_problematic_cell.tex | 12 +- ...ving_threeparagraphs_cell_in_first_col.tex | 10 +- .../expects/table_having_verbatim.tex | 14 +- .../expects/table_having_widths.tex | 18 +- ...ble_having_widths_and_problematic_cell.tex | 14 +- .../expects/tabular_having_widths.tex | 14 +- .../expects/tabularcolumn.tex | 17 +- .../expects/tabulary_having_widths.tex | 14 +- tests/roots/test-latex-table/longtable.rst | 2 +- tests/roots/test-latex-table/tabular.rst | 3 +- tests/test_build_latex.py | 42 +- 45 files changed, 1815 insertions(+), 417 deletions(-) create mode 100644 tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex diff --git a/CHANGES b/CHANGES index 4371efa40d4..19d58edb729 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Deprecated Features added -------------- +* #10759: LaTeX: add :confval:`latex_table_style` and support the + ``'booktabs'``, ``'borderless'``, and ``'colorrows'`` styles. * #10840: One can cross-reference including an option value like ``:option:`--module=foobar```, ``:option:`--module[=foobar]``` or ``:option:`--module foobar```. Patch by Martin Liska. diff --git a/doc/conf.py b/doc/conf.py index eafa42a7d1a..fc7959d4dca 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -78,7 +78,7 @@ {\begin{sphinxtheindex}\end{sphinxtheindex}} ''', 'sphinxsetup': """% -VerbatimColor={RGB}{242,242,242},% +VerbatimColor=black!5,% tests 5.2.0 extended syntax VerbatimBorderColor={RGB}{32,32,32},% pre_border-radius=3pt,% pre_box-decoration-break=slice,% @@ -86,6 +86,7 @@ } latex_show_urls = 'footnote' latex_use_xindy = True +latex_table_style = ['booktabs', 'colorrows'] autodoc_member_order = 'groupwise' autosummary_generate = False diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 8c850ceb6b4..1692f2d4ec3 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -10,7 +10,7 @@ major versions (for more details, please see :ref:`deprecation-policy`). The following is a list of deprecated interfaces. -.. tabularcolumns:: |>{\raggedright}\Y{.4}|>{\centering}\Y{.1}|>{\centering}\Y{.12}|>{\raggedright\arraybackslash}\Y{.38}| +.. tabularcolumns:: >{\raggedright}\Y{.4}>{\centering}\Y{.1}>{\sphinxcolorblend{!95!red}\centering\noindent\bfseries\color{red}}\Y{.12}>{\raggedright\arraybackslash}\Y{.38} .. list-table:: deprecated APIs :header-rows: 1 @@ -19,7 +19,7 @@ The following is a list of deprecated interfaces. * - Target - Deprecated - - (will be) Removed + - Removed - Alternatives * - HTML 4 support diff --git a/doc/latex.rst b/doc/latex.rst index ae8c256cbdc..e467ac4e9a8 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -823,16 +823,31 @@ Do not use quotes to enclose values, whether numerical or strings. definition of the continuation symbol was changed at 1.5 to accommodate various font sizes (e.g. code-blocks can be in footnotes). +.. note:: + + Values for colour keys must either: + + - obey the syntax of the ``\definecolor`` LaTeX command, e.g. something + such as ``VerbatimColor={rgb}{0.2,0.3,0.5}`` or ``{RGB}{37,23,255}`` or + ``{gray}{0.75}`` or (only with package ``xcolor``) ``{HTML}{808080}`` or + ... + + - or obey the syntax of the ``\colorlet`` command from package ``xcolor`` + (which then must exist in the LaTeX installation), + e.g. ``VerbatimColor=red!10`` or ``red!50!green`` or ``-red!75`` or + ``MyPreviouslyDefinedColour`` or... Refer to xcolor_ documentation for + this syntax. + + .. _xcolor: https://ctan.org/pkg/xcolor + + .. versionchanged:: 5.2.0 + Formerly only the ``\definecolor`` syntax was accepted. + ``TitleColor`` The colour for titles (as configured via use of package "titlesec".) Default: ``{rgb}{0.126,0.263,0.361}`` - .. warning:: - - Colours set via ``'sphinxsetup'`` must obey the syntax of the - argument of the ``color/xcolor`` packages ``\definecolor`` command. - ``InnerLinkColor`` A colour passed to ``hyperref`` as value of ``linkcolor`` and ``citecolor``. @@ -862,10 +877,47 @@ Do not use quotes to enclose values, whether numerical or strings. .. versionadded:: 1.6.6 - .. note:: +.. _tablecolors: + +``TableRowColorHeader`` + Sets the background colour for (all) the header rows of tables. + + It will have an effect only if either the :confval:`latex_table_style` + contains ``'colorrows'`` or if the table is assigned the ``colorrows`` + class. It is ignored for tables with ``nocolorrows`` class. - Starting with this colour, and for all others following, the - names declared to "color" or "xcolor" are prefixed with "sphinx". + As for the other ``'sphinxsetup'`` keys, it can also be set or modified + from a ``\sphinxsetup{...}`` LaTeX command inserted via the :dudir:`raw` + directive, or also from a LaTeX environment associated to a `container + class `_ and using such ``\sphinxsetup{...}``. + + Default: ``{gray}{0.86}`` + + There is also ``TableMergeColorHeader``. If used, sets a specific colour + for merged single-row cells in the header. + + .. versionadded:: 5.2.0 + +``TableRowColorOdd`` + Sets the background colour for odd rows in tables (the row count starts at + ``1`` at the first non-header row). Has an effect only if the + :confval:`latex_table_style` contains ``'colorrows'`` or for specific + tables assigned the ``colorrows`` class. + + Default: ``{gray}{0.92}`` + + There is also ``TableMergeColorOdd``. + + .. versionadded:: 5.2.0 + +``TableRowColorEven`` + Sets the background colour for even rows in tables. + + Default ``{gray}{0.98}`` + + There is also ``TableMergeColorEven``. + + .. versionadded:: 5.2.0 ``verbatimsep`` The separation between code lines and the frame. @@ -1425,6 +1477,8 @@ Miscellany Formerly, use of *fncychap* with other styles than ``Bjarne`` was dysfunctional. +.. _latexcontainer: + - Docutils :dudir:`container` directives are supported in LaTeX output: to let a container class with name ``foo`` influence the final PDF via LaTeX, it is only needed to define in the preamble an environment diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 906827ff32e..b2196a9e5af 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -2233,6 +2233,101 @@ These options influence LaTeX output. .. versionadded:: 1.6 +.. confval:: latex_table_style + + A list of styling classes (strings). Currently supported: + + - ``'booktabs'``: no vertical lines, and only 2 or 3 horizontal lines (the + latter if there is a header), using the booktabs_ package. + + - ``'borderless'``: no lines whatsoever. + + - ``'colorrows'``: the table rows are rendered with alternating background + colours. The interface to customize them is via :ref:`dedicated keys + ` of :ref:`latexsphinxsetup`. + + .. important:: + + With the ``'colorrows'`` style, the ``\rowcolors`` LaTeX command + becomes a no-op (this command has limitations and has never correctly + supported all types of tables Sphinx produces in LaTeX). Please + update your project to use instead + the :ref:`latex table color configuration ` keys. + + Default: ``[]`` + + .. versionadded:: 5.2.0 + + If using ``'booktabs'`` or ``'borderless'`` it seems recommended to also + opt for ``'colorrows'``... + + Each table can override the global style via ``:class:`` option, or + ``.. rst-class::`` for no-directive tables (cf. :ref:`table-directives`). + Currently recognized classes are ``booktabs``, ``borderless``, + ``standard``, ``colorrows``, ``nocolorrows``. The latter two can be + combined with any of the first three. The ``standard`` class produces + tables with both horizontal and vertical lines (as has been the default so + far with Sphinx). + + A single-row multi-column merged cell will obey the row colour, if it is + set. See also ``TableMergeColor{Header,Odd,Even}`` in the + :ref:`latexsphinxsetup` section. + + .. note:: + + - It is hard-coded in LaTeX that a single cell will obey the row colour + even if there is a column colour set via ``\columncolor`` from a + column specification (see :rst:dir:`tabularcolumns`). Sphinx provides + ``\sphinxnorowcolor`` which can be used like this: + + .. code-block:: latex + + >{\columncolor{blue}\sphinxnorowcolor} + + in a table column specification. + + - Sphinx also provides ``\sphinxcolorblend`` which however requires the + xcolor_ package. Here is an example: + + .. code-block:: latex + + >{\sphinxcolorblend{!95!red}} + + It means that in this column, the row colours will be slightly tinted + by red; refer to xcolor_ documentation for more on the syntax of its + ``\blendcolors`` command (a ``\blendcolors`` in place of + ``\sphinxcolorblend`` would modify colours of the cell *contents*, not + of the cell *background colour panel*...). You can find an example of + usage in the :ref:`dev-deprecated-apis` section of this document in + PDF format. + + .. hint:: + + If you want to use a special colour for the *contents* of the + cells of a given column use ``>{\noindent\color{}}``, + possibly in addition to the above. + + - Multi-row merged cells, whether single column or multi-column + currently ignore any set column, row, or cell colour. + + - It is possible for a simple cell to set a custom colour via the + :dudir:`raw` directive and the ``\cellcolor`` LaTeX command used + anywhere in the cell contents. This currently is without effect + in a merged cell, whatever its kind. + + .. hint:: + + In a document not using ``'booktabs'`` globally, it is possible to style + an individual table via the ``booktabs`` class, but it will be necessary + to add ``r'\usepackage{booktabs}'`` to the LaTeX preamble. + + On the other hand one can use ``colorrows`` class for individual tables + with no extra package (as Sphinx since 5.2.0 always loads colortbl_). + + .. _booktabs: https://ctan.org/pkg/booktabs + .. _colortbl: https://ctan.org/pkg/colortbl + .. _xcolor: https://ctan.org/pkg/xcolor + .. confval:: latex_use_xindy If ``True``, the PDF build from the LaTeX files created by Sphinx diff --git a/doc/usage/restructuredtext/basics.rst b/doc/usage/restructuredtext/basics.rst index c846dc145f6..824b59ee2c2 100644 --- a/doc/usage/restructuredtext/basics.rst +++ b/doc/usage/restructuredtext/basics.rst @@ -370,7 +370,15 @@ Docutils supports the following directives: - :dudir:`include` (include reStructuredText from another file) -- in Sphinx, when given an absolute include file path, this directive takes it as relative to the source directory - - :dudir:`class` (assign a class attribute to the next element) [1]_ + + .. _rstclass: + + - :dudir:`class` (assign a class attribute to the next element) + + .. note:: + + When the default domain contains a ``class`` directive, this directive + will be shadowed. Therefore, Sphinx re-exports it as ``rst-class``. * HTML specifics: @@ -621,10 +629,3 @@ There are some problems one commonly runs into while authoring reST documents: * **No nested inline markup:** Something like ``*see :func:`foo`*`` is not possible. - - -.. rubric:: Footnotes - -.. [1] When the default domain contains a :rst:dir:`class` directive, this - directive will be shadowed. Therefore, Sphinx re-exports it as - :rst:dir:`rst-class`. diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index 4029b04e67b..44e4b5ffead 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -371,8 +371,9 @@ units as well as normal text. .. centered:: LICENSE AGREEMENT .. deprecated:: 1.1 - This presentation-only directive is a legacy from older versions. Use a - :rst:dir:`rst-class` directive instead and add an appropriate style. + This presentation-only directive is a legacy from older versions. + Use a :ref:`rst-class ` directive instead and add an + appropriate style. .. rst:directive:: hlist @@ -1045,114 +1046,78 @@ Use :ref:`reStructuredText tables `, i.e. either The :dudir:`table` directive serves as optional wrapper of the *grid* and *simple* syntaxes. -They work fine in HTML output, however there are some gotchas when using tables -in LaTeX: the column width is hard to determine correctly automatically. For -this reason, the following directive exists: +They work fine in HTML output, but rendering tables to LaTeX is complex. +Check the :confval:`latex_table_style`. -.. rst:directive:: .. tabularcolumns:: column spec - - This directive gives a "column spec" for the next table occurring in the - source file. The spec is the second argument to the LaTeX ``tabulary`` - package's environment (which Sphinx uses to translate tables). It can have - values like :: - - |l|l|l| - - which means three left-adjusted, nonbreaking columns. For columns with - longer text that should automatically be broken, use either the standard - ``p{width}`` construct, or tabulary's automatic specifiers: +.. versionchanged:: 1.6 + Merged cells (multi-row, multi-column, both) from grid tables containing + complex contents such as multiple paragraphs, blockquotes, lists, literal + blocks, will render correctly to LaTeX output. - +-----+------------------------------------------+ - |``L``| flush left column with automatic width | - +-----+------------------------------------------+ - |``R``| flush right column with automatic width | - +-----+------------------------------------------+ - |``C``| centered column with automatic width | - +-----+------------------------------------------+ - |``J``| justified column with automatic width | - +-----+------------------------------------------+ +.. rst:directive:: .. tabularcolumns:: column spec - The automatic widths of the ``LRCJ`` columns are attributed by ``tabulary`` - in proportion to the observed shares in a first pass where the table cells - are rendered at their natural "horizontal" widths. + This directive influences only the LaTeX output for the next table in + source. The mandatory argument is a column specification (known as an + "alignment preamble" in LaTeX idiom). Please refer to a LaTeX + documentation, such as the `wiki page`_, for basics of such a column + specification. - By default, Sphinx uses a table layout with ``J`` for every column. + .. _wiki page: https://en.wikibooks.org/wiki/LaTeX/Tables .. versionadded:: 0.3 - .. versionchanged:: 1.6 - Merged cells may now contain multiple paragraphs and are much better - handled, thanks to custom Sphinx LaTeX macros. This novel situation - motivated the switch to ``J`` specifier and not ``L`` by default. - - .. hint:: + .. note:: - Sphinx actually uses ``T`` specifier having done ``\newcolumntype{T}{J}``. - To revert to previous default, insert ``\newcolumntype{T}{L}`` in the - LaTeX preamble (see :confval:`latex_elements`). + :rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table + directives. If both are specified, ``:widths:`` option will be ignored. - A frequent issue with tabulary is that columns with little contents are - "squeezed". The minimal column width is a tabulary parameter called - ``\tymin``. You may set it globally in the LaTeX preamble via - ``\setlength{\tymin}{40pt}`` for example. + Sphinx will render tables with more than 30 rows with ``longtable``. + Besides the ``l``, ``r``, ``c`` and ``p{width}`` column specifiers, one can + also use ``\X{a}{b}`` (new in version 1.5) which configures the column + width to be a fraction ``a/b`` of the total line width and ``\Y{f}`` (new + in version 1.6) where ``f`` is a decimal: for example ``\Y{0.2}`` means that + the column will occupy ``0.2`` times the line width. - Else, use the :rst:dir:`tabularcolumns` directive with an explicit - ``p{40pt}`` (for example) for that column. You may use also ``l`` - specifier but this makes the task of setting column widths more difficult - if some merged cell intersects that column. + When this directive is used for a table with at most 30 rows, Sphinx will + render it with ``tabulary``. One can then use specific column types ``L`` + (left), ``R`` (right), ``C`` (centered) and ``J`` (justified). They have + the effect of a ``p{width}`` (i.e. each cell is a LaTeX ``\parbox``) with + the specified internal text alignment and an automatically computed + ``width``. .. warning:: - Tables with more than 30 rows are rendered using ``longtable``, not - ``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ... - specifiers do not work for these tables. - - Tables that contain list-like elements such as object descriptions, - blockquotes or any kind of lists cannot be set out of the box with - ``tabulary``. They are therefore set with the standard LaTeX ``tabular`` - (or ``longtable``) environment if you don't give a ``tabularcolumns`` - directive. If you do, the table will be set with ``tabulary`` but you - must use the ``p{width}`` construct (or Sphinx's ``\X`` and ``\Y`` - specifiers described below) for the columns containing these elements. - - Literal blocks do not work with ``tabulary`` at all, so tables containing - a literal block are always set with ``tabular``. The verbatim environment - used for literal blocks only works in ``p{width}`` (and ``\X`` or ``\Y``) - columns, hence Sphinx generates such column specs for tables containing - literal blocks. - - Since Sphinx 1.5, the ``\X{a}{b}`` specifier is used (there *is* a backslash - in the specifier letter). It is like ``p{width}`` with the width set to a - fraction ``a/b`` of the current line width. You can use it in the - :rst:dir:`tabularcolumns` (it is not a problem if some LaTeX macro is also - called ``\X``.) - - It is *not* needed for ``b`` to be the total number of columns, nor for the - sum of the fractions of the ``\X`` specifiers to add up to one. For example - ``|\X{2}{5}|\X{1}{5}|\X{1}{5}|`` is legitimate and the table will occupy - 80% of the line width, the first of its three columns having the same width - as the sum of the next two. - - This is used by the ``:widths:`` option of the :dudir:`table` directive. - - Since Sphinx 1.6, there is also the ``\Y{f}`` specifier which admits a - decimal argument, such has ``\Y{0.15}``: this would have the same effect as - ``\X{3}{20}``. + - Cells that contain list-like elements such as object descriptions, + blockquotes or any kind of lists are not compatible with the ``LRCJ`` + column types. The column type must then be some ``p{width}`` with an + explicit ``width`` (or ``\X{a}{b}`` or ``\Y{f}``). - .. versionchanged:: 1.6 + - Literal blocks do not work with ``tabulary`` at all. Sphinx will + fall back to ``tabular`` or ``longtable`` environments and generate a + suitable column specification. - Merged cells from complex grid tables (either multi-row, multi-column, or - both) now allow blockquotes, lists, literal blocks, ... as do regular - cells. +In absence of the :rst:dir:`tabularcolumns` directive, and for a table with at +most 30 rows and no problematic cells as described in the above warning, +Sphinx uses ``tabulary`` and the ``J`` column-type for every column. - Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, - ``\Y{f}`` and tabulary's columns. +.. versionchanged:: 1.6 - .. note:: + Formerly, the ``L`` column-type was used (text is flushed-left). To revert + to this, include ``\newcolumntype{T}{L}`` in the LaTeX preamble, as in fact + Sphinx uses ``T`` and sets it by default to be an alias of ``J``. - :rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table - directives. If both are specified, ``:widths:`` option will be ignored. +.. hint:: + + A frequent issue with ``tabulary`` is that columns with little contents + appear to be "squeezed". One can add to the LaTeX preamble for example + ``\setlength{\tymin}{40pt}`` to ensure a minimal column width of ``40pt``, + the ``tabulary`` default of ``10pt`` being too small. + +.. hint:: + To force usage of the LaTeX ``longtable`` environment pass ``longtable`` as + a ``:class:`` option to :dudir:`table`, :dudir:`csv-table`, or + :dudir:`list-table`. Use :ref:`rst-class ` for other tables. Math ---- diff --git a/doc/usage/theming.rst b/doc/usage/theming.rst index 0e4b4a64dde..c33c7d4770d 100644 --- a/doc/usage/theming.rst +++ b/doc/usage/theming.rst @@ -88,7 +88,7 @@ writing your own themes, refer to :doc:`/development/theming`. Builtin themes ~~~~~~~~~~~~~~ -.. cssclass:: longtable +.. cssclass:: longtable, standard +--------------------+--------------------+ | **Theme overview** | | diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index d07093fd2f0..2979589db98 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -170,6 +170,9 @@ def init_context(self) -> None: self.context.update(self.config.latex_elements) self.context['release'] = self.config.release self.context['use_xindy'] = self.config.latex_use_xindy + self.context['booktabs'] = 'booktabs' in self.config.latex_table_style + self.context['borderless'] = 'borderless' in self.config.latex_table_style + self.context['colorrows'] = 'colorrows' in self.config.latex_table_style if self.config.today: self.context['date'] = self.config.today @@ -524,6 +527,7 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value('latex_show_pagerefs', False, False) app.add_config_value('latex_elements', {}, False) app.add_config_value('latex_additional_files', [], False) + app.add_config_value('latex_table_style', [], False, [list]) app.add_config_value('latex_theme', 'manual', False, [str]) app.add_config_value('latex_theme_options', {}, False) app.add_config_value('latex_theme_path', [], False, [list]) diff --git a/sphinx/templates/latex/latex.tex_t b/sphinx/templates/latex/latex.tex_t index 66408a4c4a5..deb030504db 100644 --- a/sphinx/templates/latex/latex.tex_t +++ b/sphinx/templates/latex/latex.tex_t @@ -25,6 +25,15 @@ %% memoir class requires extra handling \makeatletter\@ifclassloaded{memoir} {\ifdefined\memhyperindexfalse\memhyperindexfalse\fi}{}\makeatother +<% endif %> +<% if booktabs -%> +\PassOptionsToPackage{booktabs}{sphinx} +<% endif -%> +<% if borderless -%> +\PassOptionsToPackage{borderless}{sphinx} +<% endif -%> +<% if colorrows -%> +\PassOptionsToPackage{colorrows}{sphinx} <% endif -%> <%= passoptionstopackages %> \PassOptionsToPackage{warn}{textcomp} diff --git a/sphinx/templates/latex/longtable.tex_t b/sphinx/templates/latex/longtable.tex_t index 8d4cd748c1e..f5cb522cef3 100644 --- a/sphinx/templates/latex/longtable.tex_t +++ b/sphinx/templates/latex/longtable.tex_t @@ -1,4 +1,28 @@ -\begin{savenotes}\sphinxatlongtablestart\begin{longtable} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> +\begin{longtable} <%- if table.align in ('center', 'default') -%> [c] <%- elif table.align == 'left' -%> @@ -10,25 +34,37 @@ <%- if table.caption -%> \sphinxthelongtablecaptionisattop \caption{<%= ''.join(table.caption) %>\strut}<%= labels %>\\*[\sphinxlongtablecapskipadjust] -\hline <% elif labels -%> -\hline\noalign{\phantomsection<%= labels %>}% -<% else -%> -\hline +\noalign{\phantomsection<%= labels %>}% +<% endif -%> +\sphinxtoprule +<%= ''.join(table.header) -%> +<%- if table.header -%> +\sphinxmidrule <% endif -%> -<%= ''.join(table.header) %> \endfirsthead -\multicolumn{<%= table.colcount %>}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} <%= _('continued from previous page') %>}}}\\ -\hline -<%= ''.join(table.header) %> +\multicolumn{<%= table.colcount %>}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} <%= _('continued from previous page') %>}}% +}\\ +\sphinxtoprule +<%= ''.join(table.header) -%> +<%- if table.header -%> +\sphinxmidrule +<% endif -%> \endhead -\hline -\multicolumn{<%= table.colcount %>}{r}{\makebox[0pt][r]{\sphinxtablecontinued{<%= _('continues on next page') %>}}}\\ +\sphinxbottomrule +\multicolumn{<%= table.colcount %>}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{<%= _('continues on next page') %>}}% +}\\ \endfoot \endlastfoot -<%= ''.join(table.body) %> -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxtableatstartofbodyhook +<%= ''.join(table.body) -%> +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/sphinx/templates/latex/tabular.tex_t b/sphinx/templates/latex/tabular.tex_t index a0db7faff1f..0a9310a5ed2 100644 --- a/sphinx/templates/latex/tabular.tex_t +++ b/sphinx/templates/latex/tabular.tex_t @@ -1,4 +1,26 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> <% if table.align -%> <%- if table.align in ('center', 'default') -%> \centering @@ -19,9 +41,14 @@ \phantomsection<%= labels %>\nobreak <% endif -%> \begin{tabular}[t]<%= table.get_colspec() -%> -\hline -<%= ''.join(table.header) %> -<%=- ''.join(table.body) %> +\sphinxtoprule +<%= ''.join(table.header) -%> +<%- if table.header -%> +\sphinxmidrule +<% endif -%> +\sphinxtableatstartofbodyhook +<%=- ''.join(table.body) -%> +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/sphinx/templates/latex/tabulary.tex_t b/sphinx/templates/latex/tabulary.tex_t index 3236b798a52..6ebcec6d264 100644 --- a/sphinx/templates/latex/tabulary.tex_t +++ b/sphinx/templates/latex/tabulary.tex_t @@ -1,4 +1,26 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +<% if 'booktabs' in table.styles -%> +\sphinxthistablewithbooktabsstyle +<% endif -%> +<% if 'borderless' in table.styles -%> +\sphinxthistablewithborderlessstyle +<% endif -%> +<% if 'standard' in table.styles -%> +\sphinxthistablewithstandardstyle +<% endif -%> +<% if 'vlines' in table.styles -%> +\sphinxthistablewithvlinesstyle +<% endif -%> +<% if 'novlines' in table.styles -%> +\sphinxthistablewithnovlinesstyle +<% endif -%> +<% if 'colorrows' in table.styles -%> +\sphinxthistablewithcolorrowsstyle +<% endif -%> +<% if 'nocolorrows' in table.styles -%> +\sphinxthistablewithnocolorrowsstyle +<% endif -%> <% if table.align -%> <%- if table.align in ('center', 'default') -%> \centering @@ -19,9 +41,14 @@ \phantomsection<%= labels %>\nobreak <% endif -%> \begin{tabulary}{\linewidth}[t]<%= table.get_colspec() -%> -\hline -<%= ''.join(table.header) %> -<%=- ''.join(table.body) %> +\sphinxtoprule +<%= ''.join(table.header) -%> +<%- if table.header -%> +\sphinxmidrule +<% endif -%> +\sphinxtableatstartofbodyhook +<%=- ''.join(table.body) -%> +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 8e01c8ac24c..748f8b977b1 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -6,7 +6,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{sphinx}[2022/06/30 v5.1.0 LaTeX package (Sphinx markup)] +\ProvidesPackage{sphinx}[2022/08/15 v5.2.0 LaTeX package (Sphinx markup)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but @@ -17,6 +17,7 @@ %% for deprecation warnings \newcommand\sphinxdeprecationwarning[4]{% #1 the deprecated macro or name, % #2 = when deprecated, #3 = when removed, #4 = additional info + {% limit scope of \spx@tempa, \AtEndDocument works even if nested. \edef\spx@tempa{\detokenize{#1}}% \ltx@ifundefined{sphinx_depr_\spx@tempa}{% \global\expandafter\let\csname sphinx_depr_\spx@tempa\endcsname\spx@tempa @@ -28,7 +29,43 @@ \@spaces- and removed at Sphinx #3.^^J #4^^J****}}% }{% warning already emitted (at end of latex log), don't repeat - }} + }% + }% end of scope limiting group for \spx@tempa +} +%% important build warnings use an undefined reference to induce latexmk +%% into complaining (once per warning) at very end of console output +\newcommand\sphinxbuildwarning[1]{% + \ifcsname sphinx_emitted_#1\endcsname + \else + \global\expandafter\let\csname sphinx_emitted_#1\endcsname\@empty + \AtEndDocument{\hbox{% should the printing of text be made conditional on + % some boolean? + \bfseries\color{red}% + \@nameuse{sphinx_buildwarning_#1}% + % place an undefined reference deliberately + \let\nfss@text\@gobble % no ?? + \ref{!!\@nameuse{sphinx_buildwarning_#1}}% + }}% + \fi +} +\@namedef{sphinx_buildwarning_coloursyntax}{% + The colours whose definition used xcolor syntax were set to white + as xcolor was not found; check the latex log warnings for details} +\@namedef{sphinx_buildwarning_colorblend}{% + Command \string\sphinxcolorblend\space seen but ignored in tables + as xcolor was not found; check the latex log warnings for details} +\@namedef{sphinx_buildwarning_nopict2e}{% + Some radii options for box corners used; they were ignored as pict2e + was not found} +\@namedef{sphinx_buildwarning_badtitlesec}{% + Your system has titlesec version 2.10.1 which causes disappearance + of section numbers; check the latex log warning for details} +\@namedef{sphinx_buildwarning_booktabs}{% + Some tables with booktabs class (check latex log) but booktabs + package not loaded; add its loading to the latex preamble}% +\@namedef{sphinx_buildwarning_badfootnotes}{% + Footnote rendering may have had problems, due to extra package or + document class; check latex log for instructions}% %% OPTION HANDLING @@ -47,16 +84,62 @@ }{ \RequirePackage{color} } -% the \colorlet of xcolor (if at all loaded) is overkill for our use case + +% the \colorlet of xcolor (if at all loaded) is overkill for our internal use \newcommand{\sphinxcolorlet}[2] {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname \csname\@backslashchar color@#2\endcsname } +% (5.2.0) allow colour options to use both the \definecolor and the \colorlet +% syntaxes, for example VerbatimColor={gray}{0.9} or VerbatimColor=red!10 +% In the latter case we need the real \colorlet from xcolor package. +\def\spx@defineorletcolor#1{% + \def\spx@definedcolor{{#1}}% + \futurelet\spx@token\spx@defineorlet} +\def\spx@defineorlet{% + \ifx\spx@token\bgroup + \expandafter\spx@definecolor\else\expandafter\spx@colorlet\fi} +\def\spx@colorlet#1\relax{\expandafter\colorlet\spx@definedcolor{#1}} +\def\spx@definecolor{\expandafter\definecolor\spx@definedcolor} +% +\@ifpackageloaded{xcolor}% + {}% + {% xcolor not loaded because it was not found in the LaTeX installation +\def\spx@colorlet#1\relax{% + \sphinxbuildwarning{coloursyntax}% + \PackageWarning{sphinx}{% +Sorry, the #1 syntax requires package xcolor,\MessageBreak +which was not found on your TeX/LaTeX installation.\MessageBreak +\@spaces\expandafter\@firstofone\spx@definedcolor\MessageBreak +will be set to white}% + \expandafter\definecolor\spx@definedcolor{rgb}{1,1,1}% + }% end of redefinition of \spx@colorlet + }% end of xcolor not found branch + % Handle options via "kvoptions" (later loaded by hyperref anyhow) \RequirePackage{kvoptions} \SetupKeyvalOptions{prefix=spx@opt@} % use \spx@opt@ prefix +% Optional usage of booktabs package for tables +\DeclareBoolOption[false]{booktabs} +\DeclareBoolOption[false]{borderless} +\DeclareBoolOption[true]{booktabscolorgaps} +\DeclareVoidOption{booktabsnogaps}{% + \ifx\@nodocument\relax + % in body + \expandafter\@firstofone + \else + % in preamble, wait for at begin document + \expandafter\AtBeginDocument + \fi + {\ifdefined\abovetopsep % silently do nothing if booktabs not loaded + \abovetopsep\z@\belowrulesep\z@\aboverulesep\z@\belowbottomsep\z@ + \fi + }% +} +% Coloured table rows +\DeclareBoolOption[false]{colorrows} % Sphinx legacy text layout: 1in margins on all four sides \ifx\@jsc@uplatextrue\@undefined \DeclareStringOption[1in]{hmargin} @@ -143,20 +226,42 @@ % same problems as for dimensions: we want the key handler to use \definecolor. % first, some colours with no prefix, for backwards compatibility \newcommand*{\sphinxDeclareColorOption}[2]{% + % set the initial default; only \definecolor syntax for defaults! \definecolor{#1}#2% - \define@key{sphinx}{#1}{\definecolor{#1}##1}% + % set the key handler to accept both \definecolor and \colorlet syntax + \define@key{sphinx}{#1}{\spx@defineorletcolor{#1}##1\relax}% }% \sphinxDeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} \sphinxDeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} \sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} \sphinxDeclareColorOption{VerbatimColor}{{rgb}{1,1,1}} \sphinxDeclareColorOption{VerbatimBorderColor}{{rgb}{0,0,0}} -% now the colours defined with "sphinx" prefix in their names +% all other colours will be named with a "sphinx" prefix \newcommand*{\sphinxDeclareSphinxColorOption}[2]{% - % set the initial default + % set the initial default; only \definecolor syntax for defaults! \definecolor{sphinx#1}#2% - % set the key handler. The "value" ##1 must be acceptable by \definecolor. - \define@key{sphinx}{#1}{\definecolor{sphinx#1}##1}% + % set the key handler to accept both \definecolor and \colorlet syntax + \define@key{sphinx}{#1}{\spx@defineorletcolor{sphinx#1}##1\relax}% +}% +% table row colors +\sphinxDeclareSphinxColorOption{TableRowColorHeader}{{gray}{0.86}} +\sphinxDeclareSphinxColorOption{TableRowColorOdd}{{gray}{0.92}} +\sphinxDeclareSphinxColorOption{TableRowColorEven}{{gray}{0.98}} +% if not set, the "Merge" colour will keep in sync with the "Row" colour +\def\sphinxTableMergeColorHeader{sphinxTableRowColorHeader} +\define@key{sphinx}{TableMergeColorHeader}{% + \spx@defineorletcolor{sphinxTableMergeColorHeader}#1\relax + \def\sphinxTableMergeColorHeader{sphinxTableMergeColorHeader}% +}% +\def\sphinxTableMergeColorOdd{sphinxTableRowColorOdd} +\define@key{sphinx}{TableMergeColorOdd}{% + \spx@defineorletcolor{sphinxTableMergeColorOdd}#1\relax + \def\sphinxTableMergeColorOdd{sphinxTableMergeColorOdd}% +}% +\def\sphinxTableMergeColorEven{sphinxTableRowColorEven} +\define@key{sphinx}{TableMergeColorEven}{% + \spx@defineorletcolor{sphinxTableMergeColorEven}#1\relax + \def\sphinxTableMergeColorEven{sphinxTableMergeColorEven}% }% % Default color chosen to be as in minted.sty LaTeX package! \sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} @@ -292,21 +397,21 @@ \newif\ifspx@pre@withbordercolor \define@key{sphinx}{pre_border-TeXcolor}{% \spx@pre@withbordercolortrue - \definecolor{VerbatimBorderColor}#1% legacy colour name with no sphinx prefix + \spx@defineorletcolor{VerbatimBorderColor}#1\relax } \expandafter\let\expandafter\KV@sphinx@VerbatimBorderColor \csname KV@sphinx@pre_border-TeXcolor\endcsname \newif\ifspx@pre@withbackgroundcolor \define@key{sphinx}{pre_background-TeXcolor}{% \spx@pre@withbackgroundcolortrue - \definecolor{VerbatimColor}#1% legacy colour name with no sphinx prefix + \spx@defineorletcolor{VerbatimColor}#1\relax } \expandafter\let\expandafter\KV@sphinx@VerbatimColor \csname KV@sphinx@pre_background-TeXcolor\endcsname \newif\ifspx@pre@withshadowcolor \define@key{sphinx}{pre_box-shadow-TeXcolor}{% \spx@pre@withshadowcolortrue - \definecolor{sphinxVerbatimShadowColor}#1% + \spx@defineorletcolor{sphinxVerbatimShadowColor}#1\relax } \definecolor{sphinxVerbatimShadowColor}{rgb}{0,0,0} % topics @@ -412,17 +517,17 @@ \newif\ifspx@topic@withbordercolor \define@key{sphinx}{div.topic_border-TeXcolor}{% \spx@topic@withbordercolortrue - \definecolor{sphinxTopicBorderColor}#1% + \spx@defineorletcolor{sphinxTopicBorderColor}#1\relax } \newif\ifspx@topic@withbackgroundcolor \define@key{sphinx}{div.topic_background-TeXcolor}{% \spx@topic@withbackgroundcolortrue - \definecolor{sphinxTopicBackgroundColor}#1% + \spx@defineorletcolor{sphinxTopicBackgroundColor}#1\relax } \newif\ifspx@topic@withshadowcolor \define@key{sphinx}{div.topic_box-shadow-TeXcolor}{% \spx@topic@withshadowcolortrue - \definecolor{sphinxTopicShadowColor}#1% + \spx@defineorletcolor{sphinxTopicShadowColor}#1\relax } % warning, caution, attention, danger, error \def\spx@tempa#1{% @@ -572,9 +677,12 @@ \definecolor{sphinx#4BorderColor}{rgb}{0,0,0}% \definecolor{sphinx#4BgColor}{rgb}{1,1,1}% \definecolor{sphinx#4ShadowColor}{rgb}{0,0,0}% - \define@key{sphinx}{div.#4_border-TeXcolor}{#1\definecolor{sphinx#4BorderColor}##1}% - \define@key{sphinx}{div.#4_background-TeXcolor}{#2\definecolor{sphinx#4BgColor}##1}% - \define@key{sphinx}{div.#4_box-shadow-TeXcolor}{#3\definecolor{sphinx#4ShadowColor}##1}% + \define@key{sphinx}{div.#4_border-TeXcolor}% + {#1\spx@defineorletcolor{sphinx#4BorderColor}##1\relax}% + \define@key{sphinx}{div.#4_background-TeXcolor}% + {#2\spx@defineorletcolor{sphinx#4BgColor}##1\relax}% + \define@key{sphinx}{div.#4_box-shadow-TeXcolor}% + {#3\spx@defineorletcolor{sphinx#4ShadowColor}##1\relax}% \expandafter\let\csname KV@sphinx@#4BorderColor\expandafter\endcsname \csname KV@sphinx@div.#4_border-TeXcolor\endcsname \expandafter\let\csname KV@sphinx@#4BgColor\expandafter\endcsname @@ -594,6 +702,9 @@ \DisableKeyvalOption{sphinx}{numfigreset} \DisableKeyvalOption{sphinx}{nonumfigreset} \DisableKeyvalOption{sphinx}{mathnumfig} +\DisableKeyvalOption{sphinx}{booktabs} +\DisableKeyvalOption{sphinx}{borderless} +\DisableKeyvalOption{sphinx}{rowcolors} % FIXME: this is unrelated to an option, move this elsewhere % To allow hyphenation of first word in narrow contexts; no option, % customization to be done via 'preamble' key @@ -693,11 +804,8 @@ {\PackageWarningNoLine{sphinx}{% The package pict2e is required for rounded boxes.\MessageBreak It does not seem to be available on your system.\MessageBreak - Options for setting radii will thus be ignored}% - \AtEndDocument{\PackageWarningNoLine{sphinx}{% - I issued a warning which may have gotten lost in the\MessageBreak - gigantic console output: pict2e.sty was not found,\MessageBreak - and radii setting options have been ignored}}% + Options for setting radii have thus been ignored}% + \sphinxbuildwarning{nopict2e}% \def\spx@boxes@fcolorbox@rounded{\spx@boxes@fcolorbox}% }% }% diff --git a/sphinx/texinputs/sphinxlatexstyleheadings.sty b/sphinx/texinputs/sphinxlatexstyleheadings.sty index fa9be82b44d..a54980bc03b 100644 --- a/sphinx/texinputs/sphinxlatexstyleheadings.sty +++ b/sphinx/texinputs/sphinxlatexstyleheadings.sty @@ -1,7 +1,7 @@ %% TITLES % % change this info string if making any custom modification -\ProvidesFile{sphinxlatexstyleheadings.sty}[2021/01/27 headings] +\ProvidesFile{sphinxlatexstyleheadings.sty}[2022/08/15 headings] \RequirePackage[nobottomtitles*]{titlesec} \@ifpackagelater{titlesec}{2016/03/15}% @@ -25,6 +25,7 @@ ******** and Sphinx could not patch it, perhaps because your local ...|^^J% ******** copy is already fixed without a changed release date. .......|^^J% ******** If not, you must update titlesec! ...........................|}}% + \sphinxbuildwarning{badtitlesec}% \fi }% }{} diff --git a/sphinx/texinputs/sphinxlatextables.sty b/sphinx/texinputs/sphinxlatextables.sty index c3c1d6ad1ff..247ad7a7674 100644 --- a/sphinx/texinputs/sphinxlatextables.sty +++ b/sphinx/texinputs/sphinxlatextables.sty @@ -1,7 +1,7 @@ %% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS) % % change this info string if making any custom modification -\ProvidesFile{sphinxlatextables.sty}[2021/01/27 tables]% +\ProvidesFile{sphinxlatextables.sty}[2022/08/15 tables]% % Provides support for this output mark-up from Sphinx latex writer % and table templates: @@ -25,12 +25,31 @@ % - \sphinxtablestrut % - \sphinxthecaptionisattop % - \sphinxthelongtablecaptionisattop +% - \sphinxhline +% - \sphinxcline +% - \sphinxvlinecrossing +% - \sphinxfixclines +% - \sphinxtoprule +% - \sphinxmidrule +% - \sphinxbottomrule +% - \sphinxtableatstartofbodyhook +% - \sphinxtableafterendhook +% - \sphinxthistablewithglobalstyle +% - \sphinxthistablewithbooktabsstyle +% - \sphinxthistablewithborderlessstyle +% - \sphinxthistablewithstandardstyle +% - \sphinxthistablewithcolorrowsstyle +% - \sphinxthistablewithnocolorrowsstyle +% - \sphinxthistablewithvlinesstyle +% - \sphinxthistablewithnovlinesstyle % % Executes \RequirePackage for: % % - tabulary % - longtable % - varwidth +% - colortbl +% - booktabs if 'booktabs' in latex_table_style % % Extends tabulary and longtable via patches and custom macros to support % merged cells possibly containing code-blocks in complex tables @@ -43,9 +62,13 @@ % X or S (Sphinx) may have meanings if some table package is loaded hence % \X was chosen to avoid possibility of conflict \newcolumntype{\X}[2]{p{\dimexpr - (\linewidth-\arrayrulewidth)*#1/#2-\tw@\tabcolsep-\arrayrulewidth\relax}} + (\linewidth-\spx@arrayrulewidth)*#1/#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} \newcolumntype{\Y}[1]{p{\dimexpr - #1\dimexpr\linewidth-\arrayrulewidth\relax-\tw@\tabcolsep-\arrayrulewidth\relax}} + #1\dimexpr\linewidth-\spx@arrayrulewidth\relax-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} +% \spx@arrayrulewidth is used internally and its meaning will be set according +% to the table type; no extra user code should modify it. In particular any +% \setlength{\spx@arrayrulewidth}{...} may break all of LaTeX... (really...) +\def\spx@arrayrulewidth{\arrayrulewidth}% 5.2.0, to be adjusted by each table % using here T (for Tabulary) feels less of a problem than the X could be \newcolumntype{T}{J}% % For tables allowing pagebreaks @@ -167,6 +190,11 @@ \unexpanded\expandafter{\@vwid@setup}}% }% +% NOTA BENE: since the multicolumn and multirow code was written Sphinx +% decided to prefix non public internal macros by \spx@ and in fact all +% such macros here should now be prefixed by \spx@table@, but doing the +% update is delayed to later. (written at 5.2.0) + %%%%%%%%%%%%%%%%%%%%% % --- MULTICOLUMN --- % standard LaTeX's \multicolumn @@ -208,6 +236,16 @@ % \arrayrulewidth space for each column separation in its estimate of available % width). % +% Update at 5.2.0: code uses \spx@arrayrulewidth which is kept in sync with the +% table column specification (aka preamble): +% - no | in preamble: \spx@arrayrulewidth -> \z@ +% - at least a | in the preamble: \spx@arrayrulewidth -> \arrayrulewidth +% This is used for computation of merged cells widths. Mixed preambles using +% at least a | but not using it for all columns (as can be obtained via the +% tabularcolumns directive) may cause some merged cells contents to be slightly +% shifted to the left as they assume merged columns are | separated where in +% fact they perhaps are not. +% % TN. 1b: as Sphinx multicolumn uses neither \omit nor \span, it can not % (easily) get rid of extra macros from >{...} or <{...} between columns. At % least, it has been made compatible with colortbl's \columncolor. @@ -229,7 +267,19 @@ % Sphinx generates no nested tables, and if some LaTeX macro uses internally a % tabular this will not have a \sphinxstartmulticolumn within it! % -\def\sphinxstartmulticolumn{% +% 5.2.0 adds a check for multirow as single-row multi-column will allow a row +% colour but multi-row multi-column should not. +% Attention that this assumes \sphinxstartmulticolumn is always followed +% in latex mark-up either by \sphinxmultirow or \begin (from \begin{varwidth}). +\def\sphinxstartmulticolumn#1#2{% + \ifx\sphinxmultirow#2% + \gdef\spx@table@hackCT@inmergedcell{\spx@table@hackCT@nocolor}% + \else + \global\let\spx@table@hackCT@inmergedcell\spx@@table@hackCT@inmergedcell + \fi + \sphinx@startmulticolumn{#1}#2% +}% +\def\sphinx@startmulticolumn{% \ifx\equation$% $ tabulary's first pass \expandafter\sphinx@TYI@start@multicolumn \else % either not tabulary or tabulary's second pass @@ -285,32 +335,21 @@ \else % if in an l, r, c type column, try and hope for the best \xdef\sphinx@tempb{\the\dimexpr(\ifx\TY@final\@undefined\linewidth\else - \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa - -\tw@\tabcolsep-\arrayrulewidth\relax}% + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% \fi \noindent\kern\sphinx@tempb\relax \xdef\sphinx@multiwidth - {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\arrayrulewidth}% - % hack the \vline and the colortbl macros - \sphinx@hack@vline\sphinx@hack@CT&\relax + {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\spx@arrayrulewidth}% + \spx@table@hackCT@fixcolorpanel + % silence a | column separator in our merged cell + \spx@table@hackCT@inhibitvline + % prevent column colours to interfere with our multi-column but allow row + % colour (we can't obey a \cellcolor as it has not be seen yet at this stage) + \spx@table@hackCT@inmergedcell&\relax % repeat \expandafter\sphinx@multispan\expandafter{\the\numexpr#1-\@ne}% }% -% packages like colortbl add group levels, we need to "climb back up" to be -% able to hack the \vline and also the colortbl inserted tokens. This creates -% empty space whether or not the columns were | separated: -\def\sphinx@hack@vline{\ifnum\currentgrouptype=6\relax - \kern\arrayrulewidth\arrayrulewidth\z@\else\aftergroup\sphinx@hack@vline\fi}% -\def\sphinx@hack@CT{\ifnum\currentgrouptype=6\relax - \let\CT@setup\sphinx@CT@setup\else\aftergroup\sphinx@hack@CT\fi}% -% It turns out \CT@row@color is not expanded contrarily to \CT@column@color -% during LaTeX+colortbl preamble preparation, hence it would be possible for -% \sphinx@CT@setup to discard only the column color and choose to obey or not -% row color and cell color. It would even be possible to propagate cell color -% to row color for the duration of the Sphinx multicolumn... the (provisional?) -% choice has been made to cancel the colortbl colours for the multicolumn -% duration. -\def\sphinx@CT@setup #1\endgroup{\endgroup}% hack to remove colour commands \def\sphinx@multispan@end#1{% % first, trace back our steps horizontally \noindent\kern-\dimexpr\sphinx@multiwidth\relax @@ -320,11 +359,12 @@ \else \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+ (\ifx\TY@final\@undefined\linewidth\else - \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa - -\tw@\tabcolsep-\arrayrulewidth\relax}% + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% \fi - % we need to remove colour set-up also for last cell of the multi-column - \aftergroup\sphinx@hack@CT + % last cell of the multi-column + \aftergroup\spx@table@hackCT@fixcolorpanel + \aftergroup\spx@table@hackCT@inmergedcell }% \newcommand*\sphinxcolwidth[2]{% % this dimension will always be used for varwidth, and serves as maximum @@ -345,8 +385,8 @@ \linewidth \else % l, c, r columns. Do our best. - \dimexpr(\linewidth-\arrayrulewidth)/#2- - \tw@\tabcolsep-\arrayrulewidth\relax + \dimexpr(\linewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax \fi \else % in tabulary \ifx\equation$%$% first pass @@ -357,8 +397,8 @@ \linewidth % in a L, R, C, J column or a p, \X, \Y ... \else % we have hacked \TY@final to put in \sphinx@TY@tablewidth the table width - \dimexpr(\sphinx@TY@tablewidth-\arrayrulewidth)/#2- - \tw@\tabcolsep-\arrayrulewidth\relax + \dimexpr(\sphinx@TY@tablewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax \fi \fi \fi @@ -368,7 +408,125 @@ % \sphinxcolwidth will use this only inside LaTeX's standard \multicolumn \def\sphinx@multiwidth #1#2{\dimexpr % #1 to gobble the \@gobble (!) (\ifx\TY@final\@undefined\linewidth\else\sphinx@TY@tablewidth\fi - -\arrayrulewidth)*#2-\tw@\tabcolsep-\arrayrulewidth\relax}% + -\spx@arrayrulewidth)*#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}% + +% \spx@table@hackCT@inhibitvline +% packages like colortbl add group levels, we need to "climb back up" to be +% able to hack the \vline and also the colortbl inserted tokens. The hack +% sets the \arrayrulewidth to \z@ to inhibit a | separator at right end +% of the cell, if present (our code does not use \omit so can not avoid the +% \vline insertion, but setting its width to zero makes it do nothing). +% Some subtlety with colour panels must be taken care of. +\def\spx@table@hackCT@inhibitvline{\ifnum\currentgrouptype=6\relax + \kern\spx@arrayrulewidth % will be compensated by extra colour panel left overhang + \arrayrulewidth\z@% trick to inhibit the {\vrule width \arrayrulewidth} + \else\aftergroup\spx@table@hackCT@inhibitvline\fi}% + +% hacking around colour matters +% Sphinx 1.6 comment: +% It turns out \CT@row@color is not expanded contrarily to \CT@column@color +% during LaTeX+colortbl preamble preparation, hence it would be possible for +% \CT@setup to discard only the column color and choose to obey or not +% row color and cell color. It would even be possible to propagate cell color +% to row color for the duration of the Sphinx multicolumn... the (provisional?) +% choice has been made to cancel the colortbl colours for the multicolumn +% duration. +% Sphinx 5.2.0 comment: +% - colortbl has no mechanism to disable colour background in a given cell: +% \cellcolor triggers one more \color, but has no possibility to revert +% a previously emitted \color, only to override it via an additional \color +% - prior to <5.2.0, Sphinx did not officially support colour in tables, +% but it did have a mechanism to protect merged cells from being partly +% covered by colour panels at various places. At 5.2.0 this mechanism +% is relaxed a bit to allow row colour for a single-row merged cell. +% +% fixcolorpanel +\def\spx@table@hackCT@fixcolorpanel{\ifnum\currentgrouptype=6\relax + \edef\spx@table@leftcolorpanelextra + % \edef as \arrayrulewidth will be set to \z@ next, + % hence also \spx@arrayrulewidth... + {\sphinxcolorpanelextraoverhang+\the\spx@arrayrulewidth}% + \else\aftergroup\spx@table@hackCT@fixcolorpanel\fi}% +% +% inmergedcell +% \spx@table@hackCT@inmergedcell will be locally set to either this +% \spx@@table@hackCT@inmergedcell or to \spx@table@hackCT@nocolor +% "\let\spx@original@CT@setup\CT@setup" is done after loading colortbl +\def\spx@@table@hackCT@inmergedcell{\ifnum\currentgrouptype=6\relax + \let\CT@setup\spx@CT@setup@inmergedcell + \else\aftergroup\spx@@table@hackCT@inmergedcell\fi +}% +\newif\ifspx@table@inmergedcell +\def\spx@CT@setup@inmergedcell #1\endgroup{% + % - obey only row color and disable effect of \sphinxblendcolor + % - turn on the inmergedcell boolean to signal to \CT@row@color + \spx@original@CT@setup + \spx@table@inmergedcelltrue % needed by \CT@row@color + % deactivate effect of \sphinxcolorblend if it happened at all + \ifdefined\blendcolors\blendcolors{}\fi + \CT@row@color + \CT@do@color + \global\let\CT@cell@color\relax + \endgroup +}% +% +% nocolor +\def\spx@table@hackCT@nocolor{\ifnum\currentgrouptype=6\relax +% sadly \CT@column@color is possibly already expanded so we can't +% simply do \let\CT@column@color\relax etc... +% admittedly we could perhaps hack \CT@color but well + \let\CT@setup\spx@CT@setup@nocolor + \else\aftergroup\spx@table@hackCT@nocolor\fi +} +\def\spx@CT@setup@nocolor#1\endgroup{% + \global\let\CT@cell@color\relax + % the above fix was added at 5.2.0 + % formerly a \cellcolor added by a raw latex directive in the merged cell + % would have caused colour to apply to the *next* cell after the merged + % one; we don't support \cellcolor from merged cells contents anyhow. + \endgroup} +% +% norowcolor +\def\spx@table@hackCT@norowcolor{% +% a bit easier although merged cells complicate the matter as they do need +% to keep the rowcolor; and we can't know yet if we are in a merged cell + \ifnum\currentgrouptype=6\relax + \ifx\CT@row@color\relax + \else + \let\spx@saved@CT@row@color\CT@row@color + \def\CT@row@color{% + \ifspx@table@inmergedcell\expandafter\spx@saved@CT@row@color\fi + }% + \fi + \else\aftergroup\spx@table@hackCT@norowcolor\fi +} +% +% \sphinxcolorblend +\def\spx@table@hackCT@colorblend{% + \ifnum\currentgrouptype=6\relax + \expandafter\blendcolors\spx@colorblendparam + % merged cells will do a \blendcolors{} to cancel the effet + % we can not know here yet if in merged cell as the boolean + % \ifspx@table@inmergedcell is not yet updated + \else + \aftergroup\spx@table@hackCT@colorblend + \fi +} +\def\sphinxcolorblend#1{\gdef\spx@colorblendparam{{#1}}\spx@table@hackCT@colorblend} +% Either xcolor.sty exists on user system and has been loaded by sphinx.sty, +% or it does not exist, so we can use \@ifpackageloaded without delaying. +\@ifpackageloaded{xcolor}% + {}% + {\def\sphinxcolorblend#1{% +\PackageWarning{sphinx}{This table uses \string\sphinxcolorblend\space + but xcolor is not in\MessageBreak + the TeX/LaTeX installation, the command will be\MessageBreak + ignored in this and the next tables}% + \global\let\sphinxcolorblend\@gobble + \sphinxbuildwarning{colorblend}% + }% + } + %%%%%%%%%%%%%%%%%% % --- MULTIROW --- @@ -390,9 +548,22 @@ % that the table rows have the needed height. The needed mark-up is done % by LaTeX writer, which has its own id for the merged cells. % -% The colour issue is solved by clearing colour panels in all cells, +% The colour issue is "solved" by clearing colour panels in all cells, % whether or not the multirow is single-column or multi-column. % +% MEMO at 5.2.0: to allow a multirow cell in a single column to react to +% \columncolor correctly, it seems only way is that the contents +% are inserted by bottom cell (this is mentioned in multirow.sty doc, too). +% Sphinx could at Python level "move" the contents to that cell. But the +% mechanism used here via \sphinxtablestrut to enlarge rows to make room for +% the contents if needed becomes more challenging yet, because \sphinxtablestrut +% mark-up will be parsed by TeX *before* it sees the contents of the merged +% cell.. So it seems the best way would be to actually store the contents into +% some owned-by-Sphinx box storage which needs to be globally allocated to +% that usage ; then we need multiple such boxes, say at least 5 to cover +% 99% or use case. Or perhaps some trick with storing in a \vbox and recovering +% via some \vsplit but this becomes complicated... perhaps in future. +% % In passing we obtain baseline alignements across rows (only if % \arraystretch is 1, as LaTeX's does not obey \arraystretch in "p" % multi-line contents, only first and last line...) @@ -410,6 +581,15 @@ \setbox\z@\hbox\bgroup\aftergroup\sphinx@@multirow\strut }% \def\sphinx@@multirow {% +% MEMO: we could check status of \CT@cell@color here, but unfortunately we +% can't know the exact height which will be covered by the cells in total +% (it may be more than our \box\z@ dimensions). We could use an \fcolorbox +% wrapper on \box\z@ but this will not extend precisely to the bottom rule. +% +% Only solution if we want to obey a raw \cellcolor, or a \columncolor, seems +% to delay unboxing the gathered contents as part of the bottom row with +% a suitable vertical adjustment... +% % The contents, which is a varwidth environment, has been captured in % \box0 (a \hbox). % We have with \sphinx@cellid an assigned unique id. The goal is to give @@ -475,7 +655,592 @@ \@width\z@ \endgroup % we need this to avoid colour panels hiding bottom parts of multirow text - \sphinx@hack@CT + \spx@table@hackCT@nocolor }% +%%%%%%%%%%%%%%%%%% +% --- STYLING --- +% + +% +% Support for colour in table +% +% Core LaTeX package (very old, part of texlive-latex-base on Debian distr.) +% providing \columncolor, \rowcolor, \cellcolor and \arrayrulecolor. +\RequirePackage{colortbl} +\let\spx@original@CT@setup\CT@setup + +% LaTeX's \cline has **strong** deficiencies +% ****************************************** +% We work around them via an added \sphinxfixclines{number of columns} in the +% table mark-up, and also extra mark-up \sphinxvlinecrossing{col no} for +% crossings not contiguous to any cline. To fix the gap at left extremity of a +% \cline, we redefine the core LaTeX \c@line because this avoids adjoining a +% small square with potential PDF viewer anti-aliasing issues. We waited +% after loading colortbl because it also redefines \c@line for it to obey the +% colour set by \arrayrulecolor. +% MEMO: booktabs package does *not* redefine \@cline so we are safe here. +\def\@cline#1-#2\@nil{% + \omit + \@multicnt#1% + \advance\@multispan\m@ne + \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi + \@multicnt#2% + \advance\@multicnt-#1% + \advance\@multispan\@ne + {\CT@arc@ +% start of Sphinx modification + \ifnum#1>\@ne\kern-\spx@arrayrulewidth\fi% fix gap at join with vertical lines +% end of Sphinx modification +% Comments: +% +% If we had the information whether the previous column ended with a | or +% not, we could decide what to do here. Alternatively the mark-up could +% use either original \cline or the one modified as here depending on case. +% One wonders why LaTeX does not provide itself the alternative as a +% complement to \cline, to use on case by case basis. +% Here we handle both at same time via using the \spx@arrayrulewidth which +% will be \z@ if no | at all so will induce here nothing. +% +% As a result Sphinx basically supports well only tables having either all +% columns |-separated, or no | at all, as it uses \spx@arrayrrulewidth in +% all columns (here and in multicolumn code). +% +% We also considered a method not modifying \c@line but it requires too +% much extra mark-up from Python LaTeX writer and/or extra LaTeX coding. +% back to LaTeX+colortbl code + \leaders\hrule\@height\arrayrulewidth\hfill}% + \cr +% the last one will need to be compensated, this is job of \sphinxclines + \noalign{\vskip-\arrayrulewidth}% +} +\def\spx@table@fixvlinejoin{% + {\CT@arc@ % this is the color command set up by \arrayrulecolor + \vrule\@height\arrayrulewidth +% side remark: LaTeX has only a single \arrayrulewidth for all kinds +% for cell borders in table, horizontal or vertical... + \@depth\z@ + \@width\spx@arrayrulewidth + }% +} +% Sphinx LaTeX writer issues one such for each vertical line separating two +% contiguous multirow cells; i.e. those crossings which can are not already +% taken care of by our modified at left extremity \cline. +% One could imagine a more \...crossingS (plural) receiving a comma delimited +% list, which would simplify the mark-up but this would complexify both the +% Python and the LaTeX coding. +\def\sphinxtablevlinecrossing#1{% + \sphinxtabledecrementrownum + \omit + \@multispan{#1}% + \hfill + \spx@table@fixvlinejoin + \cr + \noalign{\vskip-\arrayrulewidth}% +} +% This "fixclines" is also needed if no \sphinxcline emitted and is useful +% even in extreme case with no \sphinxvlinecrossing either, to give correct +% height to multirow extending across all table width assuming other rows are +% separated generally by an \hline, so as to keep coherent line spacing. +% +% It is designed to work ok even if no | separators are in the table (because +% \spx@table@fixvlinejoin uses \spx@arrayrulewidth which is \z@ in that case). +\def\sphinxtablefixclines#1{% #1 is the number of columns of the table + \sphinxtabledecrementrownum + \omit + \spx@table@fixvlinejoin% unneeded if first \cline started at column 1 but does + % not hurt; fills small gap at left-bordered table + \@multispan{#1}% + \hfill + \spx@table@fixvlinejoin% fill small gap at right-bordered table + \cr + % this final one does NO \vskip-\arrayrulewidth... that's the whole point +} +%%%% end of \cline workarounds + +% +% - passing option "table" to xcolor also loads colortbl but we needed to +% load color or xcolor prior to the handling of the options +% +% - the \rowcolors command from [table]{xcolor} has various problems: +% +% * it is rigid and does not out-of-the-box allow a more complex scheme +% such as colorA+colorB+colorC+colorB+colorC+colorB+colorC... suitable to +% distinguish a header row. +% +% * its code does not export the used colour, an information which we may +% need for example to colourize the rule via \arrayrulecolor in the +% appropriate manner, for example to colourize the booktabs induced vertical +% whitespace to avoid gaps (if one wants to). +% +% * incompatibility with tabulary: the output depends on parity of total +% number of rows! +% +% * problems with longtable: the caption will receive a background colour +% panel, if we do not deactivate the \rowcolors action during definition of +% the headers and footers; this requires extra mark-up. Besides if we +% deactivate using \hiderowcolors during header and footer formation, the +% parity of the body rows is shifted, \rownum is even, not odd, at first body +% row. And setting \rownum at start of first body row is too late for +% influencing the colour. +% +% * it has a global impact and must be reset at each table. We can not +% issue it only once and it provides no public interface (without @) to +% cancel its effect conveniently (\hiderowcolors can only be used from +% *inside* a table.) +% +% * its core mechanism which increments the row count is triggered +% if a \cline is encountered... so this offsets the alternating colours... +% ... or not if there are two \cline's in the row... +% (as we will use same mechanism we have to correct this increment). +% +% So we need our own code. + +% Provide \rownum and rownum LaTeX counter (code copied from colortbl v1.0f) +\ltx@ifundefined{rownum}{% + \ltx@ifundefined{c@rownum}% + {\newcount\rownum\let\c@rownum\rownum}% + {\let\rownum\c@rownum}% + }% +{\let\c@rownum\rownum} +\providecommand\therownum{\arabic{rownum}} + +% extra overhang for color panels to avoid visual artifacts in pdf viewers +% (particularly if borderless) +\def\sphinxcolorpanelextraoverhang{0.1pt} +\def\spx@table@leftcolorpanelextra {\sphinxcolorpanelextraoverhang} +\def\spx@table@rightcolorpanelextra{\sphinxcolorpanelextraoverhang} +% the macro to which \CT@row@color will be set for coloured rows, serves both +% in header and body, the colours must have been defined at time of use +\def\spx@table@CT@row@color{\ifspx@table@inmergedcell + \CT@color{sphinxTableMergeColor}% + \else + \CT@color{sphinxTableRowColor}% + \fi + \@tempdimb\dimexpr\col@sep+\spx@table@leftcolorpanelextra\relax + \@tempdimc\dimexpr\col@sep+\spx@table@rightcolorpanelextra\relax + }% +% used by itself this will influence a single row if \CT@everycr is the +% colortbl one, to influences all rows the \CT@everycr must be modified (see +% below) +\def\sphinxrowcolorON {\global\let\CT@row@color\spx@table@CT@row@color}% +% this one turns off row colours until the next \sphinxrowcolorON +\def\sphinxrowcolorOFF{\global\let\CT@row@color\relax}% +% this one inhibits the row colour in one cell only (can be used as +% >{\sphinxnorowcolor} for turning off row colours in a given column) +\def\sphinxnorowcolor{\spx@table@hackCT@norowcolor}% + +% \sphinxtoprule (or rather \sphinxtabletoprulehook) will be modified by +% the colorrows class to execute this one: +\def\spx@table@@toprule@rowcolorON{% + \noalign{% + % Because of tabulary 2-pass system, the colour set-up at end of table + % would contaminate the header colours at start of table, so must reset + % them here. We want all header rows to obey same colours, so we don't + % use original \CT@everycr which sets \CT@row@color to \relax. + \global\CT@everycr{\the\everycr}% + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorHeader}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorHeader}% + \sphinxrowcolorON + }% +}% + +% \sphinxtableatstartofbodyhook will be modified by colorrows class to +% execute this one; it starts the alternating colours and triggers increment +% or \rownum count at each new row (the xcolor base method for \rowcolors) +\def\spx@table@@startbodycolorrows{% + \noalign{% + \global\CT@everycr{% Nota Bene: in a longtable with \hline the \everycr is + % done two extra times! but 2 is even, so this is ok + \noalign{\global\advance\rownum\@ne % the xcolor \rowcolors base trick +% MEMO: colortbl \CT@row@color is expanded *after* the cell contents have been +% gathered and measured, so it can't be used to expose e.g. the colour to the +% cell contents macro code. Of course if it is known how the colour is chosen +% the procedure could be done from inside the cell. Simpler to expose the colour +% in a public name sphinxTableRowColor at start of the row in this \noalign. + \sphinxSwitchCaseRowColor\rownum + }% + \the\everycr + }% + \global\rownum\@ne % is done from inside table so ok with tabulary two passes + \sphinxSwitchCaseRowColor\rownum % set up color for the first body row + \sphinxrowcolorON % has been done from \sphinxtoprule location but let's do + % it again in case \sphinxtabletoprulehook has been used + % to inhibit colours in the header rows + }% end of noalign contents +} +% set the colours according to row parity; a priori #1 is \rownum, but +% the macro has been designed to be usable in user level added code +\def\sphinxSwitchCaseRowColor#1{% + \ifodd#1\relax + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorOdd}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorOdd}% + \else + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorEven}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorEven}% + \fi +} + +% each \cline or \cmidrule (booktabs) consumes one \cr, offsetting the \rownum +% parity; so this macro serves to compensate and must be added to each such +% \cline or \cmidrule (see below) +\def\spx@table@@decrementrownum{\noalign{\global\advance\rownum\m@ne}} +\let\sphinxtabledecrementrownum\@empty + +% \sphinxtableafterendhook will be modified by colorrows class to execute +% this after the table +\def\spx@table@resetcolortbl{% + \sphinxrowcolorOFF + \spx@table@reset@CTeverycr +% this last bit is done in order for the \sphinxbottomrule from the "foot" +% longtable template to be able to use same code as the \sphinxbottomrule +% at end of table body; see \sphinxbooktabsspecialbottomrule code + \global\rownum\z@ +} +\def\spx@table@reset@CTeverycr{% +% we should probably be more cautious and not hard-code here the colortbl +% set-up; so the macro is defined without @ to fac + \global\CT@everycr{\noalign{\global\let\CT@row@color\relax}\the\everycr}% +} + +% At last the style macros \sphinxthistablewithstandardstyle etc... + +% They are executed before the table environments in a scope limiting +% wrapper "savenotes" environment. +% +% 0) colour support is enacted via adding code to three hooks: +% - \sphinxtabletoprulehook (implicit from \sphinxtoprule expansion) +% - \sphinxtableatstartofbodyhook (explicit from table templates) +% - \sphinxtableafterendhook (explicit from table templates) +% additionally special adjustment must be made in \sphinxcline +% +\def\sphinxtoprule{\spx@toprule\sphinxtabletoprulehook} +% \spx@toprule is what is defined by the standard, booktabs and borderless +% styles. +% The colorrows class will prepend \spx@table@toprule@rowcolorON into +% \sphinxtabletoprulehook which a priori is \@empty but can contain user added +% extra code, and is executed after \spx@toprule. +\let\sphinxtabletoprulehook \@empty +\let\sphinxtableatstartofbodyhook\@empty +\let\sphinxtableafterendhook \@empty +% +% 1) we manage these three hooks in a way allowing a custom user extra wrapper +% environment from a container class to use them as entry point for some +% custom code. The container code is done first, prior to table templates. +% So, the style macros will *prepend* the needed color-code to the existing +% custom user code, so the custom user code can override them. The custom +% user code should not redefine any of the 3 \sphinxtable...hook macros via a +% \global\def, but their contents can use \gdef. In fact they probably need +% to for the first two hooks which are executed from inside the table and +% a priori need their code to be in a \noalign which limits scope. +% +% 2) the table templates and LaTeX writer code make it so that only +% one of either +% \sphinxthistablewithcolorrowsstyle, +% or \sphinxthistablewithnocolorrowsstyle +% will be inserted explicitly depending on local :class: for table. +% The global 'colorrows' style in latex_table_style translates at bottom +% of this file into code for inserting \sphinxthistablewithcolorrowsstyle +% at end of \sphinxthistablewithglobalstyle. So it is impossible +% to have first \sphinxthistablewithnocolorrowsstyle, then +% \sphinxthistablewithcolorrowsstyle. Nevertheless we have written +% the code so that in this case colorrows would indeed activate (except +% if it was already executed before as it self-annihilates). + +% standard style +\def\sphinxthistablewithstandardstyle{% + % Those two are produced by the latex writer + \def\sphinxhline {\hline}% + % \sphinxtabledecrementrownum is a no-op which is redefined by colorrows + % to correct the \rownum increment induced by \cline in colorrows regime + \def\sphinxcline {\sphinxtabledecrementrownum\cline}% + % LaTeX's \cline needs fixing + \let\sphinxvlinecrossing\sphinxtablevlinecrossing + \let\sphinxfixclines \sphinxtablefixclines + % Those three are inserted by the table templates + \def\spx@toprule {\hline}% + \def\sphinxmidrule {\hline}% + \def\sphinxbottomrule {\hline}% + % Do not tamper with this internal + \def\spx@arrayrulewidth{\arrayrulewidth}% +} + +% booktabs style +% The \@xcmidrule patch below will do beyond its main stuff +% \sphinxadjustcmidrulebelowsep +% Indeed the poor booktabs spacing with \cmidrule (if \sphinxbooktabscmidrule +% defined below is overwritten to use it) is quite awful. Do +% \let\sphinxadjustcmidrulebelowsep\empty +% if you prefer booktabs defaults. +\def\sphinxadjustcmidrulebelowsep{\belowrulesep=\aboverulesep} +\AtBeginDocument{% patch booktabs to avoid extra vertical space from + % consecutive \sphinxcline, if defined to use \cmidrule + \ifdefined\@xcmidrule + \let\spx@original@@xcmidrule\@xcmidrule + \def\@xcmidrule{\sphinxadjustcmidrulebelowsep + % if we don't do that, two \sphinxcline in the same row + % will cause the second short rule to be shifted down + \ifx\@tempa\sphinxcline\let\@tempa\cmidrule\fi + \spx@original@@xcmidrule}% + \fi +} +% wrappers to allow customization, e.g. via a container class +% the top, mid, bottom definitions are in fact overwritten (later, below) +% byt more complex ones needed to handle booktabs+colorrows context +\def\sphinxbooktabstoprule {\toprule} +\def\sphinxbooktabsmidrule {\midrule} +\def\sphinxbooktabsbottomrule{\bottomrule} +% +\let\sphinxbooktabscmidrule \@gobble % i.e. draw no short rules at all! +% You can redefine this to use \cmidrule with various options, such +% as \cmidrule(lr), but: +% Attention, if you want this to use \cmidrule (or \cline) you must, +% if the table uses row colours, +% also include the \sphinxtabledecrementrownum token like e.g. this +% \def\sphinxbooktabscmidrule{\sphinxtabledecrementrownum\cmidrule(lr)} +% and it must be first due to internals of the \cmidrule usage of \futurelet. + +\def\sphinxthistablewithbooktabsstyle{% + \let\sphinxhline\@empty % there is no wrapper macro here so if you want to change that + % you will have to redefine \sphinxthistablewithbooktabsstyle + \def\sphinxcline {\sphinxbooktabscmidrule}% defaults to give \@gobble + \let\sphinxvlinecrossing\@gobble % no | in a booktabs-style table ! + \let\sphinxfixclines \@gobble % should not be used with booktabs + \cmidrule + \def\spx@toprule {\sphinxbooktabstoprule}% + \def\sphinxmidrule {\sphinxbooktabsmidrule}% + \def\sphinxbottomrule{\sphinxbooktabsbottomrule}% + \def\spx@arrayrulewidth{\z@}% +} +\AtBeginDocument{\@ifpackageloaded{booktabs}% + {}% + {\def\sphinxthistablewithbooktabsstyle{% + \PackageWarning{sphinx}{% +Add \string\usepackage{booktabs} to the preamble to allow\MessageBreak +local use of booktabs table style}% + \sphinxbuildwarning{booktabs}% + \sphinxthistablewithstandardstyle + }}% +}% + +% borderless style +\def\sphinxthistablewithborderlessstyle{% + \let\sphinxhline \@empty + \let\sphinxcline \@gobble + \let\sphinxvlinecrossing\@gobble + \let\sphinxfixclines \@gobble + \let\spx@toprule \@empty + \let\sphinxmidrule \@empty + \let\sphinxbottomrule \@empty + \def\spx@arrayrulewidth{\z@}% +}% + +% colorrows style +% +\let\sphinxifthistablewithcolorrowsTF\@secondoftwo +\def\sphinxthistablewithcolorrowsstyle{% + \let\sphinxifthistablewithcolorrowsTF\@firstoftwo +% this is defined to auto-silence itself (in the surrounding scope-limiting +% environment) after one execution ("colorrows" can never follow "nocolorrows") + \let\sphinxthistablewithcolorrowsstyle\@empty +% + \let\spx@table@toprule@rowcolorON \spx@table@@toprule@rowcolorON + \let\spx@table@startbodycolorrows \spx@table@@startbodycolorrows + \let\sphinxtabledecrementrownum \spx@table@@decrementrownum +% Is it the best choice to "prepend" to existing code there? + \spx@prepend\spx@table@toprule@rowcolorON\to\sphinxtabletoprulehook + \spx@prepend\spx@table@startbodycolorrows\to\sphinxtableatstartofbodyhook +% +% this one is not set to \@empty by nocolorrows, because it looks harmless +% to execute it always, as it simply resets to standard colortbl state after +% the table; so we don't need an @@ version for this one + \spx@prepend\spx@table@resetcolortbl\to\sphinxtableafterendhook +} +\def\spx@prepend#1\to#2{% attention about using this only with #2 "storage macro" + \toks@{#1}% + \toks@\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@#2}% + \edef#2{\the\toks@}% +}% + +\def\sphinxthistablewithnocolorrowsstyle{% + \let\sphinxifthistablewithcolorrowsTF\@secondoftwo +% rather than trying to remove the code added by 'colorrows' style, we +% simply make it no-op, without even checking if really it was activated. + \let\spx@table@toprule@rowcolorON\@empty + \let\spx@table@startbodycolorrows\@empty + \let\sphinxtabledecrementrownum \@empty +% we don't worry about \sphinxtableafterendhook as the \spx@table@resetcolortbl +% done at end can not do harm; and we could also have not bothered with the +% \sphinxtabledecrementrownum as its \rownum decrement, if active, is harmless +% in non-colorrows context +} + +% (not so easy) implementation of the booktabscolorgaps option. This option +% defaults to true and is not officially documented, as already colorrows is +% only opt-in, so it is there only as a "turn-off" switch, but if nobody +% complains in next few months, it will probably be removed altogether at +% 6.0.0. The reason it exists is because of longtable aspeces described +% below. +% +% As it is used via \sphinxsetup booktabscolorgaps status is not known here +% and may change locally. So it must be implemented via delayed or +% conditional code. +% +% We do not know the order of execution of \sphinxthistablewithbooktabsstyle +% versus \sphinxthistablewithcolorrows: if booktabs is global option it +% will be executed first; but if colorrows is global option and not booktabs +% then colorrows will be executed first via \sphinxthistablewithglobalstyle +% +% Modifying things from locations such as \sphinxtabletoprulehook which are +% executed within the table is not convenient as it must use \global +% but then we would have to undo this after the table. +% +% So what we do is to prepare booktabs specific macros to incorporate +% a conditional to check the colorrows status. We must each time check +% both if colorrows is activated and if colorgaps is. We do this via +% macros without @ so they can be used easily in customization code. +% When and if booktabscolorgaps option is removed, we can then replace +% \sphinxifbooktabswithcolorgapsTF by \sphinxifthistablewithcolorrowsTF +\def\sphinxifbooktabswithcolorgapsTF{% + \if1\ifspx@opt@booktabscolorgaps + \sphinxifthistablewithcolorrowsTF{1}{0}% + \else0\fi + \expandafter\@firstoftwo + \else\expandafter\@secondoftwo + \fi +} +% as this is done without "@" it can be relatively easily be overwritten +% by user in customization code +\def\sphinxbooktabstoprule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialtoprule}% + {\toprule}% +}% +\def\sphinxbooktabscolorgapsoverhang{0.1pt}% avoid pixel/rounding effects +% auxiliary fork +\long\def\spx@table@crazyfork + #1\endfirsthead\endhead\sphinxtableatstartofbodyhook#2#3\@nil{#2} +% we fetch the next token to check if there is a header or not +% this is a bit fragile as it relies on the table templates +% and it assumes this token #1 is never braced... +% let's make this \long in case #1 is \par (should not be) +\long\def\sphinxbooktabsspecialtoprule\sphinxtabletoprulehook#1{% + \specialrule{\heavyrulewidth}{\abovetopsep}{\z@}% + % this macro contains colour init code (and defines sphinxTableRowColor) + \sphinxtabletoprulehook + % unfortunately colortbl provides no way to save/restore the + % \arrayrulecolor status, we have to code it ourselves + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ +% \@declaredcolor is not \long. Although #1 can probably never be \par with +% our templates, let's be cautious and not use the creazyfork inside the \color + \spx@table@crazyfork +% this crazy code checks if #1 is one of \endfirsthead, \endhead or +% \sphinxtableatstartofbodyhook, as criterion for table with no header + #1\endhead\sphinxtableatstartofbodyhook\@secondoftwo + \endfirsthead#1\sphinxtableatstartofbodyhook\@secondoftwo + \endfirsthead\endhead#1\@secondoftwo + \endfirsthead\endhead\sphinxtableatstartofbodyhook\@firstoftwo + \@nil + {\gdef\CT@arc@{\color{sphinxTableRowColor}}}% + {\gdef\CT@arc@{\color{sphinxTableRowColorOdd}}}% + }% end of \noalign + % \specialrule uses \noalign itself + \specialrule{\dimexpr\belowrulesep+\sphinxbooktabscolorgapsoverhang\relax}% + {\z@}{-\sphinxbooktabscolorgapsoverhang}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + #1% let's not forget to re-insert this #1 in token stream + % fortunately longtable's \endfirsthead/\endhead are not delimiters but + % are really tokens awaiting expansion... +}% +\def\sphinxbooktabsmidrule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialmidrule}% + {\midrule}% +}% +\def\sphinxbooktabsspecialmidrule{% + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ + \gdef\CT@arc@{\color{sphinxTableRowColor}}% this is RowColorHeader + }% + \specialrule{\dimexpr\aboverulesep+\sphinxbooktabscolorgapsoverhang\relax\relax}% + {-\sphinxbooktabscolorgapsoverhang}{\z@}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + \specialrule{\lightrulewidth}{\z@}{\z@}% + \noalign{\gdef\CT@arc@{\color{sphinxTableRowColorOdd}}}% + \specialrule{\dimexpr\belowrulesep+\sphinxbooktabscolorgapsoverhang\relax\relax}% + {\z@}{-\sphinxbooktabscolorgapsoverhang}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% +}% +\def\sphinxbooktabsbottomrule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialbottomrule}% + {\bottomrule}% +}% +% The colour here is already updated because of the \\ before so we must +% execute again the colour selection code, but this is not too complicated. +% What is annoying though is that \sphinxbottomrule in the longtable context +% appears both in the "foot" part and after the last body row. For the first +% occurrence the \rownum could be arbitrary if it had not been reset by each +% table using it via the \sphinxtableafterendhook (see above). This avoids +% having to modify the longtable template. But as \rownum is thus 0 in the +% "foot", the \sphinxSwitchCaseRowColor has to know how to handle negative +% inputs (in fact the -1 value), the Sphinx definition has no issue with that +% but any redefinition must be aware of this constraint. +\def\sphinxbooktabsspecialbottomrule{% + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ + \sphinxSwitchCaseRowColor{\numexpr\rownum-\@ne\relax}% + \gdef\CT@arc@{\color{sphinxTableRowColor}}% + }% + \specialrule{\dimexpr\aboverulesep+\sphinxbooktabscolorgapsoverhang\relax}% + {-\sphinxbooktabscolorgapsoverhang}{\z@}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + \specialrule{\heavyrulewidth}{\z@}{\belowbottomsep}% +}% +% +% MEMO: with longtable \sphinxtoprule, \sphinxmidrule and \sphinxbottomrule +% are evaluated at time of constructing the headers and footers as boxes +% (already typeset material and expanded macros; \sphinxbottomrule is also +% evaluated at very end of table body, i.e. "normally"). So the used colour +% to fill the booktabs gaps is decided during the headers and footers +% construction by longtable. Actually they are expanded twice: in firsthead +% then in head, respectively in foot and lastfoot. But in current design the +% header row colours are fixed, not alternating, so there is at least no +% coherence issue there. + +% The \spx@arrayrulewidth is used for some complex matters of merged +% cells size computations. +% tabularcolumns argument will override any global or local style and +% trigger the appropriate adjustment of \spx@arrayrulewidth. +% Notice that this will be bad if the table uses booktabs style +% but anyhow table with booktabs should not use any | separator. +\def\sphinxthistablewithvlinesstyle{% + \def\spx@arrayrulewidth{\arrayrulewidth}% + \let\sphinxvlinecrossing\sphinxtablevlinecrossing + \let\sphinxfixclines \sphinxtablefixclines +}% +\def\sphinxthistablewithnovlinesstyle{% + \def\spx@arrayrulewidth{\z@}% + \let\sphinxvlinecrossing\@gobble + % let's not bother to modify \sphinxfixclines, it works fine and is + % useful in standard style + no vline (only hlines and clines); + % besides, only one of vline or novline style macro is executed +}% + +% default is the standard style +\def\sphinxthistablewithglobalstyle{\sphinxthistablewithstandardstyle} + +\ifspx@opt@booktabs + \RequirePackage{booktabs} + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithbooktabsstyle} +\fi +\ifspx@opt@borderless + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithborderlessstyle} +\fi +% colorrows appends to the current globalstyle (standard, booktabs, or borderless) +\ifspx@opt@colorrows % let the globalstyle trigger the colorrows style on top of it + \expandafter\def\expandafter\sphinxthistablewithglobalstyle\expandafter + {\sphinxthistablewithglobalstyle + \sphinxthistablewithcolorrowsstyle + } +\fi + + \endinput diff --git a/sphinx/texinputs/sphinxpackagefootnote.sty b/sphinx/texinputs/sphinxpackagefootnote.sty index 6a7884f83bd..39d8cfacf20 100644 --- a/sphinx/texinputs/sphinxpackagefootnote.sty +++ b/sphinx/texinputs/sphinxpackagefootnote.sty @@ -1,6 +1,6 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{sphinxpackagefootnote}% - [2022/02/12 v4.5.0 Sphinx custom footnotehyper package (Sphinx team)] + [2022/08/15 v5.2.0 Sphinx custom footnotehyper package (Sphinx team)] %% %% Package: sphinxpackagefootnote %% Version: based on footnotehyper.sty 2021/02/04 v1.1d @@ -338,6 +338,7 @@ }% % slight reformulation for Sphinx \def\FNH@bad@makefntext@alert{% + \sphinxbuildwarning{badfootnotes}% \PackageWarningNoLine{sphinxpackagefootnote}% {Footnotes will be sub-optimal, sorry. This is due to the document class or^^J some package modifying macro \string\@makefntext.^^J diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index fbff3d906ed..0e2250c176f 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -97,8 +97,24 @@ def __init__(self, node: Element) -> None: self.body: List[str] = [] self.align = node.get('align', 'default') self.classes: List[str] = node.get('classes', []) + self.styles: List[str] = [] + if 'standard' in self.classes: + self.styles.append('standard') + elif 'borderless' in self.classes: + self.styles.append('borderless') + elif 'booktabs' in self.classes: + self.styles.append('booktabs') + if 'nocolorrows' in self.classes: + self.styles.append('nocolorrows') + elif 'colorrows' in self.classes: + self.styles.append('colorrows') self.colcount = 0 self.colspec: str = None + self.colsep: str = None + if 'booktabs' in self.styles or 'borderless' in self.styles: + self.colsep = '' + elif 'standard' in self.styles: + self.colsep = '|' self.colwidths: List[int] = [] self.has_problematic = False self.has_oldproblematic = False @@ -143,23 +159,30 @@ def get_colspec(self) -> str: This is what LaTeX calls the 'preamble argument' of the used table environment. - .. note:: the ``\\X`` and ``T`` column type specifiers are defined in ``sphinx.sty``. + .. note:: + + The ``\\X`` and ``T`` column type specifiers are defined in + ``sphinxlatextables.sty``. """ if self.colspec: return self.colspec - elif self.colwidths and 'colwidths-given' in self.classes: + + _colsep = self.colsep + if self.colwidths and 'colwidths-given' in self.classes: total = sum(self.colwidths) colspecs = [r'\X{%d}{%d}' % (width, total) for width in self.colwidths] - return '{|%s|}' % '|'.join(colspecs) + CR + return '{%s%s%s}' % (_colsep, _colsep.join(colspecs), _colsep) + CR elif self.has_problematic: - return r'{|*{%d}{\X{1}{%d}|}}' % (self.colcount, self.colcount) + CR + return r'{%s*{%d}{\X{1}{%d}%s}}' % (_colsep, self.colcount, + self.colcount, _colsep) + CR elif self.get_table_type() == 'tabulary': # sphinx.sty sets T to be J by default. - return '{|' + ('T|' * self.colcount) + '}' + CR + return '{' + _colsep + (('T' + _colsep) * self.colcount) + '}' + CR elif self.has_oldproblematic: - return r'{|*{%d}{\X{1}{%d}|}}' % (self.colcount, self.colcount) + CR + return r'{%s*{%d}{\X{1}{%d}%s}}' % (_colsep, self.colcount, + self.colcount, _colsep) + CR else: - return '{|' + ('l|' * self.colcount) + '}' + CR + return '{' + _colsep + (('l' + _colsep) * self.colcount) + '}' + CR def add_cell(self, height: int, width: int) -> None: """Adds a new cell to a table. @@ -857,8 +880,19 @@ def visit_table(self, node: Element) -> None: (self.curfilestack[-1], node.line or '')) self.tables.append(Table(node)) + if self.table.colsep is None: + self.table.colsep = '' if ( + 'booktabs' in self.builder.config.latex_table_style or + 'borderless' in self.builder.config.latex_table_style + ) else '|' if self.next_table_colspec: self.table.colspec = '{%s}' % self.next_table_colspec + CR + if '|' in self.table.colspec: + self.table.styles.append('vlines') + self.table.colsep = '|' + else: + self.table.styles.append('novlines') + self.table.colsep = '' if 'colwidths-given' in node.get('classes', []): logger.info(__('both tabularcolumns and :widths: option are given. ' ':widths: is ignored.'), location=node) @@ -896,6 +930,8 @@ def visit_thead(self, node: Element) -> None: self.pushbody(self.table.header) def depart_thead(self, node: Element) -> None: + if self.body and self.body[-1] == r'\sphinxhline': + self.body.pop() self.popbody() def visit_tbody(self, node: Element) -> None: @@ -903,11 +939,13 @@ def visit_tbody(self, node: Element) -> None: self.pushbody(self.table.body) def depart_tbody(self, node: Element) -> None: + if self.body and self.body[-1] == r'\sphinxhline': + self.body.pop() self.popbody() def visit_row(self, node: Element) -> None: self.table.col = 0 - + _colsep = self.table.colsep # fill columns if the row starts with the bottom of multirow cell while True: cell = self.table.cell(self.table.row, self.table.col) @@ -921,24 +959,35 @@ def visit_row(self, node: Element) -> None: # insert suitable strut for equalizing row heights in given multirow self.body.append(r'\sphinxtablestrut{%d}' % cell.cell_id) else: # use \multicolumn for wide multirow cell - self.body.append(r'\multicolumn{%d}{|l|}{\sphinxtablestrut{%d}}' % - (cell.width, cell.cell_id)) + self.body.append(r'\multicolumn{%d}{%sl%s}{\sphinxtablestrut{%d}}' % + (cell.width, _colsep, _colsep, cell.cell_id)) def depart_row(self, node: Element) -> None: self.body.append(r'\\' + CR) cells = [self.table.cell(self.table.row, i) for i in range(self.table.colcount)] underlined = [cell.row + cell.height == self.table.row + 1 for cell in cells] if all(underlined): - self.body.append(r'\hline') + self.body.append(r'\sphinxhline') else: i = 0 underlined.extend([False]) # sentinel - while i < len(underlined): - if underlined[i] is True: - j = underlined[i:].index(False) - self.body.append(r'\cline{%d-%d}' % (i + 1, i + j)) - i += j + if underlined[0] is False: + i = 1 + while i < self.table.colcount and underlined[i] is False: + if cells[i - 1].cell_id != cells[i].cell_id: + self.body.append(r'\sphinxvlinecrossing{%d}' % i) + i += 1 + while i < self.table.colcount: + # each time here underlined[i] is True + j = underlined[i:].index(False) + self.body.append(r'\sphinxcline{%d-%d}' % (i + 1, i + j)) + i += j i += 1 + while i < self.table.colcount and underlined[i] is False: + if cells[i - 1].cell_id != cells[i].cell_id: + self.body.append(r'\sphinxvlinecrossing{%d}' % i) + i += 1 + self.body.append(r'\sphinxfixclines{%d}' % self.table.colcount) self.table.row += 1 def visit_entry(self, node: Element) -> None: @@ -947,12 +996,14 @@ def visit_entry(self, node: Element) -> None: self.table.add_cell(node.get('morerows', 0) + 1, node.get('morecols', 0) + 1) cell = self.table.cell() context = '' + _colsep = self.table.colsep if cell.width > 1: if self.config.latex_use_latex_multicolumn: if self.table.col == 0: - self.body.append(r'\multicolumn{%d}{|l|}{%%' % cell.width + CR) + self.body.append(r'\multicolumn{%d}{%sl%s}{%%' % + (cell.width, _colsep, _colsep) + CR) else: - self.body.append(r'\multicolumn{%d}{l|}{%%' % cell.width + CR) + self.body.append(r'\multicolumn{%d}{l%s}{%%' % (cell.width, _colsep) + CR) context = '}%' + CR else: self.body.append(r'\sphinxstartmulticolumn{%d}%%' % cell.width + CR) @@ -992,6 +1043,7 @@ def depart_entry(self, node: Element) -> None: cell = self.table.cell() self.table.col += cell.width + _colsep = self.table.colsep # fill columns if next ones are a bottom of wide-multirow cell while True: @@ -999,16 +1051,16 @@ def depart_entry(self, node: Element) -> None: if nextcell is None: # not a bottom of multirow cell break else: # a bottom part of multirow cell - self.table.col += nextcell.width self.body.append('&') if nextcell.width == 1: # insert suitable strut for equalizing row heights in multirow # they also serve to clear colour panels which would hide the text self.body.append(r'\sphinxtablestrut{%d}' % nextcell.cell_id) else: - # use \multicolumn for wide multirow cell - self.body.append(r'\multicolumn{%d}{l|}{\sphinxtablestrut{%d}}' % - (nextcell.width, nextcell.cell_id)) + # use \multicolumn for not first row of wide multirow cell + self.body.append(r'\multicolumn{%d}{l%s}{\sphinxtablestrut{%d}}' % + (nextcell.width, _colsep, nextcell.cell_id)) + self.table.col += nextcell.width def visit_acks(self, node: Element) -> None: # this is a list in the source, but should be rendered as a diff --git a/tests/roots/test-latex-table/complex.rst b/tests/roots/test-latex-table/complex.rst index fa84f8266cf..d648ff194c4 100644 --- a/tests/roots/test-latex-table/complex.rst +++ b/tests/roots/test-latex-table/complex.rst @@ -4,6 +4,27 @@ complex tables grid table ---------- +.. rst-class:: nocolorrows + ++---------+---------+---------+ +| header1 | header2 | header3 | ++=========+=========+=========+ +| cell1-1 | cell1-2 | cell1-3 | ++---------+ +---------+ +| cell2-1 | | cell2-3 | ++ +---------+---------+ +| | cell3-2-par1 | ++---------+ | +| cell4-1 | cell3-2-par2 | ++---------+---------+---------+ +| cell5-1 | ++---------+---------+---------+ + +grid table with tabularcolumns having no vline +---------------------------------------------- + +.. tabularcolumns:: TTT + +---------+---------+---------+ | header1 | header2 | header3 | +=========+=========+=========+ @@ -26,6 +47,8 @@ table having ... * consecutive multirow at top of row (1-1 and 1-2) * consecutive multirow at end of row (1-4 and 1-5) +.. rst-class:: standard + +-----------+-----------+-----------+-----------+-----------+ | | | cell1-3 | | | | | +-----------+ | cell1-5 | diff --git a/tests/roots/test-latex-table/expects/complex_spanning_cell.tex b/tests/roots/test-latex-table/expects/complex_spanning_cell.tex index 966f39a955e..d2d61894251 100644 --- a/tests/roots/test-latex-table/expects/complex_spanning_cell.tex +++ b/tests/roots/test-latex-table/expects/complex_spanning_cell.tex @@ -14,10 +14,12 @@ \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithstandardstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|T|T|T|} -\hline -\sphinxmultirow{3}{1}{% +\sphinxtoprule +\sphinxtableatstartofbodyhook\sphinxmultirow{3}{1}{% \begin{varwidth}[t]{\sphinxcolwidth{1}{5}} \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -49,7 +51,7 @@ \vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% }% \\ -\cline{3-3}\sphinxtablestrut{1}&\sphinxtablestrut{2}&\sphinxmultirow{2}{6}{% +\sphinxvlinecrossing{1}\sphinxcline{3-3}\sphinxvlinecrossing{4}\sphinxfixclines{5}\sphinxtablestrut{1}&\sphinxtablestrut{2}&\sphinxmultirow{2}{6}{% \begin{varwidth}[t]{\sphinxcolwidth{1}{5}} \sphinxAtStartPar cell2\sphinxhyphen{}3 @@ -57,11 +59,11 @@ \vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% }% &\sphinxtablestrut{4}&\sphinxtablestrut{5}\\ -\cline{5-5}\sphinxtablestrut{1}&\sphinxtablestrut{2}&\sphinxtablestrut{6}&\sphinxtablestrut{4}& +\sphinxvlinecrossing{1}\sphinxvlinecrossing{2}\sphinxvlinecrossing{3}\sphinxcline{5-5}\sphinxfixclines{5}\sphinxtablestrut{1}&\sphinxtablestrut{2}&\sphinxtablestrut{6}&\sphinxtablestrut{4}& \sphinxAtStartPar cell3\sphinxhyphen{}5 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/gridtable.tex b/tests/roots/test-latex-table/expects/gridtable.tex index a71c9e202a0..407abe7f2c8 100644 --- a/tests/roots/test-latex-table/expects/gridtable.tex +++ b/tests/roots/test-latex-table/expects/gridtable.tex @@ -1,9 +1,11 @@ \label{\detokenize{complex:grid-table}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnocolorrowsstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|T|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -14,7 +16,8 @@ \sphinxAtStartPar header3 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 &\sphinxmultirow{2}{5}{% @@ -28,7 +31,7 @@ \sphinxAtStartPar cell1\sphinxhyphen{}3 \\ -\cline{1-1}\cline{3-3}\sphinxmultirow{2}{7}{% +\sphinxcline{1-1}\sphinxcline{3-3}\sphinxfixclines{3}\sphinxmultirow{2}{7}{% \begin{varwidth}[t]{\sphinxcolwidth{1}{3}} \sphinxAtStartPar cell2\sphinxhyphen{}1 @@ -39,7 +42,7 @@ \sphinxAtStartPar cell2\sphinxhyphen{}3 \\ -\cline{2-3}\sphinxtablestrut{7}&\sphinxstartmulticolumn{2}% +\sphinxcline{2-3}\sphinxfixclines{3}\sphinxtablestrut{7}&\sphinxstartmulticolumn{2}% \sphinxmultirow{2}{9}{% \begin{varwidth}[t]{\sphinxcolwidth{2}{3}} \sphinxAtStartPar @@ -52,11 +55,11 @@ }% \sphinxstopmulticolumn \\ -\cline{1-1} +\sphinxcline{1-1}\sphinxfixclines{3} \sphinxAtStartPar cell4\sphinxhyphen{}1 &\multicolumn{2}{l|}{\sphinxtablestrut{9}}\\ -\hline\sphinxstartmulticolumn{3}% +\sphinxhline\sphinxstartmulticolumn{3}% \begin{varwidth}[t]{\sphinxcolwidth{3}{3}} \sphinxAtStartPar cell5\sphinxhyphen{}1 @@ -64,7 +67,7 @@ \vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% \sphinxstopmulticolumn \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex b/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex new file mode 100644 index 00000000000..c77b99041ff --- /dev/null +++ b/tests/roots/test-latex-table/expects/gridtable_with_tabularcolumn.tex @@ -0,0 +1,73 @@ +\label{\detokenize{complex:grid-table-with-tabularcolumns-having-no-vline}} + +\begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnovlinesstyle +\centering +\begin{tabulary}{\linewidth}[t]{TTT} +\sphinxtoprule +\sphinxstyletheadfamily +\sphinxAtStartPar +header1 +&\sphinxstyletheadfamily +\sphinxAtStartPar +header2 +&\sphinxstyletheadfamily +\sphinxAtStartPar +header3 +\\ +\sphinxmidrule +\sphinxtableatstartofbodyhook +\sphinxAtStartPar +cell1\sphinxhyphen{}1 +&\sphinxmultirow{2}{5}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +cell1\sphinxhyphen{}2 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +& +\sphinxAtStartPar +cell1\sphinxhyphen{}3 +\\ +\sphinxcline{1-1}\sphinxcline{3-3}\sphinxfixclines{3}\sphinxmultirow{2}{7}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +cell2\sphinxhyphen{}1 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +&\sphinxtablestrut{5}& +\sphinxAtStartPar +cell2\sphinxhyphen{}3 +\\ +\sphinxcline{2-3}\sphinxfixclines{3}\sphinxtablestrut{7}&\sphinxstartmulticolumn{2}% +\sphinxmultirow{2}{9}{% +\begin{varwidth}[t]{\sphinxcolwidth{2}{3}} +\sphinxAtStartPar +cell3\sphinxhyphen{}2\sphinxhyphen{}par1 + +\sphinxAtStartPar +cell3\sphinxhyphen{}2\sphinxhyphen{}par2 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +\sphinxstopmulticolumn +\\ +\sphinxcline{1-1}\sphinxfixclines{3} +\sphinxAtStartPar +cell4\sphinxhyphen{}1 +&\multicolumn{2}{l}{\sphinxtablestrut{9}}\\ +\sphinxhline\sphinxstartmulticolumn{3}% +\begin{varwidth}[t]{\sphinxcolwidth{3}{3}} +\sphinxAtStartPar +cell5\sphinxhyphen{}1 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +\sphinxstopmulticolumn +\\ +\sphinxbottomrule +\end{tabulary} +\sphinxtableafterendhook\par +\sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable.tex b/tests/roots/test-latex-table/expects/longtable.tex index e2138ad58fe..754d10249e1 100644 --- a/tests/roots/test-latex-table/expects/longtable.tex +++ b/tests/roots/test-latex-table/expects/longtable.tex @@ -1,7 +1,11 @@ \label{\detokenize{longtable:longtable}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithborderlessstyle +\begin{longtable}[c]{ll} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +13,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +27,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -37,19 +45,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_align.tex b/tests/roots/test-latex-table/expects/longtable_having_align.tex index 764ef55f301..dcf8f83a1a2 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_align.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_align.tex @@ -1,7 +1,10 @@ \label{\detokenize{longtable:longtable-having-align-option}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[r]{|l|l|} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[r]{|l|l|} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +12,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +26,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -37,19 +44,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_caption.tex b/tests/roots/test-latex-table/expects/longtable_having_caption.tex index 0ca5506be9a..dd2a87fa68f 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_caption.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_caption.tex @@ -1,9 +1,12 @@ \label{\detokenize{longtable:longtable-having-caption}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|l|l|} +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|l|l|} \sphinxthelongtablecaptionisattop \caption{caption for longtable\strut}\label{\detokenize{longtable:id1}}\\*[\sphinxlongtablecapskipadjust] -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,12 +14,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -24,14 +28,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -39,19 +46,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex index 9551a0a3b25..8258612f50c 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_problematic_cell.tex @@ -1,7 +1,10 @@ \label{\detokenize{longtable:longtable-having-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{2}{\X{1}{2}|}} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +12,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +26,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{itemize} \item {} \sphinxAtStartPar @@ -44,19 +51,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex index e54f8acec03..44114ce78c2 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_stub_columns_and_problematic_cell.tex @@ -1,7 +1,10 @@ \label{\detokenize{longtable:longtable-having-both-stub-columns-and-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{3}{\X{1}{3}|}} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{3}{\X{1}{3}|}} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -12,12 +15,13 @@ \sphinxAtStartPar header3 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{3}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{3}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -28,14 +32,17 @@ \sphinxAtStartPar header3 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{3}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{3}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxstyletheadfamily \begin{itemize} \item {} \sphinxAtStartPar @@ -53,7 +60,7 @@ \sphinxAtStartPar notinstub1\sphinxhyphen{}3 \\ -\hline\sphinxstyletheadfamily +\sphinxhline\sphinxstyletheadfamily \sphinxAtStartPar cell2\sphinxhyphen{}1 &\sphinxstyletheadfamily @@ -63,5 +70,8 @@ \sphinxAtStartPar cell2\sphinxhyphen{}3 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex index a0e7ecfcd07..fc78914a9cf 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex @@ -1,7 +1,10 @@ \label{\detokenize{longtable:longtable-having-verbatim}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|*{2}{\X{1}{2}|}} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|*{2}{\X{1}{2}|}} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +12,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +26,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} @@ -38,19 +45,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths.tex b/tests/roots/test-latex-table/expects/longtable_having_widths.tex index cdd0e7a2b32..5bf1507a7a4 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths.tex @@ -1,7 +1,11 @@ \label{\detokenize{longtable:longtable-having-widths-option}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} -\hline\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}% +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} +\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}% +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +13,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +27,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -37,22 +45,25 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} \sphinxAtStartPar See {\hyperref[\detokenize{longtable:mylongtable}]{\sphinxcrossref{mylongtable}}}, same as {\hyperref[\detokenize{longtable:namedlongtable}]{\sphinxcrossref{\DUrole{std,std-ref}{this one}}}}. diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex index ea868ffe4ea..bf9192009ca 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths_and_problematic_cell.tex @@ -1,7 +1,10 @@ \label{\detokenize{longtable:longtable-having-both-widths-and-problematic-cell}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\begin{longtable}[c]{|\X{30}{100}|\X{70}{100}|} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +12,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +26,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \begin{itemize} \item {} \sphinxAtStartPar @@ -44,19 +51,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex b/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex index 426086de5ce..6383d9d5667 100644 --- a/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex +++ b/tests/roots/test-latex-table/expects/longtable_with_tabularcolumn.tex @@ -1,7 +1,11 @@ \label{\detokenize{longtable:longtable-with-tabularcolumn}} -\begin{savenotes}\sphinxatlongtablestart\begin{longtable}[c]{|c|c|} -\hline +\begin{savenotes} +\sphinxatlongtablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithvlinesstyle +\begin{longtable}[c]{|c|c|} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -9,12 +13,13 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endfirsthead -\multicolumn{2}{c}% -{\makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}}\\ -\hline +\multicolumn{2}{c}{\sphinxnorowcolor + \makebox[0pt]{\sphinxtablecontinued{\tablename\ \thetable{} \textendash{} continued from previous page}}% +}\\ +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -22,14 +27,17 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule \endhead -\hline -\multicolumn{2}{r}{\makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}}\\ +\sphinxbottomrule +\multicolumn{2}{r}{\sphinxnorowcolor + \makebox[0pt][r]{\sphinxtablecontinued{continues on next page}}% +}\\ \endfoot \endlastfoot +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 @@ -37,19 +45,22 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline -\end{longtable}\sphinxatlongtableend\end{savenotes} +\sphinxbottomrule +\end{longtable} +\sphinxtableafterendhook +\sphinxatlongtableend +\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/simple_table.tex b/tests/roots/test-latex-table/expects/simple_table.tex index a06bfb1cfad..7bd85c737b2 100644 --- a/tests/roots/test-latex-table/expects/simple_table.tex +++ b/tests/roots/test-latex-table/expects/simple_table.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:simple-table}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabulary}{\linewidth}[t]{|T|T|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,28 +12,29 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_caption.tex b/tests/roots/test-latex-table/expects/table_having_caption.tex index 33a5f1d8fdb..f2ce5536021 100644 --- a/tests/roots/test-latex-table/expects/table_having_caption.tex +++ b/tests/roots/test-latex-table/expects/table_having_caption.tex @@ -1,13 +1,14 @@ \label{\detokenize{tabular:table-having-caption}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \sphinxcapstartof{table} \sphinxthecaptionisattop \sphinxcaption{caption for table}\label{\detokenize{tabular:id1}} \sphinxaftertopcaption \begin{tabulary}{\linewidth}[t]{|T|T|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -15,28 +16,29 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex index c5c57e2f758..7d7ad4b715b 100644 --- a/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_problematic_cell.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{2}{\X{1}{2}|}} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,7 +12,8 @@ \sphinxAtStartPar header2 \\ -\hline\begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\begin{itemize} \item {} \sphinxAtStartPar item1 @@ -25,21 +27,21 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex index 13c48a21322..fbd797a1bd3 100644 --- a/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_stub_columns_and_problematic_cell.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-both-stub-columns-and-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{3}{\X{1}{3}|}} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -14,7 +15,8 @@ \sphinxAtStartPar header3 \\ -\hline\sphinxstyletheadfamily \begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\sphinxstyletheadfamily \begin{itemize} \item {} \sphinxAtStartPar instub1\sphinxhyphen{}1a @@ -31,7 +33,7 @@ \sphinxAtStartPar notinstub1\sphinxhyphen{}3 \\ -\hline\sphinxstyletheadfamily +\sphinxhline\sphinxstyletheadfamily \sphinxAtStartPar cell2\sphinxhyphen{}1 &\sphinxstyletheadfamily @@ -41,7 +43,7 @@ \sphinxAtStartPar cell2\sphinxhyphen{}3 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex b/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex index c1a440558e6..9acd9a86d46 100644 --- a/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex +++ b/tests/roots/test-latex-table/expects/table_having_threeparagraphs_cell_in_first_col.tex @@ -1,14 +1,16 @@ \label{\detokenize{tabular:table-with-cell-in-first-column-having-three-paragraphs}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabulary}{\linewidth}[t]{|T|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1\sphinxhyphen{}par1 @@ -18,7 +20,7 @@ \sphinxAtStartPar cell1\sphinxhyphen{}1\sphinxhyphen{}par3 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_verbatim.tex b/tests/roots/test-latex-table/expects/table_having_verbatim.tex index 23faac55e19..a002de58618 100644 --- a/tests/roots/test-latex-table/expects/table_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/table_having_verbatim.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-verbatim}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|*{2}{\X{1}{2}|}} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,7 +12,8 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} \end{sphinxVerbatimintable} @@ -19,21 +21,21 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/table_having_widths.tex b/tests/roots/test-latex-table/expects/table_having_widths.tex index d01a40576bb..fe5f4c44d72 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths.tex @@ -1,10 +1,13 @@ \label{\detokenize{tabular:table-having-widths-option}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithbooktabsstyle +\sphinxthistablewithcolorrowsstyle \centering \phantomsection\label{\detokenize{tabular:namedtabular}}\label{\detokenize{tabular:mytabular}}\nobreak -\begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} -\hline +\begin{tabular}[t]{\X{30}{100}\X{70}{100}} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -12,30 +15,31 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} \sphinxAtStartPar diff --git a/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex b/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex index ca6b697e5ec..1baf92c1ae6 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths_and_problematic_cell.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-both-widths-and-problematic-cell}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \centering \begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,7 +12,8 @@ \sphinxAtStartPar header2 \\ -\hline\begin{itemize} +\sphinxmidrule +\sphinxtableatstartofbodyhook\begin{itemize} \item {} \sphinxAtStartPar item1 @@ -25,21 +27,21 @@ \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabular_having_widths.tex b/tests/roots/test-latex-table/expects/tabular_having_widths.tex index 596ba4868e3..15321d693cf 100644 --- a/tests/roots/test-latex-table/expects/tabular_having_widths.tex +++ b/tests/roots/test-latex-table/expects/tabular_having_widths.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-align-option-tabular}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \raggedright \begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,28 +12,29 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabular} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabularcolumn.tex b/tests/roots/test-latex-table/expects/tabularcolumn.tex index c020e0cb4eb..fcb01be3f50 100644 --- a/tests/roots/test-latex-table/expects/tabularcolumn.tex +++ b/tests/roots/test-latex-table/expects/tabularcolumn.tex @@ -1,9 +1,11 @@ \label{\detokenize{tabular:table-with-tabularcolumn}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\sphinxthistablewithnovlinesstyle \centering -\begin{tabulary}{\linewidth}[t]{|c|c|} -\hline +\begin{tabulary}{\linewidth}[t]{cc} +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,28 +13,29 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/expects/tabulary_having_widths.tex b/tests/roots/test-latex-table/expects/tabulary_having_widths.tex index 0b42fb0cfa3..24634163010 100644 --- a/tests/roots/test-latex-table/expects/tabulary_having_widths.tex +++ b/tests/roots/test-latex-table/expects/tabulary_having_widths.tex @@ -1,9 +1,10 @@ \label{\detokenize{tabular:table-having-align-option-tabulary}} \begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle \raggedleft \begin{tabulary}{\linewidth}[t]{|T|T|} -\hline +\sphinxtoprule \sphinxstyletheadfamily \sphinxAtStartPar header1 @@ -11,28 +12,29 @@ \sphinxAtStartPar header2 \\ -\hline +\sphinxmidrule +\sphinxtableatstartofbodyhook \sphinxAtStartPar cell1\sphinxhyphen{}1 & \sphinxAtStartPar cell1\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell2\sphinxhyphen{}1 & \sphinxAtStartPar cell2\sphinxhyphen{}2 \\ -\hline +\sphinxhline \sphinxAtStartPar cell3\sphinxhyphen{}1 & \sphinxAtStartPar cell3\sphinxhyphen{}2 \\ -\hline +\sphinxbottomrule \end{tabulary} -\par +\sphinxtableafterendhook\par \sphinxattableend\end{savenotes} diff --git a/tests/roots/test-latex-table/longtable.rst b/tests/roots/test-latex-table/longtable.rst index bace9d4d2d8..da6fa5c5cec 100644 --- a/tests/roots/test-latex-table/longtable.rst +++ b/tests/roots/test-latex-table/longtable.rst @@ -5,7 +5,7 @@ longtable --------- .. table:: - :class: longtable + :class: longtable, borderless ======= ======= header1 header2 diff --git a/tests/roots/test-latex-table/tabular.rst b/tests/roots/test-latex-table/tabular.rst index 7f090954004..15db823a05b 100644 --- a/tests/roots/test-latex-table/tabular.rst +++ b/tests/roots/test-latex-table/tabular.rst @@ -20,6 +20,7 @@ table having :widths: option .. table:: :widths: 30,70 :name: namedtabular + :class: booktabs, colorrows ======= ======= header1 header2 @@ -63,7 +64,7 @@ table having :align: option (tabular) table with tabularcolumn ------------------------ -.. tabularcolumns:: |c|c| +.. tabularcolumns:: cc ======= ======= header1 header2 diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index efdbcb29878..ae141a4f245 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -22,7 +22,8 @@ DOCCLASSES = ['howto', 'manual'] STYLEFILES = ['article.cls', 'fancyhdr.sty', 'titlesec.sty', 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty', - 'fncychap.sty', 'geometry.sty', 'kvoptions.sty', 'hyperref.sty'] + 'fncychap.sty', 'geometry.sty', 'kvoptions.sty', 'hyperref.sty', + 'booktabs.sty'] LATEX_WARNINGS = ENV_WARNINGS + """\ %(root)s/index.rst:\\d+: WARNING: unknown option: '&option' @@ -90,6 +91,10 @@ def skip_if_stylefiles_notfound(testfunc): def test_build_latex_doc(app, status, warning, engine, docclass): app.config.latex_engine = engine app.config.latex_documents = [app.config.latex_documents[0][:4] + (docclass,)] + if engine == 'xelatex': + app.config.latex_table_style = ['booktabs'] + elif engine == 'lualatex': + app.config.latex_table_style = ['colorrows'] app.builder.init() LaTeXTranslator.ignore_missing_images = True @@ -723,7 +728,8 @@ def test_footnote(app, status, warning): assert '\\sphinxcite{footnote:bar}' in result assert ('\\bibitem[bar]{footnote:bar}\n\\sphinxAtStartPar\ncite\n') in result assert '\\sphinxcaption{Table caption \\sphinxfootnotemark[4]' in result - assert ('\\hline%\n\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n' + assert ('\\sphinxmidrule\n\\sphinxtableatstartofbodyhook%\n' + '\\begin{footnotetext}[4]\\sphinxAtStartFootnote\n' 'footnote in table caption\n%\n\\end{footnotetext}\\ignorespaces %\n' '\\begin{footnotetext}[5]\\sphinxAtStartFootnote\n' 'footnote in table header\n%\n\\end{footnotetext}\\ignorespaces ' @@ -731,9 +737,9 @@ def test_footnote(app, status, warning): 'VIDIOC\\_CROPCAP\n&\n\\sphinxAtStartPar\n') in result assert ('Information about VIDIOC\\_CROPCAP %\n' '\\begin{footnote}[6]\\sphinxAtStartFootnote\n' - 'footnote in table not in header\n%\n\\end{footnote}\n\\\\\n\\hline\n' - '\\end{tabulary}\n' - '\\par\n\\sphinxattableend\\end{savenotes}\n') in result + 'footnote in table not in header\n%\n\\end{footnote}\n\\\\\n' + '\\sphinxbottomrule\n\\end{tabulary}\n' + '\\sphinxtableafterendhook\\par\n\\sphinxattableend\\end{savenotes}\n') in result @pytest.mark.sphinx('latex', testroot='footnotes') @@ -761,7 +767,8 @@ def test_reference_in_caption_and_codeblock_in_footnote(app, status, warning): 'caption of normal table}\\label{\\detokenize{index:id36}}') in result assert ('\\caption{footnote \\sphinxfootnotemark[10] ' 'in caption \\sphinxfootnotemark[11] of longtable\\strut}') in result - assert ('\\endlastfoot\n%\n\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n' + assert ('\\endlastfoot\n\\sphinxtableatstartofbodyhook\n%\n' + '\\begin{footnotetext}[10]\\sphinxAtStartFootnote\n' 'Foot note in longtable\n%\n\\end{footnotetext}\\ignorespaces %\n' '\\begin{footnotetext}[11]\\sphinxAtStartFootnote\n' 'Second footnote in caption of longtable\n') in result @@ -1309,12 +1316,35 @@ def get_expected(name): expected = get_expected('gridtable') assert actual == expected + # grid table with tabularcolumns + # MEMO: filename should end with tabularcolumns but tabularcolumn has been + # used in existing other cases + actual = tables['grid table with tabularcolumns having no vline'] + expected = get_expected('gridtable_with_tabularcolumn') + assert actual == expected + # complex spanning cell actual = tables['complex spanning cell'] expected = get_expected('complex_spanning_cell') assert actual == expected +@pytest.mark.sphinx('latex', testroot='latex-table', + confoverrides={'latex_table_style': ['booktabs', 'colorrows']}) +def test_latex_table_with_booktabs_and_colorrows(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'python.tex').read_text(encoding='utf8') + assert r'\PassOptionsToPackage{booktabs}{sphinx}' in result + assert r'\PassOptionsToPackage{colorrows}{sphinx}' in result + # tabularcolumns + assert r'\begin{longtable}[c]{|c|c|}' in result + # class: standard + assert r'\begin{tabulary}{\linewidth}[t]{|T|T|T|T|T|}' in result + assert r'\begin{longtable}[c]{ll}' in result + assert r'\begin{tabular}[t]{*{2}{\X{1}{2}}}' in result + assert r'\begin{tabular}[t]{\X{30}{100}\X{70}{100}}' in result + + @pytest.mark.sphinx('latex', testroot='latex-table', confoverrides={'templates_path': ['_mytemplates/latex']}) def test_latex_table_custom_template_caseA(app, status, warning):