\NeedsTeXFormat{LaTeX2e} \ProvidesExplPackage{PrimeTeX/packages/Boxout}{2025-09-03}{1.0}{ Commands for typesetting boxouts. } \ProvideLength{\boxoutpadding}[1em] \ProvideLength{\boxoutrule}[1pt] \NewTblrEnviron{tblrBoxout} \SetTblrInner[tblrBoxout]{ cells = {boxoutBGColor}, hborder{1} = {belowspace=\boxoutpadding}, hborder{Z} = {abovespace=\boxoutpadding}, hlines = {0pt,boxoutBGColor}, hline{1,Z} = {\boxoutrule,boxoutFGColor}, vborder{1} = {rightspace=\boxoutpadding}, vborder{Z} = {leftspace=\boxoutpadding}, vlines = {0pt,boxoutBGColor}, vline{1,Z} = {\boxoutrule,boxoutFGColor}, } \tl_const:Nn \c_Boxout_innerspec_tl {colspec={X[l,h]}} \bool_const:Nn \c_Boxout_warning_bool {\c_false_bool} \tl_new:N \l_Boxout_title_tl \cs_new:Nn \__Boxout_default_format: { \justifying \setlength{\parindent}{0pt} \setlength{\parskip}{\medskipamount} } \keys_define:nn {Boxout} { innerspec .tl_set_e:N= \l_Boxout_innerspec_tl, innerspec .initial:e = {\c_Boxout_innerspec_tl}, danger .code:n = {\int_set:Nn \l_Boxout_severity_int {4}}, warning .code:n = {\int_set:Nn \l_Boxout_severity_int {3}}, info .code:n = {\int_set:Nn \l_Boxout_severity_int {2}}, tip .code:n = {\int_set:Nn \l_Boxout_severity_int {1}}, severity .int_set:N = {\l_Boxout_severity_int}, severity .initial:n = {0}, format .cs_set:Np = \__Boxout_format:, format .initial:n = {}, } \NewDocumentEnvironment{Boxout}{ % #1: Key-value options. O{} % #2: Label. >{\TrimSpaces}m % #3: Caption. O{} % #4: Body. +b }{ \group_begin: \keys_set:nn{Boxout}{#1} \int_case:nn \l_Boxout_severity_int { {1} { \colorlet{boxoutBGColor}{tipBGColor} \colorlet{boxoutFGColor}{tipFGColor} } {2} { \colorlet{boxoutBGColor}{infoBGColor} \colorlet{boxoutFGColor}{infoFGColor} } {3} { \colorlet{boxoutBGColor}{warningBGColor} \colorlet{boxoutFGColor}{warningFGColor} } {4} { \colorlet{boxoutBGColor}{dangerBGColor} \colorlet{boxoutFGColor}{dangerFGColor} } } \color{textColor} \label{box:#2} \tl_if_empty:nTF {#3} { % No header \expanded{\noexpand\begin{tblrBoxout}{\l_Boxout_innerspec_tl}} \__Boxout_format:\ignorespaces#4\\ \end{tblrBoxout} }{ % Yes header \expanded{\noexpand\begin{tblrBoxout}{\l_Boxout_innerspec_tl}} \SetCell{halign=c, font={\sbfamily\bfseries}}{#3}\\ \__Boxout_default_format:\__Boxout_format:\ignorespaces#4\\ \end{tblrBoxout} } \group_end: }{} \keys_define:nn{}{ BigBoxout .inherit:n = {BigFloat, Boxout}, } \NewDocumentEnvironment{BigBoxout}{ % #1: Key-value options. O{} % #2: Label, passed to Boxout argument #1. >{\TrimSpaces}m % #3: Caption, passed to Boxout argument #3. O{} % #4: Body, passed to Boxout. +b }{ \group_begin: \keys_set:nn{BigBoxout}{#1} \begin{BigFloat}[ type = generic, overhang = \l_BigFloat_overhang_dim, placement:V = \l_Float_placement_clist, offset = \l_BigFloat_offset_fp, ] \begin{Boxout}[ innerspec:V = \l_Boxout_innerspec_tl, severity:V = \l_Boxout_severity_int, ]{#2}[#3] #4 \end{Boxout} \end{BigFloat} \group_end: }{} \str_const:Nn \c_MarginBoxout_position_str {auto} \dim_const:Nn \c_MarginBoxout_width_dim {\marginparwidth} \keys_define:nn{}{ MarginBoxout .inherit:n = Boxout, } \keys_define:nn{MarginBoxout}{ position .choices:nn = {auto,reverse,left,right,nearest}{ \str_set:Ne \l_MarginBoxout_position_str {\l_keys_choice_tl} }, position .initial:e = {\c_MarginBoxout_position_str}, width .dim_set:N = \l_MarginBoxout_width_dim, width .initial:e = {\c_MarginBoxout_width_dim}, } \NewDocumentCommand{\MarginBoxout}{ % #1: Key-value options. O{} % #2: Label. >{\TrimSpaces}m % #3: Caption O{} % #4: Content. +m }{ \group_begin: \keys_set:nn {MarginBoxout} {#1} \marginalia[ width = \l_MarginBoxout_width_dim, ]{ \begin{Boxout}[ innerspec:V = \l_Boxout_innerspec_tl, severity:V = \l_Boxout_severity_int, format = {\RaggedOutside}, ]{#2}[#3] #4 \end{Boxout} } \group_end: } \dim_const:Nn \c_WrapBoxout_width_dim {3in} \dim_const:Nn \c_WrapBoxout_justifywidth_dim {18em} \str_new:N \l_WrapBoxout_passed_keys_str \keys_define:nn{}{ WrapBoxout .inherit:n = {WrapFig, Boxout}, } \keys_define:nn{WrapBoxout}{ justifywidth.dim_set:N = \l_WrapBoxout_justifywidth_dim, justifywidth.initial:e = {\c_WrapBoxout_justifywidth_dim}, width .dim_set:N = \l_WrapBoxout_width_dim, width .initial:e = {\c_WrapBoxout_width_dim}, unknown.code:n = { \str_put_right:Ne \l_WrapBoxout_passed_keys_str {\l_keys_key_str=\l_keys_value_tl,} } } \cs_new:Npn \__WrapBoxout_format: {} \NewDocumentEnvironment{WrapBoxout}{ % #1: Key-value options. O{} % #2: Label. >{\TrimSpaces}m % #3: Caption O{} % #4: Body. +b }{ \group_begin: \keys_set:nn{WrapBoxout}{#1} \__WrapFig_process_options: \message{WrapBoxout:~\l_WrapFig_passed_keys_str} \dim_compare:nNnTF {\l_WrapBoxout_width_dim} > {\l_WrapBoxout_justifywidth_dim} { \cs_set:Nn \__WrapBoxout_format: {\justifying} } { \cs_set:Nn \__WrapBoxout_format: {\l_WrapFig_format_tl} } \expanded{\noexpand\begin{wrapstuff}[ \l_WrapFig_placement_str, hoffset = {\dim_use:N \l_WrapFig_hoffset_dim}, \l_WrapBoxout_passed_keys_str, ]} \begin{Boxout}[ innerspec:e = { \l_Boxout_innerspec_tl, columns={\dim_use:N \l_WrapBoxout_width_dim} }, severity:V = \l_Boxout_severity_int, format = \__WrapBoxout_format:, ]{#2}[#3] #4 \end{Boxout} \end{wrapstuff} \group_end: }{}