diff --git a/README b/README index 023525b..319b2a5 100644 --- a/README +++ b/README @@ -50,13 +50,10 @@ All four templates build with LuaLaTeX (via latexmk -lualatex). The text fonts are Libertinus Serif and TeX Gyre Heros, both provided by texlive-fonts-extra. -The paper, memo, and letter templates need TeX Live 2025 or later. The -tagging code they rely on is not in TeX Live 2024, where the build -stops with "the key 'document/metadata/tagging' is unknown". Debian -trixie ships TeX Live 2024, so a trixie machine needs a newer TeX Live -from elsewhere in the archive. On Overleaf, choose the TeX Live -version under Menu > Settings > TeX Live version; 2025 or later is -required and is not always the default for an older project. +The tagging code requires TeX Live 2025 or later. On Overleaf, set the +version under Menu > Settings > TeX Live version. Debian Trixie ships +TeX Live 2024; sid (unstable) has TeX Live 2026, which also works and +installs without pulling in much else. ================================ === Accessibility ============== @@ -65,15 +62,10 @@ required and is not always the default for an older project. The paper, memo, and letter templates produce tagged PDFs that declare PDF/UA-2 (ISO 14289-2). The poster template does not; see below. -Tagging is switched on by the tagging=on key in the \DocumentMetadata -block at the top of each template. That key is what does the work: it -loads the kernel code that puts headings, paragraphs, lists, tables, -and figures into the PDF's structure tree, which is what a screen -reader walks. The neighbouring pdfstandard=ua-2 key only writes the -conformance claim into the file's metadata. Setting the standard -without setting tagging=on yields a PDF that announces itself as -accessible and contains nothing for assistive software to read, so -keep the two together. +Two keys in the \DocumentMetadata block at the top of each template do +this, and both are needed: tagging=on loads the kernel code that puts +headings, paragraphs, lists, tables, and figures into the PDF's +structure tree, and pdfstandard=ua-2 writes the conformance claim. The paper and memo templates were originally built on the memoir class, which is incompatible with the LaTeX tagged-PDF code. They now @@ -85,62 +77,50 @@ Writing an accessible document ------------------------------ Tagging gets you the structure; the content is still up to the author. -Three things matter most, and the paper template carries a worked -example of each: +The paper template carries a worked example of each of these: * Use \section and \subsection for headings rather than setting type - in bold by hand. Screen reader users navigate by the heading tree, - and hand-formatted text is invisible to it. + in bold by hand. Screen reader users navigate by the heading tree. * Give every figure an alt= description on \includegraphics, saying what the reader is meant to take from it. A decorative image takes - \includegraphics[artifact]{...} instead, keeping it out of the - reading order. + \includegraphics[artifact]{...} instead. * Mark header rows on data tables with \tagpdfsetup{table/header-rows - ={1}} so their cells become TH rather than TD. Without it a table - reads as an undifferentiated grid of values. + ={1}} so their cells become TH rather than TD. Customizing the styles ---------------------- -Some common packages defeat tagging, and the failure is usually -silent: the document compiles without complaint and the tags are -simply missing. Before adding a package, check its status against the -LaTeX Tagging Project's list: +Some common packages defeat tagging, and the failure is silent: the +document compiles without complaint and the tags are simply missing. +Before adding a package, check it against the LaTeX Tagging Project's +list: https://latex3.github.io/tagging-project/tagging-status/ -titlesec and titling are the two to know about here, because they are -the obvious tools for the job cdsc-paper.sty and cdsc-memo.sty do. -titlesec replaces the \@startsection hook that the tagging code uses -to emit heading tags, so loading it produces a PDF with no headings in -the structure tree and no error to say so. Both style files therefore -build their headings and title blocks from the article class's own -\@startsection and \@maketitle hooks. +titlesec and titling are the two to know about, because they are the +obvious tools for the job cdsc-paper.sty and cdsc-memo.sty do. +titlesec replaces the \@startsection hook the tagging code uses to +emit heading tags, so loading it produces a PDF with no headings in +the structure tree. Verifying --------- -Check a built PDF against the standard with veraPDF: +You can check a built PDF with veraPDF (https://verapdf.org/): verapdf -f ua2 text.pdf -It prints PASS or FAIL for the file, and --format text will list the -clauses that failed. All four of the tagged templates pass as shipped, -so a FAIL means something in the document needs attention rather than -something in the template. +It prints PASS or FAIL, and --format text lists the failing clauses. +All three tagged templates pass as shipped, so a FAIL points at the +document rather than the template. -Run it. A document that declares PDF/UA-2 and does not meet it is -worse than one that makes no claim, because the claim is what a reader -relying on assistive software will trust. The declaration costs one -line and validating it is the only thing that makes the line true. +Note that a PASS is necessary but not sufficient. A document whose +body text is all marked as artifact passes too, because the standard +only requires that content which is not real be an artifact. -veraPDF is not packaged in Debian; download it from -https://verapdf.org/ and put it on your PATH. - -For a quicker look at whether a PDF carries any structure at all, -without checking conformance: +You can confirm there is something in the structure tree as well: python3 -c "import pikepdf,sys; d=pikepdf.open(sys.argv[1]); \ print(d.Root.get('/StructTreeRoot') and 'tagged' or 'UNTAGGED')" file.pdf diff --git a/letter_template/text.tex b/letter_template/text.tex index ccec5cf..fd72b4f 100644 --- a/letter_template/text.tex +++ b/letter_template/text.tex @@ -1,12 +1,4 @@ % Tagged PDF (PDF/UA-2) accessibility setup. -% -% tagging=on is what actually builds the structure tree: it loads the -% kernel code that tags paragraphs, headings, lists, tables, and -% floats. Declaring pdfstandard=ua-2 on its own only writes the claim -% into the metadata; without tagging=on the PDF is marked as UA-2 but -% carries no structure for a screen reader to read. This needs TeX -% Live 2025 or later --- on Overleaf, set it in Menu > Settings > -% TeX Live version. \DocumentMetadata{ tagging=on, pdfversion=2.0, diff --git a/memo_template/cdsc-memo.sty b/memo_template/cdsc-memo.sty index 0332b9e..dc2290c 100644 --- a/memo_template/cdsc-memo.sty +++ b/memo_template/cdsc-memo.sty @@ -8,12 +8,8 @@ % line, sans-serif uppercase section headings, no paragraph indent, % and a small-caps "page/total" footer. % -% Headings come from the article class's own \@startsection hook -% rather than from titlesec. The tagging code hooks into -% \@startsection to emit the H1, H2, and H3 tags a screen reader -% navigates by; titlesec bypasses that hook, so loading it silently -% produces a PDF with no headings in the structure tree. See the -% Accessibility section of the README. +% Headings use the class's own \@startsection hook, not titlesec, +% which breaks tagging. See the Customizing section of the README. % % Copyright 2009-2026 Benjamin Mako Hill % Copyright 2008-2009 Kieran Healy @@ -43,15 +39,9 @@ \pagestyle{cdsc-page-memo} -%%% Section headings: sans-serif bold uppercase, with the tight -%%% before/after spacing the original memo style used. -%%% -%%% \@startsection takes {name}{level}{indent}{beforeskip}{afterskip} -%%% {style}. The style argument is applied to the whole heading as an -%%% argument, so \MakeUppercase can be appended to it; the tagging -%%% code wraps the section number in \NoCaseChange so the number is -%%% left alone. A negative afterskip makes a heading run in to the -%%% paragraph that follows it. +%%% Section headings: sans-serif bold uppercase. \@startsection applies +%%% the style argument to the whole heading, so \MakeUppercase can be +%%% appended; the tagging code wraps the number in \NoCaseChange. \makeatletter diff --git a/memo_template/text.tex b/memo_template/text.tex index 9fbe5c7..841608c 100644 --- a/memo_template/text.tex +++ b/memo_template/text.tex @@ -1,14 +1,4 @@ -% Tagged PDF (PDF/UA-2) accessibility setup. The article class works -% with the LaTeX tagging project, so we use the full \DocumentMetadata -% path here. -% -% tagging=on is what actually builds the structure tree: it loads the -% kernel code that tags paragraphs, headings, lists, tables, and -% floats. Declaring pdfstandard=ua-2 on its own only writes the claim -% into the metadata; without tagging=on the PDF is marked as UA-2 but -% carries no structure for a screen reader to read. This needs TeX -% Live 2025 or later --- on Overleaf, set it in Menu > Settings > -% TeX Live version. +% Tagged PDF (PDF/UA-2) accessibility setup. \DocumentMetadata{ tagging=on, pdfversion=2.0, diff --git a/paper_template/cdsc-paper.sty b/paper_template/cdsc-paper.sty index ee532e0..5e0df13 100644 --- a/paper_template/cdsc-paper.sty +++ b/paper_template/cdsc-paper.sty @@ -6,12 +6,9 @@ % that work. The look-and-feel is kept as close to the previous % cdsc-article chapterstyle as is practical. % -% Headings and the title block are built from the article class's own -% \@startsection and \@maketitle hooks rather than from titlesec and -% titling. The tagging code hooks into \@startsection to emit the H1, -% H2, and H3 tags a screen reader navigates by; titlesec bypasses that -% hook, so loading it silently produces a PDF with no headings in the -% structure tree. See the Accessibility section of the README. +% Headings and the title block use the class's own \@startsection and +% \@maketitle hooks, not titlesec and titling, which break tagging. +% See the Customizing section of the README. % % Copyright 2009-2026 Benjamin Mako Hill % Copyright 2008-2009 Kieran Healy @@ -50,15 +47,9 @@ \pagestyle{cdsc-page} -%%% Section heading styles. -%%% -%%% Each heading is declared through \@startsection, which takes: -%%% {name}{level}{indent}{beforeskip}{afterskip}{style} -%%% A negative beforeskip suppresses the paragraph indent that would -%%% otherwise follow the heading; a negative afterskip makes the -%%% heading run into the paragraph text rather than sit on its own -%%% line. The style argument receives the whole heading as its -%%% argument, so a case-changing command may be appended to it. +%%% Section headings. \@startsection takes {name}{level}{indent} +%%% {beforeskip}{afterskip}{style}; a negative afterskip runs the +%%% heading in to the following paragraph. \makeatletter @@ -75,7 +66,6 @@ {\normalsize\itshape}} % Subsubsections: small bold, run in to the following paragraph -% (the negative afterskip is what makes it run in) \renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}% {-3.25ex \@plus -1ex \@minus -.2ex}% {-0.5em}% @@ -99,14 +89,9 @@ \newcommand{\puB}{} \newcommand{\published}[1]{\gdef\puB{#1}} -% \raggedright rather than \flushleft: the flushleft environment is a -% trivlist, and starting one as a bare declaration leaves a list open -% in the structure tree. That produces "the number of automatic begin -% and end text-unit para hooks differ" and a mis-nested PDF. -% The vertical skips reproduce what titling's \pretitle/\posttitle, -% \preauthor/\postauthor, and \predate/\postdate produced. The date -% slot keeps its space even when \date{} is empty, which is what the -% previous title block did and what the template's spacing assumes. +% \raggedright, not \flushleft: flushleft is a trivlist and would leave +% a list open in the structure tree. The skips match titling's output; +% the date slot keeps its space even when \date{} is empty. \renewcommand{\@maketitle}{% \null \vskip 2em% diff --git a/paper_template/text.tex b/paper_template/text.tex index 5a3bc2d..db02162 100644 --- a/paper_template/text.tex +++ b/paper_template/text.tex @@ -1,14 +1,4 @@ -% Tagged PDF (PDF/UA-2) accessibility setup. The article class works -% with the LaTeX tagging project, so we use the full \DocumentMetadata -% path here. -% -% tagging=on is what actually builds the structure tree: it loads the -% kernel code that tags paragraphs, headings, lists, tables, and -% floats. Declaring pdfstandard=ua-2 on its own only writes the claim -% into the metadata; without tagging=on the PDF is marked as UA-2 but -% carries no structure for a screen reader to read. This needs TeX -% Live 2025 or later --- on Overleaf, set it in Menu > Settings > -% TeX Live version. +% Tagged PDF (PDF/UA-2) accessibility setup. \DocumentMetadata{ tagging=on, pdfversion=2.0, @@ -215,14 +205,9 @@ and the commented-out block below it shows a figure carrying alt text. Both are here as worked examples; delete them along with this section when you start writing. -% ACCESSIBILITY: every figure needs an alt= description, which is what -% a screen reader announces in place of the image. Describe what the -% reader is meant to take from the figure rather than naming it: "Edit -% counts rising sharply after 2005" tells them something, "Figure 1" -% does not. The caption is read separately, so alt text that repeats -% the caption is wasted. For a purely decorative image, use -% \includegraphics[artifact]{...} instead, which keeps it out of the -% reading order entirely. +% alt= is what a screen reader announces in place of the image. Say what +% the reader should take from it, not what it is called. A decorative +% image takes [artifact] instead, keeping it out of the reading order. % % \begin{figure} % \centering @@ -232,11 +217,7 @@ when you start writing. % \label{fig:example} % \end{figure} -% ACCESSIBILITY: header-rows tells the tagging code which rows are -% headers, so their cells become TH rather than TD and a screen reader -% can announce the column a value belongs to. Without it, a data table -% reads as an undifferentiated grid of numbers. Set it for each table -% that has headers; use {1,2} if two rows are headers. +% header-rows makes the first row TH rather than TD. Use {1,2} for two. \tagpdfsetup{table/header-rows={1}} \begin{table} \centering @@ -249,9 +230,8 @@ when you start writing. \label{tab:example} \end{table} -% A table used only to position things on the page, rather than to -% present data, should be marked so assistive software skips its -% structure: \tagpdfsetup{table/tagging=presentation} +% A layout table, used to position rather than present, takes +% \tagpdfsetup{table/tagging=presentation} % bibliography here \setcounter{biburlnumpenalty}{9001} diff --git a/poster_template/main.tex b/poster_template/main.tex index 6c549f6..e4ec7e8 100644 --- a/poster_template/main.tex +++ b/poster_template/main.tex @@ -1,15 +1,6 @@ -% ACCESSIBILITY: this poster is not a tagged PDF. The beamer class -% rejects \DocumentMetadata outright ("Class beamer Error: The beamer -% class is not compatible with \DocumentMetadata"), and the LaTeX -% Tagging Project lists both beamer and beamerposter as no-support, -% meaning incompatible and not expected to change. beamerposter also -% pulls in textpos and subfig, which are incompatible in their own -% right. -% -% There is no way to make this template produce an accessible PDF -% today. Rather than declare PDF/UA-2 and ship an untagged file, it -% makes no claim at all. If a poster has to be accessible, supply a -% tagged companion document built from the paper or memo template. +% Not a tagged PDF: beamer rejects \DocumentMetadata, and the LaTeX +% Tagging Project lists beamer and beamerposter as no-support. See the +% Posters section of the README. \documentclass[xcolor=dvipsnames, 12pt]{beamer} \usepackage[size=custom, width=114, height=80, scale=1.5]{beamerposter}