logo

LaTeX Tagging Project

Tagging Heading Structures

Generic headings

Packages

KOMA

Memoir

Current work on the LaTeX Tagging project is centered around providing a framework for declaring accessible section heading structures via LaTeX Templates. This will form the basis for providing updates to existing document classes, either directly or via emulations of existing packages such as titlesec.

This page allows selected LaTeX tagging examples to be processed with LaTeX to produce PDF which may then be viewed or validated to the PDF/UA-2 accessibility standard.

Validation is provided by the open source veraPDF validator hosted at texlive.net and by the LaTeX project show-pdf-tags validation hosted on the same server. As a convenience, a link is provided to open the generated PDF at ngPDF. ngPDF is provided free of charge by its authors, although is not open source, it is not a necessary component of the validation services shown on this page.

The tagging status page lists many test files showing the tagging status of over a thousand LaTeX packages. A small sample are highlighted here, corresponding to current work items.

The examples are presented in an online editor to allow you to experiment and change the examples. The resulting TeX files are not stored and all generated PDF are deleted from the server after an hour. The current public release of lualatex-dev from TeXLive is used to process all examples. Development code from the LaTeX git repositories is not used here.


We are grateful that a part of this project is funded through NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission’s Next Generation Internet program. Learn more at the NLnet project page.

NLnet foundation logo NGI Zero Logo

1. Generic Heading Template Implementation

The standard article class will already use the heading templates as shown in the example below. This is included here to demonstrate this test infrastructure, before the emulation of the heading packages has been undertaken.

%
\DocumentMetadata{tagging=on,pdfstandard=ua-2}
\documentclass{article}

\EditInstance{heading}{section}{
 number-format=\fbox{\theheading},
 before-vspace=2cm
}
\EditInstance{heading}{subsection}
{number-format=\fbox{\theheading}}

\title{Heading templates example}
\author{L. Team}
\begin{document}
\maketitle
\section{Introduction}
some text

\subsection{subsec a}
some text
\subsection{subsec b}
some text

\section{Main section}
more text
\end{document}
%

1a. Implement generic order key handling

In layouts for headings, captions, etc. the placement of individual data items (such as fixed strings like “Chapter”, a generated number, the title, an optional sub-title, some punctuation, etc.) needs a flexible solution in templates. This avoids the need for different templates just because the order of title and number got swapped or because of similar minor differences.

To allow for such variations within a single template, the concept of “order” keys has been developed. The template support code was augmented to offer a \template_process_order_clist:nnn command that takes an order key defined by the template and processes its comma list to typeset the items (and generate approriate tagging for them). You may find the documentation in latex-lab on CTAN or on your LaTeX installation with texdoc latex-lab-template.

At the moment only the .dtx file was added to the last dev release but not the .pdf documentation. That will happen with the next update.

The test file below defines a small template (that is not doing much) but lets you experiment with the mechanism and its results.

%
\DocumentMetadata
  {
    lang=en-US,
    pdfversion=2.0,
    pdfstandard=ua-2,
    tagging=on,
  }

% not doing math so set this to use less run resources
  
\tagpdfsetup {math/mathml/luamml/load=false}

  
\documentclass{article}


%
%  Define and implement a simple template that takes 3 arguments:
%   #1  key/value list for overwriting instance parameter settings
%   #2  a title
%   #3  a note
%
%  Internally it generates a number (or rather it has one hardwired in as this is
%  only for testing purposes.


% ---------------------------- define a template for testing ---------------------

\ExplSyntaxOn

\NewTemplateType{threeargs}{3}

\DeclareTemplateInterface{threeargs}{trial}{3}{
%
%  In the order key it supports ordering of prefix,number,title,punct,note and
%  3 customizable separators. The default makes use of all of them, but as prefix
%  is \NoValue and separator-a is empty nothing is typeset for them
%
  ,order       : commalist = {prefix,separator-a,number,separator-b,title,
                              punct,separator-c,note}
  ,prefix      : tokenlist = \NoValue
  ,number      : tokenlist = 4711
  ,punct       : tokenlist = .
  ,separator-a : tokenlist = 
  ,separator-b : tokenlist = \
  ,separator-c : tokenlist = \quad
%
% title and note have no keys because they are part of the arguments.
%
% Declarations (like font setting) that can be used:
%
  ,heading-decls: tokenlist = 
%
  ,prefix-decls : tokenlist = 
  ,number-decls : tokenlist = 
  ,punct-decls  : tokenlist =
  ,note-decls   : tokenlist = 
  ,title-decls  : tokenlist =
%
%
% Alternatively, or in addition, formatting commands can be used.
% The punct-format ensures that a punctuation is only added if there isn't one
% already at this point.
% The one for note adds (...) by default.
%
  ,prefix-format : function{1} = #1
  ,number-format : function{1} = #1
  ,punct-format  : function{1} = \AddPunct{#1}
  ,note-format   : function{1} = (#1)
  ,title-format  : function{1} = #1
%  
%  This is for surounding the number with a Lbl structure for tagging (see documentation).
%  
  ,number-tag  : tokenlist = Lbl
}

\DeclareTemplateCode{threeargs}{trial}{3}{
%  
%  Key bindings have to have standard names to work with order process, the conventions
%  are straight forward (see documentation).
%  
  ,order       = \l__trial_order_clist
  ,prefix      = \l__trial_prefix_tl
  ,number      = \l__trial_number_tl
  ,punct       = \l__trial_punct_tl
  ,separator-a = name {l__trial_separator-a_tl} % special because of 1 and - in the name
  ,separator-b = name {l__trial_separator-b_tl}
  ,separator-c = name {l__trial_separator-c_tl}
%
  ,heading-decls = \l__trial_heading_decls_tl
%
  ,prefix-decls  = \l__trial_prefix_decls_tl
  ,number-decls  = \l__trial_number_decls_tl
  ,punct-decls   = \l__trial_punct_decls_tl
  ,title-decls   = \l__trial_title_decls_tl
  ,note-decls    = \l__trial_note_decls_tl
%
  ,prefix-format = \__trial_prefix_format:n
  ,number-format = \__trial_number_format:n
  ,punct-format  = \__trial_punct_format:n
  ,title-format  = \__trial_title_format:n
  ,note-format   = \__trial_note_format:n
%
  ,number-tag  = \l__trial_number_tag_tl
}
{
%  This now implementes the template.
%
%  Process the key/value list is any and overwrite settings:
%  
  \SetKnownTemplateKeys{threeargs}{trial}{#1}
%  
% Set the missing variables for title and note from the mandatory arguments
% of the template: 
%  
  \tl_set:Nn \l__trial_title_tl {#2}  % save title arg
  \tl_set:Nn \l__trial_note_tl  {#3}  % save note arg
%  
%  Then typeset the whole thing as a simple paragraph, with order
%  key processing in the middle.
%  
  \par \noindent
  %
  \group_begin:
    \l__trial_heading_decls_tl
    \template_process_order_clist:nnn
     { trial }{ order }
     { note, number, prefix, punct, separator-a, separator-b, separator-c, title }
  %
    \par
  \group_end:
  \bigskip
  \hrule
  \bigskip
}


% ---------------------------- define a few instances  ---------------------



\DeclareInstance{threeargs}{default}{trial}{
  % no parameter settings, just use what the template has a defaults
}


\DeclareInstance{threeargs}{section}{trial}{
    prefix        = §
   ,separator-a   =       % no space
   ,heading-decls = \large\bfseries
   ,title-decls   = \scshape
   ,note-decls    = \mdseries\normalshape
}

\DeclareInstance{threeargs}{chapter}{trial}{
    prefix        = Chapter
   ,separator-a   = \ \rule[-10pt]{2pt}{50pt}\
   ,separator-b   = \\[10pt]
   ,order         = {number,separator-a,prefix,separator-b,title,punct} % no note
   ,heading-decls = \Large\bfseries
   ,title-decls   = \Huge\mdseries\scshape
}


% -------- define a simple command to use one of the instances  ---------------------

%
% Arguments are
%   #1  instance name
%   #1  key/value list with parameters (optional)
%   #3  title
%   #4  note (optional


\NewDocumentCommand\head{m O{} m o }
{ \UseInstance{threeargs}
              {#1}            % instance name
              {#2}{#3}{#4}    % template arguments
}


\newcommand\mynotes[1]{\par\noindent\texttt{\itshape #1}\par\medskip}

\ExplSyntaxOff



\begin{document}

\title{Testing order keys}
\author{Frank Mittelbach, \LaTeX{} Project}
\maketitle

% A bit of tracing (\checkstatus needs to be disabled because it currently
% does a \show which signals to to online server that the run has an error):

\DebugTemplatesOn
\renewcommand\checkstatus[1]{\typeout{----- #1 ------}}

\head{default}
     {Title}[default result] 

\head{default}
     {Title ending in punctuation!}[no period added] 


\mynotes{Use the optional argument for parameter changes:}
     
\head{default}
     [prefix=Chapter,separator-a=\ ,title-decls=\itshape]
     {Title}[prefix added]


\mynotes{Use section template instead:}
     
\head{section}
     {Title}[default result] 

\head{section}
     {Title ending in punctuation!}[no period added] 


\head{section}
     [prefix=Chapter,separator-a=\ ,title-decls=\itshape]
     {Title}[prefix added]


\head{default}
    [order={title,separator-b,number,separator-c,note}]
    {Title and number swapped}[and punctuation always dropped] 


\mynotes{Use (strange) chapter template instead:}
     
\head{chapter}
     {Title}[default result] 

\head{chapter}
     {Title ending in punctuation!}[no period added] 


\end{document}
%

1e. Extend key binding setup

In some templates the variable names in the key binds need to contain characters normally not directly usable, e.g., a number or a hyphen. To support this the template declaration syntax was extended with the keyword name so that one can write

 separator-1 = name {l__trial_separator-1_tl}

which generates \__trial_separator-1_tl a macro name that can’t be written directly because of the number and the hyphen, both of which are normally not allowed in macro names. This is, for example, needed in the order processing implementation where such variables are constructed from key names that may contain such characters.

As an example testing the implementation for the new keyword look at the test in section 1a which makes use of the functionality in 3 places.

2. Package Reimplementations/adjustments

2a-2e. titlesec

The titlesec package is currently incompatible with the LaTeX tagging code, and this example demonstrates that no PDF is generated and just the error log is shown.

It is included here as it is expected that an accessible version of this package functionality will be developed soon as part of a wider effort to implement LaTeX section headings via a new template interface producing accessible PDF outputs.

%
\DocumentMetadata
  {
    lang=en-US,
    pdfversion=2.0,
    pdfstandard=ua-2,
    tagging=on,
  }
\documentclass{report}
\usepackage{titlesec}

\titleformat{\section}
  {\LARGE\sffamily\slshape}
  {\thesection}{1em}{}
\titlespacing{\section}
  {-6pc}{3.5ex plus .1ex minus .2ex}{1.5ex minus .1ex}

\begin{document}

\chapter{Some chapter}
\section{Some section}
\subsection{Some subsection}
Normal text

\end{document}
%

2f. The fncychap package

2g. The quotechappackage

2h. The tocloft package

The tocloft package is currently incompatible with the LaTeX tagging code and this example demonstrates one of the issues with it: the TOC data is incomplete and not correctly tagged.

%
\DocumentMetadata { lang=en-US, pdfstandard=ua-2, tagging=on } % comment out to see untagged result

\documentclass{article}

\usepackage{hyperref}
\usepackage{tocloft}

\begin{document}

\title{Test for tocloft with hyperref} \maketitle

\tableofcontents

\section{Introduction}
Check whether in the TOC the reference to this section is hyperlinked.
\end{document}
%

3. KOMA-Script Classes

4. memoir Class