If I want to do something with the node’s content (which, to my recollection, cannot be accessed by a key), I collect it in a savebox via the lrbox
environment.
In the following example, the text is saved in the savebox \qrrTikzNodeContent
and then, still in the execute at end node
key, used.
Firstly it is typeset in \phantom
so that the node gets re-sized appropriately (as if the content would be typeset as usual). The following \usebox
command is firstly \llap
ed to occupy the same horizontal space like its phantom-ed version, and than \smash
ed so that it doesn’t occupy any vertical space.
I added some hopefully useful keys, that should help how \raisebox
may affect the node:
phantom
re-sizes the node as if the content would be typeset in the usual way;
smash
deactivates re-sizing of the node as forced by \raisebox
.
This does not work with the keys text width
and align
as \tikz@atbegin@node
is executed after the minipage is applied that is used to realize those keys.
For this special use-case I want to point out that there’s also the text depth
key.
For <content>
without a depth setting this to <value>
is like a \raisebox{<value>}{<depth>}
.
The following code procudes a matrix of nodes:
normal raise raise + phantom
text depth raise + smash raise + phantom + smash
Additionally it shows the baseline of the node.
Code
\documentclass[tikz]{standalone}
\newsavebox\qrrTikzNodeContent
\newif\ifphantom% remove for 'clean' version
\newif\ifsmash % remove for 'clean' version
\tikzset{
nodes={draw,circle},
bl/.style={append after command={\pgfextra{\draw[very thin] (\tikzlastnode.base west) -- (\tikzlastnode.base east);}}},% debug, remove for 'clean' version
phantom/.is if=phantom,% remove for 'clean' version
smash/.is if=smash, % remove for 'clean' version
raise/.style={
execute at begin node={\begingroup\begin{lrbox}{\qrrTikzNodeContent}},
execute at end node={\end{lrbox}% remove for 'clean' version
\ifphantom
\phantom{\usebox\qrrTikzNodeContent}%
\fi
\ifsmash\smash{\fi
\ifphantom\llap{\fi
\raisebox{#1}{\usebox\qrrTikzNodeContent}%
\ifphantom}\fi
\ifsmash}\fi
\endgroup
},
% execute at end node={\end{lrbox}% 'clean' version
% \phantom{\usebox\qrrTikzNodeContent}%
% \smash{%
% \llap{%
% \raisebox{#1}{\usebox\qrrTikzNodeContent}%
% }%
% }%
% \endgroup
% }
},
}
\begin{document}
\begin{tikzpicture}
\matrix[draw=none, append after command={}, row sep=1ex, column sep=1ex] {
\node[bl, ] {g}; &
\node[bl, raise=-.2cm, ] {g}; & % only raisebox
\node[bl, raise=-.2cm, phantom] {g}; \\ % phantom
\node[bl, text depth=-.2cm ] {g}; & % text depth
\node[bl, raise=-.2cm, smash, ] {g}; & % smash
\node[bl, raise=-.2cm, smash, phantom] {g}; \\ % smash + phantom
};
\end{tikzpicture}
\begin{tikzpicture}
\matrix[draw=none, append after command={}, row sep=1ex, column sep=1ex] {
\node[bl, ] {h}; &
\node[bl, raise=-.2cm, ] {h}; & % only raisebox
\node[bl, raise=-.2cm, phantom] {h}; \\ % phantom
\node[bl, text depth=-.2cm ] {h}; & % text depth
\node[bl, raise=-.2cm, smash, ] {h}; & % smash
\node[bl, raise=-.2cm, smash, phantom] {h}; \\ % smash + phantom
};
\end{tikzpicture}
\end{document}
Output
Please respect expl3
naming conventions and avoid \cs_set
for functions not previously declared.
I don't know that this is 'the recommended way', but it uses the hooks documented in ltpara
and is informed to some extent by the examples in section 2.3. But note that the section warns the examples are insufficiently careful for production use and that the code below is less careful than the examples.
Kant provides a minimal check that I've successfully removed the code from the hook.
Note that I couldn't find a way to insert code at precisely the same point, so I altered the paragraph indent box, which is documented as available for modification in paragraph hooks.
\documentclass{article}
% ateb: https://tex.stackexchange.com/a/702496/
% i gwestiwn Yiannis Lazarides: https://tex.stackexchange.com/q/702429/
\usepackage{kantlipsum}
\ExplSyntaxOn
\dim_new:N \l_lazarides_epindent_dim
\dim_set:Nn \l_lazarides_epindent_dim { 3cm }
\int_new:N \g_lazarides_eplinenumber_int
\int_gzero:N \g_lazarides_eplinenumber_int
\int_new:N \l_lazarides_modstep_int
\int_set:Nn \l_lazarides_modstep_int { 5 }
\cs_new_protected:Nn \lazarides_inscriptionprefix:n {
\hbox_gset:Nn \g_para_indent_box
{
\skip_horizontal:n { \l_lazarides_epindent_dim }
\hbox_overlap_left:n
{
Line : \skip_horizontal:n { 3pt}
\int_to_arabic:n { #1 }
\skip_horizontal:n { 2pt }
}
}
}
\NewDocumentEnvironment{inscription}{}
{
\dim_set_eq:NN \parindent \l_lazarides_epindent_dim
\bigskip
\obeylines
\AddToHook { para / begin } [ lazarides ]
{
\int_gincr:N \g_lazarides_eplinenumber_int
\int_compare:nNnTF
{
\int_mod:nn { \g_lazarides_eplinenumber_int } { \l_lazarides_modstep_int }
} = { 0 }
{
\lazarides_inscriptionprefix:n { \g_lazarides_eplinenumber_int }
}{
\int_compare:nNnT { \g_lazarides_eplinenumber_int } = { 1 }
{
\lazarides_inscriptionprefix:n { 1 }
}
}
}
}
{
\bigskip
\int_gzero:N \g_lazarides_eplinenumber_int
\RemoveFromHook { para / begin }[ lazarides ]
}
\ExplSyntaxOff
\begin{document}
\begin{inscription}
L(ucius) Albinius f(ilius)]
[cum Galli ob]siderent Capitolium
[virgines Ve]stales Caere deduxit
[ibi sacra at]que ritus sollemnes ne
[intermitte]rentur curai sibi habuit
[urbe recup]erata sacra et virgines
[Romam rev]
\end{inscription}
\kant[2]
\end{document}
Best Answer
Polyfills exist for features of the LaTeX kernel that came into existence by pulling a useful LaTeX package into the kernel. However, the concept of hooks is brand new and was inspired by a ragtag of different LaTeX packages:
etoolbox
,filehook
,atbegshi
,atveryend
, and others.As Ulrike points out in the comments below the original question, the
\AfterEndPreamble
command from theetoolbox
package resembles thebegindocument/end
hook but only works in the preamble. Therefore, the answer seems to be a no: Although parts of the functionality of LaTeX hooks are available in different LaTeX packages, no comprehensive polyfill exists.LaTeX hooks have been available since LaTeX 2020-10-01. Therefore, one migration path would be to write different code for LaTeX before and after 2020-10-01:
Alternatively, you can roll the LaTeX format forward by loading a current
latexrelease.sty
file, as noted by David in the comments below the original question and in Joseph's answer, or wait until you no longer need to support TeX Live < 2021.