\documentclass[a4paper,11pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{geometry}
\geometry{margin=3cm}
\usepackage{microtype}
\usepackage{booktabs}
\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage[colorlinks,linkcolor=blue!60!black,urlcolor=blue!60!black]{hyperref}
\usepackage{chemidentifier}
% this manual is written in English, the package's default (see §7)

\newcommand{\cmd}[1]{\texttt{\textbackslash #1}}
\newcommand{\opt}[1]{\texttt{#1}}

% --- compounds used in this manual's examples --------------------------
\chemid*{benz}
\chemid*{benz.cl}
\chemid*{benz.br}
\chemid*{benz.i}
\chemid*{amine}
\chemid*{amine.a}
\chemid*{amine.b}
\chemid*{target}{target\textsubscript{final}}[final target]
\chemid*{seriesa}
\chemid*{seriesb}
\chemid*{seriesc}
\chemidfamily{lcoum}{ name = Lcoum-C , placeholder = n }
\chemid*{lcoum.four}{4}
\chemid*{lcoum.eight}{8}
\chemid*{lcoum.twelve}{12}
\chemidfamily{ser}{ name = Series , sub-style = lower-greek ,
                    child-format = plain }
\chemid*{ser.a}
\chemid*{ser.b}
\chemid*{ser.c}

\title{The \texttt{chemidentifier} package}
\author{Aliocha SKRZYPCZAK \\ \small Version 2.0.0}
\date{2026-08-19}

\begin{document}
\maketitle

\begin{abstract}
\noindent
\texttt{chemidentifier} numbers the compounds of a synthesis-chemistry
paper in \emph{the logical order of the synthesis} — the order in which
you declare them — rather than the order in which they appear in the
text. Every printed number is clickable and jumps to the scheme showing
the compound. The package is written in \LaTeX3 (expl3); like
\cmd{ref}/\cmd{label}, everything settles over \textbf{two
compilations}.
\end{abstract}

\tableofcontents

\section{Installation and loading}

Copy \texttt{chemidentifier.sty} next to your document, or run
\texttt{make install} to install it into \texttt{\textasciitilde/texmf}.

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage{hyperref}          % preferably before chemidentifier
\usepackage{chemidentifier}
\end{Verbatim}

\noindent
\texttt{hyperref} is not loaded by the package: it is \emph{detected},
leaving you full control over its options and the loading order. If it
is missing, everything is still numbered normally, nothing is
clickable, and a warning reports it once.

\subsection{Which version gets loaded}
\label{sec:version}

\texttt{chemidentifier.sty} is a loader: it reads the \opt{version}
option and nothing else, then hands over to the implementation asked
for. Version~2 is the default and the one described here; version~1 is
kept unchanged, for good, for the documents written against it.

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage{chemidentifier}             % version 2
\usepackage[version=1]{chemidentifier}  % version 1, frozen
\end{Verbatim}

\noindent
Version~2 changes three things a version~1 document may notice, all
three deliberate:

\begin{itemize}
  \item \cmd{herechemid} is now called \cmd{chemidhere}. The old name
        still works and will keep working; it says once per document
        that it has been renamed.
  \item A compound with no anchor is printed \emph{without} a link
        rather than linked to nothing (§\ref{sec:strict}). Links
        therefore settle on the second compilation, as \cmd{ref} does.
  \item \cmd{chemidhere\{parent\}} now anchors the whole family,
        children included (§\ref{sec:anchor}).
\end{itemize}

\noindent
Everything else is unchanged, and the version~1 manual is installed
next to this one as \texttt{chemidentifier-doc-v1.pdf}. The regression
suite compiles every version~1 test document through the frozen
implementation and checks it against its original references, byte for
byte.

\section{The three commands}

\begin{center}
\begin{tabular}{@{}lll@{}}
\toprule
Command & Role & Output \\
\midrule
\cmd{chemid*\{key\}}  & declaration & none \\
\cmd{chemid\{key\}}   & use & the number, clickable \\
\cmd{chemidhere\{key\}} & anchor     & none \\
\bottomrule
\end{tabular}
\end{center}

\subsection{\cmd{chemid*} — declaring}

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{key}
\chemid*{key}{rich name}
\chemid*{key}{rich name}[raw name]
\chemid*{key}[rich name][raw name]     % equivalent variant
\end{Verbatim}

The declaration prints nothing. \textbf{The order of declarations sets
the numbering}: place them in the preamble, in the order of your
synthesis scheme.

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{benz}        % 1
\chemid*{benz.cl}     % 1a
\chemid*{benz.br}     % 1b
\chemid*{amine}       % 2
\end{Verbatim}

\noindent
The main counter advances on every new \emph{parent}. Each parent has
its own letter counter, so you can declare children later without
breaking the numbering: \chemid{benz} and \chemid{benz.cl,benz.br},
then \chemid{amine}.

A \emph{rich name} entirely replaces the automatic number:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{target}{target\textsubscript{final}}[final target]
\end{Verbatim}

\noindent
gives \chemid{target}. The second argument, in brackets, is the
plain-text version used in PDF bookmarks and metadata, where no
formatting is allowed. If you omit it, it is derived automatically
from the rich name (see §\ref{sec:purify}).

\subsubsection*{Declaring several keys at once}

A comma-separated list of keys declares each of them, auto-numbered in
turn — the same convention as \cmd{chemid}:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{mol1,mol2,mol3}     % three parents: 1, 2, 3
\chemid*{mol1.a,mol1.b}      % two children of mol1: 1a, 1b
\end{Verbatim}

\noindent
A custom name cannot accompany a multiple declaration —
\verb|\chemid*{a,b}{name}| would be ambiguous: which key would it
belong to? This is an error; declare that key on its own instead. A
comma \emph{inside} a single key (the result of a malformed key, e.g.\
one built by a macro) is also rejected.

\subsubsection*{A child without its parent}

Declaring children in bulk without ever declaring their parent on its
own also works: the parent is created implicitly (§\ref{sec:parsing}),
with its own number, and \cmd{chemid} of its name alone prints it
normally, without error:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{molz.a,molz.b}      % molz was never declared on its own
...
\chemid{molz}                 % -> its number
\end{Verbatim}

\subsection{\cmd{chemid} — using}

\cmd{chemid} accepts a comma-separated list of keys and works
everywhere: body text, \cmd{caption}, section titles.

\begin{center}
\begin{tabular}{@{}ll l@{}}
\toprule
Call & Result & Rule \\
\midrule
\verb|\chemid{benz}|                  & \chemid{benz}                  & plain key \\
\verb|\chemid{benz.cl}|               & \chemid{benz.cl}               & child key \\
\verb|\chemid{benz.cl,benz.br,benz.i}|& \chemid{benz.cl,benz.br,benz.i}& 3 contiguous: range \\
\verb|\chemid{benz.cl,benz.br}|       & \chemid{benz.cl,benz.br}       & 2 contiguous \\
\verb|\chemid{benz.cl,benz.i}|        & \chemid{benz.cl,benz.i}        & non-contiguous \\
\verb|\chemid{benz,amine.a}|          & \chemid{benz,amine.a}          & different families \\
\verb|\chemid{target}|                & \chemid{target}                & custom name \\
\verb|\chemid{seriesa,seriesb,seriesc}| & \chemid{seriesa,seriesb,seriesc} & 3 consecutive parents: range \\
\bottomrule
\end{tabular}
\end{center}

\noindent
The order you give is respected as-is: nothing is sorted. An
undeclared key produces a compilation error and prints \texttt{??},
like an unresolved \cmd{ref}.

\noindent
Several plain parents cited in a row contract into a range exactly like
several children of the same parent do: \verb|\chemid{seriesa,seriesb}|
(only two, below \opt{range-threshold}) still gives
\chemid{seriesa,seriesb}, but a gap breaks the range rather than being
papered over, e.g.\ \chemid{seriesa,seriesc} for
\verb|\chemid{seriesa,seriesc}| (\texttt{seriesb} not cited in between).
A custom name, an undeclared key, or a child key never joins such a
run — it simply ends it, exactly as a different family would.

\subsection{\cmd{chemidhere} — anchoring}
\label{sec:anchor}

\cmd{chemidhere\{key\}} places the target of the link. Put it in the
figure that shows the compound, typically near the \cmd{caption}:

\begin{Verbatim}[frame=single,fontsize=\small]
\begin{figure}
  \centering
  \includegraphics{schema}
  \chemidhere{benz}\chemidhere{benz.cl}\chemidhere{benz.br}
  \caption{Halogenation of \chemid{benz}}
\end{figure}
\end{Verbatim}

% Real anchors for this manual: the numbers printed above are clickable
% and land here.
\chemidhere{benz}\chemidhere{benz.cl}\chemidhere{benz.br}\chemidhere{benz.i}%
\chemidhere{amine}\chemidhere{amine.a}\chemidhere{amine.b}\chemidhere{target}%
\chemidhere{seriesa,seriesb,seriesc}\chemidhere{lcoum,ser}

\noindent
It prints nothing and \emph{never} affects the layout, in horizontal
mode as well as in vertical mode (this is checked by the test suite).
A click brings the reader to the figure; the PDF format does not allow
targeting a sub-part of an image, an anchor there being a point, not
an area.

\subsubsection*{Several keys, and whole families, at once}

\cmd{chemidhere} takes a list, with the same comma convention as
\cmd{chemid} and \cmd{chemid*}. And since a scheme usually shows a
parent with all of its children, naming the \emph{parent} anchors the
family:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemidhere{cmbr.4,cmbr.6,cmbr.8}   % three keys, three anchors
\chemidhere{cmbr}                   % the same three, plus cmbr itself
\chemidhere{cmbr,cmal}              % two families in one call
\end{Verbatim}

\noindent
A child that carries an anchor of its own is left alone by the family
anchor — the explicit one wins, and says nothing about it. Children
declared \emph{after} the scheme are anchored too, being read back
from the \texttt{.aux}. Set \opt{anchor-children} to \opt{false} to
keep \cmd{chemidhere\{parent\}} to the parent alone.

\subsubsection*{Diagnostics}

Placing the anchor of the same key twice triggers a warning: the PDF
target would be ambiguous. Using a key that was never declared is an
error. Finally, a key that is used but never anchored is reported at
the end of compilation, like an unresolved \cmd{ref} — and, version~2
having nowhere to send that link, it is printed without one
(§\ref{sec:strict}).

\subsubsection*{\cmd{herechemid}, the old name}

Version~1 called this command \cmd{herechemid}. It still works, and
will keep working, but it was the odd one out among \cmd{chemid},
\cmd{chemidkey}, \cmd{chemidnote}, \cmd{chemidscheme} and
\cmd{chemidsetup}; using it says so once per document.

\section{What happens in the table of contents and bookmarks}

A compound number in a section title must behave differently depending
on where that title gets reused.

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
Context & Behaviour \\
\midrule
Body text, caption, displayed title & clickable number \\
Table of contents, list of figures  & number shown, \emph{not} clickable \\
PDF bookmarks, metadata             & plain text, no formatting \\
\bottomrule
\end{tabular}
\end{center}

\noindent
The link is dropped from the table of contents because the entry is
\emph{already} a link to the section: two nested links cannot be
represented in PDF. The three renderings are produced by the same,
fully expandable internal code, which guarantees they cannot diverge.

\section{Numbering}

\subsection{Keys}
\label{sec:parsing}

A key is written \texttt{parent} or \texttt{parent.child} — a single
level of hierarchy; \texttt{a.b.c} is an error. Keys are case-sensitive
and accept digits, hyphens and underscores (\texttt{2nd},
\texttt{my\_key}, \texttt{compound-3}), but no comma: that is the list
separator of \cmd{chemid} and \cmd{chemid*}.

Declaring \texttt{parent.child} without having declared \texttt{parent}
creates the latter automatically, with its own number, and reports it
in the \texttt{.log}. The option \opt{implicit-parent=false} turns this
into an error instead.

\subsection{Beyond 26 children}

Letters keep going past \texttt{z}: \texttt{aa}, \texttt{ab}, \dots{}
There is no limit at 26.

\subsection{Resetting}

\cmd{chemidreset} resets the main counter to zero: the next declaration
will start again from 1. This is the only reset offered — no resetting
to an arbitrary value, no partial reset. Compounds already declared
keep the number they were given.

\section{Templated families}
\label{sec:family}

A parent numbers its children with letters: \texttt{1a}, \texttt{1b},
\texttt{1c}. That is right for a series of analogues, and wrong for a
series whose members are told apart by something the chemist already
has a name for --- a chain length, an oxidation state, a substituent.
A \emph{family} lets the parent hold the stem, and each child carry
only what varies:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemidfamily{lcoum}{ name = Lcoum-C , placeholder = n }
  \chemid*{lcoum.four}{4}
  \chemid*{lcoum.eight}{8}
  \chemid*{lcoum.twelve}{12}
\end{Verbatim}

\noindent
\cmd{chemidfamily} declares the parent, exactly as \cmd{chemid*} would
--- it takes the same place in the numbering --- and gives it a shape
its children inherit. Inside such a family, the argument that would
otherwise \emph{name} a key is read as its \emph{value}: the second
argument of \verb|\chemid*{lcoum.four}{4}| is the \texttt{4}, not a
compound called ``4''.

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
Written & Printed \\
\midrule
\verb|\chemid{lcoum.four}| & \chemid{lcoum.four} \\
\verb|\chemid{lcoum.four,lcoum.eight}| & \chemid{lcoum.four,lcoum.eight} \\
\verb|\chemid{lcoum.four,lcoum.eight,lcoum.twelve}| & \chemid{lcoum.four,lcoum.eight,lcoum.twelve} \\
\verb|\chemid{lcoum}| & \chemid{lcoum} \\
\bottomrule
\end{tabular}
\end{center}

\noindent
The stem is printed \emph{once} for a whole group and the values are
gathered in a single subscript, just as \texttt{1a,b} factors out the
\texttt{1}. Each value keeps its own link, and the stem links to the
first of them.

\subsection{The options of a family}

\begin{center}
\begin{tabular}{@{}llp{5.9cm}@{}}
\toprule
Option & Default & Role \\
\midrule
\opt{name}            & (empty)          & the stem; without one, the parent's number is used \\
\opt{raw}             & derived          & its PDF-string form, as for \cmd{chemid*} \\
\opt{sub-style}       & \opt{sub-style}  & numbering of the children that carry no value \\
\opt{child-format}    & \opt{subscript}  & \opt{subscript}, \opt{superscript}, \opt{plain}, or code \\
\opt{placeholder}     & (empty)          & what \cmd{chemid\{parent\}} shows in place of a value \\
\opt{placeholder-raw} & derived          & its PDF-string form \\
\bottomrule
\end{tabular}
\end{center}

\noindent
\opt{child-format} takes one of the three keywords or, for anything
they cannot express, the code itself, with \cmd{chemidvalue} standing
where the value belongs:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemidfamily{cu}{ name = Cu , child-format = \textsuperscript{\chemidvalue} }
\end{Verbatim}

\subsection{Children numbered by the family}

A child declared with no value of its own is numbered by the family's
\opt{sub-style} --- including \opt{lower-greek}, which is what such
series are usually labelled with:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemidfamily{ser}{ name = Series , sub-style = lower-greek ,
                    child-format = plain }
  \chemid*{ser.a}\chemid*{ser.b}\chemid*{ser.c}
\end{Verbatim}

\noindent
\verb|\chemid{ser.a}| gives \chemid{ser.a}, and
\verb|\chemid{ser.a,ser.b,ser.c}| gives \chemid{ser.a,ser.b,ser.c}:
automatically numbered children are consecutive, so they contract into
a range like any other run. In PDF bookmarks, where there is no maths
to be had, the Greek letter appears as the character itself.

Values given by hand never contract: \texttt{4}, \texttt{8} and
\texttt{12} have no notion of ``consecutive'', and \texttt{4-12} would
claim something nobody wrote. They are always listed one by one.

\subsection{One family, one kind of child}

Inside a family, either every child carries a value of its own or none
does. Mixing the two is an error: the ones in between would have to be
numbered by a rule the others visibly do not follow, and no reading of
the list would be honest. The child is still declared --- a diagnostic
must not shift the numbering of everything after it.

\section{Options}

They are given at load time, or at any point with
\cmd{chemidsetup\{\dots\}}; in the latter case they follow the scope of
the current \TeX{} group.

\begin{center}
\begin{tabular}{@{}llp{6.2cm}@{}}
\toprule
Option & Default & Role \\
\midrule
\opt{list-sep}        & \verb|{, }|   & between two families \\
\opt{last-sep}        & \verb|{ and }| & before the last family \\
\opt{sub-sep}         & \verb|{,}|    & between letters of the same family \\
\opt{range-sep}       & \verb|{-}|    & inside a range \texttt{1a-c} \\
\opt{range-threshold} & \opt{3}       & size from which a range is contracted \\
\opt{format}          & (empty)       & formatting applied to each identifier, e.g.\ \verb|\textbf| \\
\opt{main-style}      & \opt{arabic}  & \opt{arabic}, \opt{alph}, \opt{Alph}, \opt{roman}, \opt{Roman} \\
\opt{sub-style}       & \opt{alph}    & same, plus \opt{lower-greek}, for the letter \\
\opt{prefix}          & \verb|{chemid.}| & prefix of PDF anchors \\
\opt{unknown-text}    & \verb|{??}|   & shown for an undeclared key \\
\opt{purify}          & \opt{true}    & derive the raw name from the rich name \\
\opt{implicit-parent} & \opt{true}    & create a missing parent automatically \\
\opt{strict-anchors}  & \opt{true}    & no anchor, no link — see §\ref{sec:strict} \\
\opt{links}           & \opt{true}    & \opt{false} drops every link and every anchor \\
\opt{anchor-children} & \opt{true}    & \cmd{chemidhere\{parent\}} anchors the family \\
\opt{auto-lang}       & \opt{true}    & see §\ref{sec:lang} \\
\opt{version}         & \opt{2}       & which implementation to load, §\ref{sec:version} \\
\bottomrule
\end{tabular}
\end{center}

\noindent
The chemistry-journal typographic convention — bold numbers — is
obtained as follows:

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage[format=\textbf]{chemidentifier}
\end{Verbatim}

\section{Multilingual documents}
\label{sec:lang}

The separator before the last item is, by default, the English
\verb|and| (\opt{last-sep}). To choose a fixed language, without
\texttt{babel}:

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage[last-sep={~et~}]{chemidentifier}   % at load time
\chemidsetup{last-sep={~et~}}                  % or at any time
\end{Verbatim}

In a thesis mixing several languages with \texttt{babel}, the
separator automatically follows the current language — the one that
\cmd{selectlanguage} just set — without anything further needed:

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage[french,ngerman,spanish,italian,english]{babel}
...
\selectlanguage{french}   \chemid{a,b}   % ... et ...
\selectlanguage{ngerman}  \chemid{a,b}   % ... und ...
\selectlanguage{spanish}  \chemid{a,b}   % ... y ...
\selectlanguage{italian}  \chemid{a,b}   % ... e ...
\selectlanguage{english}  \chemid{a,b}   % ... and ...
\end{Verbatim}

\noindent
The mechanism reads \cmd{languagename}, which babel updates on every
\cmd{selectlanguage}, in a fully expandable way: it therefore works
identically in the text, the table of contents and PDF bookmarks.
Without babel loaded, or for an unregistered language, the package
silently falls back to the \opt{last-sep} option.

Five languages are known by default, with their usual babel variants:

\begin{center}
\begin{tabular}{@{}lll@{}}
\toprule
Language & Separator & Recognized babel names \\
\midrule
English  & \texttt{and} & \texttt{english}, \texttt{american}, \texttt{british}, \texttt{australian}, \texttt{UKenglish}, \texttt{USenglish} \\
French   & \texttt{et}  & \texttt{french}, \texttt{francais}, \texttt{acadian}, \texttt{canadien} \\
German   & \texttt{und} & \texttt{german}, \texttt{ngerman}, \texttt{austrian}, \texttt{naustrian} \\
Spanish  & \texttt{y}   & \texttt{spanish}, \texttt{mexican} \\
Italian  & \texttt{e}   & \texttt{italian} \\
\bottomrule
\end{tabular}
\end{center}

\noindent
To add or redefine a language:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemidaddlanguage{portuguese}{ e }
\end{Verbatim}

\noindent
To disable the automatic switch — a fixed separator, whatever the
current language — set \opt{auto-lang=false}; \opt{last-sep} then
becomes the sole source again, as before this feature existed. Like
any option, this can be done locally inside a group:

\begin{Verbatim}[frame=single,fontsize=\small]
\begingroup
  \chemidsetup{auto-lang=false,last-sep={ or else }}
  \chemid{a,b}                          % ... or else ...
\endgroup
\chemid{a,b}                            % the language takes over again
\end{Verbatim}

\section{Two points worth knowing}

\subsection{The raw name derived automatically}
\label{sec:purify}

When you give a rich name without its raw counterpart, the latter is
derived using expl3's \cmd{text\_purify:n}: \verb|H\textsubscript{2}O|
becomes \texttt{H2O}. The result is good for common cases (subscripts,
superscripts, bold, italics) but \textbf{is not guaranteed} for nested
mathematics. For a non-trivial rich name, provide the raw version
yourself:

\begin{Verbatim}[frame=single,fontsize=\small]
\chemid*{k}{$\alpha$-D-glucopyranose}[alpha-D-glucopyranose]
\end{Verbatim}

\subsection{A number is a link only when it has somewhere to go}
\label{sec:strict}

A compound that is never anchored is printed as a plain number: no
link at all, rather than one landing wherever the reader's viewer
decides to put it. This is \opt{strict-anchors}, and it is the default
in version~2.

For that, the package must know, at the moment it prints a number,
whether an anchor for it exists \emph{anywhere} in the document —
which it cannot know on the way in. Anchors are therefore recorded in
the \texttt{.aux} and read back on the next run: the first compilation
links only what it has already seen anchored, the second links
everything, and it stays that way afterwards. The same trade-off as
\cmd{ref}/\cmd{label}, for the same reason.

A parent is a case worth knowing about. A scheme often anchors only
the children — \cmd{chemidhere\{parent.a\}}, \cmd{chemidhere\{parent.b\}}
— while the text also cites the parent on its own. Rather than drop
that link, the package sends it to the \emph{first anchored child}:
\cmd{chemid\{parent\}} lands on the same figure, which is where the
reader wanted to go. With \cmd{chemidhere\{parent\}}
(§\ref{sec:anchor}) the question does not even arise, the parent being
anchored as well.

Set \opt{strict-anchors} to \opt{false} to go back to version~1's
behaviour: the link is always written, and only the missing anchor is
reported at the end of the compilation.

\subsection{Turning every link off}

\opt{links=false} removes the whole hyperlinking layer: no
\cmd{hyperlink} around a number, and no \cmd{hypertarget} either, not
even where a \cmd{chemidhere} asks for one. The end-of-document report
about compounds without an anchor goes quiet as well, having nothing
left to protect. Numbering, names and every other rendering are
untouched.

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage[links=false]{chemidentifier}
\chemidsetup{links=false}     % or from here on, or inside a group
\end{Verbatim}

\section{Declaring after using}
\label{sec:forward}

\cmd{chemid} and \cmd{chemidhere} may appear \emph{before} the
\cmd{chemid*} that declares the key — useful when you don't want to be
forced to declare everything at the top of the document, in particular
when the table of contents precedes the text:

\begin{Verbatim}[frame=single,fontsize=\small]
Compound \chemid{mol1} is mentioned here, before its declaration.
...
\chemid*{mol1}
\end{Verbatim}

\noindent
Every declared key is recorded in the \texttt{.aux} at the end of
compilation (number, letter, rich name, raw name), and read back on
the next \cmd{begin}\texttt{\{document\}} — the same mechanism as
\cmd{label}/\cmd{ref}, with the same trade-off: the first compilation
shows \texttt{??} for any reference ahead of its declaration, the
second resolves it, and the result stays stable afterwards, since the
order of declarations never depends on where they are used. A key
still unknown at the end of the second pass is genuinely undeclared:
the error then keeps showing.

\noindent
If you have no particular constraint, declaring at the top of the
preamble remains the simplest approach: the number is then known as
soon as the key is read, with no forward reference to resolve.

\section{Text substitution in \texttt{.pdf\_tex} figures (LuaLaTeX only)}
\label{sec:pdftex}

A scheme exported by Inkscape (a \texttt{.pdf\_tex} + \texttt{.pdf}
pair) can have its compound labels wired to \cmd{chemid}, the same way
\texttt{psfrag} once patched text into \texttt{.eps} figures — without
the \texttt{.eps}/\texttt{psfrag} baggage: a \texttt{.pdf\_tex} is just
\LaTeX{} text calling \cmd{includegraphics}, so a plain, line-by-line
substitution is enough. This requires compiling with \texttt{lualatex}
(or another engine providing \cmd{directlua}): the substitution is
implemented in Lua, reading the file as plain text and handing the
result back to \TeX{} once the placeholders are replaced. The file on
disk is never modified, so re-exporting from Inkscape loses nothing.

A plain-\TeX{} catcode-trick alternative (à la \texttt{psfrag}) was
considered and rejected: a \texttt{.pdf\_tex} is genuine \TeX/PGF code,
full of \verb|\|, \verb|{|, \verb|}|, \verb|%|, \verb|#|, \verb|_|,
\verb|~|... Reading it verbatim and then re-executing it as code
requires the same character to carry two contradictory catcodes —
inert while captured, active while replayed — for arbitrary content,
which is precisely what made \texttt{psfrag} fragile. Lua sidesteps
this entirely by treating the file as a plain string throughout, and
handing the result to \TeX{} only at the very end, read under \TeX's
own, ordinary catcode regime.

Put a plain-text placeholder in the drawing for each compound label
(\texttt{TMP1}, \texttt{TMP2}\ldots anything, as long as it does not
also occur as a substring elsewhere in the figure text), then:

\begin{Verbatim}[frame=single,fontsize=\small]
\usepackage{graphicx}          % needed by the .pdf_tex itself
\usepackage{chemidentifier}
\chemidsetup{ pdftex-font = \sffamily\small }   % optional, once

\chemid*{precursor}
\chemid*{product}

\begin{figure}
  \centering
  \chemidkey{TMP1}{precursor}               % TMP1 -> \chemid{precursor}
  \chemidkey[1.3]{TMP2}{product}            % 1.3x bigger than the rest
  \chemidnote{TMPCOND}{K$_2$CO$_3$, acetone, 70~\textcelsius}
  \chemidscheme[0.8]{figures/scheme.pdf_tex}   % scale is optional
  \chemidhere{precursor}\chemidhere{product}
  \caption{Synthesis of \chemid{product} from \chemid{precursor}.}
\end{figure}
\end{Verbatim}

\begin{center}
\begin{tabular}{@{}ll@{}}
\toprule
Command & Role \\
\midrule
\cmd{chemidkey[factor]\{motif\}\{key\}} & placeholder $\to$ the compound's current number, e.g. \cmd{chemid}\texttt{\{key\}} \\
\cmd{chemidnote[factor]\{motif\}\{text\}} & placeholder $\to$ any other text, free-form \\
\cmd{chemidscheme[scale]\{path\}} & reads the file, substitutes, typesets; also extends \cmd{graphicspath} \\
\bottomrule
\end{tabular}
\end{center}

\noindent
\cmd{chemidscheme} consumes the pending \cmd{chemidkey}/\cmd{chemidnote}
list as it reads the file, so the next figure automatically starts
from an empty list — there is no separate "clear" step to remember.

The size of a substituted label is the product of three independent
factors, so a figure scaled down still reads fine without retouching
every label by hand:

\begin{enumerate}
  \item \opt{pdftex-font} (\cmd{chemidsetup}) -- the base style, set
        once, independently of the body text (Inkscape otherwise
        reinjects the document's own family, at whatever size the
        drawing used, typically too large), e.g.
        \verb|\chemidsetup{ pdftex-font = \sffamily\fontsize{9}{11}\selectfont }|.
  \item the \texttt{[scale]} of \cmd{chemidscheme} -- the same number
        handed to the figure's own \cmd{svgscale}, so labels
        shrink/grow together with the drawing.
  \item the optional \texttt{[factor]} of \cmd{chemidkey}/\cmd{chemidnote}
        -- one label singled out, relative to the others in the same
        figure; defaults to \texttt{1}.
\end{enumerate}

Under a non-Lua engine, \cmd{chemidscheme} raises a clear error instead
of silently doing nothing or mis-rendering. \cmd{chemidkey} takes the
compound's \emph{current} number: it does not declare or renumber
anything, so keys still need a matching \cmd{chemid*} declared
elsewhere.

\section{Assumed limitations}

\begin{itemize}
  \item A single level of hierarchy (\texttt{parent.child}), families
        included.
  \item Lists are neither sorted nor deduplicated: what you write is
        what gets printed — \verb|\chemid{a,b,a}| prints
        \texttt{1, 2 and 1}, without error.
  \item \texttt{cleveref} is not handled (out of scope).
  \item A key removed from the document keeps resolving to its last
        known value until the \texttt{.aux} file is cleared — the same
        limitation as \cmd{ref}/\cmd{label}.
  \item The optional arguments of \cmd{chemid*} are only recognized
        when \emph{glued} to the key, with no space or line break at
        all: \verb|\chemid*{k}{rich}[raw]|. Any space before \verb|{|
        or \verb|[| excludes them from being read; the content that
        follows is then treated as ordinary text, never absorbed.
\end{itemize}

\end{document}
