texlive[59797] Master/texmf-dist: tabularray (1jul21)

commits+karl at tug.org commits+karl at tug.org
Thu Jul 1 23:36:52 CEST 2021


Revision: 59797
          http://tug.org/svn/texlive?view=revision&revision=59797
Author:   karl
Date:     2021-07-01 23:36:51 +0200 (Thu, 01 Jul 2021)
Log Message:
-----------
tabularray (1jul21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/tabularray/README
    trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.pdf
    trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex
    trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty

Modified: trunk/Master/texmf-dist/doc/latex/tabularray/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tabularray/README	2021-07-01 21:36:39 UTC (rev 59796)
+++ trunk/Master/texmf-dist/doc/latex/tabularray/README	2021-07-01 21:36:51 UTC (rev 59797)
@@ -1,4 +1,6 @@
 Package: Typeset tabulars and arrays with LaTeX3
 Author: Jianrui Lyu <tolvjr at 163.com>
+CTAN: https://ctan.org/pkg/tabularray
 Repository: https://github.com/lvjr/tabularray
+Repository: https://bitbucket.org/lvjr/tabularray
 License: The LaTeX Project Public License 1.3

Modified: trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex	2021-07-01 21:36:39 UTC (rev 59796)
+++ trunk/Master/texmf-dist/doc/latex/tabularray/tabularray.tex	2021-07-01 21:36:51 UTC (rev 59797)
@@ -6,7 +6,10 @@
 \usepackage{codehigh} % https://ctan.org/pkg/codehigh
 \usepackage{tabularray}
 \usepackage{array,multirow,amsmath}
+\usepackage{chemmacros}
 
+\UseTblrLibrary{booktabs,diagbox,siunitx}
+
 \usepackage{hyperref}
 \hypersetup{
   colorlinks=true,
@@ -13,17 +16,43 @@
   urlcolor=blue3,
   linkcolor=red3,
 }
+
+\usepackage{tcolorbox}
+\tcbset{sharp corners, boxrule=0.5pt, colback=red9}
+
+\usepackage{float}
+
+\setcounter{tocdepth}{1}
+
+\newcommand*{\K}[1]{\texttt{#1}}
+\newcommand*{\V}[1]{\texttt{#1}}
+
+\NewTblrEnviron{spectblr}
+\SetTblrOuter[spectblr]{long}
+\SetTblrInner[spectblr]{
+  hlines = {white},
+  row{odd}={brown8},row{even}={gray8},row{1}={fg=white,bg=purple2,font=\bfseries\sffamily},
+  column{2} = {co=1},
+  rowhead = 1,
+}
+
+\newcommand{\mywarning}[1]{%
+  \begin{tcolorbox}
+  The interfaces in this #1 should be seen as
+  \textcolor{red3}{\bfseries experimental}
+  and are likely to change in future releases, if necessary.
+  Don’t use them in important documents.
+  \end{tcolorbox}
+}
+
 \renewcommand*{\thefootnote}{*}
 
-\newcommand*{\myversion}{2021K}
+\newcommand*{\myversion}{2021L}
 \newcommand*{\mydate}{Version \myversion\ (\the\year-\mylpad\month-\mylpad\day)\\\myrepo}
 \newcommand*{\myrepo}{\url{https://github.com/lvjr/tabularray}}
 \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
 
-\colorlet{highback}{\ifcase\month\or
-  red9\or brown9\or yellow9\or cyan9\or azure9\or blue9\or
-  red9\or brown9\or yellow9\or cyan9\or azure9\or blue9\fi
-}
+\colorlet{highback}{\ifodd\month azure9\else blue9\fi}
 \CodeHigh{language=latex/table,style/main=highback,style/code=highback}
 \NewCodeHighEnv{code}{style/main=gray9,style/code=gray9}
 \NewCodeHighEnv{demo}{style/main=gray9,style/code=gray9,demo}
@@ -39,11 +68,11 @@
 
 \tableofcontents
 
-\chapter{From Old to New}
+\chapter{Overview of Features}
 
 \section{Vertical Space}
 
-After loading \verb!tabularrray! package in the preamble,
+After loading \verb!tabularray! package in the preamble,
 we can use \verb!tblr! environments to typeset tabulars and arrays.
 The name \verb!tblr! is short for \verb!tabularray! or \verb!top-bottom-left-right!.
 The following is our first example:
@@ -74,10 +103,10 @@
 
 You may notice that there is extra space above and below the table rows with \verb!tblr! envirenment.
 This space makes the table look better.
-If you don't like it, you could use \verb!\SetTblrDefault! command:
+If you don't like it, you could use \verb!\SetTblrInner! command:
 
 \begin{demohigh}
-\SetTblrDefault{rowsep=0pt}
+\SetTblrInner{rowsep=0pt}
 \begin{tblr}{lccr}
 \hline
  Alpha   & Beta  & Gamma  & Delta \\
@@ -191,8 +220,8 @@
 \end{demohigh}
 
 Note that you don't need to load \verb!multirow! package first,
-since \verb!tabularrray! doesn't depend on it.
-Furthermore, \verb!tabularray! will always typeset descent multirow cells.
+since \verb!tabularray! doesn't depend on it.
+Furthermore, \verb!tabularray! will always typeset decent multirow cells.
 First, it will set correct vertical \verb!c! alignment,
 even though some rows have large height:
 
@@ -309,7 +338,7 @@
 
 \verb!Tabularray! package supports all normal column types, as well as
 the extendable \verb!X! column type,
-which first occured in \verb!tabularx! package and was largely improved by \verb!tabu! package:
+which first occurred in \verb!tabularx! package and was largely improved by \verb!tabu! package:
 
 \begin{demohigh}
 \begin{tblr}{|X[2,l]|X[3,l]|X[1,r]|X[r]|}
@@ -453,7 +482,7 @@
 All commands which change the specifications of tables \textcolor{red3}{must} be defined with \verb!\NewTableCommand!.
 The following example demonstrates how to define similar rules as in \verb!booktabs! package:
 
-\begin{demohigh}
+\begin{codehigh}
 \NewTableCommand\toprule{\hline[0.08em]}
 \NewTableCommand\midrule{\hline[0.05em]}
 \NewTableCommand\bottomrule{\hline[0.08em]}
@@ -466,14 +495,189 @@
  Nu      & Xi    & Omicron & Pi    \\
 \bottomrule
 \end{tblr}
+\end{codehigh}
+
+\chapter{The Old Interfaces}
+
+With tabularray package, you can still use improved table commands to change the styles of tables.
+Same as \verb!tabular! and \verb!array! environments,
+all table commands \textcolor{red3}{must} be put at the beginning ot the cell text.
+Also, new table commands \textcolor{red3}{must} be defined with \verb!\NewTableCommand!.
+
+\section{Hline Commands}
+
+The \verb!\hline! command has an optional argument which accepts key-value options.
+The available keys are described in Table \ref{key:hvline}.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\hline
+ Alpha   & Beta  & Gamma  & Delta \\
+\hline[dashed]
+ Epsilon & Zeta  & Eta    & Theta \\
+\hline[dotted]
+ Iota    & Kappa & Lambda & Mu    \\
+\hline[2pt,blue5]
+\end{tblr}
 \end{demohigh}
 
-\chapter{New Interfaces}
+The \verb!\cline! command also has an optional argument which is the same as \verb!\hline!.
 
+\begin{demohigh}
+\begin{tblr}{llll}
+\cline{1-4}
+ Alpha   & Beta  & Gamma  & Delta \\
+\cline[dashed]{1,3}
+ Epsilon & Zeta  & Eta    & Theta \\
+\cline[dashed]{2,4}
+ Iota    & Kappa & Lambda & Mu    \\
+\cline[2pt,blue5]{-}
+\end{tblr}
+\end{demohigh}
+
+You can use child selectors in the mandatory argument of \verb!\cline!.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\cline{1-4}
+ Alpha   & Beta  & Gamma  & Delta \\
+\cline[dashed]{odd}
+ Epsilon & Zeta  & Eta    & Theta \\
+\cline[dashed]{even}
+ Iota    & Kappa & Lambda & Mu    \\
+\cline[2pt,blue5]{-}
+\end{tblr}
+\end{demohigh}
+
+\section{Cell Commands}
+
+The \verb!\SetCell! command has a mandatory argument for setting the styles of current cell.
+The available keys are described in Table \ref{key:cell}.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\hline[1pt]
+ Alpha   & \SetCell{bg=teal2,fg=white} Beta & Gamma & Delta \\
+\hline
+ Epsilon & Zeta & \SetCell{r,font=\scshape} Eta & Theta \\
+\hline
+ Iota    & Kappa & Lambda & Mu    \\
+\hline[1pt]
+\end{tblr}
+\end{demohigh}
+
+The \verb!\SetCell! command also has an optional argument for setting the multispan of current cell.
+The available keys are described in Table \ref{key:cellspan}.
+
+\begin{demohigh}
+\begin{tblr}{|X|X|X|X|X|X|}
+\hline
+ Alpha & Beta & Gamma & Delta & Epsilon & Zeta \\
+\hline
+ \SetCell[c=2]{c} Eta & 2-2
+              & \SetCell[c=2]{c} Iota & 2-4
+                              & \SetCell[c=2]{c} Lambda  & 2-6 \\
+\hline
+ \SetCell[c=3]{l} Nu & 3-2 & 3-3
+                      & \SetCell[c=3]{l} Pi & 3-5 & 3-6   \\
+\hline
+ \SetCell[c=6]{r} Tau & 4-2 & 4-3 & 4-4 & 4-5 & 4-6 \\
+\hline
+\end{tblr}
+\end{demohigh}
+
+\section{Row Commands}
+
+The \verb!\SetRow! command has a mandatory argument for setting the styles of current row.
+The available keys are described in Table \ref{key:row}.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\hline[1pt]
+ \SetRow{azure8} Alpha & Beta & Gamma & Delta \\
+\hline
+ \SetRow{blue8,c} Epsilon & Zeta & Eta & Theta \\
+\hline
+ \SetRow{violet8} Iota & Kappa & Lambda & Mu \\
+\hline[1pt]
+\end{tblr}
+\end{demohigh}
+
+\section{Column Types}
+
+The \verb!tabularray! package has only one type of primitive column: the \verb!Q! column.
+Other types of columns are defined as \verb!Q! columns with some keys.
+
+\begin{codehigh}
+\NewColumnType{l}{Q[l]}
+\NewColumnType{c}{Q[c]}
+\NewColumnType{r}{Q[r]}
+\NewColumnType{t}[1]{Q[t,wd=#1]}
+\NewColumnType{m}[1]{Q[m,wd=#1]}
+\NewColumnType{b}[1]{Q[b,wd=#1]}
+\NewColumnType{h}[1]{Q[h,wd=#1]}
+\NewColumnType{f}[1]{Q[f,wd=#1]}
+\NewColumnType{X}[1][]{Q[co=1,#1]}
+\end{codehigh}
+
+\begin{demohigh}
+\begin{tblr}{|t{15mm}|m{15mm}|b{20mm}|}
+ Alpha   & Beta  & {Gamma\\Gamma} \\
+ Epsilon & Zeta  & {Eta\\Eta} \\
+ Iota    & Kappa & {Lambda\\Lambda} \\
+\end{tblr}
+\end{demohigh}
+
+Any new column type must be defined with \verb!\NewColumnType! command.
+It can have an optional argument when it's defined.
+
+\section{Row Types}
+
+The \verb!tabularray! package has only one type of primitive row: the \verb!Q! row.
+Other types of rows are defined as \verb!Q! rows with some keys.
+
+\begin{codehigh}
+\NewRowType{l}{Q[l]}
+\NewRowType{c}{Q[c]}
+\NewRowType{r}{Q[r]}
+\NewRowType{t}[1]{Q[t,ht=#1]}
+\NewRowType{m}[1]{Q[m,ht=#1]}
+\NewRowType{b}[1]{Q[b,ht=#1]}
+\NewRowType{h}[1]{Q[h,ht=#1]}
+\NewRowType{f}[1]{Q[f,ht=#1]}
+\end{codehigh}
+
+\begin{demohigh}
+\begin{tblr}{rowspec={|t{12mm}|m{10mm}|b{10mm}|}}
+ Alpha   & Beta  & {Gamma\\Gamma} \\
+ Epsilon & Zeta  & {Eta\\Eta} \\
+ Iota    & Kappa & {Lambda\\Lambda} \\
+\end{tblr}
+\end{demohigh}
+
+Any new row type must be defined with \verb!\NewRowType! command.
+It can have an optional argument when it's defined.
+
+\chapter{The New Interfaces}
+
 With \verb!tabularray! package, you can separate style and content totally in tables.
 
 \section{Hlines and Vlines}
 
+All available keys for hlines and vlines are described in Table \ref{key:hvline}.
+
+\begin{spectblr}[
+  caption = {Keys for Hlines and Vlines},
+  label = {key:hvline},
+  remark{Note} = {In most cases, you can omit the underlined key names and write only their values.}
+]{}
+  Key & Description and Values & Initial Value \\
+  \underline{\K{dash}} & dash style: \V{solid}, \V{dashed} or \V{dotted} & \V{solid} \\
+  \K{text}             & replace hline/vline with text (like \V{!} specifier in \K{colspec}) & None \\
+  \underline{\K{wd}}   & rule width dimension & None \\
+  \underline{\K{fg}}   & rule color name & None \\
+\end{spectblr}
+
 Options \verb!hlines! and \verb!vlines! are for setting all hlines and vlines, respectively.
 With empty value, all hlines/vlines will be solid.
 
@@ -571,10 +775,63 @@
 \end{tblr}
 \end{demohigh}
 
+At last we show the usage of \verb!text! key by the following example%
+\footnote{Code from \url{https://tex.stackexchange.com/questions/603023/tabularray-and-tabularx-column-separator}.}:
+
+\begin{demohigh}
+\begin{tblr}{
+  vlines, hlines,
+  colspec = {lX[c]X[c]X[c]X[c]},
+  vline{2} = {1}{text=\clap{:}},
+  vline{3} = {1}{text=\clap{\ch{+}}},
+  vline{4} = {1}{text=\clap{\ch{->}}},
+  vline{5} = {1}{text=\clap{\ch{+}}},
+}
+  Equation & \ch{CH4} & \ch{2 O2} & \ch{CO2} & \ch{2 H2O} \\
+  Initial  & $n_1$    & $n_2$     & 0        & 0 \\
+  Final    & $n_1-x$  & $n_2-2x$  & $x$      & $2x$ \\
+\end{tblr}
+\end{demohigh}
+
+You need to load \verb!chemmacros! package for the \verb!\ch! command.
+
 \section{Cells and Spancells}
 
+All available keys for cells are described in Table \ref{key:cell} and Table \ref{key:cellspan}.
+\nopagebreak
+\begin{spectblr}[
+  caption = {Keys for the Content of Cells},
+  label = {key:cell},
+  remark{Note} = {In most cases, you can omit the underlined key names and write only their values.}
+]{}
+  Key & Description and Values & Initial Value \\
+  \underline{\K{halign}}
+    & horizontal alignment: \V{l} (left), \V{c} (center), or \V{r} (right)
+    & \V{l} \\
+  \underline{\K{valign}}
+    & vertical alignment: \V{t} (top), \V{m} (middle), \V{b} (bottom),
+      \V{h} (head) or \V{f} (foot)
+    & \V{t} \\
+  \underline{\K{wd}} & width dimension & None \\
+  \underline{\K{bg}} & background color name & None \\
+  \K{fg}    & foreground color name & None \\
+  \K{font}  & font commands & None \\
+  \K{preto} & prepend text to the cell & None \\
+  \K{appto} & append text to the cell & None \\
+  \K{cmd}   & execute command for the cell text & None \\
+\end{spectblr}
+\vspace{-2em}
+\begin{spectblr}[
+  caption = {Keys for Multispan of Cells},
+  label = {key:cellspan},
+]{}
+  Key & Description and Values & Initial Value \\
+  \K{r} & number of rows the cell spans    & 1 \\
+  \K{c} & number of columns the cell spans & 1 \\
+\end{spectblr}
+
 Option \verb!cells! is for setting all cells.
-
+\nopagebreak
 \begin{demohigh}
 \begin{tblr}{hlines={white},cells={c,blue7}}
  Alpha   & Beta  & Gamma   & Delta   \\
@@ -581,8 +838,6 @@
  Epsilon & Zeta  & Eta     & Theta   \\
  Iota    & Kappa & Lambda  & Mu      \\
  Nu      & Xi    & Omicron & Pi      \\
- Rho     & Sigma & Tau     & Upsilon \\
- Phi     & Chi   & Psi     & Omega   \\
 \end{tblr}
 \end{demohigh}
 
@@ -609,8 +864,67 @@
 
 \section{Rows and Columns}
 
+All available keys for rows and columns are described in Table \ref{key:row} and Table \ref{key:column}.
+
+\begin{spectblr}[
+  caption = {Keys for Rows},
+  label = {key:row},
+  remark{Note} = {In most cases, you can omit the underlined key names and write only their values.}
+]{}
+  Key & Description and Values & Initial Value \\
+  \underline{\K{halign}}
+    & horizontal alignment: \V{l} (left), \V{c} (center), or \V{r} (right)
+    & \V{l} \\
+  \underline{\K{valign}}
+    & vertical alignment: \V{t} (top), \V{m} (middle), \V{b} (bottom),
+      \V{h} (head) or \V{f} (foot)
+    & \V{t} \\
+  \underline{\K{ht}} & height dimension & None \\
+  \underline{\K{bg}} & background color name & None \\
+  \K{fg} & foreground color name & None \\
+  \K{font} & font commands & None \\
+  \K{abovesep} & set vertical space above the row & \V{2pt} \\
+  \K{abovesep+} & increase vertical space above the row & None \\
+  \K{belowsep} & set vertical space below the row & \V{2pt} \\
+  \K{belowsep+} & increase vertical space below the row & None \\
+  \K{rowsep} & set vertical space above and below the row & \V{2pt} \\
+  \K{rowsep+} & increase vertical space above and below the row & None \\
+  \K{preto} & prepend text to every cell (like \V{>} specifier in \K{rowspec}) & None \\
+  \K{appto} & append text to every cell (like \V{<} specifier in \K{rowspec}) & None \\
+  \K{cmd}   & execute command for every cell text & None \\
+\end{spectblr}
+\vspace{-2em}
+\begin{spectblr}[
+  caption = {Keys for Columns},
+  label = {key:column},
+  remark{Note} = {In most cases, you can omit the underlined key names and write only their values.}
+]{}
+  Key & Description and Values & Initial Value \\
+  \underline{\K{halign}}
+    & horizontal alignment: \V{l} (left), \V{c} (center), or \V{r} (right)
+    & \V{l} \\
+  \underline{\K{valign}}
+    & vertical alignment: \V{t} (top), \V{m} (middle), \V{b} (bottom),
+      \V{h} (head) or \V{f} (foot)
+    & \V{t} \\
+  \underline{\K{wd}} & width dimension & None \\
+  \underline{\K{co}} & coefficient for the extendable column (\V{X} column) & None \\
+  \underline{\K{bg}} & background color name & None \\
+  \K{fg} & foreground color name & None \\
+  \K{font} & font commands & None \\
+  \K{leftsep} & set horizontal space to the left of the column & \V{6pt} \\
+  \K{leftsep+} & increase horizontal space to the left of the column & None \\
+  \K{rightsep} & set horizontal space to the right of the column & \V{6pt} \\
+  \K{rightsep+} & increase horizontal space to the right of the column & None \\
+  \K{colsep} & set horizontal space to both sides of the column & \V{6pt} \\
+  \K{colsep+} & increase horizontal space to both sides of the column & None \\
+  \K{preto} & prepend text to every cell (like \V{>} specifier in \K{colspec}) & None \\
+  \K{appto} & append text to every cell (like \V{<} specifier in \K{colspec}) & None \\
+  \K{cmd}   & execute command for every cell text & None \\
+\end{spectblr}
+
 Options \verb!rows! and \verb!columns! are for setting all rows and columns, respectively.
-
+\nopagebreak
 \begin{demohigh}
 \begin{tblr}{
  hlines,
@@ -642,13 +956,10 @@
 \end{tblr}
 \end{demohigh}
 
-We can specify foreground colors, background colors and fonts with
-\verb!bg!, \verb!fg! and \verb!font! keys, respectively, for cells/rows/columns.
-In most cases, \verb!bg! key can be omitted, which you can see in the previous examples.
-
+The following example demonstrates the usages of \verb!bg!, \verb!fg! and \verb!font! keys.
+\nopagebreak
 \begin{demohigh}
 \begin{tblr}{
- colspec  = {lcr},
  row{odd} = {bg=azure8},
  row{1}   = {bg=azure3, fg=white, font=\sffamily},
 }
@@ -660,22 +971,10 @@
 \end{tblr}
 \end{demohigh}
 
-\section{Space in Tables}
-
-Options \verb!rowsep! and \verb!colsep! are for setting padding for rows and columns, respectively.
-
+The following example demonstrates the usages of
+\verb!abovesep!, \verb!belowsep!, \verb!leftsep!, \verb!rightsep! keys.
+\nopagebreak
 \begin{demohigh}
-\SetTblrDefault{rowsep=2pt,colsep=2pt}
-\begin{tblr}{hlines,vlines}
- Alpha   & Beta  & Gamma  & Delta \\
- Epsilon & Zeta  & Eta    & Theta \\
- Iota    & Kappa & Lambda & Mu    \\
-\end{tblr}
-\end{demohigh}
-
-Also \verb!abovesep!, \verb!belowsep!, \verb!leftsep!, \verb!rightsep! options are available:
-
-\begin{demohigh}
 \begin{tblr}{
  hlines,
  vlines,
@@ -688,7 +987,7 @@
 \end{tblr}
 \end{demohigh}
 
-And \verb!\\[dimen]! can be replaced by \verb!belowsep+! option:
+The following example shows that we can replace \verb!\\[dimen]! with \verb!belowsep+! key.
 
 \begin{demohigh}
 \begin{tblr}{
@@ -700,9 +999,43 @@
 \end{tblr}
 \end{demohigh}
 
-Also \verb!\doublerulesep! parameter can be replaced by \verb!rulesep! option:
+\section{The Whole Table}
 
+All available keys for the whole table are described in Table \ref{key:table}.
+
+\begin{spectblr}[
+  caption = {Keys for the Whole Table},
+  label = {key:table},
+]{}
+  Key & Description and Values & Initial Value \\
+  \K{rowspec} & set row specifications with row type specifiers & None \\
+  \K{colspec} & set column specifications with column type specifiers & None \\
+  \K{width} & width of the table with extendable columns & None \\
+  \K{rulesep} & space between two hlines or vlines & \V{2pt} \\
+  \K{stretch} & stretch ratio for struts added to cell text & \V{1} \\
+  \K{abovesep} & set vertical space above every row & \V{2pt} \\
+  \K{belowsep} & set vertical space below every row & \V{2pt} \\
+  \K{rowsep} & set vertical space above and below every row & \V{2pt} \\
+  \K{leftsep} & set horizontal space to the left of every column & \V{6pt} \\
+  \K{rightsep} & set horizontal space to the right of every column & \V{6pt} \\
+  \K{colsep} & set horizontal space to both sides of every column & \V{6pt} \\
+  \K{hspan} & horizontal span algorithm: \V{default}, \V{even}, or \V{minimal} & \V{default} \\
+  \K{vspan} & vertical span algorithm: \V{default} or \V{even} & \V{default} \\
+\end{spectblr}
+
+The following example demonstrates the usage of \verb!width! key.
+\nopagebreak
 \begin{demohigh}
+\begin{tblr}{width=0.8\textwidth, colspec={|l|X[2]|X[3]|X[-1]|}}
+ Alpha   & Beta  & Gamma  & Delta \\
+ Epsilon & Zeta  & Eta    & Theta \\
+ Iota    & Kappa & Lambda & Mu    \\
+\end{tblr}
+\end{demohigh}
+
+The following example shows that we can replace \verb!\doublerulesep! parameter with \verb!rulesep! key.
+\nopagebreak
+\begin{demohigh}
 \begin{tblr}{
  colspec={||llll||},rowspec={|QQQ|},rulesep=4pt,
 }
@@ -712,7 +1045,7 @@
 \end{tblr}
 \end{demohigh}
 
-Also \verb!\arraystretch! parameter can be replaced by \verb!stretch! option:
+The following example shows that we can replace \verb!\arraystretch! parameter with \verb!stretch! key.
 
 \begin{demohigh}
 \begin{tblr}{hlines,stretch=1.5}
@@ -722,39 +1055,34 @@
 \end{tblr}
 \end{demohigh}
 
-\section{Counters in Tables}
+The following example uses \verb!rowsep! and \verb!colsep! keys to set padding for all rows and columns.
+\nopagebreak
+\begin{demohigh}
+\SetTblrInner{rowsep=2pt,colsep=2pt}
+\begin{tblr}{hlines,vlines}
+ Alpha   & Beta  & Gamma  & Delta \\
+ Epsilon & Zeta  & Eta    & Theta \\
+ Iota    & Kappa & Lambda & Mu    \\
+\end{tblr}
+\end{demohigh}
 
-Counters \verb!rownum!, \verb!colnum!, \verb!rowcount!, \verb!colcount! can be used in cell text:
+With \verb!hspan=default! or \verb!hspan=even!,
+\verb!tabularray! package will compute column widths from span widths.
+But with \verb!hspan=minimal!, it will compute span widths from column widths.
+The following examples show the results from different \verb!hspan! values.
 
 \begin{demohigh}
-\begin{tblr}{hlines}
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
- Row=\arabic{rowcount}, Col=\arabic{colcount} &
- Row=\arabic{rowcount}, Col=\arabic{colcount} &
- Row=\arabic{rowcount}, Col=\arabic{colcount} &
- Row=\arabic{rowcount}, Col=\arabic{colcount} \\
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
- Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+\SetTblrInner{hlines, vlines, hspan=default}
+\begin{tblr}{cell{2}{1}={c=2}{l},cell{3}{1}={c=3}{l},cell{4}{2}={c=2}{l}}
+ 111 111 & 222 222 & 333 333 \\
+ 12 Multi Columns Multi Columns 12 & & 333 \\
+ 13 Multi Columns Multi Columns Multi Columns 13 & & \\
+ 111 & 23 Multi Columns Multi Columns 23 & \\
 \end{tblr}
 \end{demohigh}
 
-\section{Experimental Interfaces}
-
-Everything described in this section is in \underline{\textcolor{red3}{\textbf{experimental}}} status.
-Don’t use them in important documents, unless you have time
-to update them for the newer versions of \verb!tabularray! package in the future.
-
-By default \verb!tabularray! package will compute column widths from span widths.
-By setting option \verb!hspan=minimal!, it will compute span widths from column widths.
-The following two examples show this difference:
-
 \begin{demohigh}
-\SetTblrDefault{hlines,vlines}
+\SetTblrInner{hlines, vlines, hspan=even}
 \begin{tblr}{cell{2}{1}={c=2}{l},cell{3}{1}={c=3}{l},cell{4}{2}={c=2}{l}}
  111 111 & 222 222 & 333 333 \\
  12 Multi Columns Multi Columns 12 & & 333 \\
@@ -764,7 +1092,7 @@
 \end{demohigh}
 
 \begin{demohigh}
-\SetTblrDefault{hlines,vlines,hspan=minimal}
+\SetTblrInner{hlines, vlines, hspan=minimal}
 \begin{tblr}{cell{2}{1}={c=2}{l},cell{3}{1}={c=3}{l},cell{4}{2}={c=2}{l}}
  111 111 & 222 222 & 333 333 \\
  12 Multi Columns Multi Columns 12 & & 333 \\
@@ -773,6 +1101,84 @@
 \end{tblr}
 \end{demohigh}
 
+The following examples show the results from different \verb!vspan! values.
+\nopagebreak
+\begin{demohigh}
+\SetTblrInner{hlines, vlines, vspan=default}
+\begin{tblr}{column{2}={3.25cm}, cell{2}{2}={r=3}{l}}
+  Column1 & Column2 \\
+  Row1 & Long text that needs multiple lines.
+         Long text that needs multiple lines.
+         Long text that needs multiple lines. \\
+  Row2 & \\
+  Row3 & \\
+  Row4 & Short text \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\SetTblrInner{hlines, vlines, vspan=even}
+\begin{tblr}{column{2}={3.25cm}, cell{2}{2}={r=3}{l}}
+  Column1 & Column2 \\
+  Row1 & Long text that needs multiple lines.
+         Long text that needs multiple lines.
+         Long text that needs multiple lines. \\
+  Row2 & \\
+  Row3 & \\
+  Row4 & Short text \\
+\end{tblr}
+\end{demohigh}
+
+\section{Default Specifications}
+
+\verb!Tabularray! package provides \verb!\SetTblrInner! and \verb!\SetTblrOuter! commands
+for you to change the default inner and outer specifications of tables.
+Inner specifications are all specifications written in the mandatory argument of the \verb!tblr! environment,
+while outer specifications are all specifications written in the optional argument of the \verb!tblr! environment.
+At this time, most of the outer specifications are used for long tables (see Chapter \ref{chap:long}).
+
+In the below example, the first line draws all hlines and vlines for all tables created afterwards,
+while the second line makes all tables created afterwards vertically align at bottom.
+
+\begin{codehigh}
+\SetTblrInner{hlines,vlines}
+\SetTblrOuter{valign=b}
+\end{codehigh}
+
+You can define new \verb!tabularray! environments using \verb!\NewTblrEnviron! command:
+
+\begin{demohigh}
+\NewTblrEnviron{mytblr}
+\SetTblrInner[mytblr]{hlines,vlines}
+\SetTblrOuter[mytblr]{valign=b}
+Text \begin{mytblr}{cccc}
+ Alpha   & Beta  & Gamma  & Delta \\
+ Epsilon & Zeta  & Eta    & Theta \\
+ Iota    & Kappa & Lambda & Mu    \\
+\end{mytblr} Text
+\end{demohigh}
+
+\section{Counters and Lengths}
+
+Counters \verb!rownum!, \verb!colnum!, \verb!rowcount!, \verb!colcount! can be used in cell text:
+\nopagebreak
+\begin{demohigh}
+\begin{tblr}{hlines}
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} &
+ Row=\arabic{rowcount}, Col=\arabic{colcount} \\
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] &
+ Cell[\arabic{rownum}][\arabic{colnum}] & Cell[\arabic{rownum}][\arabic{colnum}] \\
+\end{tblr}
+\end{demohigh}
+
+Also, lengths \verb!\leftsep!, \verb!\rightsep!, \verb!\abovesep!, \verb!\belowsep! can be used in cell text.
+
+\section{Tracing Tabularray}
+
 To trace internal data behind \verb!tblr! environment, you can use \verb!\SetTblrTracing! command.
 For example, \verb!\SetTblrTracing{all}! will turn on all tracings,
 and \verb!\SetTblrTracing{none}! will turn off all tracings.
@@ -779,8 +1185,680 @@
 \verb!\SetTblrTracing{+row,+column}! will only tracing row and column data.
 All tracing messages will be written to the log files.
 
-\chapter{Source Code}
+\chapter{Use Long Tables}
+\label{chap:long}
 
+\mywarning{chapter}
+
+\section{A Simple Example}
+
+In fact, to make a decent long table with header and footer, it is better to separate header/footer as
+\underline{table head/foot} (which includes caption, footnotes, continuation text)
+and \underline{row head/foot} (which includes some rows of the table that should appear in every page).
+By this approach, alternating row colors should work as expected.
+
+\NewTblrTheme{fancy}{
+  \SetTblrStyle{firsthead}{font=\bfseries}
+  \SetTblrStyle{firstfoot}{fg=blue2}
+  \SetTblrStyle{middlefoot}{\itshape}
+  \SetTblrStyle{caption-tag}{red2}
+}
+\begin{longtblr}[
+  theme = fancy,
+  caption = {A Long Long Long Long Long Long Long Table},
+  entry = {Short Caption},
+  label = {tblr:test},
+  note{a} = {It is the first footnote.},
+  note{$\dag$} = {It is the second long long long long long long footnote.},
+  remark{Note} = {Some general note. Some general note. Some general note.},
+  remark{Source} = {Made up by myself. Made up by myself. Made up by myself.},
+]{
+  colspec = {XXX}, width = 0.85\linewidth,
+  row{odd} = {gray9}, row{even} = {brown9}, rowhead = 2, rowfoot = 1,
+}
+\hline
+ \SetRow{purple7} Head & Head & Head \\
+\hline
+ \SetRow{purple7} Head & Head & Head \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta\TblrNote{a} & Eta \\
+\hline
+ Iota    & Kappa\TblrNote{$\dag$} & Lambda \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma\footnote{Hello}   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+%\hline
+% Alpha   & Beta  & Gamma   \\
+%\hline
+% Epsilon & Zeta  & Eta     \\
+%\hline
+% Iota    & Kappa & Lambda  \\
+%\hline
+% Nu      & Xi    & Omicron \\
+%\hline
+% Rho     & Sigma & Tau     \\
+%\hline
+% Phi     & Chi   & Psi     \\
+\hline
+ \SetRow{blue7} Foot & Foot & Foot \\
+\hline
+\end{longtblr}
+
+As you can see in the above example, the appearance of long tables of \verb!tabularray! package
+is similar to that of \verb!threeparttable! and \verb!threeparttablex! packages.
+We support table footnotes, but not page footnotes in \verb!tabularray! package.
+
+\newpage
+
+The source code for the above long table is shown below. It is mainly self-explanatory.
+
+\begin{codehigh}
+\NewTblrTheme{fancy}{
+  \SetTblrStyle{firsthead}{font=\bfseries}
+  \SetTblrStyle{firstfoot}{fg=blue2}
+  \SetTblrStyle{middlefoot}{\itshape}
+  \SetTblrStyle{caption-tag}{red2}
+}
+\begin{longtblr}[
+  theme = fancy,
+  caption = {A Long Long Long Long Long Long Long Table},
+  entry = {Short Caption},
+  label = {tblr:test},
+  note{a} = {It is the first footnote.},
+  note{$\dag$} = {It is the second long long long long long long footnote.},
+  remark{Note} = {Some general note. Some general note. Some general note.},
+  remark{Source} = {Made up by myself. Made up by myself. Made up by myself.},
+]{
+  colspec = {XXX}, width = 0.85\linewidth,
+  row{odd} = {gray9}, row{even} = {brown9}, rowhead = 2, rowfoot = 1,
+}
+\hline
+ \SetRow{purple7} Head & Head & Head \\
+\hline
+ \SetRow{purple7} Head & Head & Head \\
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta\TblrNote{a} & Eta \\
+\hline
+ Iota    & Kappa\TblrNote{$\dag$} & Lambda \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+......
+\hline
+ Alpha   & Beta  & Gamma   \\
+\hline
+ Epsilon & Zeta  & Eta     \\
+\hline
+ Iota    & Kappa & Lambda  \\
+\hline
+ Nu      & Xi    & Omicron \\
+\hline
+ Rho     & Sigma & Tau     \\
+\hline
+ Phi     & Chi   & Psi     \\
+\hline
+ \SetRow{blue7} Foot & Foot & Foot \\
+\hline
+\end{longtblr}
+\end{codehigh}
+
+As you can see in the above code, we typeset long tables with \verb!longtblr! environemnt.
+And we can totally separate contents and styles of long tables with \verb!tabularray! package.
+
+Row head and row foot consist of some lines of the table and should appear in every page.
+Their options are inner specifications and should be put in the mandatory argument of the \verb!longtblr! environment.
+In the above example, We set \verb!rowhead=2! and \verb!rowfoot=1!.
+
+\begin{spectblr}[
+  caption = {Inner Specifications for Row Heads and Row Foots}
+]{}
+  Key Nama    & Key Description & Initial Value \\
+  \V{rowhead} & number of the first rows of the table appear in every page & \V{0} \\
+  \V{rowfoot} & number of the last rows of the table appear in every page  & \V{0} \\
+\end{spectblr}
+
+Table head and table foot consist of the caption, continuation text, footnotes and remarks.
+Their options are outer specifications and should be put in the optional argument of the \verb!longtblr! environment.
+
+\begin{spectblr}[
+  caption = {Outer Specifications for Table Heads and Table Foots}
+]{}
+  Key Nama            & Key Description & Initial Value \\
+  \V{headsep}         & vertical space between table head and table body & \V{6pt} \\
+  \V{footsep}         & vertical space between table foot and table body & \V{6pt} \\
+  \V{presep}          & vertical space between table head and the above text & \texttt{1.5\string\bigskipamount} \\
+  \V{postsep}         & vertical space between table foot and the below text & \texttt{1.5\string\bigskipamount} \\
+  \V{theme}           & table theme (including settings for templates and styles) & None \\
+  \V{caption}         & table caption & None \\
+  \V{entry}           & short table caption to be put in List of Tables & None \\
+  \V{label}           & table label & None \\
+  \V{note\{<name>\}}   & table note with \V{<name>} as tag & None \\
+  \V{remark\{<name>\}} & table remark with \V{<name>} as tag & None \\
+\end{spectblr}
+
+\section{Customize Templates}
+
+\subsection{Overview of Templates}
+
+The template system for table heads and table foots in \verb!tabularray! is largely inspired by \verb!beamer!,
+\verb!caption! and \verb!longtable! packages. You can use \verb!\DefTblrTemplate! command to define and
+modify templates, and \verb!\SetTblrTemplate! command to choose default templates. In defining templates,
+you can include other templates with \verb!\UseTblrTemplate! and \verb!\ExpTblrTemplate! commands.
+
+\begin{spectblr}[
+  caption = {Templates for Table Heads and Table Foots}
+]{}
+  Template Name    & Template Description \\
+  \V{contfoot-text}& continuation text in the foot, normally ``Continued on next page'' \\
+  \V{contfoot}     & continuation paragraph in the foot, normally including \V{contfoot-text} template \\
+  \V{conthead-text}& continuation text in the head, normally ``(Continued)'' \\
+  \V{conthead}     & continuation paragraph in the head, normally including \V{conthead-text} template \\
+  \V{caption-tag}  & caption tag, normally like ``Table 4.2'' \\
+  \V{caption-sep}  & caption separator, normally like ``:\quad'' \\
+  \V{caption-text} & caption text, normally using user provided value \\
+  \V{caption}      & including \V{caption-tag} + \V{caption-sep} + \V{caption-text} \\
+  \V{note-tag}     & note tag, normally using user provided value \\
+  \V{note-sep}     & note separator, normally like ``\enskip'' \\
+  \V{note-text}    & note tag, normally using user provided value \\
+  \V{note}         & including \V{note-tag} + \V{note-sep} + \V{note-text} \\
+  \V{remark-tag}   & remark tag, normally using user provided value \\
+  \V{remark-sep}   & remark separator, normally like ``:\enskip'' \\
+  \V{remark-text}  & remark text, normally using user provided value\\
+  \V{remark}       & including \V{remark-tag} + \V{remark-sep} + \V{remark-text} \\
+  \V{firsthead}    & table head on the first page, normally including \V{caption} template \\
+  \V{middlehead}   & table head on middle pages, normally including \V{caption} and \V{conthead} templates \\
+  \V{lasthead}     & table head on the last page, normally including \V{caption} and \V{conthead} templates \\
+  \V{head}         & setting all of \V{firsthead}, \V{middlehead} and \V{lasthead} \\
+  \V{firstfoot}    & table foot on the first page, normally including \V{contfoot} template \\
+  \V{middlefoot}   & table foot on middle pages, normally including \V{contfoot} template \\
+  \V{lastfoot}     & table foot on the last page, normally including \V{note} and \V{remark} templates \\
+  \V{foot}         & setting all of \V{firstfoot}, \V{middlefoot} and \V{lastfoot} \\
+\end{spectblr}
+
+A template which only includes short text is called a \underline{sub template}.
+Normally there is one \verb!-! in the name of a sub template.
+A template which includes one or more paragraphs is called a \underline{main template}.
+Normally there isn't any \verb!-! in the name of a main template.
+
+\subsection{Continuation Templates}
+
+Let us have a look at the code for defining templates of continuation text first:
+
+\begin{codehigh}
+\DefTblrTemplate{contfoot-text}{normal}{Continued on next page}
+\SetTblrTemplate{contfoot-text}{normal}
+\DefTblrTemplate{conthead-text}{normal}{(Continued)}
+\SetTblrTemplate{conthead-text}{normal}
+\end{codehigh}
+
+In the above code, command \verb!\DefTblrTemplate! defines the templates with name \verb!normal!,
+and then command \verb!\SetTblrTemplate! sets the templates with name \verb!normal! as default.
+The \verb!normal! template is always defined and set as default for any template element in \verb!tabularray!.
+Therefore you had better use another name when defining new templates.
+
+If you use \verb!default! as template name in \verb!\DefTblrTemplate!,
+you define and set it as default at the same time.
+Therefore the above code can be written in another way:
+
+\begin{codehigh}
+\DefTblrTemplate{contfoot-text}{default}{Continued on next page}
+\DefTblrTemplate{conthead-text}{default}{(Continued)}
+\end{codehigh}
+
+You may modify the code to customize continuation text to fit your needs.
+
+The \verb!contfoot! and \verb!conthead! templates normally
+include their sub templates with \verb!\UseTblrTemplate! commands.
+But you can also handle user settings such as horizontal alignment here.
+
+\begin{codehigh}
+\DefTblrTemplate{contfoot}{default}{\UseTblrTemplate{contfoot-text}{default}}
+\DefTblrTemplate{conthead}{default}{\UseTblrTemplate{conthead-text}{default}}
+\end{codehigh}
+
+\subsection{Caption Templates}
+
+Normally a caption consists of three parts, and their templates are defined with the follow code:
+
+\begin{codehigh}
+\DefTblrTemplate{caption-tag}{default}{Table\hspace{0.25em}\thetable}
+\DefTblrTemplate{caption-sep}{default}{:\enskip}
+\DefTblrTemplate{caption-text}{default}{\InsertTblrText{caption}}
+\end{codehigh}
+
+The command \verb!\InsertTblrText{caption}! inserts the value of \verb!caption! key,
+which you could write in the optional argument of \verb!longtblr! environment.
+
+The \verb!caption! template normally includes three sub templates with \verb!\UseTblrTemplate! commands:
+The \verb!caption! template will be used in \verb!firsthead! template.
+
+\begin{codehigh}
+\DefTblrTemplate{caption}{default}{
+  \UseTblrTemplate{caption-tag}{default}
+  \UseTblrTemplate{caption-sep}{default}
+  \UseTblrTemplate{caption-text}{default}
+}
+\end{codehigh}
+
+Furthermore \verb!capcont! template includes \verb!conthead! template as well.
+The \verb!capcont! template will be used in \verb!middlehead! and \verb!lasthead! templates.
+
+\begin{codehigh}
+\DefTblrTemplate{capcont}{default}{
+  \UseTblrTemplate{caption-tag}{default}
+  \UseTblrTemplate{caption-sep}{default}
+  \UseTblrTemplate{caption-text}{default}
+  \UseTblrTemplate{conthead}{default}
+}
+\end{codehigh}
+
+\subsection{Note and Remark Templates}
+
+The templates for table notes can be defined like this:
+
+\begin{codehigh}
+\DefTblrTemplate{note-tag}{default}{\textsuperscript{\InsertTblrNoteTag}}
+\DefTblrTemplate{note-sep}{default}{\space}
+\DefTblrTemplate{note-text}{default}{\InsertTblrNoteText}
+\end{codehigh}
+\begin{codehigh}
+\DefTblrTemplate{note}{default}{
+  \MapTblrNotes{
+    \noindent
+    \UseTblrTemplate{note-tag}{default}
+    \UseTblrTemplate{note-sep}{default}
+    \UseTblrTemplate{note-text}{default}
+    \par
+  }
+}
+\end{codehigh}
+
+The \verb!\MapTblrNotes! command loops for all table notes,
+which are written in the optional argument of \verb!longtblr! environment.
+Inside the loop, you can use \verb!\InsertTblrNoteTag! and \verb!\InsertTblrNoteText!
+commands to insert current note tag and note text, respectively.
+
+The definition of remark templates are similar to note templates.
+\nopagebreak
+\begin{codehigh}
+\DefTblrTemplate{remark-tag}{default}{\InsertTblrRemarkTag}
+\DefTblrTemplate{remark-sep}{default}{:\space}
+\DefTblrTemplate{remark-text}{default}{\InsertTblrRemarkText}
+\end{codehigh}
+\begin{codehigh}
+\DefTblrTemplate{remark}{default}{
+  \MapTblrRemarks{
+    \noindent
+    \UseTblrTemplate{remark-tag}{default}
+    \UseTblrTemplate{remark-sep}{default}
+    \UseTblrTemplate{remark-text}{default}
+    \par
+  }
+}
+\end{codehigh}
+
+\subsection{Head and Foot Templates}
+
+The templates for table heads and foots are defined as including other templates:
+
+\begin{codehigh}
+\DefTblrTemplate{firsthead}{default}{
+  \UseTblrTemplate{caption}{default}
+}
+\DefTblrTemplate{middlehead,lasthead}{default}{
+  \UseTblrTemplate{capcont}{default}
+}
+\DefTblrTemplate{firstfoot,middlefoot}{default}{
+  \UseTblrTemplate{contfoot}{default}
+}
+\DefTblrTemplate{lastfoot}{default}{
+  \UseTblrTemplate{note}{default}
+  \UseTblrTemplate{remark}{default}
+}
+\end{codehigh}
+
+Note that you can define the same template for multiple elements in \verb!\DefTblrTemplate! command.
+
+\section{Change Styles}
+
+You may change the styles of template elements.
+
+\begin{codehigh}
+\SetTblrStyle{firsthead}{font=\bfseries}
+\SetTblrStyle{firstfoot}{fg=blue2}
+\SetTblrStyle{middlefoot}{\itshape}
+\SetTblrStyle{caption-tag}{red2}
+\end{codehigh}
+
+All available keys for template elements are described in Table \ref{key:element}.
+
+\begin{spectblr}[
+  caption = {Keys for the Styles of Template Elements},
+  label = {key:element},
+  remark{Note} = {In most cases, you can omit the underlined key names and write only their values.
+                  The keys \K{halign}, \K{indent} and \K{hang} are only for main templates.}
+]{}
+  Key Name               & Key Description \\
+  \underline{\K{fg}}     & foreground color \\
+  \underline{\K{font}}   & font commands \\
+  \underline{\K{halign}} & horizontal alignment: \V{l} (left), \V{c} (center), or \V{r} (right) \\
+  \K{indent}             & parindent value \\
+  \K{hang}               & hangindent value \\
+\end{spectblr}
+
+When you write \verb!\UseTblrTemplate{element}{default}! in defining a template,
+beside including the code of template \verb!element!, the foreground color and font commands
+of the template \verb!element! will be set up automatically.
+In contrast, \verb!\ExpTblrTemplate{element}{default}! will only include template code.
+
+\section{Define Themes}
+
+You may define your own themes for table heads and foots with \verb!\NewTblrTheme! command.
+a theme consists of some template and style settings. For example:
+\nopagebreak
+\begin{codehigh}
+\NewTblrTheme{fancy}{
+  \DefTblrTemplate{conthead}{default}{[Continued]}
+  \SetTblrStyle{firsthead}{font=\bfseries}
+  \SetTblrStyle{firstfoot}{fg=blue2}
+  \SetTblrStyle{middlefoot}{\itshape}
+  \SetTblrStyle{caption-tag}{red2}
+}
+\end{codehigh}
+
+After defining the theme \verb!fancy!, you can use it
+by writing \verb!theme=fancy! in the optional argument of \verb!longtblr! environment.
+
+\chapter{Use Some Libraries}
+
+\mywarning{chapter}
+
+The \verb!tabularray! package emulates or fixes some commands in other packages.
+To avoid potential conflict, you need to enable them with \verb!\UseTblrLibrary! command.
+
+\section{Library \V{booktabs}}
+
+When you write \verb!\UseTblrLibrary{booktabs}!,
+\verb!tabularray! package will define commands \verb!\toprule!, \verb!\midrule!,
+\verb!\bottomrule! and \verb!\cmidrule! inside \verb!tblr! environment.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\toprule
+ Alpha   & Beta  & Gamma   & Delta \\
+\midrule
+ Epsilon & Zeta  & Eta     & Theta \\
+\cmidrule{1-3}
+ Iota    & Kappa & Lambda  & Mu    \\
+\cmidrule{2-4}
+ Nu      & Xi    & Omicron & Pi    \\
+\bottomrule
+\end{tblr}
+\end{demohigh}
+
+At this moment, \verb!trim! options for \verb!\cmidrule! command are not supported.
+But rule colors are possible just like \verb!\hline! and \verb!\cline! commands.
+
+\begin{demohigh}
+\begin{tblr}{llll}
+\toprule[purple3]
+ Alpha   & Beta  & Gamma   & Delta \\
+\midrule[blue3]
+ Epsilon & Zeta  & Eta     & Theta \\
+\cmidrule[azure3]{1-3}
+ Iota    & Kappa & Lambda  & Mu    \\
+\cmidrule[azure3]{2-4}
+ Nu      & Xi    & Omicron & Pi    \\
+\bottomrule[purple3]
+\end{tblr}
+\end{demohigh}
+
+\section{Library \V{diagbox}}
+
+When writing \verb!\UseTblrLibrary{diagbox}! in the preamble of the document,
+\verb!tabularray! package loads \verb!diagbox! package,
+and you can use \verb!\diagbox! and \verb!\diagboxthree! commands inside \verb!tblr! environment.
+
+\begin{demohigh}
+\begin{tblr}{hlines,vlines}
+ \diagbox{Aa}{Pp} & Beta & Gamma \\
+ Epsilon & Zeta  & Eta \\
+ Iota    & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+\begin{demohigh}
+\begin{tblr}{hlines,vlines}
+ \diagboxthree{Aa}{Pp}{Hh} & Beta & Gamma \\
+ Epsilon & Zeta  & Eta \\
+ Iota    & Kappa & Lambda \\
+\end{tblr}
+\end{demohigh}
+
+You can also use \verb!\diagbox! and \verb!\diagboxthree! commands in math mode.
+\nopagebreak
+\begin{demohigh}
+$\begin{tblr}{|c|cc|}
+\hline
+ \diagbox{X_1}{X_2} & 0 & 1 \\
+\hline
+  0 & 0.1 & 0.2 \\
+  1 & 0.3 & 0.4 \\
+\hline
+\end{tblr}$
+\end{demohigh}
+
+\section{Library \V{siunitx}}
+
+When writing \verb!\UseTblrLibrary{siunitx}! in the preamble of the document,
+\verb!tabularray! package loads \verb!siunitx! package,
+and defines \verb!S! column for \verb!tblr! environment.
+
+\begin{demohigh}
+\begin{tblr}{
+  hlines, vlines,
+  colspec={
+    S[table-format=2.2]
+    S[table-format=2.2]
+    S[table-format=2.2]
+  }
+}
+ {{{Head}}} & {{{Head}}} & {{{Head}}} \\
+    11      &    11      &    11      \\
+     2.1    &     2.2    &     2.3    \\
+    33.11   &    33.22   &    33.33   \\
+\end{tblr}
+\end{demohigh}
+
+Note that you need to use \underline{triple} pairs of braces to guard non-numeric cells.
+If you need to apply other specifications for the \verb!S! columns,
+you need to move \verb!siunitx! options into \verb!si! keys of the \verb!Q! columns.
+
+\begin{demohigh}
+\begin{tblr}{
+  hlines, vlines,
+  colspec={
+    Q[si={table-format=2.2},blue7]
+    Q[si={table-format=2.2},teal7]
+    Q[si={table-format=2.2},purple7]
+  }
+}
+ {{{Head}}} & {{{Head}}} & {{{Head}}} \\
+    11      &    11      &    11      \\
+     2.1    &     2.2    &     2.3    \\
+    33.11   &    33.22   &    33.33   \\
+\end{tblr}
+\end{demohigh}
+
+\chapter{The Source Code}
+
 %\CodeHigh{lite}
 \dochighinput[language=latex/latex3]{tabularray.sty}
 

Modified: trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty	2021-07-01 21:36:39 UTC (rev 59796)
+++ trunk/Master/texmf-dist/tex/latex/tabularray/tabularray.sty	2021-07-01 21:36:51 UTC (rev 59797)
@@ -12,12 +12,17 @@
 
 \NeedsTeXFormat{LaTeX2e}
 \RequirePackage{expl3}
-\ProvidesExplPackage{tabularray}{2021-06-05}{2021K}
+\ProvidesExplPackage{tabularray}{2021-07-01}{2021L}
   {Typeset tabulars and arrays with LaTeX3}
 
 \RequirePackage{xparse}
-\AtBeginDocument{\@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}}
 
+\AtBeginDocument
+  {
+    \@ifpackageloaded{xcolor}{\RequirePackage{ninecolors}}{}
+    \@ifpackageloaded{hyperref}{\hypersetup{pdfborder={0 0 0}}}{}
+  }
+
 \ExplSyntaxOn
 
 %% Backport \tl_if_eq:NnTF for old texlive 2020
@@ -57,6 +62,7 @@
 \prg_generate_conditional_variant:Nnn \prop_if_in:Nn { c } { T }
 \prg_generate_conditional_variant:Nnn \str_if_eq:nn { xn } { TF }
 \prg_generate_conditional_variant:Nnn \tl_if_eq:nn { en } { T, TF }
+\prg_generate_conditional_variant:Nnn \tl_if_head_eq_catcode:nN { VN } { TF }
 \prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { VN } { T, TF }
 
 \tl_new:N  \l__tblr_a_tl
@@ -97,6 +103,14 @@
 \box_new:N \l__tblr_c_box % for cell box
 \box_new:N \l__tblr_d_box
 
+%% Total number of tblr tables
+\int_new:N \g__tblr_table_count_int
+
+%% Some commands for horizontal alignment
+\cs_new_eq:NN \__tblr_halign_command_l: \raggedright
+\cs_new_eq:NN \__tblr_halign_command_c: \centering
+\cs_new_eq:NN \__tblr_halign_command_r: \raggedleft
+
 %% Some counters for row and column numbering
 \newcounter{rownum}
 \newcounter{colnum}
@@ -103,6 +117,12 @@
 \newcounter{rowcount}
 \newcounter{colcount}
 
+%% Some dimensions for row and column spacing
+\dim_new:N \abovesep
+\dim_new:N \belowsep
+\dim_new:N \leftsep
+\dim_new:N \rightsep
+
 %%% --------------------------------------------------------
 %%  \section{Data Structures Based on Property Lists}
 %%% --------------------------------------------------------
@@ -113,7 +133,10 @@
   {
     \prop_gclear_new:c { g__tblr_text_ \int_use:N \g_tblr_level_int _prop }
     \prop_gclear_new:c { g__tblr_command_ \int_use:N \g_tblr_level_int _prop }
-    \prop_gclear_new:c { g__tblr_table_ \int_use:N \g_tblr_level_int _prop }
+    \prop_gclear_new:c { g__tblr_inner_ \int_use:N \g_tblr_level_int _prop }
+    \prop_gclear_new:c { g__tblr_note_ \int_use:N \g_tblr_level_int _prop }
+    \prop_gclear_new:c { g__tblr_remark_ \int_use:N \g_tblr_level_int _prop }
+    \prop_gclear_new:c { g__tblr_more_ \int_use:N \g_tblr_level_int _prop }
     \prop_gclear_new:c { g__tblr_row_ \int_use:N \g_tblr_level_int _prop }
     \prop_gclear_new:c { g__tblr_column_ \int_use:N \g_tblr_level_int _prop }
     \prop_gclear_new:c { g__tblr_cell_ \int_use:N \g_tblr_level_int _prop }
@@ -184,7 +207,7 @@
       { \dim_compare_p:nNn { #3 } > { \l__tblr_put_if_larger_tl } }
       { \prop_put:Nnn #1 { #2 } { #3 }  }
   }
-\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx }
+\cs_generate_variant:Nn \__tblr_put_if_larger:Nnn { Nnx, Nxn, Nxx, NnV }
 
 \cs_new_protected:Npn \__tblr_gput_if_larger:Nnn #1 #2 #3
   {
@@ -215,63 +238,78 @@
 %%  \section{Data Structures Based on Token Lists}
 %%% --------------------------------------------------------
 
-\cs_new_protected:Npn \__tblr_clear_text_lists:
+\cs_new_protected:Npn \__tblr_clear_spec_lists:
   {
-    \__tblr_clear_one_text_lists:n { text }
-    \__tblr_clear_one_text_lists:n { hline }
-    \__tblr_clear_one_text_lists:n { vline }
+    %\__tblr_clear_one_spec_lists:n { row }
+    %\__tblr_clear_one_spec_lists:n { column }
+    %\__tblr_clear_one_spec_lists:n { cell }
+    \__tblr_clear_one_spec_lists:n { text }
+    \__tblr_clear_one_spec_lists:n { hline }
+    \__tblr_clear_one_spec_lists:n { vline }
+    \__tblr_clear_one_spec_lists:n { outer }
   }
 
-\cs_new_protected:Npn \__tblr_clear_one_text_lists:n #1
+\cs_new_protected:Npn \__tblr_clear_one_spec_lists:n #1
   {
     \clist_if_exist:cTF { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
       {
         \clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
           {
-            \tl_gclear:c { g__tblr_text_ \int_use:N \g_tblr_level_int _#1_##1_tl }
+            \tl_gclear:c { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_##1_tl }
           }
       }
       { \clist_new:c { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } }
   }
 
-\cs_new_protected:Npn \__tblr_text_gput:nnn #1 #2 #3
+\cs_new_protected:Npn \__tblr_spec_gput:nnn #1 #2 #3
   {
     \tl_gset:cn
-      { g__tblr_text_ \int_use:N \g_tblr_level_int _#1_#2_tl } {#3}
+      { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl } {#3}
     \clist_gput_right:cx { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist } {#2}
   }
-\cs_generate_variant:Nn \__tblr_text_gput:nnn { nne, nnV, nen, nee, neV }
+\cs_generate_variant:Nn \__tblr_spec_gput:nnn { nne, nnV, nen, nee, neV }
 
-\cs_new:Npn \__tblr_text_item:nn #1 #2
+\cs_new:Npn \__tblr_spec_item:nn #1 #2
   {
-    \tl_if_exist:cT { g__tblr_text_ \int_use:N \g_tblr_level_int _#1_#2_tl }
+    \tl_if_exist:cT { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
       {
         \exp_args:Nv \exp_not:n
-          { g__tblr_text_ \int_use:N \g_tblr_level_int _#1_#2_tl }
+          { g__tblr_spec_ \int_use:N \g_tblr_level_int _#1_#2_tl }
       }
   }
-\cs_generate_variant:Nn \__tblr_text_item:nn { ne }
+\cs_generate_variant:Nn \__tblr_spec_item:nn { ne }
 
-\cs_new_protected:Npn \__tblr_text_gput_if_larger:nnn #1 #2 #3
+\cs_new_protected:Npn \__tblr_spec_gput_if_larger:nnn #1 #2 #3
   {
-    \tl_set:Nx \l__tblr_put_if_larger_tl { \__tblr_text_item:nn {#1} {#2} }
+    \tl_set:Nx \l__tblr_put_if_larger_tl { \__tblr_spec_item:nn {#1} {#2} }
     \bool_lazy_or:nnT
       { \tl_if_empty_p:N \l__tblr_put_if_larger_tl }
       { \dim_compare_p:nNn {#3} > { \l__tblr_put_if_larger_tl } }
-      { \__tblr_text_gput:nnn {#1} {#2} {#3} }
+      { \__tblr_spec_gput:nnn {#1} {#2} {#3} }
   }
-\cs_generate_variant:Nn \__tblr_text_gput_if_larger:nnn { nne, nnV, nen, nee, neV }
+\cs_generate_variant:Nn \__tblr_spec_gput_if_larger:nnn { nne, nnV, nen, nee, neV }
 
-\cs_new_protected:Npn \__tblr_text_log:n #1
+\cs_new_protected:Npn \__tblr_spec_gadd_dimen_value:nnn #1 #2 #3
   {
+    \__tblr_spec_gput:nne {#1} {#2}
+      { \dim_eval:n { \__tblr_spec_item:ne {#1} {#2} + #3 } }
+  }
+\cs_generate_variant:Nn \__tblr_spec_gadd_dimen_value:nnn { nne, nnV, nen, nee }
+
+\cs_new_protected:Npn \__tblr_spec_log:n #1
+  {
     \clist_gremove_duplicates:c
       { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
-    \tl_log:n { ----------~----------~----------~----------~---------- }
+    \tl_log:x
+      {
+        The ~ spec ~ list ~ #1 _ \int_use:N \g_tblr_level_int
+              \space contains ~ the ~ pairs:
+      }
     \clist_map_inline:cn { g__tblr_#1_ \int_use:N \g_tblr_level_int _clist }
       {
         \tl_log:x
           {
-            \space { #1 ##1 } ~\space=>~\space { \__tblr_text_item:nn {#1} {##1} }
+            \space { ##1 } ~\space=>~\space { \__tblr_spec_item:nn {#1} {##1} }
           }
       }
   }
@@ -336,6 +374,7 @@
 \__tblr_data_new_key:nnn { cell } { halign }       { str }
 \__tblr_data_new_key:nnn { cell } { valign }       { str }
 \__tblr_data_new_key:nnn { cell } { background }   { str }
+\__tblr_data_new_key:nnn { cell } { font }         { str }
 \__tblr_data_new_key:nnn { cell } { omit }         { int }
 \__tblr_data_new_key:nnn { cell } { @cell-width }  { dim }
 \__tblr_data_new_key:nnn { cell } { @cell-height } { dim }
@@ -350,12 +389,12 @@
 \tl_const:Nn \g__tblr_data_cell_index_number_tl {2}
 \int_new:N \g__tblr_array_int
 
-\cs_new_protected:Npn \__tblr_initial_table_data:
+\cs_new_protected:Npn \__tblr_init_table_data:
   {
-    \clist_map_function:NN \g__tblr_data_clist \__tblr_initial_one_data:n
+    \clist_map_function:NN \g__tblr_data_clist \__tblr_init_one_data:n
   }
 
-\cs_new_protected:Npn \__tblr_initial_one_data:n #1
+\cs_new_protected:Npn \__tblr_init_one_data:n #1
   {
     \int_gincr:N \g__tblr_array_int
     \intarray_new:cn { g__tblr_#1_ \int_use:N \g__tblr_array_int _intarray }
@@ -507,18 +546,18 @@
 
 \cs_new_protected:Npn \__tblr_data_int_from_str:n #1
   {
-    \tl_if_exist:cTF { g__tblr_data_#1_to_int_tl }
+    \tl_if_exist:cTF { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
       {
         \tl_gset_eq:Nc \g__tblr_data_int_from_value_tl
-          { g__tblr_data_#1_to_int_tl }
+          { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
       }
       {
         \int_gincr:N \g__tblr_data_str_value_count_int
-        \tl_gset:cx { g__tblr_data_#1_to_int_tl }
+        \tl_gset:cx { g__tblr_data_ \tl_to_str:n {#1} _to_int_tl }
           { \int_use:N \g__tblr_data_str_value_count_int }
-        \tl_gset:cx
+        \tl_gset:cn
           { g__tblr_data_ \int_use:N \g__tblr_data_str_value_count_int _to_str_tl }
-          { #1 }
+          { \exp_not:n {#1} }
         \tl_gset:Nx \g__tblr_data_int_from_value_tl
           { \int_use:N \g__tblr_data_str_value_count_int }
       }
@@ -661,7 +700,8 @@
       { \__tblr_data_key_to_int:nnn {#1} {#2} {#3} }
       { \g__tblr_data_int_from_value_tl }
   }
-\cs_generate_variant:Nn \__tblr_data_gadd_dimen_value:nnnn { nnne, nnnV, nene }
+\cs_generate_variant:Nn \__tblr_data_gadd_dimen_value:nnnn
+  { nnne, nnnV, nenn, nene }
 
 \cs_new_protected:Npn \__tblr_array_gadd_value:Nnn #1 #2 #3
   {
@@ -678,39 +718,39 @@
       {
         \cs_set_protected:Npn \__tblr_data_gput:nnnn #1 #2 #3 #4
           {
-            \__tblr_prop_gput:nnn {#1} { [#2] / #3 } {#4}
+            \__tblr_spec_gput:nnn {#1} { [#2] / #3 } {#4}
           }
         \cs_set_protected:Npn \__tblr_data_gput:nnnnn #1 #2 #3 #4 #5
           {
-            \__tblr_prop_gput:nnn {#1} { [#2][#3] / #4 } {#5}
+            \__tblr_spec_gput:nnn {#1} { [#2][#3] / #4 } {#5}
           }
         \cs_set:Npn \__tblr_data_item:nnn #1 #2 #3
           {
-            \__tblr_prop_item:nn {#1} { [#2] / #3 }
+            \__tblr_spec_item:nn {#1} { [#2] / #3 }
           }
         \cs_set:Npn \__tblr_data_item:nnnn #1 #2 #3 #4
           {
-            \__tblr_prop_item:nn {#1} { [#2][#3] / #4 }
+            \__tblr_spec_item:nn {#1} { [#2][#3] / #4 }
           }
         \cs_set_protected:Npn \__tblr_data_log:n #1
           {
-            \__tblr_prop_log:n {#1}
+            \__tblr_spec_log:n {#1}
           }
         \cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnn #1 #2 #3 #4
           {
-            \__tblr_prop_gput_if_larger:nnn {#1} { [#2] / #3 } {#4}
+            \__tblr_spec_gput_if_larger:nnn {#1} { [#2] / #3 } {#4}
           }
         \cs_set_protected:Npn \__tblr_data_gput_if_larger:nnnnn #1 #2 #3 #4 #5
           {
-            \__tblr_prop_gput_if_larger:nnn {#1} { [#2][#3] / #4 } {#5}
+            \__tblr_spec_gput_if_larger:nnn {#1} { [#2][#3] / #4 } {#5}
           }
         \cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnn #1 #2 #3 #4
           {
-            \__tblr_prop_gadd_dimen_value:nnn {#1} { [#2] / #3 } {#4}
+            \__tblr_spec_gadd_dimen_value:nnn {#1} { [#2] / #3 } {#4}
           }
         \cs_set_protected:Npn \__tblr_data_gadd_dimen_value:nnnnn #1 #2 #3 #4 #5
           {
-            \__tblr_prop_gadd_dimen_value:nnn {#1} { [#2][#3] / #4 } {#5}
+            \__tblr_spec_gadd_dimen_value:nnn {#1} { [#2][#3] / #4 } {#5}
           }
       }
   }
@@ -890,6 +930,40 @@
   }
 
 %%% --------------------------------------------------------
+%%> \section{New Content Commands}
+%%% --------------------------------------------------------
+
+%% We need to emulate or fix some commands such as \diagbox in other packages
+%% These commands must be defined with \NewContentCommand command
+%% We only enable them inside tblr environment to avoid potential conflict
+
+\clist_new:N \g__tblr_content_commands_clist
+
+\msg_new:nnn { tabularray } { defined-content-command }
+  { Content ~ commnad ~ #1 has ~ been ~ defined! }
+
+\NewDocumentCommand \NewContentCommand { m O{0} o m }
+  {
+    \clist_if_in:NnTF \g__tblr_content_commands_clist { #1 }
+      {
+        \msg_warning:nnn { tabularray } { defined-content-command } { #1 }
+        \clist_log:N \g__tblr_content_commands_clist
+      }
+      {
+        \__tblr_make_xparse_arg_spec:nnN { #2 } { #3 } \l__tblr_a_tl
+        \exp_args:NcV \NewDocumentCommand
+          { __tblr_content_command_ \cs_to_str:N #1 :w } \l__tblr_a_tl { #4 }
+        \clist_gput_right:Nn \g__tblr_content_commands_clist { #1 }
+      }
+  }
+
+\cs_new_protected:Npn \__tblr_enable_content_commands:
+  {
+    \clist_map_inline:Nn \g__tblr_content_commands_clist
+      { \cs_set_eq:Nc ##1 { __tblr_content_command_ \cs_to_str:N ##1 :w } }
+  }
+
+%%% --------------------------------------------------------
 %%  \section{New Dash Styles}
 %%% --------------------------------------------------------
 
@@ -1068,12 +1142,12 @@
   {
     \tl_clear:N \l__tblr_hline_num_tl
     \tl_set:Nx \l__tblr_hline_count_tl
-      { \__tblr_text_item:ne { hline } { [\int_use:N \c at rownum] / @hline-count } }
+      { \__tblr_spec_item:ne { hline } { [\int_use:N \c at rownum] / @hline-count } }
     %% \l__tblr_hline_count_tl may be empty when rowspec has extra |'s
     \int_compare:nNnTF { \l__tblr_hline_count_tl + 0 } = {0}
       {
         \tl_set:Nx \l__tblr_hline_num_tl { 1 }
-        \__tblr_text_gput:nen { hline }
+        \__tblr_spec_gput:nen { hline }
           { [\int_use:N \c at rownum] / @hline-count } { 1 }
       }
       {
@@ -1095,7 +1169,7 @@
   {
     \tl_set:Nx \l__tblr_hline_count_tl
       { \int_eval:n { \l__tblr_hline_count_tl + 1 } }
-    \__tblr_text_gput:nee { hline }
+    \__tblr_spec_gput:nee { hline }
       { [\int_use:N \c at rownum] / @hline-count } { \l__tblr_hline_count_tl }
     \tl_set_eq:NN \l__tblr_hline_num_tl \l__tblr_hline_count_tl
   }
@@ -1131,18 +1205,18 @@
     \__tblr_get_childs:nx {#1} { \int_use:N \c at colcount }
     \clist_map_inline:Nn \l_tblr_childs_clist
       {
-        \__tblr_text_gput:nee { hline }
+        \__tblr_spec_gput:nee { hline }
           { [\int_use:N \c at rownum][##1](\l__tblr_hline_num_tl) / @dash }
           { \l__tblr_hline_dash_tl }
         \tl_if_empty:NF \l__tblr_hline_wd_tl
           {
-            \__tblr_text_gput:nee { hline }
+            \__tblr_spec_gput:nee { hline }
               { [\int_use:N \c at rownum][##1](\l__tblr_hline_num_tl) / wd }
               { \l__tblr_hline_wd_tl }
           }
         \tl_if_empty:NF \l__tblr_hline_fg_tl
           {
-            \__tblr_text_gput:nee { hline }
+            \__tblr_spec_gput:nee { hline }
               { [\int_use:N \c at rownum][##1](\l__tblr_hline_num_tl) / fg }
               { \l__tblr_hline_fg_tl }
           }
@@ -1156,13 +1230,13 @@
   {
     \tl_if_eq:nnTF {#1} {above}
       {
-        \__tblr_prop_gput:nnx { table }
+        \__tblr_prop_gput:nnx { inner }
           { baseline } { \int_eval:n { \c at rownum - 1 } }
       }
       {
         \tl_if_eq:nnT {#1} {below}
           {
-            \__tblr_prop_gput:nnx { table } { baseline } { \int_use:N \c at rownum }
+            \__tblr_prop_gput:nnx { inner } { baseline } { \int_use:N \c at rownum }
           }
       }
   }
@@ -1267,12 +1341,12 @@
   {
     \tl_clear:N \l__tblr_vline_num_tl
     \tl_set:Nx \l__tblr_vline_count_tl
-      { \__tblr_text_item:ne { vline } { [\int_use:N \c at colnum] / @vline-count } }
+      { \__tblr_spec_item:ne { vline } { [\int_use:N \c at colnum] / @vline-count } }
     %% \l__tblr_vline_count_tl may be empty when colspec has extra |'s
     \int_compare:nNnTF { \l__tblr_vline_count_tl + 0 } = {0}
       {
         \tl_set:Nx \l__tblr_vline_num_tl { 1 }
-        \__tblr_text_gput:nen { vline }
+        \__tblr_spec_gput:nen { vline }
           { [\int_use:N \c at colnum] / @vline-count } { 1 }
       }
       {
@@ -1294,7 +1368,7 @@
   {
     \tl_set:Nx \l__tblr_vline_count_tl
       { \int_eval:n { \l__tblr_vline_count_tl + 1 } }
-    \__tblr_text_gput:nee { vline }
+    \__tblr_spec_gput:nee { vline }
       { [\int_use:N \c at colnum] / @vline-count } { \l__tblr_vline_count_tl }
     \tl_set_eq:NN \l__tblr_vline_num_tl \l__tblr_vline_count_tl
   }
@@ -1329,18 +1403,18 @@
     \__tblr_get_childs:nx {#1} { \int_use:N \c at rowcount }
     \clist_map_inline:Nn \l_tblr_childs_clist
       {
-        \__tblr_text_gput:nee { vline }
+        \__tblr_spec_gput:nee { vline }
           { [##1][\int_use:N \c at colnum](\l__tblr_vline_num_tl) / @dash }
           { \l__tblr_vline_dash_tl }
         \tl_if_empty:NF \l__tblr_vline_wd_tl
           {
-            \__tblr_text_gput:nee { vline }
+            \__tblr_spec_gput:nee { vline }
               { [##1][\int_use:N \c at colnum](\l__tblr_vline_num_tl) / wd }
               { \l__tblr_vline_wd_tl }
           }
         \tl_if_empty:NF \l__tblr_vline_fg_tl
           {
-            \__tblr_text_gput:nee { vline }
+            \__tblr_spec_gput:nee { vline }
               { [##1][\int_use:N \c at colnum](\l__tblr_vline_num_tl) / fg }
               { \l__tblr_vline_fg_tl }
           }
@@ -1440,36 +1514,41 @@
 
 \keys_define:nn { tblr-cell-spec }
   {
-    l .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { halign } {l},
-    c .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { halign } {c},
-    r .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { halign } {r},
-    t .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {t},
-    p .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {t},
-    m .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {m},
-    b .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {b},
-    h .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {h},
-    f .code:n = \__tblr_data_gput:neenn { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { valign} {f},
-    wd .code:n = \__tblr_data_gput:neene { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { width } {#1},
-    bg .code:n = \__tblr_data_gput:neene { cell }
-                  { \int_use:N \c at rownum } { \int_use:N \c at colnum }
-                  { background } {#1},
-    preto .code:n = \__tblr_cell_preto_text:n {#1},
-    appto .code:n = \__tblr_cell_appto_text:n {#1},
-    fg .code:n = \__tblr_cell_preto_text:n { \color{#1} },
-    font .code:n = \__tblr_cell_preto_text:n { #1 \selectfont },
+    halign  .code:n = \__tblr_cell_gput:nn { halign } {#1},
+    valign  .code:n = \__tblr_cell_gput:nn { valign } {#1},
+    l       .meta:n = { halign = l },
+    c       .meta:n = { halign = c },
+    r       .meta:n = { halign = r },
+    t       .meta:n = { valign = t },
+    p       .meta:n = { valign = t },
+    m       .meta:n = { valign = m },
+    b       .meta:n = { valign = b },
+    h       .meta:n = { valign = h },
+    f       .meta:n = { valign = f },
+    wd      .code:n = \__tblr_cell_gput:ne { width } {#1},
+    bg      .code:n = \__tblr_cell_gput:ne { background } {#1},
+    preto   .code:n = \__tblr_cell_preto_text:n {#1},
+    appto   .code:n = \__tblr_cell_appto_text:n {#1},
+    cmd     .code:n = \__tblr_cell_process_text:n {#1},
+    fg      .code:n = \__tblr_cell_preto_text:n { \color{#1} },
+    font    .code:n = \__tblr_cell_gput:nn { font } { #1 \selectfont },
     unknown .code:n = \__tblr_cell_unknown_key:V \l_keys_key_str,
   }
 
+\cs_new_protected:Npn \__tblr_cell_gput:nn #1 #2
+  {
+    \__tblr_data_gput:neenn { cell }
+      { \int_use:N \c at rownum } { \int_use:N \c at colnum } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_cell_gput:nn { ne }
+
+\cs_new_protected:Npn \__tblr_cell_gput:nnnn #1 #2 #3 #4
+  {
+    \__tblr_data_gput:nnnnn { cell } {#1} {#2} {#3} {#4}
+  }
+\cs_generate_variant:Nn \__tblr_cell_gput:nnnn
+  { nenn, ennn, eenn, nene, enne, eene }
+
 \tl_new:N \l__tblr_cell_text_tl
 
 \cs_new_protected:Npn \__tblr_cell_preto_text:n #1
@@ -1480,9 +1559,9 @@
 
 \cs_new_protected:Npn \__tblr_cell_preto_text:nnn #1 #2 #3
   {
-    \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_text_item:nn { text } { [#1][#2] } }
+    \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:nn { text } { [#1][#2] } }
     \tl_put_left:Nn \l__tblr_cell_text_tl {#3}
-    \__tblr_text_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl
+    \__tblr_spec_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl
   }
 \cs_generate_variant:Nn \__tblr_cell_preto_text:nnn { nen, enn, een }
 
@@ -1494,12 +1573,29 @@
 
 \cs_new_protected:Npn \__tblr_cell_appto_text:nnn #1 #2 #3
   {
-    \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_text_item:ne { text } { [#1][#2] } }
+    \tl_set:Nx \l__tblr_cell_text_tl { \__tblr_spec_item:ne { text } { [#1][#2] } }
     \tl_put_right:Nn \l__tblr_cell_text_tl {#3}
-    \__tblr_text_gput:neV { text } { [#1][#2] } \l__tblr_cell_text_tl
+    \__tblr_spec_gput:neV { text } { [#1][#2] } \l__tblr_cell_text_tl
   }
 \cs_generate_variant:Nn \__tblr_cell_appto_text:nnn { nen, enn, een }
 
+\cs_new_protected:Npn \__tblr_cell_process_text:n #1
+  {
+    \__tblr_cell_process_text:een
+      { \int_use:N \c at rownum } { \int_use:N \c at colnum } {#1}
+  }
+
+\cs_new_protected:Npn \__tblr_cell_process_text:nnn #1 #2 #3
+  {
+    \tl_set:Nx \l__tblr_cell_text_tl
+      {
+        { \__tblr_spec_item:nn { text } { [#1][#2] } }
+      }
+    \tl_put_left:Nn \l__tblr_cell_text_tl {#3}
+    \__tblr_spec_gput:nnV { text } { [#1][#2] } \l__tblr_cell_text_tl
+  }
+\cs_generate_variant:Nn \__tblr_cell_process_text:nnn { nen, enn, een }
+
 \cs_new_protected:Npn \__tblr_cell_unknown_key:n #1
   {
     \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
@@ -1520,13 +1616,13 @@
   {
     \int_compare:nNnT { #1 } > { 1 }
       {
-        \__tblr_prop_gput:nnn {table} {rowspan} {true}
+        \__tblr_prop_gput:nnn { inner } { rowspan } { true }
         \__tblr_data_gput:neenn { cell }
           { \int_use:N \c at rownum } { \int_use:N \c at colnum } { rowspan } {#1}
       }
     \int_compare:nNnT { #2 } > { 1 }
       {
-        \__tblr_prop_gput:nnn {table} {colspan} {true}
+        \__tblr_prop_gput:nnn { inner } { colspan } { true }
         \__tblr_data_gput:neenn { cell }
           { \int_use:N \c at rownum } { \int_use:N \c at colnum } { colspan } {#2}
       }
@@ -1546,12 +1642,12 @@
               }
             \int_compare:nNnF { \l__tblr_i_tl } = { \c at rownum }
               {
-                \__tblr_text_gput:nen { hline }
+                \__tblr_spec_gput:nen { hline }
                   { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
               }
             \int_compare:nNnF { \l__tblr_j_tl } = { \c at colnum }
               {
-                \__tblr_text_gput:nee { vline }
+                \__tblr_spec_gput:nee { vline }
                   { [\l__tblr_i_tl][\l__tblr_j_tl] / omit } {true}
               }
           }
@@ -1678,53 +1774,59 @@
 
 \keys_define:nn { tblr-column }
   {
-    l .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { halign } {l},
-    c .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { halign } {c},
-    r .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { halign } {r},
-    t .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {t},
-    p .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {t},
-    m .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {m},
-    b .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {b},
-    h .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {h},
-    f .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { valign } {f},
-    bg .code:n = \__tblr_set_key_for_every_column_cell:nnn
-                  { \int_use:N \c at colnum } { background } {#1},
-    fg .code:n = \__tblr_preto_text_for_every_column_cell:n { \color{#1} },
-    font .code:n = \__tblr_preto_text_for_every_column_cell:n { #1 \selectfont },
-    wd .code:n = \__tblr_data_gput:nene { column }
-                   { \int_use:N \c at colnum } { width } { \dim_eval:n {#1} },
-    co .code:n = \__tblr_data_gput:nene { column }
-                   { \int_use:N \c at colnum } { coefficient } {#1},
-    leftsep .code:n = \__tblr_data_gput:nene { column }
-                   { \int_use:N \c at colnum } { leftsep } { \dim_eval:n {#1} },
-    rightsep .code:n = \__tblr_data_gput:nene { column }
-                   { \int_use:N \c at colnum } { rightsep } { \dim_eval:n {#1} },
-    colsep .meta:n = { leftsep = #1, rightsep = #1},
-    leftsep+ .code:n = \__tblr_data_gadd_dimen_value:nene { column }
-                   { \int_use:N \c at colnum } { leftsep } { \dim_eval:n {#1} },
-    rightsep+ .code:n = \__tblr_data_gadd_dimen_value:nene { column }
-                   { \int_use:N \c at colnum } { rightsep } { \dim_eval:n {#1} },
-    colsep+ .meta:n = { leftsep+ = #1, rightsep+ = #1},
-    unknown .code:n = \__tblr_column_unknown_key:V \l_keys_key_str,
+    halign    .code:n = \__tblr_column_gput_cell:nn { halign } {#1},
+    valign    .code:n = \__tblr_column_gput_cell:nn { valign } {#1},
+    l         .meta:n = { halign = l },
+    c         .meta:n = { halign = c },
+    r         .meta:n = { halign = r },
+    t         .meta:n = { valign = t },
+    p         .meta:n = { valign = t },
+    m         .meta:n = { valign = m },
+    b         .meta:n = { valign = b },
+    h         .meta:n = { valign = h },
+    f         .meta:n = { valign = f },
+    bg        .code:n = \__tblr_column_gput_cell:nn { background } {#1},
+    fg        .code:n = \__tblr_preto_text_for_every_column_cell:n { \color{#1} },
+    font      .code:n = \__tblr_column_gput_cell:nn { font } { #1 \selectfont },
+    wd        .code:n = \__tblr_column_gput:ne { width } { \dim_eval:n {#1} },
+    co        .code:n = \__tblr_column_gput:ne { coefficient } {#1},
+    preto     .code:n = \__tblr_preto_text_for_every_column_cell:n {#1},
+    appto     .code:n = \__tblr_appto_text_for_every_column_cell:n {#1},
+    cmd       .code:n = \__tblr_process_text_for_every_column_cell:n {#1},
+    leftsep   .code:n = \__tblr_column_gput:ne { leftsep } { \dim_eval:n {#1} },
+    rightsep  .code:n = \__tblr_column_gput:ne { rightsep } { \dim_eval:n {#1} },
+    colsep    .meta:n = { leftsep = #1, rightsep = #1},
+    leftsep+  .code:n = \__tblr_column_gadd_dimen:ne
+                          { leftsep } { \dim_eval:n {#1} },
+    rightsep+ .code:n = \__tblr_column_gadd_dimen:ne
+                          { rightsep } { \dim_eval:n {#1} },
+    colsep+   .meta:n = { leftsep+ = #1, rightsep+ = #1},
+    unknown   .code:n = \__tblr_column_unknown_key:V \l_keys_key_str,
   }
 
-%% #1: column number; #2: key; #3: value
-\cs_new_protected:Npn \__tblr_set_key_for_every_column_cell:nnn #1 #2 #3
+%% #1: key; #2: value
+\cs_new_protected:Npn \__tblr_column_gput:nn #1 #2
   {
+    \__tblr_data_gput:nenn { column } { \int_use:N \c at colnum } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_column_gput:nn { ne }
+
+\cs_new_protected:Npn \__tblr_column_gadd_dimen:nn #1 #2
+  {
+    \__tblr_data_gadd_dimen_value:nenn { column }
+      { \int_use:N \c at colnum } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_column_gadd_dimen:nn { ne }
+
+%% #1: key; #2: value
+\cs_new_protected:Npn \__tblr_column_gput_cell:nn #1 #2
+  {
     \int_step_inline:nn { \c at rowcount }
       {
-        \__tblr_data_gput:neenn { cell } {##1} {#1} {#2} {#3}
+        \__tblr_cell_gput:nenn {##1} { \int_use:N \c at colnum } {#1} {#2}
       }
   }
+\cs_generate_variant:Nn \__tblr_column_gput_cell:nn { ne }
 
 \cs_new_protected:Npn \__tblr_preto_text_for_every_column_cell:n #1
   {
@@ -1742,25 +1844,26 @@
       }
   }
 
+\cs_new_protected:Npn \__tblr_process_text_for_every_column_cell:n #1
+  {
+    \int_step_inline:nn { \c at rowcount }
+      {
+        \__tblr_cell_process_text:nen {##1} { \int_use:N \c at colnum } {#1}
+      }
+  }
+
 \regex_const:Nn \c__tblr_is_number_key_regex { ^[\+\-]? (\d+|\d*\.\d+)$ }
 
 \cs_new_protected:Npn \__tblr_column_unknown_key:n #1
   {
     \regex_match:NnTF \c__tblr_is_number_key_regex {#1}
+      { \__tblr_column_gput:ne { coefficient } {#1} }
       {
-        \__tblr_data_gput:nene { column }
-          { \int_use:N \c at colnum } { coefficient } {#1}
-      }
-      {
         \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+          { \__tblr_column_gput_cell:nn { background } {#1} }
           {
-            \__tblr_set_key_for_every_column_cell:nnn
-              { \int_use:N \c at colnum } { background } {#1}
-          }
-          {
             \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
-            \__tblr_data_gput:nene { column }
-              { \int_use:N \c at colnum } { width } { \dim_eval:n { \l__tblr_v_tl } }
+            \__tblr_column_gput:ne { width } { \dim_eval:n { \l__tblr_v_tl } }
           }
       }
   }
@@ -1830,55 +1933,58 @@
 
 \keys_define:nn { tblr-row }
   {
-    l .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { halign } {l},
-    c .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { halign } {c},
-    r .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { halign } {r},
-    t .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {t},
-    p .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {t},
-    m .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {m},
-    b .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {b},
-    h .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {h},
-    f .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { valign } {f},
-    bg .code:n = \__tblr_set_key_for_every_row_cell:nnn
-                  { \int_use:N \c at rownum } { background } {#1},
-    fg .code:n = \__tblr_preto_text_for_every_row_cell:n { \color{#1} },
-    font .code:n = \__tblr_preto_text_for_every_row_cell:n { #1 \selectfont },
-    ht .code:n = \__tblr_data_gput:nene { row } { \int_use:N \c at rownum }
-                   { height } { \dim_eval:n {#1} },
-    co .code:n = \__tblr_data_gput:nene { row } { \int_use:N \c at rownum }
-                   { coefficient } {#1},
-    abovesep .code:n = \__tblr_data_gput:nene { row } { \int_use:N \c at rownum }
-                         { abovesep } { \dim_eval:n {#1} },
-    belowsep .code:n = \__tblr_data_gput:nene { row } { \int_use:N \c at rownum }
-                         { belowsep } { \dim_eval:n {#1} },
-    rowsep .meta:n = { abovesep = #1, belowsep = #1},
-    abovesep+ .code:n = \__tblr_data_gadd_dimen_value:nene { row }
-                   { \int_use:N \c at rownum } { abovesep } { \dim_eval:n {#1} },
-    belowsep+ .code:n = \__tblr_data_gadd_dimen_value:nene { row }
-                   { \int_use:N \c at rownum } { belowsep } { \dim_eval:n {#1} },
-    rowsep+ .meta:n = { abovesep+ = #1, belowsep+ = #1},
-    nobreak .code:n = \__tblr_prop_gput:nxx { row }
-                   { [\int_eval:n {\c at rownum - 1}] / nobreak } { true },
-    unknown .code:n = \__tblr_row_unknown_key:V \l_keys_key_str,
+    halign    .code:n = \__tblr_row_gput_cell:nn { halign } {#1},
+    valign    .code:n = \__tblr_row_gput_cell:nn { valign } {#1},
+    l         .meta:n = { halign = l },
+    c         .meta:n = { halign = c },
+    r         .meta:n = { halign = r },
+    t         .meta:n = { valign = t },
+    p         .meta:n = { valign = t },
+    m         .meta:n = { valign = m },
+    b         .meta:n = { valign = b },
+    h         .meta:n = { valign = h },
+    f         .meta:n = { valign = f },
+    bg        .code:n = \__tblr_row_gput_cell:nn { background } {#1},
+    fg        .code:n = \__tblr_preto_text_for_every_row_cell:n { \color{#1} },
+    font      .code:n = \__tblr_row_gput_cell:nn { font } { #1 \selectfont },
+    ht        .code:n = \__tblr_row_gput:ne { height } { \dim_eval:n {#1} },
+    co        .code:n = \__tblr_row_gput:ne { coefficient } {#1},
+    preto     .code:n = \__tblr_preto_text_for_every_row_cell:n {#1},
+    appto     .code:n = \__tblr_appto_text_for_every_row_cell:n {#1},
+    cmd       .code:n = \__tblr_process_text_for_every_row_cell:n {#1},
+    abovesep  .code:n = \__tblr_row_gput:ne { abovesep } { \dim_eval:n {#1} },
+    belowsep  .code:n = \__tblr_row_gput:ne { belowsep } { \dim_eval:n {#1} },
+    rowsep    .meta:n = { abovesep = #1, belowsep = #1},
+    abovesep+ .code:n = \__tblr_row_gadd_dimen:ne { abovesep } { \dim_eval:n {#1} },
+    belowsep+ .code:n = \__tblr_row_gadd_dimen:ne { belowsep } { \dim_eval:n {#1} },
+    rowsep+   .meta:n = { abovesep+ = #1, belowsep+ = #1},
+    nobreak   .code:n = \__tblr_prop_gput:nxx { row }
+                          { [\int_eval:n {\c at rownum - 1}] / nobreak } { true },
+    unknown   .code:n = \__tblr_row_unknown_key:V \l_keys_key_str,
   }
 
-%% #1: row number; #2: key; #3: value
-\cs_new_protected:Npn \__tblr_set_key_for_every_row_cell:nnn #1 #2 #3
+%% #1: key; #2: value
+\cs_new_protected:Npn \__tblr_row_gput:nn #1 #2
   {
+    \__tblr_data_gput:nenn { row } { \int_use:N \c at rownum } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_row_gput:nn { ne }
+
+\cs_new_protected:Npn \__tblr_row_gadd_dimen:nn #1 #2
+  {
+    \__tblr_data_gadd_dimen_value:nenn { row } { \int_use:N \c at rownum } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_row_gadd_dimen:nn { ne }
+
+%% #1: key; #2: value
+\cs_new_protected:Npn \__tblr_row_gput_cell:nn #1 #2
+  {
     \int_step_inline:nn { \c at colcount }
       {
-        \__tblr_data_gput:neenn { cell } {#1} {##1} {#2} {#3}
+        \__tblr_cell_gput:ennn { \int_use:N \c at rownum } {##1} {#1} {#2}
       }
   }
+\cs_generate_variant:Nn \__tblr_row_gput_cell:nn { ne }
 
 \cs_new_protected:Npn \__tblr_preto_text_for_every_row_cell:n #1
   {
@@ -1896,6 +2002,14 @@
       }
   }
 
+\cs_new_protected:Npn \__tblr_process_text_for_every_row_cell:n #1
+  {
+    \int_step_inline:nn { \c at colcount }
+      {
+        \__tblr_cell_process_text:enn { \int_use:N \c at rownum } {##1} {#1}
+      }
+  }
+
 \cs_new_protected:Npn \__tblr_row_unknown_key:n #1
   {
     \regex_match:NnTF \c__tblr_is_number_key_regex {#1}
@@ -1905,15 +2019,11 @@
       }
       {
         \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+          { \__tblr_row_gput_cell:nn { background } {#1} }
           {
-            \__tblr_set_key_for_every_row_cell:nnn
-              { \int_use:N \c at rownum } { background } {#1}
+            \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
+            \__tblr_row_gput:ne { height } { \dim_eval:n { \l__tblr_v_tl } }
           }
-          {
-          \tl_set_rescan:Nnn \l__tblr_v_tl {} {#1}
-            \__tblr_data_gput:nene { row } { \int_use:N \c at rownum }
-              { height } { \dim_eval:n { \l__tblr_v_tl } }
-          }
       }
   }
 \cs_generate_variant:Nn \__tblr_row_unknown_key:n { V }
@@ -2205,43 +2315,100 @@
   }
 
 %%% --------------------------------------------------------
-%%  \section{Tabularray Environments}
+%%  \section{Set Environments and New Environments}
 %%% --------------------------------------------------------
 
+\tl_new:N \l__tblr_initial_tblr_outer_tl
+\tl_set:Nn \l__tblr_initial_tblr_outer_tl
+  {
+    halign = c, valign = m, headsep = 6pt, footsep = 6pt,
+    presep = 1.5\bigskipamount, postsep = 1.5\bigskipamount,
+  }
+
+%% #1: env name; #2: specifications
+\NewDocumentCommand \SetTblrInner { O{tblr} m }
+  {
+    \tl_put_right:cn { l__tblr_default_ #1 _inner_tl } { , #2 }
+    \ignorespaces
+  }
+\cs_new_eq:NN \SetTblrDefault \SetTblrInner
+
+%% #1: env name; #2: specifications
+\NewDocumentCommand \SetTblrOuter { O{tblr} m }
+  {
+    \tl_put_right:cn { l__tblr_default_ #1 _outer_tl } { , #2 }
+    \ignorespaces
+  }
+
+%% #1: env name
+\NewDocumentCommand \NewTblrEnviron { m }
+  {
+    \tl_new:c { l__tblr_default_ #1 _outer_tl }
+    \tl_set_eq:cN { l__tblr_default_ #1 _outer_tl } \l__tblr_initial_tblr_outer_tl
+    \tl_new:c { l__tblr_default_ #1 _inner_tl }
+    \NewDocumentEnvironment {#1} { O{c} m +b }
+      {
+        \__tblr_environ_code:nnnn {#1} {##1} {##2} {##3}
+      } { }
+    \ignorespaces
+  }
+
+%% Create tblr and longtblr environments
+\NewTblrEnviron { tblr }
+\NewTblrEnviron { longtblr }
+\SetTblrOuter [ longtblr ] { long }
+
 \tl_new:N \l__tblr_env_name_tl
 \bool_new:N \l__tblr_math_mode_bool
 
-\NewDocumentEnvironment { tblr } { O{c} m +b }
+%% Main environment code
+\cs_new_protected:Npn \__tblr_environ_code:nnnn #1 #2 #3 #4
   {
-    \tl_set:Nn \l__tblr_env_name_tl { tblr }
+    \int_gincr:N \g__tblr_table_count_int
+    \tl_set:Nn \l__tblr_env_name_tl {#1}
     \mode_if_math:TF
       { \bool_set_true:N \l__tblr_math_mode_bool }
       { \bool_set_false:N \l__tblr_math_mode_bool }
-    \buildtblr {#1} {#2} {#3}
-  } { }
+    \__tblr_builder:nnn {#2} {#3} {#4}
+  }
 
 %% Read, split and build the table
-
-\cs_new_protected:Npn \buildtblr #1 #2 #3
+\cs_new_protected:Npn \__tblr_builder:nnn #1 #2 #3
   {
-    \mode_leave_vertical:
     \int_gincr:N \g_tblr_level_int
     \__tblr_clear_prop_lists:
-    \__tblr_clear_text_lists:
+    \__tblr_clear_spec_lists:
     \__tblr_enable_table_commands:
-    \__tblr_split_table:n { #3 }
+    \LogTblrTracing { step = split ~ table}
+    \__tblr_split_table:n {#3}
     \LogTblrTracing { command }
-    \bool_if:NT \g__tblr_use_intarray_bool { \__tblr_initial_table_data: }
-    \__tblr_initial_table_spec:
-    \LogTblrTracing { table }
-    \__tblr_parse_table_spec:n { #2 }
+    \LogTblrTracing { step = init ~ table ~ outer ~ spec}
+    \__tblr_init_table_outer_spec:
+    \LogTblrTracing { outer }
+    \LogTblrTracing { step = parse ~ table ~ options }
+    \__tblr_parse_table_option:n {#1}
+    \LogTblrTracing { option }
+    \bool_if:NT \g__tblr_use_intarray_bool { \__tblr_init_table_data: }
+    \LogTblrTracing { step = init ~ table ~ inner ~ spec}
+    \__tblr_init_table_inner_spec:
+    \LogTblrTracing { inner }
+    \LogTblrTracing { step = parse ~ table ~ inner ~ spec}
+    \__tblr_parse_table_spec:n {#2}
+    \LogTblrTracing { step = execute ~ table ~ commands}
     \__tblr_execute_table_commands:
     \__tblr_disable_table_commands:
+    \LogTblrTracing { step = calculate ~ cell ~ and ~ line ~ sizes}
+    \__tblr_enable_content_commands:
     \__tblr_calc_cell_and_line_sizes:
-    \__tblr_build_whole:n { #1 }
+    \LogTblrTracing { step = build ~ the ~ whole ~ table}
+    \__tblr_build_whole:
     \int_gdecr:N \g_tblr_level_int
   }
 
+%%% --------------------------------------------------------
+%%  \section{Split Table Contents}
+%%% --------------------------------------------------------
+
 %% Insert and remove braces for nesting environments inside cells
 %% These make line split and cell split workable
 %% We need to replace N times for N level nestings
@@ -2348,7 +2515,7 @@
         \__tblr_remove_braces:N \l_tmpa_tl
         \int_incr:N \c at colnum
         \__tblr_extract_table_commands:N \l_tmpa_tl
-        \__tblr_text_gput:neV { text } { [#1][\int_use:N \c at colnum] } \l_tmpa_tl
+        \__tblr_spec_gput:neV { text } { [#1][\int_use:N \c at colnum] } \l_tmpa_tl
         \__tblr_add_multicolumn_empty_cell:
       }
     %% Decrease row count by 1 if the last row has only one empty cell text
@@ -2373,7 +2540,7 @@
     \int_step_inline:nn { \l__multicolumn_cell_number_int - 1 }
       {
         \int_incr:N \c at colnum
-        \__tblr_text_gput:nen { text }
+        \__tblr_spec_gput:nen { text }
           { [\int_use:N \c at rownum][\int_use:N \c at colnum] } { }
       }
   }
@@ -2395,7 +2562,7 @@
     \tl_clear:N \l__tblr_saved_table_commands_before_cell_text_tl
     \tl_clear:N \l__tblr_saved_cell_text_after_table_commands_tl
     \int_set:Nn \l__multicolumn_cell_number_int {1}
-    \exp_last_unbraced:NV \__tblr_extract_table_commands_next:w #1 \scan_stop:
+    \exp_last_unbraced:NV \__tblr_extract_table_commands_next:w #1 \q_stop
     \tl_if_empty:NF \l__tblr_saved_table_commands_before_cell_text_tl
       {
         \__tblr_prop_gput:nxV { command }
@@ -2420,7 +2587,7 @@
       {
         \tl_if_single_token:nTF {#1}
           {
-            \token_if_eq_meaning:NNF #1 \scan_stop:
+            \token_if_eq_meaning:NNF #1 \q_stop
               { \__tblr_save_real_cell_text:w #1 }
           }
           { \__tblr_save_real_cell_text:w {#1} }
@@ -2477,22 +2644,22 @@
 \cs_new_protected:Npn \__tblr_last_unbraced:Nn #1 #2 { #1 #2 }
 
 %% The outermost set of braces of cell text #1 will be removed
-\cs_new_protected:Npn \__tblr_save_real_cell_text:w #1 \scan_stop:
+\cs_new_protected:Npn \__tblr_save_real_cell_text:w #1 \q_stop
   {
     \tl_set:Nn \l__tblr_saved_cell_text_after_table_commands_tl {#1}
   }
 
 %%% --------------------------------------------------------
-%%  \section{Initial Table Specifications}
+%%  \section{Initialize Table Inner Specifications}
 %%% --------------------------------------------------------
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_table_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_table_prop
   {
     stretch = 1,
     rulesep = 2pt,
   }
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_rows_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_rows_prop
   {
     abovesep = 2pt,
     belowsep = 2pt,
@@ -2503,7 +2670,7 @@
     @row-lower = 0pt,
   }
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_columns_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_columns_prop
   {
     leftsep = 6pt,
     rightsep = 6pt,
@@ -2512,7 +2679,7 @@
     @col-width = 0pt,
   }
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_cells_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_cells_prop
   {
     halign = l,
     valign = t,
@@ -2522,36 +2689,35 @@
     omit = 0,
   }
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_hlines_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_hlines_prop
   {
     @hline-count = 0,
   }
 
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_vlines_prop
+\prop_gset_from_keyval:Nn \g__tblr_initial_vlines_prop
   {
     @vline-count = 0,
   }
 
-\cs_new_protected:Npn \__tblr_initial_table_spec:
+\cs_new_protected:Npn \__tblr_init_table_inner_spec:
   {
-    \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _table_prop }
+    \prop_map_inline:Nn \g__tblr_initial_table_prop
       {
-        \__tblr_prop_gput:nxn { table } { ##1 } {##2}
+        \__tblr_prop_gput:nxn { inner } { ##1 } {##2}
       }
     \int_step_variable:nNn { \c at rowcount } \l__tblr_i_tl
       {
-        \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _rows_prop }
+        \prop_map_inline:Nn \g__tblr_initial_rows_prop
           {
             \__tblr_data_gput:nVnn { row } \l__tblr_i_tl {##1} {##2}
           }
-        \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _hlines_prop }
+        \prop_map_inline:Nn \g__tblr_initial_hlines_prop
           {
-            \__tblr_text_gput:nen { hline } { [\l__tblr_i_tl] / ##1 } {##2}
+            \__tblr_spec_gput:nen { hline } { [\l__tblr_i_tl] / ##1 } {##2}
           }
         \int_step_variable:nNn { \c at colcount } \l__tblr_j_tl
           {
-            \prop_map_inline:cn
-              { g__tblr_default_ \l__tblr_env_name_tl _cells_prop }
+            \prop_map_inline:Nn \g__tblr_initial_cells_prop
               {
                 \__tblr_data_gput:neeen { cell }
                   { \l__tblr_i_tl } { \l__tblr_j_tl } {##1} {##2}
@@ -2558,60 +2724,50 @@
               }
           }
       }
-    \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _hlines_prop }
+    \prop_map_inline:Nn \g__tblr_initial_hlines_prop
       {
-        \__tblr_text_gput:nen { hline }
+        \__tblr_spec_gput:nen { hline }
           { [\int_eval:n { \c at rowcount + 1}] / ##1 } {##2}
       }
     \int_step_variable:nNn { \c at colcount } \l__tblr_j_tl
       {
-        \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _columns_prop }
+        \prop_map_inline:Nn \g__tblr_initial_columns_prop
           {
             \__tblr_data_gput:nenn { column } { \l__tblr_j_tl } {##1} {##2}
           }
-        \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _vlines_prop }
+        \prop_map_inline:Nn \g__tblr_initial_vlines_prop
           {
-            \__tblr_text_gput:nen { vline } { [\l__tblr_j_tl] / ##1 } {##2}
+            \__tblr_spec_gput:nen { vline } { [\l__tblr_j_tl] / ##1 } {##2}
           }
       }
-    \prop_map_inline:cn { g__tblr_default_ \l__tblr_env_name_tl _vlines_prop }
+    \prop_map_inline:Nn \g__tblr_initial_vlines_prop
       {
-        \__tblr_text_gput:nen { vline }
+        \__tblr_spec_gput:nen { vline }
           { [\int_eval:n { \c at colcount + 1}] / ##1 } {##2}
       }
-    \keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _tl }
+    \keys_set:nv { tblr } { l__tblr_default_ \l__tblr_env_name_tl _inner_tl }
   }
 
-\tl_new:N \l__tblr_default_tblr_tl
-
-%% #1: env name; #2: options
-\NewDocumentCommand \SetTabularrayDefault { O{tblr} m }
-  {
-    \tl_put_right:cn { l__tblr_default_ #1 _tl } { , #2 }
-  }
-\cs_new_eq:NN \SetTblrDefault \SetTabularrayDefault
-
 %%% --------------------------------------------------------
-%%  \section{Parse Table Specifications}
+%%> \section{Parse Table Inner Specifications}
 %%% --------------------------------------------------------
 
 \clist_new:N \g__tblr_table_known_keys_clist
 \clist_gset:Nn \g__tblr_table_known_keys_clist
   {
-    long, colspec, rowspec, width, hspan, stretch,
+    colspec, rowspec, width, hspan, vspan, stretch,
     column, row, cell, vline, hline, columns, rows, cells, vlines, hlines,
     leftsep, rightsep, colsep, abovesep, belowsep, rowsep, rulesep,
+    rowhead, rowfoot,
   }
 
-\bool_new:N \l__tblr_long_table_bool
-
 \keys_define:nn { tblr }
   {
-    long .bool_set:N = \l__tblr_long_table_bool,
     colspec .code:n = \__tblr_parse_colrow_spec:nn { column } {#1},
     rowspec .code:n = \__tblr_parse_colrow_spec:nn { row } {#1},
     width .code:n = \__tblr_keys_gput:nx { width } { \dim_eval:n {#1} },
     hspan .code:n = \__tblr_keys_gput:nn { hspan } {#1},
+    vspan .code:n = \__tblr_keys_gput:nn { vspan } {#1},
     stretch .code:n = \__tblr_keys_gput:nn { stretch } {#1},
     columns .code:n = \__tblr_set_every_column_aux:n {#1},
     rows    .code:n = \__tblr_set_every_row_aux:n {#1},
@@ -2625,6 +2781,8 @@
     belowsep .code:n = \tblr_set_every_row:nn { } { belowsep = #1 },
     rowsep .meta:n = { abovesep = #1, belowsep = #1 },
     rulesep .code:n = \__tblr_keys_gput:nn { rulesep } {#1},
+    rowhead .code:n = \__tblr_keys_gput:nn { rowhead } {#1},
+    rowfoot .code:n = \__tblr_keys_gput:nn { rowfoot } {#1},
     unknown .code:n = \__tblr_table_special_key:Vn \l_keys_key_str {#1},
   }
 
@@ -2658,13 +2816,106 @@
       { \__tblr_parse_colrow_spec:nn { column } {#1} }
   }
 
-\cs_new_protected:Npn  \__tblr_keys_gput:nn #1 #2
+\cs_new_protected:Npn \__tblr_keys_gput:nn #1 #2
   {
-    \__tblr_prop_gput:nnn { table } {#1} {#2}
+    \__tblr_prop_gput:nnn { inner } {#1} {#2}
   }
 \cs_generate_variant:Nn \__tblr_keys_gput:nn { nx }
 
 %%% --------------------------------------------------------
+%%  \section{Initialize and Parse Table Outer Specifications}
+%%% --------------------------------------------------------
+
+%% #1: theme names; #2: template and style commands
+\NewDocumentCommand \NewTblrTheme { m +m }
+  {
+    \tl_set:cn { g__tblr_theme_ #1 _code_tl } {#2}
+    \ignorespaces
+  }
+
+\cs_new_protected:Npn \__tblr_use_theme:n #1
+  {
+    \ignorespaces
+    \tl_use:c { g__tblr_theme_ #1 _code_tl }
+  }
+
+\cs_new_protected:Npn \__tblr_init_table_outer_spec:
+  {
+    \keys_set:nv { tblr-outer } { l__tblr_default_ \l__tblr_env_name_tl _outer_tl }
+  }
+
+\cs_new_protected:Npn \__tblr_parse_table_option:n #1
+  {
+    \keys_set:nn { tblr-outer } {#1}
+  }
+
+\keys_define:nn { tblr-outer }
+  {
+    long    .code:n = \__tblr_outer_gput_spec:nn { long } {true},
+    halign  .code:n = \__tblr_outer_gput_spec:nn { halign } {#1},
+    valign  .code:n = \__tblr_outer_gput_spec:nn { valign } {#1},
+    l       .meta:n = { halign = l },
+    c       .meta:n = { halign = c },
+    r       .meta:n = { halign = r },
+    t       .meta:n = { valign = t },
+    m       .meta:n = { valign = m },
+    b       .meta:n = { valign = b },
+    headsep .code:n = \__tblr_outer_gput_spec:nn { headsep } {#1},
+    footsep .code:n = \__tblr_outer_gput_spec:nn { footsep } {#1},
+    presep  .code:n = \__tblr_outer_gput_spec:nn { presep }  {#1},
+    postsep .code:n = \__tblr_outer_gput_spec:nn { postsep } {#1},
+    theme   .code:n = \__tblr_use_theme:n {#1},
+    caption .code:n = \__tblr_outer_gput_spec:nn { caption } {#1},
+    entry   .code:n = \__tblr_outer_gput_spec:nn { entry } {#1},
+    label   .code:n = \__tblr_outer_gput_spec:nn { label } {#1},
+    unknown .code:n = \__tblr_table_option_key:Vn \l_keys_key_str {#1},
+  }
+
+\cs_new_protected:Npn \__tblr_outer_gput_spec:nn #1 #2
+  {
+    \__tblr_spec_gput:nen { outer } {#1} {#2}
+  }
+
+\regex_const:Nn \c__tblr_option_key_name_regex { ^ [A-Za-z\-] + $ }
+
+\msg_new:nnn { tabularray } { unknown-outer-key }
+  { Unknown ~ outer ~ key ~ name ~ #1! }
+
+\cs_new_protected:Npn \__tblr_table_option_key:nn #1 #2
+  {
+    \regex_match:NnTF \c__tblr_option_key_name_regex {#1}
+      { \msg_error:nnn { tabularray } { unknown-outer-key } {#1} }
+      {
+        \regex_extract_once:NnNT \c__tblr_split_key_name_regex {#1} \l_tmpa_seq
+          {
+            \tl_set:Nx \l__tblr_a_tl { \seq_item:Nn \l_tmpa_seq {2} }
+            \tl_set_rescan:Nnx \l__tblr_b_tl {} { \seq_item:Nn \l_tmpa_seq {3} }
+            \tl_set:Nx \l__tblr_c_tl { \tl_head:N \l__tblr_b_tl }
+            \use:c { __tblr_outer_gput_ \l__tblr_a_tl :Vn } \l__tblr_c_tl {#2}
+          }
+      }
+  }
+\cs_generate_variant:Nn \__tblr_table_option_key:nn { Vn }
+
+\cs_new_protected:Npn \__tblr_outer_gput_note:nn #1 #2
+  {
+    \__tblr_prop_gput:nnn { note } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_outer_gput_note:nn { Vn }
+
+\cs_new_protected:Npn \__tblr_outer_gput_remark:nn #1 #2
+  {
+    \__tblr_prop_gput:nnn { remark } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_outer_gput_remark:nn { Vn }
+
+\cs_new_protected:Npn \__tblr_outer_gput_more:nn #1 #2
+  {
+    \__tblr_prop_gput:nnn { more } {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_outer_gput_more:nn { Vn }
+
+%%% --------------------------------------------------------
 %%  \section{Typeset and Calculate Sizes}
 %%% --------------------------------------------------------
 
@@ -2687,7 +2938,7 @@
 
 \cs_new_protected:Npn \__tblr_make_strut_box:
   {
-    \tl_set:Nx \l__tblr_s_tl { \__tblr_prop_item:ne { table } { stretch } }
+    \tl_set:Nx \l__tblr_s_tl { \__tblr_prop_item:ne { inner } { stretch } }
     \hbox_set:Nn \l__tblr_strut_ht_box
       { \vrule height \l__tblr_s_tl \box_ht:N \strutbox width ~ 0pt }
     \hbox_set:Nn \l__tblr_strut_dp_box
@@ -2725,11 +2976,11 @@
   {
     \dim_zero:N \l__tblr_w_dim
     \tl_set:Nx \l__tblr_n_tl
-      { \__tblr_text_item:ne { vline } { [#2] / @vline-count } }
+      { \__tblr_spec_item:ne { vline } { [#2] / @vline-count } }
     \int_compare:nNnT { \l__tblr_n_tl } > {0}
       {
         \tl_set:Nx \l__tblr_s_tl
-          { \__tblr_prop_item:ne { table } { rulesep } }
+          { \__tblr_prop_item:ne { inner } { rulesep } }
         \int_step_inline:nn { \l__tblr_n_tl }
           {
             \vbox_set_to_ht:Nnn \l__tblr_b_box {1pt}
@@ -2738,7 +2989,7 @@
                   {#1} {#2} {##1} {1pt} {1pt}
               }
             \tl_set:Nx \l__tblr_w_tl { \dim_eval:n { \box_wd:N \l__tblr_b_box } }
-            \__tblr_text_gput_if_larger:nee { vline }
+            \__tblr_spec_gput_if_larger:nee { vline }
               { [#2](##1) / @vline-width } { \l__tblr_w_tl }
             \dim_add:Nn \l__tblr_w_dim { \l__tblr_w_tl }
             \dim_add:Nn \l__tblr_w_dim { \l__tblr_s_tl }
@@ -2745,7 +2996,7 @@
           }
         \dim_add:Nn \l__tblr_w_dim { - \l__tblr_s_tl }
       }
-    \__tblr_text_gput_if_larger:nee { vline }
+    \__tblr_spec_gput_if_larger:nee { vline }
       { [#2]/ @vline-width } { \dim_use:N \l__tblr_w_dim }
   }
 
@@ -2756,10 +3007,10 @@
   {
     \group_begin:
     \tl_set:Nx \l__tblr_w_tl
-      { \__tblr_text_item:ne { vline } { [#1][#2](#3) / wd } }
+      { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / wd } }
     \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
     \tl_set:Nx \l__tblr_d_tl
-      { \__tblr_text_item:ne { vline } { [#1][#2](#3) / @dash } }
+      { \__tblr_spec_item:ne { vline } { [#1][#2](#3) / @dash } }
     \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
     \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
     \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr at dash
@@ -2783,11 +3034,11 @@
   {
     \dim_zero:N \l__tblr_h_dim
     \tl_set:Nx \l__tblr_n_tl
-      { \__tblr_text_item:ne { hline } { [#1] / @hline-count } }
+      { \__tblr_spec_item:ne { hline } { [#1] / @hline-count } }
     \int_compare:nNnT { \l__tblr_n_tl } > {0}
       {
         \tl_set:Nx \l__tblr_s_tl
-          { \__tblr_prop_item:ne { table } { rulesep } }
+          { \__tblr_prop_item:ne { inner } { rulesep } }
         \int_step_inline:nn { \l__tblr_n_tl }
           {
             \hbox_set_to_wd:Nnn \l__tblr_b_box {1pt}
@@ -2797,7 +3048,7 @@
                 \dim_eval:n
                   { \box_ht:N \l__tblr_b_box + \box_dp:N \l__tblr_b_box }
               }
-            \__tblr_text_gput_if_larger:nee { hline }
+            \__tblr_spec_gput_if_larger:nee { hline }
               { [#1](##1) / @hline-height } { \l__tblr_h_tl }
             \dim_add:Nn \l__tblr_h_dim { \l__tblr_h_tl }
             \dim_add:Nn \l__tblr_h_dim { \l__tblr_s_tl }
@@ -2804,7 +3055,7 @@
           }
         \dim_add:Nn \l__tblr_h_dim { - \l__tblr_s_tl }
       }
-    \__tblr_text_gput_if_larger:nee { hline }
+    \__tblr_spec_gput_if_larger:nee { hline }
       { [#1] / @hline-height } { \dim_use:N \l__tblr_h_dim }
   }
 
@@ -2814,10 +3065,10 @@
   {
     \group_begin:
     \tl_set:Nx \l__tblr_w_tl
-      { \__tblr_text_item:ne { hline } { [#1][#2](#3) / wd } }
+      { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / wd } }
     \tl_if_empty:NF \l__tblr_w_tl { \dim_set:Nn \rulewidth { \l__tblr_w_tl } }
     \tl_set:Nx \l__tblr_d_tl
-      { \__tblr_text_item:ne { hline } { [#1][#2](#3) / @dash } }
+      { \__tblr_spec_item:ne { hline } { [#1][#2](#3) / @dash } }
     \tl_set:Nx \l__tblr_a_tl { \tl_head:N \l__tblr_d_tl }
     \tl_set:Nx \l__tblr_b_tl { \tl_tail:N \l__tblr_d_tl }
     \exp_args:NV \tl_if_eq:NNTF \l__tblr_a_tl \@tblr at dash
@@ -2893,9 +3144,11 @@
       {
         \int_incr:N \c at rownum
         \int_zero:N \c at colnum
+        \__tblr_update_rowsep_registers:
         \tl_set:Nx \l__tblr_h_tl
-           { \__tblr_data_item:nen { row } { \int_use:N \c at rownum } { height } }
-        \tl_if_empty:NF \l__tblr_h_tl
+          { \__tblr_data_item:nen { row } { \int_use:N \c at rownum } { height } }
+        %% We didn't initialize row heights with -1pt
+        \dim_compare:nNnF { \l__tblr_h_tl } = { 0pt }
           {
             \__tblr_data_gput:nenV { row } { \int_use:N \c at rownum }
               { @row-height } \l__tblr_h_tl
@@ -2903,6 +3156,7 @@
         \int_step_inline:nn { \c at colcount }
           {
             \int_incr:N \c at colnum
+            \__tblr_update_colsep_registers:
             \__tblr_measure_cell_update_sizes:nnNNNN
               { \int_use:N \c at rownum }
               { \int_use:N \c at colnum }
@@ -2912,8 +3166,33 @@
               \g__tblr_cell_foot_dim
           }
       }
+    \int_step_inline:nn { \c at colcount }
+      {
+        \tl_set:Nx \l__tblr_w_tl
+          { \__tblr_data_item:nen { column } {##1} { width } }
+        \dim_compare:nNnF { \l__tblr_w_tl } < { 0pt }
+          {
+            \__tblr_data_gput:nenV { column } {##1} { @col-width } \l__tblr_w_tl
+          }
+      }
   }
 
+\cs_new_protected:Npn \__tblr_update_rowsep_registers:
+  {
+    \dim_set:Nn \abovesep
+      { \__tblr_data_item:nen { row } { \int_use:N \c at rownum } { abovesep } }
+    \dim_set:Nn \belowsep
+      { \__tblr_data_item:nen { row } { \int_use:N \c at rownum } { belowsep } }
+  }
+
+\cs_new_protected:Npn \__tblr_update_colsep_registers:
+  {
+    \dim_set:Nn \leftsep
+      { \__tblr_data_item:nen { column } { \int_use:N \c at colnum } { leftsep } }
+    \dim_set:Nn \rightsep
+      { \__tblr_data_item:nen { column } { \int_use:N \c at colnum } { rightsep } }
+  }
+
 %% Measure and update natural dimensions of the row/column/cell
 %% #1: row number; #2 column number; #3: width dimension;
 %% #4: total height dimension; #5: head dimension; #6: foot dimension
@@ -2945,7 +3224,8 @@
 \cs_new_protected:Npn \__tblr_get_cell_text_real:nn #1 #2
   {
     \group_begin:
-    \tl_set:Nx \l__tblr_c_tl { \__tblr_text_item:ne { text } {[#1][#2]} }
+    \tl_set:Nx \l__tblr_c_tl { \__tblr_spec_item:ne { text } {[#1][#2]} }
+    \tl_set:Nx \l__tblr_f_tl { \__tblr_data_item:neen { cell } {#1} {#2} { font } }
     \tl_set:Nx \l__tblr_w_tl
       { \__tblr_data_item:neen { cell } {#1} {#2} { width } }
     \dim_compare:nNnT { \l__tblr_w_tl } < { 0pt } % cell width unset
@@ -2972,12 +3252,13 @@
             \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl
               {
                 \__tblr_remove_braces:N \l_tmpa_tl
-                \hbox_set:Nn \l_tmpa_box { \l_tmpa_tl }
+                \hbox_set:Nn \l_tmpa_box { \l__tblr_f_tl \l_tmpa_tl }
                 \tl_set:Nx \l__tblr_w_tl
                   { \dim_max:nn { \l__tblr_w_tl } { \box_wd:N \l_tmpa_box } }
               }
           }
       }
+    \tl_put_left:NV \l__tblr_c_tl \l__tblr_f_tl
     \__tblr_get_vcell_and_sizes:NN \l__tblr_c_tl \l__tblr_w_tl
     \group_end:
   }
@@ -3029,16 +3310,13 @@
     \group_end:
   }
 
-\cs_new_eq:NN \__tlbr_halign_l: \raggedright
-\cs_new_eq:NN \__tlbr_halign_c: \centering
-\cs_new_eq:NN \__tlbr_halign_r: \raggedleft
-
 %% #1: cell text; #2: box width
+%% All halign commands are defined at the beginning of the file
 \cs_new_protected:Npn \__tblr_make_vcell_text:nN #1 #2
   {
     \dim_set:Nn \tex_hsize:D { #2 }
     \@arrayparboxrestore
-    \cs:w __tlbr_halign_ \g__tblr_cell_halign_tl : \cs_end:
+    \cs:w __tblr_halign_command_ \g__tblr_cell_halign_tl : \cs_end:
     \mode_leave_vertical:
     \box_use:N \l__tblr_strut_ht_box
     \bool_if:NTF \l__tblr_math_mode_bool { $#1$ } { #1 }
@@ -3238,7 +3516,7 @@
 
 \cs_new_protected:Npn \__tblr_collect_extendable_column_width:
   {
-    \tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn {table} {width} }
+    \tl_set:Nx \l_tmpa_tl { \__tblr_prop_item:nn { inner } { width } }
     \tl_if_empty:NTF \l_tmpa_tl
       { \dim_set_eq:NN \l__column_target_dim \linewidth }
       { \dim_set:Nn \l__column_target_dim { \l_tmpa_tl } }
@@ -3271,7 +3549,7 @@
           }
           { \dim_sub:Nn \l__column_target_dim { \l__tblr_a_tl } }
         \tl_set:Nx \l__tblr_a_tl
-          { \__tblr_text_item:ne { vline } { [\l__tblr_j_tl] / @vline-width } }
+          { \__tblr_spec_item:ne { vline } { [\l__tblr_j_tl] / @vline-width } }
         \tl_set:Nx \l__tblr_b_tl
           { \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep } }
         \tl_set:Nx \l__tblr_c_tl
@@ -3281,7 +3559,7 @@
       }
     \tl_set:Nx \l__tblr_a_tl
       {
-        \__tblr_text_item:ne { vline }
+        \__tblr_spec_item:ne { vline }
           { [\int_eval:n {\c at colcount + 1}] / @vline-width }
       }
     \tl_if_empty:NF \l__tblr_a_tl
@@ -3378,11 +3656,11 @@
 
 \cs_new_protected:Npn \__tblr_adjust_sizes_for_span_cells:
   {
-    \__tblr_prop_if_in:nnT {table} {colspan}
+    \__tblr_prop_if_in:nnT { inner } { colspan }
       {
         \__tblr_collect_column_widths_skips:
         \str_if_eq:xnTF
-          { \__tblr_prop_item:ne {table} {hspan} } {minimal}
+          { \__tblr_prop_item:ne { inner } { hspan } } { minimal }
           {
             \__tblr_set_span_widths_from_column_widths:
           }
@@ -3393,12 +3671,12 @@
         \LogTblrTracing { column }
         \__tblr_calculate_cell_sizes:
       }
-    \__tblr_prop_if_in:nnT {table} {rowspan}
+    \__tblr_prop_if_in:nnT { inner } { rowspan }
       {
         \__tblr_collect_row_heights_skips:
         \__tblr_collect_span_heights:
         \__tblr_set_row_heights_from_span_heights:
-        \LogTblrTracing {row}
+        \LogTblrTracing { row }
       }
   }
 
@@ -3421,7 +3699,7 @@
                     \__tblr_data_item:nen { column }
                       { \int_eval:n { \l__tblr_j_tl - 1 } } { rightsep }
                     +
-                    \__tblr_text_item:ne { vline }
+                    \__tblr_spec_item:ne { vline }
                       { [\l__tblr_j_tl] / @vline-width }
                     +
                     \__tblr_data_item:nen { column } { \l__tblr_j_tl } { leftsep }
@@ -3453,7 +3731,7 @@
                     \__tblr_data_item:nen { row }
                       { \int_eval:n {\l__tblr_i_tl - 1} } { belowsep }
                     +
-                    \__tblr_text_item:ne { hline }
+                    \__tblr_spec_item:ne { hline }
                       { [\l__tblr_i_tl] / @hline-height }
                     +
                     \__tblr_data_item:nen { row } { \l__tblr_i_tl } { abovesep }
@@ -3585,10 +3863,21 @@
 %% Compute and set column widths from span widths
 \cs_new_protected:Npn \__tblr_set_column_widths_from_span_widths:
   {
-    \__tblr_calc_item_sizes_from_span_sizes:xNN
-      { \int_use:N \c at colcount }
-      \l__tblr_col_item_skip_size_prop
-      \l__tblr_col_span_size_prop
+    \str_if_eq:xnTF
+      { \__tblr_prop_item:ne { inner } { hspan } }
+      { even }
+      {
+        \__tblr_distribute_span_sizes_even:xNN
+          { \int_use:N \c at colcount }
+          \l__tblr_col_item_skip_size_prop
+          \l__tblr_col_span_size_prop
+      }
+      {
+        \__tblr_distribute_span_sizes_default:xNN
+          { \int_use:N \c at colcount }
+          \l__tblr_col_item_skip_size_prop
+          \l__tblr_col_span_size_prop
+      }
     \__tblr_set_all_column_widths:
   }
 
@@ -3595,10 +3884,21 @@
 %% Compute and set row heights from span heights
 \cs_new_protected:Npn \__tblr_set_row_heights_from_span_heights:
   {
-    \__tblr_calc_item_sizes_from_span_sizes:xNN
-      { \int_use:N \c at rowcount }
-      \l__tblr_row_item_skip_size_prop
-      \l__tblr_row_span_size_prop
+    \str_if_eq:xnTF
+      { \__tblr_prop_item:ne { inner } { vspan } }
+      { even }
+      {
+        \__tblr_distribute_span_sizes_even:nNN
+          { \int_use:N \c at rowcount }
+          \l__tblr_row_item_skip_size_prop
+          \l__tblr_row_span_size_prop
+      }
+      {
+        \__tblr_distribute_span_sizes_default:xNN
+          { \int_use:N \c at rowcount }
+          \l__tblr_row_item_skip_size_prop
+          \l__tblr_row_span_size_prop
+      }
     \__tblr_set_all_row_heights:
   }
 
@@ -3605,7 +3905,7 @@
 %% See page 245 in Chapter 22 of TeXbook
 %% #1: total number of items
 %% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes
-\cs_new_protected:Npn \__tblr_calc_item_sizes_from_span_sizes:nNN #1 #2 #3
+\cs_new_protected:Npn \__tblr_distribute_span_sizes_default:nNN #1 #2 #3
   {
     \int_step_variable:nNn { #1 } \l__tblr_j_tl
       {
@@ -3656,14 +3956,60 @@
       }
     \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
   }
-\cs_generate_variant:Nn \__tblr_calc_item_sizes_from_span_sizes:nNN { x }
+\cs_generate_variant:Nn \__tblr_distribute_span_sizes_default:nNN { x }
 
+%% #1: total number of items
+%% #2: prop list with item sizes and skip sizes; #3: prop list with span sizes
+\cs_new_protected:Npn \__tblr_distribute_span_sizes_even:nNN #1 #2 #3
+  {
+    \prop_clear:N \l_tmpa_prop
+    \prop_map_inline:Nn #3
+      {
+        \__tblr_get_span_from_to:w ##1
+        \dim_set:Nn \l_tmpa_dim {##2}
+        \dim_sub:Nn \l_tmpa_dim { \prop_item:Ne #2 { item[\l__tblr_a_tl] } }
+        \int_step_inline:nnn { \l__tblr_a_tl + 1 } { \l__tblr_b_tl }
+          {
+            \dim_sub:Nn \l_tmpa_dim
+              {
+                \prop_item:Ne #2 { skip[####1] } + \prop_item:Nn #2 { item[####1] }
+              }
+          }
+        \__tblr_do_if_tracing:nn { cellspan }
+          {
+            \tl_log:x { \l__tblr_a_tl -> \l__tblr_b_tl : ~ \dim_use:N \l_tmpa_dim }
+          }
+        \dim_compare:nNnT {\l_tmpa_dim} > {0pt}
+          {
+            \tl_set:Nx \l_tmpa_tl
+              { \dim_eval:n { \l_tmpa_dim / (\l__tblr_b_tl - \l__tblr_a_tl + 1) } }
+            \int_step_inline:nnn { \l__tblr_a_tl } { \l__tblr_b_tl }
+              {
+                \__tblr_put_if_larger:NnV \l_tmpa_prop {####1} \l_tmpa_tl
+              }
+          }
+      }
+    \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N \l_tmpa_prop }
+    \prop_map_inline:Nn \l_tmpa_prop
+      {
+        \__tblr_add_dimen_value:Nnn #2 {item[##1]} {##2}
+      }
+    \__tblr_do_if_tracing:nn { cellspan } { \prop_log:N #2 }
+  }
+\cs_generate_variant:Nn \__tblr_distribute_span_sizes_even:nNN { x }
+
+\cs_new_protected:Npn \__tblr_get_span_from_to:w (#1-#2)
+  {
+    \tl_set:Nn \l__tblr_a_tl {#1}
+    \tl_set:Nn \l__tblr_b_tl {#2}
+  }
+
 \cs_new_protected:Npn \__tblr_set_all_column_widths:
   {
     \int_step_variable:nNn { \c at colcount } \l__tblr_j_tl
       {
         \__tblr_data_gput:nene { column }
-          { \l__tblr_j_tl } { @col-width }
+          { \l__tblr_j_tl } { width }
           { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[\l__tblr_j_tl] } }
       }
   }
@@ -3690,12 +4036,6 @@
       }
   }
 
-\cs_new_protected:Npn \__tblr_get_span_key_row_col:w [#1][#2]
-  {
-    \tl_set:Nn \l__tblr_i_tl {#1}
-    \tl_set:Nn \l__tblr_j_tl {#2}
-  }
-
 %% Compute and set span widths from column widths
 \cs_new_protected:Npn \__tblr_set_span_widths_from_column_widths:
   {
@@ -3738,59 +4078,829 @@
 \cs_generate_variant:Nn \__tblr_calc_span_widths:nnN { xxN }
 
 %%% --------------------------------------------------------
-%%  \section{Build the Whole Table}
+%%> \section{Header and Footer Styles}
 %%% --------------------------------------------------------
 
-\tl_new:N \__tlbr_vbox_align_tl
-\tl_const:Nn \__tlbr_vbox_t_tl {t}
-\tl_const:Nn \__tlbr_vbox_m_tl {m}
-\tl_const:Nn \__tlbr_vbox_c_tl {c}
-\tl_const:Nn \__tlbr_vbox_b_tl {b}
+\prop_new:N \l__tblr_element_styles_prop
 
-\box_new:N \l__tblr_table_box
+\cs_new_protected:Npn \__tblr_style_put:nn #1 #2
+  {
+    \prop_put:Nnn \l__tblr_element_styles_prop {#1} {#2}
+  }
+\cs_generate_variant:Nn \__tblr_style_put:nn { nV, ne, en }
 
-%% #1: table alignment
-\cs_new_protected:Npn \__tblr_build_whole:n #1
+\cs_new:Npn \__tblr_style_item:n #1
   {
-    \bool_if:NTF \l__tblr_long_table_bool
-      { \__tblr_build_long_table:n {#1} }
-      { \__tblr_build_short_table:n {#1} }
+    \prop_item:Nn \l__tblr_element_styles_prop {#1}
   }
 
+\cs_new_protected:Npn \__tblr_style_log:
+  {
+    \prop_log:N \l__tblr_element_styles_prop
+  }
+
+\tl_new:N \l__tblr_element_name_tl
+\tl_new:N \l__tblr_element_styles_tl
+
+%% #1: list of element names; #2: element styles
+\NewDocumentCommand \SetTblrStyle { m +m }
+  {
+    \tl_set:Nn \l__tblr_element_styles_tl {#2}
+    \keys_set:nn { tblr-element } {#1}
+    \ignorespaces
+  }
+
+\keys_define:nn { tblr-element }
+  {
+    head    .meta:n = { firsthead, middlehead, lasthead },
+    foot    .meta:n = { firstfoot, middlefoot, lastfoot },
+    unknown .code:n = \__tblr_set_element_styles:V \l_keys_key_str,
+  }
+
+\cs_new_protected:Npn \__tblr_set_element_styles:n #1
+  {
+    \tl_set:Nn \l__tblr_element_name_tl {#1}
+    \keys_set:nV { tblr-style } \l__tblr_element_styles_tl
+  }
+\cs_generate_variant:Nn \__tblr_set_element_styles:n { V }
+
+\keys_define:nn { tblr-style }
+  {
+    halign  .code:n = \__tblr_element_gput_style:nn { halign } {#1},
+    l       .meta:n = { halign = l },
+    c       .meta:n = { halign = c },
+    r       .meta:n = { halign = r },
+    fg      .code:n = \__tblr_element_gput_style:nn { fg } {#1},
+    font    .code:n = \__tblr_element_gput_style:nn { font } {#1},
+    hang    .code:n = \__tblr_element_gput_style:nn { hang } {#1},
+    indent  .code:n = \__tblr_element_gput_style:nn { indent } {#1},
+    unknown .code:n = \__tblr_element_unknown_key:Vn \l_keys_key_str {#1},
+  }
+
+\cs_new_protected:Npn \__tblr_element_gput_style:nn #1 #2
+  {
+    \__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
+  }
+
+\cs_new_protected:Npn \__tblr_element_unknown_key:nn #1 #2
+  {
+    \regex_match:NnTF \c__tblr_is_color_key_regex {#1}
+      { \__tblr_style_put:en { \l__tblr_element_name_tl / fg } {#1} }
+      {
+        %% unknown key name has been changed to string in \l_keys_key_str
+        \tl_set_rescan:Nnn \l__tblr_f_tl {} {#1}
+        \tl_if_head_eq_catcode:VNTF \l__tblr_f_tl \scan_stop:
+          {
+            \__tblr_style_put:en { \l__tblr_element_name_tl / font } \l__tblr_f_tl
+          }
+          {
+            \__tblr_style_put:en { \l__tblr_element_name_tl / #1 } {#2}
+          }
+      }
+  }
+\cs_generate_variant:Nn \__tblr_element_unknown_key:nn { Vn }
+
+%%% --------------------------------------------------------
+%%> \section{Helper Functions for Templates}
+%%% --------------------------------------------------------
+
+\tl_new:N \l__tblr_template_name_tl
+\tl_new:N \l__tblr_template_code_tl
+
+\keys_define:nn { tblr-def-template }
+  {
+    unknown .code:n = \__tblr_def_template:V \l_keys_key_str,
+  }
+
+%% #1: head/foot element; #2: template name; #3: template code
+%% If the template name = default, we enable the template at once
+%% Otherwise, we may enable the template by using \SetTblrTemplate command
+\NewDocumentCommand \DefTblrTemplate { m m +m }
+  {
+    \tl_set:Nn \l__tblr_template_name_tl {#2}
+    \tl_set:Nn \l__tblr_template_code_tl {#3}
+    \keys_set:nn { tblr-def-template } {#1}
+    \ignorespaces
+  }
+
+\cs_new_protected:Npn \__tblr_def_template:n #1
+  {
+    \tl_set_eq:cN { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
+      \l__tblr_template_code_tl
+  }
+\cs_generate_variant:Nn \__tblr_def_template:n { V }
+
+\keys_define:nn { tblr-set-template }
+  {
+    unknown .code:n = \__tblr_set_template:V \l_keys_key_str,
+  }
+
+%% #1: head/foot element; #2: template name
+\NewDocumentCommand \SetTblrTemplate { m m }
+  {
+    \tl_set:Nn \l__tblr_template_name_tl {#2}
+    \keys_set:nn { tblr-set-template } {#1}
+    \ignorespaces
+  }
+
+\cs_new_protected:Npn \__tblr_set_template:n #1
+  {
+    \tl_set_eq:cc { l__tblr_template_ #1 _default_tl }
+      { l__tblr_template_ #1 _ \l__tblr_template_name_tl _tl }
+  }
+\cs_generate_variant:Nn \__tblr_set_template:n { V }
+
+\NewExpandableDocumentCommand \GetTblrStyle { m m }
+  {
+    \__tblr_style_item:n { #1 / #2 }
+  }
+
+\NewDocumentCommand \UseTblrFont { m }
+  {
+    \GetTblrStyle {#1} { font } \selectfont
+  }
+
+\tl_new:N \l__tblr_use_color_tl
+
+\NewDocumentCommand \UseTblrColor { m }
+  {
+    \tl_set:Nx \l__tblr_use_color_tl { \GetTblrStyle {#1} { fg } }
+    \tl_if_empty:NF \l__tblr_use_color_tl { \color { \l__tblr_use_color_tl } }
+  }
+
+%% All halign commands are defined at the beginning of the file
+\NewDocumentCommand \UseTblrAlign { m }
+  {
+    \use:c { __tblr_halign_command_ \GetTblrStyle {#1} { halign } : }
+  }
+
+\tl_new:N \l__tblr_use_hang_tl
+
+\NewDocumentCommand \UseTblrHang { m }
+  {
+    \tl_set:Nx \l__tblr_use_hang_tl { \GetTblrStyle {#1} { hang } }
+    \tl_if_empty:NF \l__tblr_use_hang_tl
+      {
+        \tl_put_left:Nn \l__tblr_use_hang_tl
+          { \hangafter = 1 \relax \hangindent = }
+        \tl_put_right:Nn \l__tblr_use_hang_tl { \relax }
+        \exp_args:NV \everypar \l__tblr_use_hang_tl
+      }
+  }
+
+\tl_new:N \l__tblr_use_indent_tl
+
+\NewDocumentCommand \UseTblrIndent { m }
+  {
+    \tl_set:Nx \l__tblr_use_indent_tl { \GetTblrStyle {#1} { indent } }
+    \tl_if_empty:NF \l__tblr_use_indent_tl
+      { \exp_args:NNV \setlength \parindent \l__tblr_use_indent_tl }
+  }
+
+\AtBeginDocument
+  {
+    \@ifpackageloaded{xcolor}{}{\RenewDocumentCommand \UseTblrColor {m} {}}
+  }
+
+%% #1: head/foot element; #2: template name
+\NewExpandableDocumentCommand \ExpTblrTemplate { m m }
+  {
+    \tl_use:c { l__tblr_template_ #1 _ #2 _tl }
+  }
+
+%% #1: head/foot element; #2: template name
+\NewDocumentCommand \UseTblrTemplate { m m }
+  {
+    \group_begin:
+    \UseTblrFont {#1}
+    \UseTblrColor {#1}
+    \tl_use:c { l__tblr_template_ #1 _ #2 _tl }
+    \group_end:
+  }
+
+\NewDocumentCommand \MapTblrNotes { +m }
+  {
+    \__tblr_prop_map_inline:nn { note }
+      {
+        \tl_set_rescan:Nnn \InsertTblrNoteTag {} {##1}
+        \tl_set:Nn \InsertTblrNoteText {##2}
+        #1
+      }
+  }
+
+\NewDocumentCommand \MapTblrRemarks { +m }
+  {
+    \__tblr_prop_map_inline:nn { remark }
+      {
+        \tl_set_rescan:Nnn \InsertTblrRemarkTag {} {##1}
+        \tl_set:Nn \InsertTblrRemarkText {##2}
+        #1
+      }
+  }
+
+\NewExpandableDocumentCommand \InsertTblrText { m }
+  {
+    \__tblr_spec_item:nn { outer } {#1}
+  }
+
+\NewExpandableDocumentCommand \InsertTblrMore { m }
+  {
+    \__tblr_prop_item:nn { more } {#1}
+  }
+
+%%% --------------------------------------------------------
+%%> \section{Table Continuation Templates}
+%%% --------------------------------------------------------
+
+\DefTblrTemplate { contfoot-text } { normal } { Continued ~ on ~ next ~ page }
+\SetTblrTemplate { contfoot-text } { normal }
+
+\DefTblrTemplate { contfoot } { plain }
+  {
+    \noindent
+    \raggedleft
+    \UseTblrTemplate { contfoot-text } { default }
+    \par
+  }
+\DefTblrTemplate { contfoot } { normal }
+  {
+    %% need to set parindent after alignment
+    \raggedleft
+    \UseTblrAlign { contfoot }
+    \UseTblrIndent { contfoot }
+    \UseTblrHang { contfoot }
+    \leavevmode
+    \UseTblrTemplate { contfoot-text } { default }
+    \par
+  }
+\SetTblrTemplate { contfoot } { normal }
+
+\DefTblrTemplate { conthead-text } { normal } { ( Continued ) }
+\SetTblrTemplate { conthead-text } { normal }
+
+\DefTblrTemplate { conthead } { plain }
+  {
+    \noindent
+    \raggedright
+    \UseTblrTemplate { conthead-text } { default }
+    \par
+  }
+\DefTblrTemplate { conthead } { normal }
+  {
+    %% need to set parindent after alignment
+    \raggedright
+    \UseTblrAlign { conthead }
+    \UseTblrIndent { conthead }
+    \UseTblrHang { conthead }
+    \leavevmode
+    \UseTblrTemplate { conthead-text } { default }
+    \par
+  }
+\SetTblrTemplate { conthead } { normal }
+
+%%% --------------------------------------------------------
+%%> \section{Table Caption Templates}
+%%% --------------------------------------------------------
+
+\tl_new:N \l__tblr_caption_short_tl
+
+\DefTblrTemplate { caption-lot } { normal }
+  {
+    \tl_set:Nx \l__tblr_caption_short_tl { \InsertTblrText { entry } }
+    \tl_if_empty:NT \l__tblr_caption_short_tl
+      { \tl_set:Nx \l__tblr_caption_short_tl { \InsertTblrText { caption } } }
+    \addcontentsline { lot } { table }
+      { \protect\numberline { \arabic { table } } { \l__tblr_caption_short_tl } }
+  }
+\SetTblrTemplate { caption-lot } { normal }
+
+%% We need to use \hspace and \enskip, but not ~ or \space,
+%% since we want a correct hangindent caption paragraph.
+
+\DefTblrTemplate { caption-tag } { normal } { Table \hspace{0.25em} \thetable }
+\SetTblrTemplate { caption-tag } { normal }
+
+\DefTblrTemplate { caption-sep } { normal } { : \enskip }
+\SetTblrTemplate { caption-sep } { normal }
+
+\DefTblrTemplate { caption-text } { normal } { \InsertTblrText { caption } }
+\SetTblrTemplate { caption-text } { normal }
+
+\box_new:N \l__tblr_caption_box
+\box_new:N \l__tblr_caption_left_box
+
+\DefTblrTemplate { caption } { plain }
+  {
+    \hbox_set:Nn \l__tblr_caption_box
+      {
+        \UseTblrTemplate { caption-tag } { default }
+        \UseTblrTemplate { caption-sep } { default }
+        \UseTblrTemplate { caption-text } { default }
+      }
+    \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
+      {
+        \noindent
+        \hbox_unpack:N \l__tblr_caption_box
+        \par
+      }
+      {
+        \centering
+        \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
+        \par
+      }
+  }
+\DefTblrTemplate { caption } { normal }
+  {
+    \hbox_set:Nn \l__tblr_caption_box
+      {
+        \UseTblrTemplate { caption-tag } { default }
+        \UseTblrTemplate { caption-sep } { default }
+        \UseTblrTemplate { caption-text } { default }
+      }
+    \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
+      {
+        \UseTblrAlign { caption }
+        \UseTblrIndent { caption }
+        \hbox_set:Nn \l__tblr_caption_left_box
+          {
+            \UseTblrTemplate { caption-tag } { default }
+            \UseTblrTemplate { caption-sep } { default }
+          }
+        \hangindent = \box_wd:N \l__tblr_caption_left_box
+        \hangafter = 1
+        \UseTblrHang { caption }
+        \leavevmode
+        \hbox_unpack:N \l__tblr_caption_box
+        \par
+      }
+      {
+        \centering
+        \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
+        \par
+      }
+  }
+\SetTblrTemplate { caption } { normal }
+
+\DefTblrTemplate { capcont } { plain }
+  {
+    \hbox_set:Nn \l__tblr_caption_box
+      {
+        \UseTblrTemplate { caption-tag } { default }
+        \UseTblrTemplate { caption-sep } { default }
+        \UseTblrTemplate { caption-text } { default }
+        \space
+        \UseTblrTemplate { conthead-text } { default }
+      }
+    \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
+      {
+        \noindent
+        \hbox_unpack:N \l__tblr_caption_box
+        \par
+      }
+      {
+        \centering
+        \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
+        \par
+      }
+  }
+\DefTblrTemplate { capcont } { normal }
+  {
+    \hbox_set:Nn \l__tblr_caption_box
+      {
+        \UseTblrTemplate { caption-tag } { default }
+        \UseTblrTemplate { caption-sep } { default }
+        \UseTblrTemplate { caption-text } { default }
+        \space
+        \UseTblrTemplate { conthead-text } { default }
+      }
+    \dim_compare:nNnTF { \box_wd:N \l__tblr_caption_box } > { \hsize }
+      {
+        \UseTblrAlign { capcont }
+        \UseTblrIndent { capcont }
+        \hbox_set:Nn \l__tblr_caption_left_box
+          {
+            \UseTblrTemplate { caption-tag } { default }
+            \UseTblrTemplate { caption-sep } { default }
+          }
+        \hangindent = \box_wd:N \l__tblr_caption_left_box
+        \hangafter = 1
+        \UseTblrHang { capcont }
+        \leavevmode
+        \hbox_unpack:N \l__tblr_caption_box
+        \par
+      }
+      {
+        \centering
+        \makebox [\hsize] [c] { \box_use:N \l__tblr_caption_box }
+        \par
+      }
+  }
+\SetTblrTemplate { capcont} { normal }
+
+%%% --------------------------------------------------------
+%%> \section{Table Notes Templates}
+%%% --------------------------------------------------------
+
+%% By default the targets generated by \hypertarget are too low
+%% Therefore we need to use \Hy at raisedlink command to fix this problem
+%% See https://tex.stackexchange.com/questions/17057
+%% We also use \use:c in case the private command \Hy at raisedlink is removed
+\cs_new_protected:Npn \__tblr_hyper_target:n #1
+  {
+    \cs_if_exist:NT \hypertarget
+      {
+        \use:c { Hy at raisedlink }
+          {
+            \hypertarget
+              { tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} }
+              { }
+          }
+      }
+  }
+\cs_generate_variant:Nn \__tblr_hyper_target:n { V }
+
+\cs_new_protected:Npn \__tblr_hyper_link:nn #1 #2
+  {
+    \cs_if_exist:NTF \hyperlink
+      {
+        \hyperlink
+          { tblr / \int_use:N \g__tblr_table_count_int / \tl_to_str:n {#1} }
+          { #2 }
+      }
+      { #2 }
+  }
+
+\NewDocumentCommand \TblrNote { m }
+  {
+    \__tblr_hyper_link:nn {#1}
+      { \textsuperscript { \sffamily \UseTblrFont { note-tag } #1 } }
+  }
+
+\DefTblrTemplate { note-tag } { normal }
+  {
+    \textsuperscript { \sffamily \UseTblrFont { note-tag } \InsertTblrNoteTag }
+  }
+\SetTblrTemplate { note-tag } { normal }
+
+\DefTblrTemplate { note-target } { normal }
+  {
+    \__tblr_hyper_target:V \InsertTblrNoteTag
+  }
+\SetTblrTemplate { note-target } { normal }
+
+\DefTblrTemplate { note-sep } { normal } { \space }
+\SetTblrTemplate { note-sep } { normal }
+
+\DefTblrTemplate { note-text } { normal } { \InsertTblrNoteText }
+\SetTblrTemplate { note-text } { normal }
+
+\DefTblrTemplate { note } { plain }
+  {
+    \MapTblrNotes
+      {
+        \noindent
+        \UseTblrTemplate { note-tag } { default }
+        \UseTblrTemplate { note-target } { default }
+        \UseTblrTemplate { note-sep } { default }
+        \UseTblrTemplate { note-text } { default }
+        \par
+      }
+  }
+\DefTblrTemplate { note } { normal }
+  {
+    \UseTblrAlign { note }
+    \UseTblrIndent { note }
+    \MapTblrNotes
+      {
+        \hangindent = 0.7em
+        \hangafter = 1
+        \UseTblrHang { note }
+        \leavevmode
+        \hbox_to_wd:nn { \the\hangindent }
+          {
+            \UseTblrTemplate { note-tag } { default }
+            \UseTblrTemplate { note-target } { default }
+            \hfil
+          }
+        \UseTblrTemplate { note-text } { default }
+        \par
+      }
+  }
+\DefTblrTemplate { note } { inline }
+  {
+    \UseTblrAlign { note }
+    \UseTblrIndent { note }
+    \UseTblrHang { note }
+    \leavevmode
+    \MapTblrNotes
+      {
+        \UseTblrTemplate { note-tag } { default }
+        \UseTblrTemplate { note-target } { default }
+        \UseTblrTemplate { note-sep } { default }
+        \UseTblrTemplate { note-text } { default }
+        \quad
+      }
+    \par
+  }
+\SetTblrTemplate { note } { normal }
+
+%%% --------------------------------------------------------
+%%> \section{Table Remarks Templates}
+%%% --------------------------------------------------------
+
+\DefTblrTemplate { remark-tag } { normal }
+  {
+    \itshape \UseTblrFont { remark-tag } \InsertTblrRemarkTag
+  }
+\SetTblrTemplate { remark-tag } { normal }
+
+\DefTblrTemplate { remark-sep } { normal } { : \space }
+\SetTblrTemplate { remark-sep } { normal }
+
+\DefTblrTemplate { remark-text } { normal } { \InsertTblrRemarkText }
+\SetTblrTemplate { remark-text } { normal }
+
+\DefTblrTemplate { remark } { plain }
+  {
+    \MapTblrRemarks
+      {
+        \noindent
+        \UseTblrTemplate { remark-tag } { default }
+        \UseTblrTemplate { remark-sep } { default }
+        \UseTblrTemplate { remark-text } { default }
+        \par
+      }
+  }
+\DefTblrTemplate { remark } { normal }
+  {
+    \UseTblrAlign { remark }
+    \UseTblrIndent { remark }
+    \MapTblrRemarks
+      {
+        \hangindent = 0.7em
+        \hangafter = 1
+        \UseTblrHang { remark }
+        \leavevmode
+        \UseTblrTemplate { remark-tag } { default }
+        \UseTblrTemplate { remark-sep } { default }
+        \UseTblrTemplate { remark-text } { default }
+        \par
+      }
+  }
+\DefTblrTemplate { remark } { inline }
+  {
+    \UseTblrAlign { remark }
+    \UseTblrIndent { remark }
+    \UseTblrHang { remark }
+    \leavevmode
+    \MapTblrRemarks
+      {
+        \UseTblrTemplate { remark-tag } { default }
+        \UseTblrTemplate { remark-sep } { default }
+        \UseTblrTemplate { remark-text } { default }
+        \quad
+      }
+    \par
+  }
+\SetTblrTemplate { remark } { normal }
+
+%%% --------------------------------------------------------
+%%> \section{Header and Footer Templates}
+%%% --------------------------------------------------------
+
+\tl_new:N \g__tblr_template_firsthead_default_tl
+\tl_new:N \g__tblr_template_middlehead_default_tl
+\tl_new:N \g__tblr_template_lasthead_default_tl
+\tl_new:N \g__tblr_template_firstfoot_default_tl
+\tl_new:N \g__tblr_template_middlefoot_default_tl
+\tl_new:N \g__tblr_template_lastfoot_default_tl
+
+\keys_define:nn { tblr-def-template }
+  {
+    head .meta:n = { firsthead, middlehead, lasthead },
+    foot .meta:n = { firstfoot, middlefoot, lastfoot },
+  }
+
+\keys_define:nn { tblr-set-template }
+  {
+    head .meta:n = { firsthead, middlehead, lasthead },
+    foot .meta:n = { firstfoot, middlefoot, lastfoot },
+  }
+
+\DefTblrTemplate { firsthead } { normal }
+  {
+    \UseTblrTemplate { caption } { default }
+    \UseTblrTemplate { caption-lot } { default }
+  }
+
+\DefTblrTemplate { middlehead, lasthead } { normal }
+  {
+    \UseTblrTemplate { capcont } { default }
+  }
+
+\DefTblrTemplate { firstfoot, middlefoot } { normal }
+  {
+    \UseTblrTemplate { contfoot } { default }
+  }
+
+\DefTblrTemplate { lastfoot } { normal }
+  {
+    \UseTblrTemplate { note } { default }
+    \UseTblrTemplate { remark } { default }
+  }
+
+\SetTblrTemplate { head } { normal }
+\SetTblrTemplate { foot } { normal }
+
+%%% --------------------------------------------------------
+%%> \section{Build the Whole Table}
+%%% --------------------------------------------------------
+
+\cs_new:Npn \__tblr_box_height:N #1
+  {
+    \dim_eval:n { \box_ht:N #1 + \box_dp:N #1 }
+  }
+
+\cs_new_protected:Npn \__tblr_build_head_foot:
+  {
+    \__tblr_build_row_head_foot:
+    \__tblr_build_table_head_foot:
+  }
+
+\tl_new:N \l__tblr_row_head_tl
+\tl_new:N \l__tblr_row_foot_tl
+\box_new:N \l__tblr_row_head_box
+\box_new:N \l__tblr_row_foot_box
+\dim_new:N \l__tblr_row_head_foot_dim
+
+\cs_new_protected:Npn \__tblr_build_row_head_foot:
+  {
+    %% \l__tblr_row_head_tl and \l__tblr_row_foot_tl may be empty
+    \tl_set:Nx \l__tblr_row_head_tl { \__tblr_prop_item:ne { inner } { rowhead } }
+    \int_compare:nNnTF { \l__tblr_row_head_tl + 0 } > { 0 }
+      { \__tblr_build_one_table:nn {1} { \l__tblr_row_head_tl } }
+      { \__tblr_build_one_hline:n {1} }
+    \box_set_eq:NN \l__tblr_row_head_box \l__tblr_table_box
+    \tl_set:Nx \l__tblr_row_foot_tl { \__tblr_prop_item:ne { inner } { rowfoot } }
+    \int_compare:nNnTF { \l__tblr_row_foot_tl + 0 } > { 0 }
+      {
+        \__tblr_build_one_table:nn
+          { \c at rowcount - \l__tblr_row_foot_tl + 1 } { \c at rowcount }
+      }
+      { \__tblr_build_one_hline:n { \int_eval:n { \c at rowcount + 1 } } }
+    \box_set_eq:NN \l__tblr_row_foot_box \l__tblr_table_box
+    \dim_set:Nn \l__tblr_row_head_foot_dim
+      {
+        \__tblr_box_height:N \l__tblr_row_head_box
+          + \__tblr_box_height:N \l__tblr_row_foot_box
+      }
+  }
+
+\dim_new:N \tablewidth
+
+\cs_new_protected:Npn \__tblr_get_table_width:
+  {
+    \dim_zero:N \tablewidth
+    \int_step_inline:nn { \c at colcount }
+      {
+        \dim_add:Nn \tablewidth
+          {
+            \__tblr_spec_item:nn { vline } { [##1] / @vline-width }
+            +
+            \__tblr_data_item:nnn { column } {##1} { leftsep }
+            +
+            \__tblr_data_item:nnn { column } {##1} { @col-width }
+            +
+            \__tblr_data_item:nnn { column } {##1} { rightsep }
+          }
+      }
+    \dim_add:Nn \tablewidth
+      {
+        \__tblr_spec_item:ne { vline }
+          { [\int_eval:n { \c at colcount + 1 }] / @vline-width }
+      }
+  }
+
+\box_new:N \l__tblr_table_firsthead_box
+\box_new:N \l__tblr_table_middlehead_box
+\box_new:N \l__tblr_table_lasthead_box
+\box_new:N \l__tblr_table_firstfoot_box
+\box_new:N \l__tblr_table_middlefoot_box
+\box_new:N \l__tblr_table_lastfoot_box
+
+\cs_new_protected:Npn \__tblr_build_table_head_foot:
+  {
+    \__tblr_get_table_width:
+    \__tblr_build_table_head_aux:Nn \l__tblr_table_firsthead_box
+      {
+        \tl_set:Nn \l_tmpa_tl { \InsertTblrText { label } }
+        \tl_if_empty:NF \l_tmpa_tl { \exp_args:NV \label \l_tmpa_tl }
+        \UseTblrTemplate { firsthead } { default }
+      }
+    \__tblr_build_table_head_aux:Nn
+      \l__tblr_table_middlehead_box { \UseTblrTemplate { middlehead } { default } }
+    \__tblr_build_table_head_aux:Nn
+      \l__tblr_table_lasthead_box  { \UseTblrTemplate { lasthead } { default } }
+    \__tblr_build_table_foot_aux:Nn
+      \l__tblr_table_firstfoot_box { \UseTblrTemplate { firstfoot } { default } }
+    \__tblr_build_table_foot_aux:Nn
+      \l__tblr_table_middlefoot_box { \UseTblrTemplate { middlefoot } { default } }
+    \__tblr_build_table_foot_aux:Nn
+      \l__tblr_table_lastfoot_box  { \UseTblrTemplate { lastfoot } { default } }
+  }
+
+\cs_new_protected:Npn \__tblr_build_table_head_aux:Nn #1 #2
+  {
+    \vbox_set:Nn #1
+      {
+        \hsize = \tablewidth
+        \parindent = 0pt \relax
+        \vbox:n {#2}
+        \skip_vertical:n { \__tblr_spec_item:nn { outer } { headsep } }
+      }
+  }
+
+\cs_new_protected:Npn \__tblr_build_table_foot_aux:Nn #1 #2
+  {
+    \vbox_set:Nn #1
+      {
+        \hsize = \tablewidth
+        \skip_vertical:n { \__tblr_spec_item:nn { outer } { footsep } }
+        \parindent = 0pt \relax
+        \vbox:n {#2}
+      }
+  }
+
+\cs_new_protected:Npn \__tblr_build_whole:
+  {
+    \tl_if_eq:enTF { \__tblr_spec_item:nn { outer } { long } } { true }
+      { \__tblr_build_long_table:e { \__tblr_spec_item:nn { outer } { halign } } }
+      { \__tblr_build_short_table:e { \__tblr_spec_item:nn { outer } { valign } } }
+  }
+
 \dim_new:N \l__tblr_remain_height_dim
 \tl_new:N \l__tblr_long_from_tl
+\tl_new:N \l__tblr_long_to_tl
+\int_new:N \l__tblr_table_page_int
+\bool_new:N \l__tblr_table_page_break_bool
 
+%% #1: table alignment
+%% For long table, we need to leave hmode first to get correct \pagetotal
+%% Also remove topskip and presep if we are at the beginning of the page
 \cs_new_protected:Npn \__tblr_build_long_table:n #1
   {
-    %\dim_log:N \pagegoal
-    %\dim_log:N \pagetotal
-    \dim_set:Nn \l__tblr_remain_height_dim { \pagegoal - \pagetotal }
-    \tl_set:Nn \l__tblr_long_from_tl {1}
-    \int_step_variable:nNn { \c at rowcount } \l__tblr_i_tl
+    \LogTblrTracing { page }
+    \par
+    \LogTblrTracing { page }
+    \dim_compare:nNnTF { \pagegoal } = { \maxdimen }
+      { \hbox{}\kern-\topskip\nobreak }
+      { \skip_vertical:n { \__tblr_spec_item:nn { outer } { presep } } }
+    \LogTblrTracing { page }
+    \nointerlineskip
+    \mode_leave_vertical:
+    \LogTblrTracing { page }
+    \hrule height ~ 0pt
+    \LogTblrTracing { page }
+    \int_set:Nn \l__tblr_table_page_int {1}
+    \refstepcounter { table }
+    \__tblr_build_head_foot:
+    \dim_set:Nn \l__tblr_remain_height_dim
+      { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim }
+    \tl_set:Nx \l__tblr_long_from_tl { \int_eval:n { \l__tblr_row_head_tl + 1 } }
+    \tl_set:Nx \l__tblr_long_to_tl
+      { \int_eval:n { \c at rowcount - ( \l__tblr_row_foot_tl + 0 ) } }
+    \int_step_variable:nnNn
+      { \l__tblr_long_from_tl } { \l__tblr_long_to_tl } \l__tblr_i_tl
       {
         \dim_set:Nn \l_tmpa_dim
           {
-            \__tblr_text_item:ne { hline } { [\l__tblr_i_tl] / @hline-height }
-            +
             \__tblr_data_item:nen { row } { \l__tblr_i_tl } { abovesep }
             +
             \__tblr_data_item:nen { row } { \l__tblr_i_tl } { @row-height }
             +
             \__tblr_data_item:nen { row } { \l__tblr_i_tl } { belowsep }
+            +
+            \__tblr_spec_item:ne { hline }
+              { [ \int_eval:n { \l__tblr_i_tl + 1} ] / @hline-height }
           }
-        \dim_compare:nNnTF
-          { \l_tmpa_dim } > { \l__tblr_remain_height_dim }
+        \__tblr_check_table_page_break:NNN
+          \l__tblr_remain_height_dim \l_tmpa_dim \l__tblr_table_page_break_bool
+        \bool_if:NTF \l__tblr_table_page_break_bool
           {
-            \tl_log:N \l__tblr_i_tl
-            \__tblr_build_page_table:nnx {#1}
-              { \l__tblr_long_from_tl } { \int_eval:n { \l__tblr_i_tl - 1 } }
+            \__tblr_do_if_tracing:nn { page } { \tl_log:N \l__tblr_i_tl }
+            \int_compare:nNnT
+              { \l__tblr_i_tl - \l__tblr_long_from_tl } > {1}
+              {
+                \__tblr_build_page_table:nnx {#1}
+                  { \l__tblr_long_from_tl } { \int_eval:n { \l__tblr_i_tl - 1 } }
+                \int_incr:N \l__tblr_table_page_int
+              }
             \newpage
             \hbox{}\kern-\topskip\nobreak
-            \leavevmode
-            %\dim_log:N \pagegoal
-            %\dim_log:N \pagetotal
+            \noindent
+            \LogTblrTracing { page }
             \dim_set:Nn \l__tblr_remain_height_dim
-              { \pagegoal - \pagetotal - \l_tmpa_dim }
+              { \pagegoal - \pagetotal - \l__tblr_row_head_foot_dim - \l_tmpa_dim }
             \tl_set_eq:NN \l__tblr_long_from_tl \l__tblr_i_tl
           }
           {
@@ -3797,12 +4907,83 @@
             \dim_add:Nn \l__tblr_remain_height_dim { -\l_tmpa_dim }
           }
       }
-    \__tblr_build_page_table:nnn {#1} { \l__tblr_long_from_tl } { \c at rowcount }
+    \int_compare:nNnTF { \l__tblr_table_page_int } = {1}
+      {
+        \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
+        \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
+      }
+      {
+        \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_lasthead_box
+        \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_lastfoot_box
+      }
+    \__tblr_build_page_table:nnn
+      {#1} { \l__tblr_long_from_tl } { \l__tblr_long_to_tl }
+    \skip_vertical:n { \__tblr_spec_item:nn { outer } { postsep } }
+    \hrule height ~ 0pt
   }
+\cs_generate_variant:Nn \__tblr_build_long_table:n { e }
 
+\box_new:N \l__tblr_table_head_box
+\box_new:N \l__tblr_table_foot_box
+\dim_new:N \l__tblr_table_head_foot_dim
+\dim_new:N \l__tblr_table_head_body_foot_dim
+
+%% #1: remain dimension; #2: row dimension; #3: break page or not
+\cs_new_protected:Npn \__tblr_check_table_page_break:NNN #1 #2 #3
+  {
+    \int_compare:nNnTF { \l__tblr_table_page_int } = {1}
+      {
+        \dim_set:Nn \l__tblr_table_head_body_foot_dim
+          {
+            \__tblr_box_height:N \l__tblr_table_firsthead_box
+              + #2 + \__tblr_box_height:N \l__tblr_table_firstfoot_box
+          }
+        \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_firsthead_box
+        \dim_compare:nNnTF
+          { \l__tblr_table_head_body_foot_dim } > {#1}
+          {
+            \bool_set_true:N #3
+            \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_firstfoot_box
+          }
+          { \bool_set_false:N #3 }
+      }
+      {
+        \dim_set:Nn \l__tblr_table_head_body_foot_dim
+          {
+            \__tblr_box_height:N \l__tblr_table_middlehead_box
+              + #2 + \__tblr_box_height:N \l__tblr_table_middlefoot_box
+          }
+        \box_set_eq:NN \l__tblr_table_head_box \l__tblr_table_middlehead_box
+        \dim_compare:nNnTF
+          { \l__tblr_table_head_body_foot_dim } > {#1}
+          {
+            \bool_set_true:N #3
+            \box_set_eq:NN \l__tblr_table_foot_box \l__tblr_table_middlefoot_box
+          }
+          { \bool_set_false:N #3 }
+      }
+  }
+
+\box_new:N \l__tblr_table_box
+
+%% #1: table alignment; #2: row from; #3: row to
 \cs_new_protected:Npn \__tblr_build_page_table:nnn #1 #2 #3
   {
+    \bool_set_false:N \l__tblr_build_first_hline_bool
+    \bool_set_false:N \l__tblr_build_last_hline_bool
     \__tblr_build_one_table:nn {#2} {#3}
+    \vbox_set:Nn \l__tblr_table_box
+      {
+        \box_use:N \l__tblr_table_head_box
+        \hrule height ~ 0pt
+        \box_use:N \l__tblr_row_head_box
+        \hrule height ~ 0pt
+        \box_use:N \l__tblr_table_box
+        \hrule height ~ 0pt
+        \box_use:N \l__tblr_row_foot_box
+        \hrule height ~ 0pt
+        \box_use:N \l__tblr_table_foot_box
+      }
     \__tblr_halign_whole:Nn \l__tblr_table_box #1
   }
 \cs_generate_variant:Nn \__tblr_build_page_table:nnn { nnx }
@@ -3818,12 +4999,21 @@
       }
   }
 
+%% #1: table alignment
+%% For short table, we need to leave vmode first
 \cs_new_protected:Npn \__tblr_build_short_table:n #1
   {
+    \mode_leave_vertical:
     \__tblr_build_one_table:nn {1} {\c at rowcount}
     \__tblr_valign_whole:Nn \l__tblr_table_box #1
   }
+\cs_generate_variant:Nn \__tblr_build_short_table:n { e }
 
+\bool_new:N \l__tblr_build_first_hline_bool
+\bool_new:N \l__tblr_build_last_hline_bool
+\bool_set_true:N \l__tblr_build_first_hline_bool
+\bool_set_true:N \l__tblr_build_last_hline_bool
+
 %% #1: row from; #2: row to
 \cs_new_protected:Npn \__tblr_build_one_table:nn #1 #2
   {
@@ -3831,29 +5021,47 @@
       {
         \int_step_variable:nnNn {#1} {#2} \l__tblr_i_tl
           {
-            \hbox:n { \__tblr_build_hline:V \l__tblr_i_tl }
+            \bool_lazy_or:nnT
+              { \int_compare_p:nNn { \l__tblr_i_tl } > {#1} }
+              { \bool_if_p:N \l__tblr_build_first_hline_bool }
+              { \hbox:n { \__tblr_build_hline:V \l__tblr_i_tl } }
             \hrule height ~ 0pt % remove lineskip between hlines and rows
             \hbox:n { \__tblr_build_row:N \l__tblr_i_tl }
             \hrule height ~ 0pt
           }
-        \hbox:n { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } }
+        \bool_if:NT \l__tblr_build_last_hline_bool
+          { \hbox:n { \__tblr_build_hline:n { \int_eval:n {#2 + 1} } } }
       }
+    \bool_set_true:N \l__tblr_build_first_hline_bool
+    \bool_set_true:N \l__tblr_build_last_hline_bool
   }
 
+%% #1: hline number
+\cs_new_protected:Npn \__tblr_build_one_hline:n #1
+  {
+    \vbox_set:Nn \l__tblr_table_box { \hbox:n { \__tblr_build_hline:n { #1 } } }
+  }
+
+\tl_new:N \__tblr_vbox_align_tl
+\tl_const:Nn \__tblr_vbox_t_tl {t}
+\tl_const:Nn \__tblr_vbox_m_tl {m}
+\tl_const:Nn \__tblr_vbox_c_tl {c}
+\tl_const:Nn \__tblr_vbox_b_tl {b}
+
 \cs_new_protected:Npn \__tblr_valign_whole:Nn #1 #2
   {
     \group_begin:
-    \tl_set:Nn \__tlbr_vbox_align_tl {#2}
+    \tl_set:Nn \__tblr_vbox_align_tl {#2}
     \dim_set:Nn \l__tblr_t_dim { \box_ht:N #1 + \box_dp:N #1 }
-    \tl_case:NnF \__tlbr_vbox_align_tl
+    \tl_case:NnF \__tblr_vbox_align_tl
       {
-        \__tlbr_vbox_m_tl
+        \__tblr_vbox_m_tl
           { \__tblr_valign_whole_middle:N #1 }
-        \__tlbr_vbox_c_tl
+        \__tblr_vbox_c_tl
           { \__tblr_valign_whole_middle:N #1 }
-        \__tlbr_vbox_t_tl
+        \__tblr_vbox_t_tl
           { \__tblr_valign_whole_top:N #1 }
-        \__tlbr_vbox_b_tl
+        \__tblr_vbox_b_tl
           { \__tblr_valign_whole_bottom:N #1 }
       }
       { \__tblr_valign_whole_middle:N #1 }
@@ -3868,10 +5076,10 @@
 \cs_new_protected:Npn \__tblr_valign_whole_top:N #1
   {
     \tl_set:Nx \l__tblr_a_tl
-      { \__tblr_text_item:ne { hline } { [1] / @hline-height } }
+      { \__tblr_spec_item:ne { hline } { [1] / @hline-height } }
     %% Note that \l__tblr_b_tl may be empty
     \tl_set:Nx \l__tblr_b_tl
-      { \__tblr_prop_item:ne { table } { baseline } }
+      { \__tblr_prop_item:ne { inner } { baseline } }
     \bool_lazy_or:nnTF
       { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } }
       { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { 1 } }
@@ -3902,12 +5110,12 @@
   {
     \tl_set:Nx \l__tblr_a_tl
       {
-        \__tblr_text_item:ne { hline }
+        \__tblr_spec_item:ne { hline }
           { [\int_eval:n {\c at rowcount + 1}] / @hline-height }
       }
     %% Note that \l__tblr_b_tl may be empty
     \tl_set:Nx \l__tblr_b_tl
-      { \__tblr_prop_item:ne { table } { baseline } }
+      { \__tblr_prop_item:ne { inner } { baseline } }
     \bool_lazy_or:nnTF
       { \dim_compare_p:nNn { \l__tblr_a_tl } = { 0pt } }
       { \int_compare_p:nNn { \l__tblr_b_tl + 0 } = { \c at rowcount } }
@@ -3937,6 +5145,10 @@
     \box_use_drop:N #1
   }
 
+%%% --------------------------------------------------------
+%%> \section{Build Table Components}
+%%% --------------------------------------------------------
+
 \dim_new:N \l__tblr_col_o_wd_dim
 \dim_new:N \l__tblr_col_b_wd_dim
 
@@ -3952,9 +5164,9 @@
 \cs_new_protected:Npn \__tblr_build_hline_segment:nn #1 #2
   {
     \tl_set:Nx \l__tblr_n_tl
-      { \__tblr_text_item:ne { hline } { [#1] / @hline-count } }
+      { \__tblr_spec_item:ne { hline } { [#1] / @hline-count } }
     \tl_set:Nx \l__tblr_o_tl
-      { \__tblr_text_item:ne { hline } { [#1][#2] / omit } }
+      { \__tblr_spec_item:ne { hline } { [#1][#2] / omit } }
     \__tblr_get_col_outer_width_border_width:nNN {#2}
       \l__tblr_col_o_wd_dim \l__tblr_col_b_wd_dim
     \tl_if_empty:NTF \l__tblr_o_tl
@@ -3975,7 +5187,7 @@
 \cs_new_protected:Npn \__tblr_build_hline_segment_real:nn #1 #2
   {
     \tl_set:Nx \l__tblr_s_tl
-      { \__tblr_prop_item:ne { table } { rulesep } }
+      { \__tblr_prop_item:ne { inner } { rulesep } }
     \vbox_set:Nn \l__tblr_c_box
       {
         %% add an empty hbox to support vbox width
@@ -3983,12 +5195,12 @@
         \int_step_inline:nn { \l__tblr_n_tl }
           {
             \tl_set:Nx \l__tblr_h_tl
-              { \__tblr_text_item:ne { hline } { [#1](##1) / @hline-height } }
+              { \__tblr_spec_item:ne { hline } { [#1](##1) / @hline-height } }
             \hrule height ~ 0pt % remove lineskip
             \hbox_set_to_wd:Nnn \l__tblr_b_box { \l__tblr_col_o_wd_dim }
               {
                 \tl_set:Nx \l__tblr_f_tl
-                  { \__tblr_text_item:ne { hline } { [#1][#2](##1) / fg } }
+                  { \__tblr_spec_item:ne { hline } { [#1][#2](##1) / fg } }
                 \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
                 \__tblr_get_hline_segment_child:nnn {#1} {#2} {##1}
               }
@@ -4009,10 +5221,10 @@
 \cs_new_protected:Npn \__tblr_get_col_outer_width_border_width:nNN #1 #2 #3
   {
     \dim_set:Nn #3
-      { \__tblr_text_item:ne { vline } { [\int_eval:n {#1 + 1}] / @vline-width } }
+      { \__tblr_spec_item:ne { vline } { [\int_eval:n {#1 + 1}] / @vline-width } }
     \dim_set:Nn #2
       {
-        \__tblr_text_item:ne { vline } { [#1] / @vline-width }
+        \__tblr_spec_item:ne { vline } { [#1] / @vline-width }
         +
         \__tblr_data_item:nen { column } {#1} { leftsep }
         +
@@ -4032,6 +5244,8 @@
 %% Build current row, #1: row number
 \cs_new_protected:Npn \__tblr_build_row:N #1
   {
+    \int_set:Nn \c at rownum {#1}
+    \__tblr_update_rowsep_registers:
     \__tblr_get_row_inner_height_depth:VNNNN #1
       \l__tblr_row_ht_dim \l__tblr_row_dp_dim
       \l__tblr_row_abovesep_dim \l__tblr_row_belowsep_dim
@@ -4078,9 +5292,9 @@
 \cs_new_protected:Npn \__tblr_build_vline_segment:nn #1 #2
   {
     \tl_set:Nx \l__tblr_n_tl
-      { \__tblr_text_item:ne { vline } { [#2] / @vline-count } }
+      { \__tblr_spec_item:ne { vline } { [#2] / @vline-count } }
     \tl_set:Nx \l__tblr_o_tl
-      { \__tblr_text_item:ne { vline } { [#1][#2] / omit } }
+      { \__tblr_spec_item:ne { vline } { [#1][#2] / omit } }
     \tl_if_empty:NTF \l__tblr_o_tl
       {
         \int_compare:nNnT { \l__tblr_n_tl } > {0}
@@ -4093,7 +5307,7 @@
 \cs_new_protected:Npn \__tblr_build_vline_segment_omit:nn #1 #2
   {
     \tl_set:Nx \l__tblr_w_tl
-      { \__tblr_text_item:ne { vline } { [#2] / @vline-width } }
+      { \__tblr_spec_item:ne { vline } { [#2] / @vline-width } }
     \skip_horizontal:N \l__tblr_w_tl
   }
 
@@ -4103,10 +5317,10 @@
 \cs_new_protected:Npn \__tblr_build_vline_segment_real:nn #1 #2
   {
     \tl_set:Nx \l__tblr_s_tl
-      { \__tblr_prop_item:ne { table } { rulesep } }
+      { \__tblr_prop_item:ne { inner } { rulesep } }
     \tl_set:Nx \l__tblr_b_tl
       {
-        \__tblr_text_item:ne { hline }
+        \__tblr_spec_item:ne { hline }
           { [\int_eval:n{#1 + 1}](1) / @hline-height }
       }
     \tl_if_empty:NT \l__tblr_b_tl { \tl_set:Nn \l__tblr_b_tl { 0pt } }
@@ -4115,12 +5329,12 @@
         \int_step_inline:nn { \l__tblr_n_tl }
           {
             \tl_set:Nx \l__tblr_w_tl
-              { \__tblr_text_item:ne { vline } { [#2](##1) / @vline-width } }
+              { \__tblr_spec_item:ne { vline } { [#2](##1) / @vline-width } }
             \vbox_set_to_ht:Nnn \l__tblr_b_box
               { \dim_eval:n { \l__tblr_row_ht_dim + \l__tblr_row_dp_dim } }
               {
                 \tl_set:Nx \l__tblr_f_tl
-                  { \__tblr_text_item:ne { vline } { [#1][#2](##1) / fg } }
+                  { \__tblr_spec_item:ne { vline } { [#1][#2](##1) / fg } }
                 \tl_if_empty:NF \l__tblr_f_tl { \color{\l__tblr_f_tl} }
                 \__tblr_get_vline_segment_child:nnnxx {#1} {#2} {##1}
                   { \dim_eval:n { \l__tblr_row_ht_dim } }
@@ -4146,8 +5360,8 @@
 
 \cs_new_protected:Npn \__tblr_build_cell:NN #1 #2
   {
-    \int_set:Nn \c at rownum {#1}
     \int_set:Nn \c at colnum {#2}
+    \__tblr_update_colsep_registers:
     \group_begin:
     \tl_set:Nx \l__tblr_w_tl
       { \__tblr_data_item:nen { column } {#2} { @col-width } }
@@ -4305,21 +5519,24 @@
 %% #1: row number; #2: column number; #3: dimen register for rowsep above.
 %% #4: dimen register for total height; #5: dimen register for rowsep below.
 %% We can use \l__tblr_row_item_skip_size_prop which was made before
+%% But when vspan=even, there are no itemskip in the prop list.
+%% Therefore we need to calculate them from the sizes of items and skips
 \cs_new_protected:Npn \__tblr_get_span_vertical_sizes:NNNNN #1 #2 #3 #4 #5
   {
     \dim_set:Nn #3
       { \__tblr_data_item:nen { row } {#1} { abovesep } }
     \dim_zero:N #4
-    \int_step_inline:nnn { #1 } { #1 + \l__tblr_cell_rowspan_tl - 2 }
+    \dim_add:Nn #4
+      { \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[#1] } }
+    \int_step_inline:nnn { #1 + 1 } { #1 + \l__tblr_cell_rowspan_tl - 1 }
       {
         \dim_add:Nn #4
-          { \prop_item:Ne \l__tblr_row_item_skip_size_prop { itemskip[##1] } }
+          {
+            \prop_item:Ne \l__tblr_row_item_skip_size_prop { skip[##1] }
+            +
+            \prop_item:Ne \l__tblr_row_item_skip_size_prop { item[##1] }
+          }
       }
-    \dim_add:Nn #4
-      {
-        \prop_item:Ne \l__tblr_row_item_skip_size_prop
-          { item[\int_eval:n { #1 + \l__tblr_cell_rowspan_tl - 1 }] }
-      }
     \dim_set:Nn #5
       {
         \__tblr_data_item:nen { row }
@@ -4331,7 +5548,7 @@
 %% #1: row number; #2: column number; #3: dimen register for colsep left.
 %% #4: dimen register for total width; #5: dimen register for colsep right.
 %% We can use \l__tblr_col_item_skip_size_prop which was made before
-%% But when hspan=minimal, there are no itemskip in the prop list.
+%% But when hspan=even or hspan=minimal, there are no itemskip in the prop list.
 %% Therefore we need to calculate them from the sizes of items and skips
 \cs_new_protected:Npn \__tblr_get_span_horizontal_sizes:NNNNN #1 #2 #3 #4 #5
   {
@@ -4338,21 +5555,17 @@
     \dim_set:Nn #3
       { \__tblr_data_item:nen { column } {#2} { leftsep } }
     \dim_zero:N #4
-    \int_step_inline:nnn { #2 } { #2 + \l__tblr_cell_colspan_tl - 2 }
+    \dim_add:Nn #4
+      { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[#2] } }
+    \int_step_inline:nnn { #2 + 1 } { #2 + \l__tblr_cell_colspan_tl - 1 }
       {
         \dim_add:Nn #4
-          { \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] } }
-        \dim_add:Nn #4
           {
-            \prop_item:Ne \l__tblr_col_item_skip_size_prop
-              { skip[\int_eval:n { ##1 + 1 }] }
+            \prop_item:Ne \l__tblr_col_item_skip_size_prop { skip[##1] }
+            +
+            \prop_item:Ne \l__tblr_col_item_skip_size_prop { item[##1] }
           }
       }
-    \dim_add:Nn #4
-      {
-        \prop_item:Ne \l__tblr_col_item_skip_size_prop
-          { item[\int_eval:n { #2 + \l__tblr_cell_colspan_tl - 1 }] }
-      }
     \dim_set:Nn #5
       {
         \__tblr_data_item:nen { column }
@@ -4373,7 +5586,10 @@
 
 \bool_new:N \g__tblr_tracing_text_bool
 \bool_new:N \g__tblr_tracing_command_bool
-\bool_new:N \g__tblr_tracing_table_bool
+\bool_new:N \g__tblr_tracing_option_bool
+\bool_new:N \g__tblr_tracing_theme_bool
+\bool_new:N \g__tblr_tracing_outer_bool
+\bool_new:N \g__tblr_tracing_inner_bool
 \bool_new:N \g__tblr_tracing_column_bool
 \bool_new:N \g__tblr_tracing_row_bool
 \bool_new:N \g__tblr_tracing_cell_bool
@@ -4384,7 +5600,11 @@
 \bool_new:N \g__tblr_tracing_target_bool
 \bool_new:N \g__tblr_tracing_cellspan_bool
 \bool_new:N \g__tblr_tracing_intarray_bool
+\bool_new:N \g__tblr_tracing_page_bool
+\bool_new:N \g__tblr_tracing_step_bool
 
+\bool_gset_true:N \g__tblr_tracing_step_bool
+
 \keys_define:nn { tblr-set-tracing }
   {
     +text .code:n = \bool_gset_true:N \g__tblr_tracing_text_bool,
@@ -4391,8 +5611,14 @@
     -text .code:n = \bool_gset_false:N \g__tblr_tracing_text_bool,
     +command .code:n = \bool_gset_true:N \g__tblr_tracing_command_bool,
     -command .code:n = \bool_gset_false:N \g__tblr_tracing_command_bool,
-    +table .code:n = \bool_gset_true:N \g__tblr_tracing_table_bool,
-    -table .code:n = \bool_gset_false:N \g__tblr_tracing_table_bool,
+    +option .code:n = \bool_gset_true:N \g__tblr_tracing_option_bool,
+    -option .code:n = \bool_gset_false:N \g__tblr_tracing_option_bool,
+    +theme .code:n = \bool_gset_true:N \g__tblr_tracing_theme_bool,
+    -theme .code:n = \bool_gset_false:N \g__tblr_tracing_theme_bool,
+    +outer .code:n = \bool_gset_true:N \g__tblr_tracing_outer_bool,
+    -outer .code:n = \bool_gset_false:N \g__tblr_tracing_outer_bool,
+    +inner .code:n = \bool_gset_true:N \g__tblr_tracing_inner_bool,
+    -inner .code:n = \bool_gset_false:N \g__tblr_tracing_inner_bool,
     +column .code:n = \bool_gset_true:N \g__tblr_tracing_column_bool,
     -column .code:n = \bool_gset_false:N \g__tblr_tracing_column_bool,
     +row .code:n = \bool_gset_true:N \g__tblr_tracing_row_bool,
@@ -4413,6 +5639,10 @@
     -cellspan .code:n = \bool_gset_false:N \g__tblr_tracing_cellspan_bool,
     +intarray .code:n = \bool_gset_true:N \g__tblr_tracing_intarray_bool,
     -intarray .code:n = \bool_gset_false:N \g__tblr_tracing_intarray_bool,
+    +page .code:n = \bool_gset_true:N \g__tblr_tracing_page_bool,
+    -page .code:n = \bool_gset_false:N \g__tblr_tracing_page_bool,
+    +step .code:n = \bool_gset_true:N \g__tblr_tracing_step_bool,
+    -step .code:n = \bool_gset_false:N \g__tblr_tracing_step_bool,
     all .code:n = \__tblr_enable_all_tracings:,
     none .code:n = \__tblr_disable_all_tracings:,
   }
@@ -4421,7 +5651,10 @@
   {
     \bool_gset_true:N \g__tblr_tracing_text_bool
     \bool_gset_true:N \g__tblr_tracing_command_bool
-    \bool_gset_true:N \g__tblr_tracing_table_bool
+    \bool_gset_true:N \g__tblr_tracing_option_bool
+    \bool_gset_true:N \g__tblr_tracing_theme_bool
+    \bool_gset_true:N \g__tblr_tracing_outer_bool
+    \bool_gset_true:N \g__tblr_tracing_inner_bool
     \bool_gset_true:N \g__tblr_tracing_column_bool
     \bool_gset_true:N \g__tblr_tracing_row_bool
     \bool_gset_true:N \g__tblr_tracing_cell_bool
@@ -4432,6 +5665,8 @@
     \bool_gset_true:N \g__tblr_tracing_target_bool
     \bool_gset_true:N \g__tblr_tracing_cellspan_bool
     \bool_gset_true:N \g__tblr_tracing_intarray_bool
+    \bool_gset_true:N \g__tblr_tracing_page_bool
+    \bool_gset_true:N \g__tblr_tracing_step_bool
   }
 
 \cs_new_protected_nopar:Npn \__tblr_disable_all_tracings:
@@ -4438,7 +5673,10 @@
   {
     \bool_gset_false:N \g__tblr_tracing_text_bool
     \bool_gset_false:N \g__tblr_tracing_command_bool
-    \bool_gset_false:N \g__tblr_tracing_table_bool
+    \bool_gset_false:N \g__tblr_tracing_option_bool
+    \bool_gset_false:N \g__tblr_tracing_theme_bool
+    \bool_gset_false:N \g__tblr_tracing_outer_bool
+    \bool_gset_false:N \g__tblr_tracing_inner_bool
     \bool_gset_false:N \g__tblr_tracing_column_bool
     \bool_gset_false:N \g__tblr_tracing_row_bool
     \bool_gset_false:N \g__tblr_tracing_cell_bool
@@ -4449,6 +5687,8 @@
     \bool_gset_false:N \g__tblr_tracing_target_bool
     \bool_gset_false:N \g__tblr_tracing_cellspan_bool
     \bool_gset_false:N \g__tblr_tracing_intarray_bool
+    \bool_gset_false:N \g__tblr_tracing_page_bool
+    \bool_gset_false:N \g__tblr_tracing_step_bool
   }
 
 \NewDocumentCommand \LogTabularrayTracing { m }
@@ -4459,6 +5699,7 @@
 
 \keys_define:nn { tblr-log-tracing }
   {
+    step .code:n = \__tblr_log_tracing_step:n {#1},
     unknown .code:n = \__tblr_log_tracing:N \l_keys_key_str
   }
 
@@ -4470,7 +5711,7 @@
 
 \cs_new_protected:Npn \__tblr_log_tracing_text:
   {
-    \__tblr_text_log:n { text }
+    \__tblr_spec_log:n { text }
   }
 
 \cs_new_protected:Npn \__tblr_log_tracing_command:
@@ -4478,11 +5719,28 @@
     \__tblr_prop_log:n { command }
   }
 
-\cs_new_protected:Npn \__tblr_log_tracing_table:
+\cs_new_protected:Npn \__tblr_log_tracing_option:
   {
-    \__tblr_prop_log:n { table }
+    \__tblr_prop_log:n { note }
+    \__tblr_prop_log:n { remark }
+    \__tblr_prop_log:n { more }
   }
 
+\cs_new_protected:Npn \__tblr_log_tracing_theme:
+  {
+    \__tblr_style_log:
+  }
+
+\cs_new_protected:Npn \__tblr_log_tracing_outer:
+  {
+    \__tblr_spec_log:n { outer }
+  }
+
+\cs_new_protected:Npn \__tblr_log_tracing_inner:
+  {
+    \__tblr_prop_log:n { inner }
+  }
+
 \cs_new_protected:Npn \__tblr_log_tracing_column:
   {
     \__tblr_data_log:n { column }
@@ -4500,12 +5758,12 @@
 
 \cs_new_protected:Npn \__tblr_log_tracing_vline:
   {
-    \__tblr_text_log:n { vline }
+    \__tblr_spec_log:n { vline }
   }
 
 \cs_new_protected:Npn \__tblr_log_tracing_hline:
   {
-    \__tblr_text_log:n { hline }
+    \__tblr_spec_log:n { hline }
   }
 
 \cs_new_protected:Npn \__tblr_log_tracing_colspec:
@@ -4537,9 +5795,124 @@
     \prop_log:N \l__tblr_row_span_to_row_prop
   }
 
+\cs_new_protected:Npn \__tblr_log_tracing_page:
+  {
+    \dim_log:N \pagegoal
+    \dim_log:N \pagetotal
+  }
+
+\cs_new_protected:Npn \__tblr_log_tracing_step:n #1
+  {
+    \bool_if:NT \g__tblr_tracing_step_bool { \tl_log:x {Step :~ #1} }
+  }
+
 \cs_new_protected:Npn \__tblr_do_if_tracing:nn #1 #2
   {
     \bool_if:cT { g__tblr_tracing_ #1 _bool } {#2}
   }
 
+%%% --------------------------------------------------------
+%%  \section{Tabularray Libraries}
+%%% --------------------------------------------------------
+
+%% \NewTblrLibrary and \UseTblrLibrary commands
+
+\NewDocumentCommand \NewTblrLibrary { m m }
+  {
+    \cs_new_protected:cpn { __tblr_use_lib_ #1: } {#2}
+  }
+
+\NewDocumentCommand \UseTblrLibrary { m }
+  {
+    \clist_map_inline:nn {#1} { \use:c { __tblr_use_lib_ ##1: } }
+  }
+
+%% Library booktabs and commands \toprule, \midrule, \bottomrule
+
+\NewTblrLibrary { booktabs }
+  {
+    \NewTableCommand \toprule [1] []    { \hline [0.08em, ##1] }
+    \NewTableCommand \midrule [1] []    { \hline [0.05em, ##1] }
+    \NewTableCommand \bottomrule [1] [] { \hline [0.08em, ##1] }
+    \NewTableCommand \cmidrule [2] []   { \cline [0.03em, ##1] { ##2 } }
+  }
+
+%% Library diagbox and command \diagbox
+
+\NewTblrLibrary { diagbox }
+  {
+    \RequirePackage{ diagbox }
+    \cs_set_eq:NN \__tblr_lib_saved_diagbox:w \diagbox
+    \NewContentCommand \diagbox [3] []
+      {
+        \__tblr_lib_diagbox_fix:n
+          {
+            \__tblr_lib_saved_diagbox:w
+              [ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
+              { \__tblr_lib_diagbox_math_or_text:n {##2} }
+              { \__tblr_lib_diagbox_math_or_text:n {##3} }
+          }
+      }
+    \NewContentCommand \diagboxthree [4] []
+      {
+        \__tblr_lib_diagbox_fix:n
+          {
+            \__tblr_lib_saved_diagbox:w
+              [ leftsep=\leftsep, rightsep=\rightsep, ##1 ]
+              { \__tblr_lib_diagbox_math_or_text:n {##2} }
+              { \__tblr_lib_diagbox_math_or_text:n {##3} }
+              { \__tblr_lib_diagbox_math_or_text:n {##4} }
+          }
+      }
+  }
+
+\cs_new_protected:Npn \__tblr_lib_diagbox_math_or_text:n #1
+  {
+    \bool_if:NTF \l__tblr_math_mode_bool {$#1$} {#1}
+  }
+
+\box_new:N \l__tblr_diag_box
+
+\cs_new_protected:Npn \__tblr_lib_diagbox_fix:n #1
+  {
+    \hbox_set:Nn \l__tblr_diag_box {#1}
+    \box_set_ht:Nn \l__tblr_diag_box { \box_ht:N \l__tblr_diag_box - \abovesep }
+    \box_set_dp:Nn \l__tblr_diag_box { \box_dp:N \l__tblr_diag_box - \belowsep }
+    \box_use:N \l__tblr_diag_box
+  }
+
+%% Library siunitx and S columns
+
+\NewTblrLibrary { siunitx }
+  {
+    \RequirePackage { siunitx }
+    \NewColumnType { S } [1] [] { Q[si = {##1}] }
+    \__tblr_data_new_key:nnn { cell } { si } { str }
+    \keys_define:nn { tblr-column }
+      {
+        si .code:n = \__tblr_siunitx_setcolumn:n {##1}
+      }
+    \cs_new_protected:Npn \__tblr_siunitx_setcolumn:n ##1
+      {
+        \__tblr_column_gput_cell:nn { si } {##1}
+        \__tblr_process_text_for_every_column_cell:n { \__tblr_siunitx_tablenum:n }
+      }
+    \cs_new_protected:Npn \__tblr_siunitx_tablenum:n ##1
+      {
+        \tl_if_head_is_group:nTF {##1}
+          { ##1 }
+          {
+            \group_begin:
+            \tl_set:Nx \l_tmpa_tl
+              {
+                \__tblr_data_item:neen { cell }
+                  { \int_use:N \c at rownum } { \int_use:N \c at colnum } { si }
+              }
+            \exp_args:NV \sisetup \l_tmpa_tl
+            \tablenum {##1}
+            \group_end:
+          }
+      }
+  }
+
 \ExplSyntaxOff



More information about the tex-live-commits mailing list.