% \iffalse meta-comment % vim: tw=80 spl=en % %% File: cellprops.dtx (C) Copyright 2016-2019 RIVAUD Julien %% %% It may be distributed and/or modified under the conditions of the %% General Public License (GPL), either version 3 of this %% license or (at your option) any later version. % %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. \NeedsTeXFormat{LaTeX2e}[1995/12/01] \RequirePackage{expl3}[2018/06/19] \def\ExplFileName{cellprops} \def\ExplFileDescription{CSS-like cell and table properties} \def\ExplFileDate{2019/09/29} \def\ExplFileVersion{1.6} % %<*driver> \documentclass[full]{l3doc} \usepackage[english]{babel} \usepackage{longtable} \usepackage{cellprops} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \textsf{\ExplFileName} package\\ \ExplFileDescription^^A % \thanks{This file describes v\ExplFileVersion, % last revised \ExplFileDate.}^^A % } % % \author{^^A % Julien ``\_FrnchFrgg\_'' \textsc{Rivaud}\thanks % {^^A % E-mail: % \href{mailto:frnchfrgg@free.fr} % {frnchfrgg@free.fr}^^A % }^^A % } % % \date{Released \ExplFileDate} % % \maketitle % % \begin{documentation} % % % % \section{\pkg{\ExplFileName} documentation} % % This package reworks the internals of \env{tabular}, \env{array}, and similar % constructs, and adds a \cs{cellprops} command accepting CSS-like selectors and % properties. It implements the "border-collapse: separate" CSS model. % % It depends on \pkg{mdwtab}, \pkg{xcolor} and of course \pkg{expl3} and % \pkg{xparse}. % % \pkg{cellprops} default settings mimick the LaTeX layout, that is left and % right padding equal to "\tabcolsep" or "\arraycolsep", zero top and bottom % padding, but minimum height and depth corresponding to the table strut box. % % I recommend to add globally: %\begin{verbatim} %\cellprops{ td { padding: 1ex; min-height: 0pt; min-depth: 0pt; } } %\end{verbatim} % so that you get better-looking tables by default. % % \subsection{Examples} % % To produce: % \[ % \cellprops{ % td { % padding: 1ex; % min-height: 0pt; % min-depth: 0pt; % border-style: none solid solid none; % text-align: center; % } % table { % background-color: black!5!white; % } % tr:nth-child(even) { % background-color: black!15!white; % } % td:nth-child(even) { % background-color: yellow!20!white % } % tr:nth-child(even) td:nth-child(even) { % background-color: yellow!50!white; % } % tr:first-child td { % border-top-style: solid; % } % td:first-child { % border-left-style: solid; % math-mode: text; % text-align: left; % } % } % \begin{array}{nnnp{5em}} % This is text & A_2 & A_3 & A_4 \\ % B1 & This is maths & B_3 & \\ % C1 & C_2 & X & Y \\ % D1 & D_2 & DX & v \\ % & F & \int_a^b f(t) dt & v \\ % \end{array} % \] % you can use: %\begin{verbatim} % \[ % \cellprops{ % td { % padding: 1ex; % min-height: 0pt; % min-depth: 0pt; % border-style: none solid solid none; % text-align: center; % } % table { % background-color: black!5!white; % } % tr:nth-child(even) { % background-color: black!15!white; % } % td:nth-child(even) { % background-color: yellow!20!white % } % tr:nth-child(even) td:nth-child(even) { % background-color: yellow!50!white; % } % tr:first-child td { % border-top-style: solid; % } % td:first-child { % border-left-style: solid; % math-mode: text; % text-align: left; % } % } % \begin{array}{nnnn} % This is text & A_2 & A_3 & A_4 \\ % B1 & This is maths & B_3 & \\ % C1 & C_2 & X & Y \\ % D1 & D_2 & DX & v \\ % E & F & \int_a^b f(t) dt & v \\ % \end{array} % \] %\end{verbatim} % % You can also use the \env{longtable} environment: % %\begingroup % %\cellprops{ % td { border: thin solid black; } % tr:nth-child(4n) td:first-child, % tr:nth-child(4n+1) td:nth-child(2), % tr:nth-child(4n+2) td:nth-child(3), % tr:nth-child(4n+3) td:nth-child(4) { % border: thick solid red; % } %} %\begin{longtable}{nnnn} % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ % aaaaa & baaaa & caaaaa & dbbbb \\ %\end{longtable} % %\endgroup % % This table has been produced by: %\begin{verbatim} %\cellprops{ % td { border: thin solid black; } % tr:nth-child(4n) td:first-child, % tr:nth-child(4n+1) td:nth-child(2), % tr:nth-child(4n+2) td:nth-child(3), % tr:nth-child(4n+3) td:nth-child(4) { % border: thick solid red; % } %} %\begin{longtable}{nnnn} % aaaaa & baaaa & caaaaa & dbbbb \\ % ... % aaaaa & baaaa & caaaaa & dbbbb \\ %\end{longtable} %\end{verbatim} % % \subsection{Usage guide} % % \def\OR{\string| } % % \def\bracket#1{\<#1>:} % \def\<#1>{{\normalfont<\textsl{#1}>}} % \begin{description}[format=\bracket, % wide,leftmargin=9em,labelwidth=!,labelsep=0pt, % ] % \item[usage] "'\cellprops{'" [ \ "'{'" \ "'}'" ]* "'}'" % \item[selectors] \ ["," \ ] % \item[selector] [\ "' '"] \ % \item[element1] % "'table'" \OR % "'tr'"[\] ["' '" \] \OR % \ % \item[element2] "'td'"[\] ["' '" \] \OR \ % \item[parbox] "'p'" % \item[pseudo-class] "':nth-child('"\"')" % \item[nth] \ \OR "'odd'" \OR "'even'" \OR \"'n+'"\ % \item[properties] [ \ "';'" ]* % \item[property] % "'padding: '" ( \ ) \{1,4\} \OR \\ % "'padding-top: '" \ \OR \\ % "'padding-right: '" \ \OR \\ % "'padding-bottom: '" \ \OR \\ % "'padding-left: '" \ \OR \\ % "'min-height: '" \ \OR \\ % "'min-depth: '" \ \OR \\ % "'min-width: '" \ \OR \\ % "'text-align: '" ( "'left'" \OR "'right'" \OR "'center'" ) \OR \\ % "'math-mode: '" ( "'text'" \OR "'math'" \OR "'auto'" ) \OR \\ % "'color: '" \ \OR \\ % "'background-color: '" ( \ \OR "'transparent'" ) \OR \\ % "'border: '" [ \ ] [ \ ] [ \ ] \OR \\ % "'border-top: '" [ \ ] [ \ ] [ \ ] \OR \\ % "'border-right: '" [ \ ] [ \ ] [ \ ] \OR \\ % "'border-bottom: '" [ \ ] [ \ ] [ \ ] \OR \\ % "'border-left: '" [ \ ] [ \ ] [ \ ] \OR \\ % "'border-width: '" ( \ ) \{1,4\} \OR \\ % "'border-top-width: '" \ ) \OR \\ % "'border-right-width: '" \ ) \OR \\ % "'border-bottom-width: '" \ ) \OR \\ % "'border-left-width: '" \ ) \OR \\ % "'border-style: '" ( \ ) \{1,4\} \OR \\ % "'border-top-style: '" \ ) \OR \\ % "'border-right-style: '" \ ) \OR \\ % "'border-bottom-style: '" \ ) \OR \\ % "'border-left-style: '" \ ) \OR \\ % "'border-color: '" ( \ ) \{1,4\} \OR \\ % "'border-top-color: '" \ ) \OR \\ % "'border-right-color: '" \ ) \OR \\ % "'border-bottom-color: '" \ ) \OR \\ % "'border-left-color: '" \ ) % \item[color] "'inherit'" \OR \ \OR \\ % "'rgb('"\"','"\"','"\"')'" \OR \\ % "'hsl('"\"','"\"','"\"')'" % \end{description} % % Most of these properties are straight-forward. You should check a % CSS documentation to get more information. A very good source is the Mozilla % Developer Network. % % Here are the supported column types: % \begin{itemize} % \item "n": The most basic cell type, hbox, honoring all properties. % \item "l", "c" and "r": Same as "n" but with forced "text-align". % \item "Ml", "Mc" and "Mr": Same as column "l", "c" and "r" but enforces % "math-mode: math". The net effect is that "Mc" will create a centered % column whose contents are in non-display math mode. % \item "T"\: Same as "M"\ but enforces "math-mode: text". % \item "p{"\"}", "m"\ and "b"\: parbox cell with the % corresponding vertical alignment (\cs{vtop}, \cs{vcenter} or \cs{vbox}). % \item "*{"\"}{"\"}": same as in \pkg{array} or % \pkg{mdwtab}. % \item ">{"\"}" and "<{"\"}": % same as in \pkg{array} or \pkg{mdwtab}. % \item You can try to use constructs of \pkg{array} or \pkg{mdwtab}, but they % might alter the function of \pkg{cellprops}. Most should be fine though. % \end{itemize} % The intended usage is to use "n"-type columns and set the properties with CSS, % but \LaTeX-like columns in the preamble are often less verbose. % % Details for some properties: % % \begin{itemize} % \item "math-mode: auto" means that the cell will be in math mode in % environments \env{array}, \env{matrix}, \dots, and in text mode in % environments like \env{tabular}, \dots % \item "background-color" is only painted on the cell, and "transparent" % actually means "inherit" except that if all values encountered are % "inherit"/"transparent" no background is painted at all. That means that % (currently) you cannot paint a row in some color and rely on % transparency to have it bleed through a cell background. % \item There are no columns in the CSS object model so you have to use % "td:nth-child()" to select a column. Currently, cells spanning several % columns actually increase the child count by the number of column they % span, so that nth-child can still be used to select columns. % This is not consistent with the CSS specification. % \item Any ":nth-child("$A$"n+"$B$")" or ":nth-child("$A$"n)" % or ":nth-child("$B$")" is supported, with arbitrary $A$~and~$B$. The % performance will slowly degrade the more different~$A$ are active % (but if in a \TeX\ group, they will become inactive again when leaving % the group). \emph{A big difference} with the CSS specification is that % currently $n$ is not enforced non-negative. In particular % ":nth-child(2n+8)" \emph{will} match for the second element. This also % prevents tricks like ":nth-child(-n+3)". I am investigating how to % handle those without slowing down the general case. % \end{itemize} % % \subsection{Compatibility} % % This package has been tested compatible with \pkg{diagbox}, \pkg{spreadtab}, % \pkg{collcell}. Compatibility with \pkg{longtable} has been specifically taken % care of, provided \pkg{cellprops} is loaded afterwards. Table packages that % only introduce new column types should be loaded after \pkg{mdwtab}, so either % you load \pkg{mdwtab} manually and load your package in between \pkg{mdwtab} % and \pkg{cellprops}, or you load your package after \pkg{cellprops} (provided % it doesn't overwrite the machinery). % % \subsection{TODO} % % Add a test suite with compatibility tests. Improve % the documentation, and test more \LaTeX\ table constructs and preamble column % types. Enforce $n\ge0$ in ":nth-child" selectors to match the CSS % specification. % % \end{documentation} % % \begin{implementation} % % \section{\pkg{\ExplFileName} implementation} % % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} %<@@=cellprops> % \end{macrocode} % % \begin{macrocode} \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \RequirePackage{xparse} \RequirePackage{xcolor} \RequirePackage{etoolbox} % \end{macrocode} % % \subsection{Loading and fixing \pkg{mdwtab}} % % There is a bug in the command \cs{colpop} of \pkg{mdwtab}: instead of just % popping one name in the stack of column sets currently used, it empties it % completely because one \cs{expandafter} is missing. This is proof that not % many package authors really use this API as recommended by Mark % \textsc{Wooding}\ldots We thus load \pkg{mdwtab} and fix \cs{colpop}. % % \begin{macrocode} \RequirePackage{mdwtab} \cs_set_nopar:Npn \tab@pop #1 { \tl_set:Nx #1 { \tl_tail:N #1 } } % \end{macrocode} % % \subsection{Parsing CSS properties} % % Properties are parsed once at setting time, by expandable parsers that leave % definitions in the input stream. All these resulting definitions are saved % in a token list that will be expanded when we need the values. The goal is % to have multiple token lists for multiple contexts, yet not to do the full % parsing dance once per cell. % % \begin{variable}{\l_@@_property_value__tl} % \begin{macro}{\@@_generic_setter:nnn} % \begin{macro}{\@@_get_property:n} % \begin{macro}{\@@_get_property:nN} % We first define a generic setter which just uses % \cs{l_@@_property_value__tl} to store the value of the property. We % define getters, one that leaves the value in the stream, and one saving the % value in a token list. % % \begin{macrocode} \cs_new:Nn \@@_generic_setter:nnn { \exp_not:N \tl_set:Nn \exp_not:c { l_@@_property_value_#2_tl } {#1 {#3}} } \cs_set_nopar:Nn \@@_get_property:n { \tl_use:c { l_@@_property_value_#1_tl } } \cs_new_protected_nopar:Nn \@@_get_property:nN { \tl_if_exist:cTF { l_@@_property_value_#1_tl } { \tl_set_eq:Nc #2 { l_@@_property_value_#1_tl } }{ \tl_clear:N #2 } } % \end{macrocode} % % \end{macro} % \end{macro} % \end{macro} % \end{variable} % % \begin{macro}{\@@_property_type_:nn} % \begin{macro}{\@@_define_properties:nn} % The control sequence \cs{_@@_property_type_:nn} holds the setter for % the property \meta{name}. It can be set by the following helper: % % \begin{macrocode} \cs_new_protected:Nn \@@_define_properties:nn { \clist_map_inline:nn {#2} { \cs_set:cpn { _@@_property_type_##1:nn } {#1} } } % \end{macrocode} % % \end{macro} % \end{macro} % % \begin{macro}{\@@_use_setter:nn} % Sometimes we need to use a setter right away rather than save its action % somewhere. The following helper does that with an x-expansion. % % \begin{macrocode} \cs_new:Nn \@@_delegate_setter:nn { \use:c {_@@_property_type_#1:nn} {#1} {#2} } \cs_new_protected:Nn \@@_use_setter:nn { \use:x { \@@_delegate_setter:nn {#1} {#2} } } % \end{macrocode} % % \end{macro} % % \begin{macrocode} \cs_new_protected:Nn \@@_parse_properties:Nn { \tl_clear:N #1 \seq_set_split:Nnn \l_tmpa_seq {;} {#2} \seq_map_inline:Nn \l_tmpa_seq { \tl_if_empty:nF {##1} { \exp_args:NNV \seq_set_split:Nnn \l_tmpb_seq \c_colon_str {##1} \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} = { 2 } { \seq_get_left:NN \l_tmpb_seq \l_tmpa_tl \exp_args:NNV \str_set:Nn \l_tmpa_str \l_tmpa_tl \seq_get_right:NN \l_tmpb_seq \l_tmpa_tl \cs_if_exist:cTF { _@@_property_type_\l_tmpa_str :nn } { \tl_put_right:Nx #1 { \exp_args:NVV \@@_delegate_setter:nn \l_tmpa_str \l_tmpa_tl } }{ % TODO: ERROR-no property with that name } }{ % TODO: ERROR-too many : or none at all } } } } \cs_new:Nn \@@_fourval_setter:nnnnnn { \@@_fourval_setter_aux:w {#1}{#2}{#3}{#4}#6~{\q_no_value}~{\q_no_value}~{\q_no_value}~\q_stop } \cs_new:Npn \@@_fourval_setter_aux:w #1#2#3#4#5~#6~#7~#8~#9\q_stop { \@@_delegate_setter:nn {#1} {#5} \quark_if_no_value:nTF {#6} { \@@_delegate_setter:nn {#2} {#5} \@@_delegate_setter:nn {#4} {#5} }{ \@@_delegate_setter:nn {#2} {#6} \quark_if_no_value:nTF {#8} { \@@_delegate_setter:nn {#4} {#6} }{ \@@_delegate_setter:nn {#4} {#8} } } \quark_if_no_value:nTF {#7} { \@@_delegate_setter:nn {#3} {#5} }{ \@@_delegate_setter:nn {#3} {#7} } } \cs_new_protected:Nn \@@_define_fourval_properties:nnnnnn { \@@_define_properties:nn {#1} { #3, #4, #5, #6 } \@@_define_properties:nn { \@@_fourval_setter:nnnnnn {#3}{#4}{#5}{#6} }{ #2 } } \tl_const:Nn \c_@@_inherit_color_tl { \q_nil } \cs_new_nopar:Nn \@@_color_setter:nn { \str_if_eq:nnTF {#2} {inherit} { \@@_generic_setter:nnn \exp_not:n {#1} {\c_@@_inherit_color_tl} }{ \str_case_e:nnF { \str_range:nnn {#2} {1} {4} } { {rgb(} { \@@_generic_setter:nnn \use:n {#1} { \exp_not:n {\color[RGB]} {\str_range:nnn {#2} {5} {-2}} }} {hsl(} { \@@_generic_setter:nnn \use:n {#1} { \exp_not:n {\color[Hsb]} {\str_range:nnn {#2} {5} {-2}} }} }{ \@@_generic_setter:nnn \exp_not:n {#1} { \color{#2} } } } } \cs_new_nopar:Nn \@@_bgcolor_setter:nn { \str_if_eq:nnTF {#2} {transparent} { \@@_color_setter:nn {#1} {inherit} }{ \@@_color_setter:nn {#1} {#2} } } \cs_new_nopar:Nn \@@_linewidth_setter:nn { \str_case:nnF {#2} { {thin} { \@@_generic_setter:nnn \exp_not:n {#1} { \fboxrule} } {medium} { \@@_generic_setter:nnn \exp_not:n {#1} { 2\fboxrule} } {thick} { \@@_generic_setter:nnn \exp_not:n {#1} { 3\fboxrule} } }{ \@@_generic_setter:nnn \exp_not:n {#1} {#2} } } \cs_new_nopar:Nn \@@_border_setter:nn { \@@_border_setter_aux:nw {#1}#2~{\q_no_value}~{\q_no_value}~\q_stop } \cs_new:Npn \@@_border_setter_aux:nw #1#2~#3~#4~#5\q_stop { \quark_if_no_value:nTF {#4} { \@@_border_setter_isstyle:nTF {#2} { \@@_delegate_setter:nn {#1-width} {thin} \@@_delegate_setter:nn {#1-style} {#2} \quark_if_no_value:nTF {#3} { \@@_delegate_setter:nn {#1-color} {inherit} }{ \@@_delegate_setter:nn {#1-color} {#3} } }{ \quark_if_no_value:nTF {#3} { %% TODO: Error, one no-style value, ambiguous }{ \@@_border_setter_isstyle:nTF {#3} { \@@_delegate_setter:nn {#1-width} {#2} \@@_delegate_setter:nn {#1-style} {#3} \@@_delegate_setter:nn {#1-color} {inherit} }{ \@@_delegate_setter:nn {#1-width} {#2} \@@_delegate_setter:nn {#1-style} {none} \@@_delegate_setter:nn {#1-color} {#3} } } } }{ \@@_delegate_setter:nn {#1-width} {#2} \@@_delegate_setter:nn {#1-style} {#3} \@@_delegate_setter:nn {#1-color} {#4} } } \cs_new:Npn \@@_border_setter_isstyle:nTF #1 { \str_case:nnTF {#1} { {none}{} {hidden}{} {dotted}{} {dashed}{} {solid}{} {double}{} {groove}{} {ridge}{} {inset}{} {outset}{} } } \@@_define_properties:nn { \@@_generic_setter:nnn \exp_not:n }{ min-height, min-depth, min-width, } \@@_define_fourval_properties:nnnnnn { \@@_generic_setter:nnn \exp_not:n } {padding} {padding-top}{padding-right}{padding-bottom}{padding-left} \@@_define_properties:nn { \@@_generic_setter:nnn \tl_to_str:n }{ text-align, math-mode, } \@@_define_properties:nn { \@@_color_setter:nn }{ color, } \@@_define_properties:nn { \@@_bgcolor_setter:nn }{ background-color, } \@@_define_fourval_properties:nnnnnn { \@@_linewidth_setter:nn } {border-width} {border-top-width}{border-right-width} {border-bottom-width}{border-left-width} \@@_define_fourval_properties:nnnnnn { \@@_generic_setter:nnn \tl_to_str:n } {border-style} {border-top-style}{border-right-style} {border-bottom-style}{border-left-style} \@@_define_fourval_properties:nnnnnn { \@@_color_setter:nn } {border-color} {border-top-color}{border-right-color} {border-bottom-color}{border-left-color} \@@_define_properties:nn { \@@_border_setter:nn }{ border, border-top, border-right, border-bottom, border-left } \NewDocumentCommand \cellprops { m } { \@@_parse_css:n {#1} } \cs_new_protected:Nn \@@_parse_css:n { \@@_parse_css:w #1 \q_mark {\q_nil} \q_stop } \tl_new:N \l_@@_parse_tmp_tl \NewDocumentCommand \@@_parse_css:w { lmu{\q_stop} } { \quark_if_nil:nF {#2} { \@@_parse_properties:Nn \l_@@_parse_tmp_tl {#2} \clist_map_inline:nn {#1} { \@@_parse_css_addprops:nV {##1} \l_@@_parse_tmp_tl } \@@_parse_css:w #3 \q_stop } } \seq_new:N \l_@@_parse_selector_seq \tl_new:N \l_@@_parse_desc_tl \str_const:Nn \c_@@_parse_nthchild_str { :nth-child( } \prop_new:N \c_@@_parse_replace_prop \prop_put:Nnn \c_@@_parse_replace_prop { :first-child } { :nth-child(1) } \cs_new_protected:Nn \@@_parse_selector:Nn { \str_set:Nx \l_tmpa_str {#2} % \end{macrocode} % % Replace some aliases with their meaning: % % \begin{macrocode} \prop_map_inline:Nn \c_@@_parse_replace_prop { \use:x { \exp_not:n { \tl_replace_all:Nnn \l_tmpa_str } { \tl_to_str:n { ##1 } } { \tl_to_str:n { ##2 } } } } % \end{macrocode} % % Replace all spaces by \cs{q_stop} to defeat the space removal feature of % \cs{seq_set_split:Nnn}. % % \begin{macrocode} \tl_replace_all:Nnn \l_tmpa_str {~} {\q_stop} \exp_args:NNVV \seq_set_split:Nnn \l_tmpa_seq \c_@@_parse_nthchild_str \l_tmpa_str \seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl % \end{macrocode} % % And replace them back. % % \begin{macrocode} \tl_replace_all:Nnn \l_tmpa_tl {\q_stop} {~} \seq_clear:N \l_@@_parse_selector_seq \seq_put_right:NV \l_@@_parse_selector_seq \l_tmpa_tl \seq_map_inline:Nn \l_tmpa_seq { \tl_set:Nn \l_tmpa_tl { ##1 } % \end{macrocode} % % And replace them back again. % % \begin{macrocode} \tl_replace_all:Nnn \l_tmpa_tl {\q_stop} {~} % \end{macrocode} % % Now replace the first closing parenthesis by \cs{q_stop}\cs{prg_do_nothing:} % to use \cs{q_stop} as a delimiter for \cs{seq_set_split:Nnn} and thus split % at most once. Note that here the space trimming feature is desired for the % left part, but not just at the right of the parenthesis, so % \cs{prg_do_nothing:} will act as a guard and will be removed afterwards. % % \begin{macrocode} \tl_replace_once:Nnn \l_tmpa_tl { ) } { \q_stop\prg_do_nothing: } \seq_set_split:NnV \l_tmpa_seq { \q_stop } \l_tmpa_tl \seq_pop_right:NN \l_tmpa_seq \l_@@_parse_desc_tl \tl_replace_once:Nnn \l_@@_parse_desc_tl { \prg_do_nothing: } {} \seq_get_left:NNT \l_tmpa_seq \l_tmpa_tl { \exp_args:NNV \@@_parse_nth:Nn \l_tmpa_tl \l_tmpa_tl \tl_put_left:Nn \l_@@_parse_desc_tl { ) } \tl_put_left:NV \l_@@_parse_desc_tl \l_tmpa_tl } \seq_put_right:NV \l_@@_parse_selector_seq \l_@@_parse_desc_tl } \tl_set:Nx #1 { \exp_args:NNV \seq_use:Nn \l_@@_parse_selector_seq \c_@@_parse_nthchild_str } } \str_const:Nn \c_@@_parse_n_str {n} \seq_new:N \l_@@_used_nth_factors_seq \cs_new_protected:Nn \@@_parse_nth:Nn { \str_case:nnF {#2} { {even} { \str_set:Nn \l_tmpa_str {2n} } {odd} { \str_set:Nn \l_tmpa_str {2n+1} } }{ \str_set:Nn \l_tmpa_str {#2} } \exp_args:NNVV \seq_set_split:Nnn \l_tmpa_seq \c_@@_parse_n_str \l_tmpa_str \seq_pop_right:NN \l_tmpa_seq \l_tmpa_tl \int_set:Nn \l_tmpb_int { 0\l_tmpa_tl } \seq_get_left:NNTF \l_tmpa_seq \l_tmpa_tl { \int_set:Nn \l_tmpa_int { 0\l_tmpa_tl } }{ \int_zero:N \l_tmpa_int } \int_compare:nNnTF \l_tmpa_int = { 0 } { \tl_set:Nx #1 { \int_use:N \l_tmpb_int } }{ \int_set:Nn \l_tmpb_int { \int_mod:nn {\l_tmpb_int} {\l_tmpa_int} } \tl_set:Nx #1 { \int_use:N \l_tmpa_int \exp_not:V \c_@@_parse_n_str + \int_use:N \l_tmpb_int } \seq_put_right:Nx \l_@@_used_nth_factors_seq { \int_use:N \l_tmpa_int } } } \cs_new_protected:Npn \@@_parse_css_addprops:nV #1 #2 { \@@_parse_selector:Nn \l_tmpa_tl {#1} \tl_set:Nx \l_tmpa_tl { l_@@_property_group_\l_tmpa_tl _tl } \tl_if_exist:cF { \l_tmpa_tl } { \tl_clear:c { \l_tmpa_tl } } \tl_put_right:cV { \l_tmpa_tl } #2 } \cs_set_protected:Nn \@@_recall_properties:n { \tl_if_exist:cT { l_@@_property_group_#1_tl } { \tl_use:c { l_@@_property_group_#1_tl } } \clist_map_inline:nn { \@currenvir } { \tl_if_exist:cT { l_@@_property_group_##1~#1_tl } { \tl_use:c { l_@@_property_group_##1~#1_tl } } } } \dim_new:N \l_@@_colsep_dim \dim_new:N \l_@@_strut_ht_dim \dim_new:N \l_@@_strut_dp_dim \ExplSyntaxOff \cellprops{ td { padding: 0pt \csname l_@@_colsep_dim\endcsname; min-height: \csname l_@@_strut_ht_dim\endcsname; min-depth: \csname l_@@_strut_dp_dim\endcsname; min-width: 0pt; text-align: left; math-mode: auto; color: inherit; background-color: transparent; border: thin none inherit; } tr { color: inherit; background-color: transparent; } table { padding: 0pt; % No change at load time color: inherit; background-color: transparent; } } \ExplSyntaxOn \int_new:N \g_@@_row_int \int_new:N \g_@@_col_int \bool_new:N \g_@@_inrow_bool \bool_gset_false:N \g_@@_inrow_bool \box_new:N \l_@@_cell_box \skip_new:N \l_@@_left_skip \skip_new:N \l_@@_right_skip \dim_new:N \g_@@_ht_dim \dim_new:N \g_@@_dp_dim \tl_new:N \g_@@_borders_tl \tl_new:N \l_@@_restore_tl \dim_new:N \l_@@_tablepadding_top_dim \dim_new:N \l_@@_tablepadding_bottom_dim \tl_new:N \l_@@_color_tl \tl_new:N \l_@@_bgcolor_tl % To count rows and columns \cs_new_protected:Nn \@@_array_init: { \tl_set:Nx \l_@@_restore_tl { \bool_if:NTF \g_@@_inrow_bool { \exp_not:n {\bool_gset_true:N \g_@@_inrow_bool} }{ \exp_not:n {\bool_gset_false:N \g_@@_inrow_bool} } \exp_not:n { \int_gset:Nn \g_@@_row_int } { \int_use:N \g_@@_row_int } \exp_not:n { \int_gset:Nn \g_@@_col_int } { \int_use:N \g_@@_col_int } \exp_not:n { \dim_gset:Nn \g_@@_ht_dim } { \dim_use:N \g_@@_ht_dim } \exp_not:n { \dim_gset:Nn \g_@@_dp_dim } { \dim_use:N \g_@@_dp_dim } \exp_not:n { \tl_gset:Nn \g_@@_borders_tl } { \exp_not:V \g_@@_borders_tl } } \int_gzero:N \g_@@_row_int \bool_gset_false:N \g_@@_inrow_bool \tl_gclear:N \g_@@_borders_tl \cs_set_eq:NN \@@_orig_tab@readpreamble:n \tab@readpreamble \cs_set_eq:NN \tab@readpreamble \@@_readpreamble:n % \end{macrocode} % % Zero \cs{col@sep} but remember its value for the default padding. % % \begin{macrocode} \dim_set_eq:NN \l_@@_colsep_dim \col@sep \dim_zero:N \col@sep % \end{macrocode} % % Also ignore \cs{*extrasep} dimensions that are not part of cellprop % interface and should be replaced by CSS equivalents. % % \begin{macrocode} \dim_zero:N \tab@extrasep \group_begin: \@@_recall_properties:n {table} \dim_gset:Nn \g_tmpa_dim { \@@_get_property:n {padding-top} } \dim_gset:Nn \g_tmpb_dim { \@@_get_property:n {padding-bottom} } \@@_update_colors: \tl_gset_eq:NN \g_tmpa_tl \l_@@_color_tl \tl_gset_eq:NN \g_tmpb_tl \l_@@_bgcolor_tl \group_end: \dim_set_eq:NN \l_@@_tablepadding_top_dim \g_tmpa_dim \dim_set_eq:NN \l_@@_tablepadding_bottom_dim \g_tmpb_dim \tl_set_eq:NN \l_@@_color_tl \g_tmpa_tl \tl_set_eq:NN \l_@@_bgcolor_tl \g_tmpb_tl \@@_recall_properties:n {tr} \dim_set:Nn \l_@@_strut_ht_dim { \box_ht:N \@arstrutbox } \dim_set:Nn \l_@@_strut_dp_dim { \box_dp:N \@arstrutbox } \box_clear:N \@arstrutbox } \cs_set_nopar:Nn \@@_array_startcontent: { \hlx{s[\l_@@_tablepadding_top_dim]} } \cs_set_protected_nopar:Nn \@@_readpreamble:n { \cs_set_eq:NN \tab@readpreamble \@@_orig_tab@readpreamble:n \tl_put_left:Nn \tab@multicol {\@@_startrow:} \tl_put_left:Nn \tab@tabtext {\int_gincr:N \g_@@_col_int} \tab@readpreamble{#1} \exp_args:Nx \tab@preamble { \exp_not:N\@@_startrow: \the\tab@preamble \exp_not:N\@@_endrow: } } % \end{macrocode} % % The color inheritance is handled with \cs{l_@@_inherit_color_tl}, % \cs{l_@@_color_tl} and \cs{l_@@_bgcolor_tl}. The role of % \cs{@@_update_color:Nn} is to set the inherit fallback to the already % existing value of \verb|#1| then set \verb|#1| to the CSS value, which can be % the inherit variable. % % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_update_color:Nn { \@@_get_property:nN {#2} \l_tmpa_tl \exp_args:NV \tl_if_eq:NNF \l_tmpa_tl \c_@@_inherit_color_tl { \tl_set_eq:NN #1 \l_tmpa_tl } } \cs_new_protected_nopar:Nn \@@_update_colors: { \@@_update_color:Nn \l_@@_color_tl {color} \@@_update_color:Nn \l_@@_bgcolor_tl {background-color} } % \end{macrocode} % % Patch the \cs{@array}, \cs{LT@array}, \cs{@mkpream}, \cs{endarray} and % \cs{endlongtable} commands, so that we can properly setup our line and column % counting system. This is the most brittle part of \pkg{cellprops}, and subject % to compatibility problems with other packages that patch those (\pkg{hyperref} % in particular). % % \begin{macrocode} \AtEndPreamble{% \cs_set_eq:NN \@@_orig_array:w \@array \cs_set_protected_nopar:Npn \@array[#1]#2 { \@@_array_init: \@@_orig_array:w [#1]{#2} \@@_array_startcontent: } \cs_set_eq:NN \@@_orig_LTmkpream:n \@mkpream \cs_set_protected_nopar:Npn \@mkpream#1 { \group_end: \@@_array_init: \group_begin: \@@_orig_LTmkpream:n {#1} } \cs_set_eq:NN \@@_orig_LTarray:w \LT@array \cs_set_protected_nopar:Npn \LT@array [#1]#2 { \@@_orig_LTarray:w [#1]{#2} \@@_array_startcontent: } \cs_new_nopar:Nn \@@_end_array:n { \tl_if_empty:NF \g_@@_borders_tl { \\ } \crcr \hlx{s[\l_@@_tablepadding_bottom_dim]} #1 \tl_use:N \l_@@_restore_tl } \cs_set_eq:NN \@@_orig_endarray: \endarray \cs_set_nopar:Npn \endarray { \@@_end_array:n { \@@_orig_endarray: } } \cs_set_eq:NN \endtabular \endarray \cs_set_eq:cN {endtabular*} \endarray \cs_set_eq:NN \@@_orig_endLT: \endlongtable \cs_set_nopar:Npn \endlongtable { \@@_end_array:n { \@@_orig_endLT: } } \cs_new_protected_nopar:Nn \@@_startrow: { \bool_if:NF \g_@@_inrow_bool { \bool_gset_true:N \g_@@_inrow_bool \int_gincr:N \g_@@_row_int \int_gset_eq:NN \g_@@_col_int \c_one_int \dim_gzero:N \g_@@_ht_dim \dim_gzero:N \g_@@_dp_dim } } \cs_new_protected_nopar:Nn \@@_endrow: { \bool_if:NT \g_@@_inrow_bool { \bool_gset_false:N \g_@@_inrow_bool } } \cs_new_protected_nopar:Nn \@@_cr:n { \@@_endrow: \tl_if_empty:NF \g_@@_borders_tl { \cr \noalign{\nobreak} \tl_use:N \g_@@_borders_tl \tl_gclear:N \g_@@_borders_tl } \cr \@@_fix_valign_end:n {#1} \use_none:n } \cs_set_protected_nopar:Npn \tab@tabcr #1#2 { \@@_cr:n {#2} } \cs_set_protected_nopar:Npn \@xargarraycr #1 { \@@_cr:n {#1} } \cs_set_protected_nopar:Npn \@yargarraycr #1 { \@@_cr:n {#1} } \tl_if_exist:NT \LT@echunk { \tl_put_left:Nn \LT@echunk { \tl_if_empty:NF \g_@@_borders_tl { \\ } } } \cs_set_eq:NN \@@_orig_multicolumn:w \multicolumn \cs_set:Npn \multicolumn#1#2#3 { \@@_orig_multicolumn:w {#1}{#2}{ #3 \int_gadd:Nn \g_@@_col_int {#1} } } } \cs_new_nopar:Nn \@@_fix_valign_end:n { \noalign{ \dim_set:Nn \l_tmpa_dim {#1} \skip_vertical:n {\l_tmpa_dim} \exp_args:NV \tl_if_eq:nnTF \tab@hlstate {b} { \dim_gadd:Nn \tab@endheight { \g_@@_dp_dim + \l_tmpa_dim } }{ \int_compare:nNnT \g_@@_row_int = \c_one_int { \dim_gadd:Nn \tab@endheight { \g_@@_ht_dim } } } } } % \end{macrocode} % % Reset \cs{firsthline} and \cs{lasthline} to \cs{hline} because the version % from \pkg{array} which might be loaded already will mess up the spacing and is % unneeded anyway. % % \begin{macrocode} \cs_set_eq:NN \firsthline \hline \cs_set_eq:NN \lasthline \hline \colpush{tabular} \coldef n{\tabcoltype{ \@@_begincell:n{} }{ \@@_endcell: }} \coldef l{\tabcoltype{ \@@_begincell:n {\@@_use_setter:nn {text-align} {left}} }{ \@@_endcell: }} \coldef c{\tabcoltype{ \@@_begincell:n {\@@_use_setter:nn {text-align} {center}} }{ \@@_endcell: }} \coldef r{\tabcoltype{ \@@_begincell:n {\@@_use_setter:nn {text-align} {right}} }{ \@@_endcell: }} \coldef M#1{\@@_MTcol:nn {math}{#1}} \coldef T#1{\@@_MTcol:nn {text}{#1}} \cs_new_protected_nopar:Nn \@@_MTcol:nn { % TODO: error if align not l, c, or r \exp_args:Nx \tabcoltype { \exp_not:N \@@_begincell:n { \exp_not:n {\@@_use_setter:nn {math-mode} {#1} } \exp_not:n {\@@_use_setter:nn {text-align}} { \str_case:nn {#2} { {l} {left} {c} {center} {r} {right} } } } }{ \@@_endcell: } } \coldef p#1{\tabcoltype{ \@@_begin_par_cell:nn \vtop {#1} }{ \@@_end_par_cell:n {} }} \coldef m#1{\tabcoltype{ \@@_begin_par_cell:nn {\c_math_toggle_token\vcenter} {#1} }{ \@@_end_par_cell:n{\c_math_toggle_token} }} \coldef b#1{\tabcoltype{ \@@_begin_par_cell:nn \vbox {#1} }{ \@@_end_par_cell:n {} }} \colpop % \end{macrocode} % % Handle various \verb|:nth-child()| forms. % % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_seq_nthchild:Nn { \seq_clear:N #1 \seq_map_inline:Nn \l_@@_used_nth_factors_seq { \seq_put_right:Nx #1 { ##1 n + \int_eval:n{\int_mod:nn{#2}{##1}} } } \seq_put_right:Nx #1 { \int_eval:n{#2} } } \cs_new_protected_nopar:Nn \@@_begincell:n { \@@_begin_raw_cell:n { #1 \hbox_set:Nw \l_@@_cell_box \str_case_e:nnF {\@@_get_property:n {math-mode}} { { text } { \tab@btext } { math } { \tab@bmaths } }{% any other treated as |auto| \tab@bgroup } } } \cs_new_protected_nopar:Nn \@@_endcell: { \str_case_e:nnF {\@@_get_property:n {math-mode}} { { text } { \tab@etext } { math } { \tab@emaths } }{% any other treated as |auto| \tab@egroup } \hbox_set_end: \@@_end_raw_cell: } \cs_new_protected_nopar:Nn \@@_begin_par_cell:nn { \savenotes \@@_begin_raw_cell:n{ \hbox_set:Nw \l_@@_cell_box #1 \bgroup \hsize#2\relax \@arrayparboxrestore \global\@minipagetrue \everypar{ \global\@minipagefalse \everypar{} } \@@_seq_nthchild:Nn \l_tmpa_seq { \g_@@_row_int } \@@_seq_nthchild:Nn \l_tmpb_seq { \g_@@_col_int } \@@_recall_properties:n {td~p} \seq_map_inline:Nn \l_tmpa_seq { \@@_recall_properties:n {tr:nth-child(##1)~p} } \seq_map_inline:Nn \l_tmpb_seq { \@@_recall_properties:n {td:nth-child(##1)~p} } \@@_recall_properties:n {tr~td~p} \seq_map_inline:Nn \l_tmpa_seq { \@@_recall_properties:n {tr:nth-child(##1)~td~p} } \seq_map_inline:Nn \l_tmpa_seq { \seq_map_inline:Nn \l_tmpb_seq { \@@_recall_properties:n {tr:nth-child(##1)~ td:nth-child(####1)~p} } } } } \cs_new_protected_nopar:Nn \@@_end_par_cell:n { \ifhmode\@maybe@unskip\par\fi \unskip \egroup #1 \hbox_set_end: \@@_end_raw_cell: \spewnotes } \cs_new_protected_nopar:Nn \@@_begin_raw_cell:n { \group_begin: \@@_seq_nthchild:Nn \l_tmpa_seq { \g_@@_row_int } \@@_seq_nthchild:Nn \l_tmpb_seq { \g_@@_col_int } \seq_map_inline:Nn \l_tmpa_seq { \@@_recall_properties:n {tr:nth-child(##1)} } \@@_update_colors: \@@_recall_properties:n {td} \@@_recall_properties:n {tr~td} \seq_map_inline:Nn \l_tmpb_seq { \@@_recall_properties:n {td:nth-child(##1)} } \seq_map_inline:Nn \l_tmpa_seq { \@@_recall_properties:n {tr:nth-child(##1)~td} } \seq_map_inline:Nn \l_tmpa_seq { \seq_map_inline:Nn \l_tmpb_seq { \@@_recall_properties:n {tr:nth-child(##1)~ td:nth-child(####1)} } } \@@_update_colors: % Additional init code #1 % Install the cell color \@@_update_colors: \tl_use:N \l_@@_color_tl } \cs_new_protected_nopar:Nn \@@_make_solid_hborder:nnn { \group_begin: \hbox_set_to_wd:Nnn \l_tmpa_box {1pt} { \hss \hbox:n { #3 % install color \vrule height~\dim_eval:n{#1+#2} ~depth~-\dim_eval:n{#2} ~width~3pt } \hss } \box_set_ht:Nn \l_tmpa_box { \c_zero_dim } \box_set_dp:Nn \l_tmpa_box { \c_zero_dim } \kern 1pt \box_use:N \l_tmpa_box \xleaders \box_use:N \l_tmpa_box \skip_horizontal:n {-4pt~plus~1fil} \box_use:N \l_tmpa_box \kern 1pt \skip_horizontal:n {0pt~plus~-1fil} \group_end: } \cs_new_protected_nopar:Nn \@@_make_solid_vborder:nnn { \group_begin: \hbox_set_to_wd:Nnn \l_tmpa_box {0pt} { \hbox:n { #3 % install color \vrule height~\dim_eval:n{#2}~width~\dim_eval:n{#1} } \hss } \box_set_ht:Nn \l_tmpa_box { \c_zero_dim } \box_set_dp:Nn \l_tmpa_box { \c_zero_dim } \box_use:N \l_tmpa_box \group_end: } \clist_map_inline:nn { dotted, dashed, solid, double, groove, ridge, inset, outset }{ \cs_set_eq:cN {@@_make_#1_hborder:nnn} \@@_make_solid_hborder:nnn \cs_set_eq:cN {@@_make_#1_vborder:nnn} \@@_make_solid_vborder:nnn } \dim_new:N \l_@@_border_width_dim \str_new:N \l_@@_border_style_str \tl_new:N \l_@@_border_color_tl \cs_new_protected_nopar:Nn \@@_get_border_info:n { \dim_set:Nn \l_@@_border_width_dim {\@@_get_property:n {border-#1-width}} \@@_get_property:nN {border-#1-style} \l_tmpa_tl \exp_args:NNV \str_set:Nn \l_@@_border_style_str \l_tmpa_tl \tl_clear:N \l_@@_border_color_tl \cs_if_exist:cTF {@@_make_\l_@@_border_style_str _hborder:nnn} { \@@_update_color:Nn \l_@@_border_color_tl {border-#1-color} }{ \dim_zero:N \l_@@_border_width_dim } } \cs_new_protected_nopar:Npn \@@_make_hborder:nnnn #1 { \use:c { @@_make_#1_hborder:nnn } } \cs_new_protected_nopar:Npn \@@_make_vborder:nnnn #1 { \use:c { @@_make_#1_vborder:nnn } } \cs_new_protected_nopar:Nn \@@_end_raw_cell: { % Here \l_@@_cell_box must contain the contents of the cell % % Prepare the borders token list \int_compare:nNnT \g_@@_col_int = 1 { \tl_gclear:N \g_@@_borders_tl } \tl_gput_right:Nx \g_@@_borders_tl { \tl_if_empty:NF \g_@@_borders_tl { \exp_not:n {&} } \exp_not:n { \omit \kern \c_zero_dim } } % Handle padding-top, min-height and border-top \@@_get_border_info:n {top} \box_set_ht:Nn \l_@@_cell_box { \dim_max:nn {\box_ht:N \l_@@_cell_box} {\@@_get_property:n {min-height}} + (\@@_get_property:n {padding-top}) + \l_@@_border_width_dim } \dim_compare:nNnT \l_@@_border_width_dim > \c_zero_dim { \tl_gput_right:Nx \g_@@_borders_tl { \exp_not:N \@@_make_hborder:nnnn { \exp_not:V \l_@@_border_style_str } { \dim_use:N \l_@@_border_width_dim } { \exp_not:n { \g_@@_dp_dim + \g_@@_ht_dim - } \dim_use:N \l_@@_border_width_dim } { \exp_not:V \l_@@_border_color_tl } } } % Handle padding-bottom, min-depth and border-bottom \@@_get_border_info:n {bottom} \box_set_dp:Nn \l_@@_cell_box { \dim_max:nn {\box_dp:N \l_@@_cell_box} {\@@_get_property:n {min-depth}} + (\@@_get_property:n {padding-bottom}) + \l_@@_border_width_dim } \dim_compare:nNnT \l_@@_border_width_dim > \c_zero_dim { \tl_gput_right:Nx \g_@@_borders_tl { \exp_not:N \@@_make_hborder:nnnn { \exp_not:V \l_@@_border_style_str } { \dim_use:N \l_@@_border_width_dim } { \exp_not:n { 0pt } } { \exp_not:V \l_@@_border_color_tl } } } % To fix vertical alignment later \dim_gset:Nn \g_@@_ht_dim { \dim_max:nn {\g_@@_ht_dim} {\box_ht:N \l_@@_cell_box} } \dim_gset:Nn \g_@@_dp_dim { \dim_max:nn {\g_@@_dp_dim} {\box_dp:N \l_@@_cell_box} } % Handle padding-left and border-left \@@_get_border_info:n {left} \skip_set:Nn \l_@@_left_skip {\@@_get_property:n {padding-left} + \l_@@_border_width_dim} \dim_compare:nNnT \l_@@_border_width_dim > \c_zero_dim { \tl_gput_right:Nx \g_@@_borders_tl { \exp_not:N \@@_make_vborder:nnnn { \exp_not:V \l_@@_border_style_str } { \dim_use:N \l_@@_border_width_dim } { \exp_not:n { \g_@@_dp_dim + \g_@@_ht_dim } } { \exp_not:V \l_@@_border_color_tl } } } \tl_gput_right:Nx \g_@@_borders_tl { \exp_not:n { \skip_horizontal:n {0pt~plus~1fil} \kern \c_zero_dim } } \@@_get_border_info:n {right} \skip_set:Nn \l_@@_right_skip {\@@_get_property:n {padding-right} + \l_@@_border_width_dim} \dim_compare:nNnT \l_@@_border_width_dim > \c_zero_dim { \tl_gput_right:Nx \g_@@_borders_tl { \exp_not:N \skip_horizontal:n { - \dim_use:N \l_@@_border_width_dim } \exp_not:N \@@_make_vborder:nnnn { \exp_not:V \l_@@_border_style_str } { \dim_use:N \l_@@_border_width_dim } { \exp_not:n { \g_@@_dp_dim + \g_@@_ht_dim } } { \exp_not:V \l_@@_border_color_tl } \exp_not:N \skip_horizontal:n { \dim_use:N \l_@@_border_width_dim } \exp_not:n { \kern \c_zero_dim } } } % Handle hpadding and halign \skip_set:Nn \l_tmpa_skip { \dim_max:nn {0pt} { (\@@_get_property:n {min-width}) - \box_wd:N \l_@@_cell_box } } \skip_add:Nn \l_tmpa_skip { 1sp plus 1fil } \str_case_e:nnF {\@@_get_property:n {text-align}} { { right } { \skip_add:Nn \l_@@_left_skip { \l_tmpa_skip } } { center } { \skip_add:Nn \l_@@_left_skip { \l_tmpa_skip / 2 } \skip_add:Nn \l_@@_right_skip { \l_tmpa_skip / 2 } } }{% any other treated as |left| \skip_add:Nn \l_@@_right_skip { \l_tmpa_skip } } \kern\c_zero_dim \tl_if_empty:NF \l_@@_bgcolor_tl { \group_begin: % Paint a background with leaders \tl_use:N \l_@@_bgcolor_tl % install the color \skip_set:Nn \l_tmpa_skip { \l_@@_left_skip + \box_wd:N \l_@@_cell_box + \l_@@_right_skip } \leaders \vrule \skip_horizontal:N \l_tmpa_skip \skip_horizontal:n {-\l_tmpa_skip} \group_end: } \skip_horizontal:N \l_@@_left_skip \box_use_drop:N \l_@@_cell_box \skip_horizontal:N \l_@@_right_skip \kern\c_zero_dim \group_end: } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation}