texlive[70311] Master/texmf-dist: minim-pdf (1mar24)

commits+karl at tug.org commits+karl at tug.org
Fri Mar 1 22:45:43 CET 2024


Revision: 70311
          https://tug.org/svn/texlive?view=revision&revision=70311
Author:   karl
Date:     2024-03-01 22:45:43 +0100 (Fri, 01 Mar 2024)
Log Message:
-----------
minim-pdf (1mar24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/minim-pdf/README
    trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.doc
    trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.pdf
    trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.lua
    trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.tex

Modified: trunk/Master/texmf-dist/doc/luatex/minim-pdf/README
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/minim-pdf/README	2024-03-01 21:45:34 UTC (rev 70310)
+++ trunk/Master/texmf-dist/doc/luatex/minim-pdf/README	2024-03-01 21:45:43 UTC (rev 70311)
@@ -1,4 +1,4 @@
-Version: 2024/1.4
+Version: 2024/1.5
 
 SUMMARY
 
@@ -27,26 +27,39 @@
 
 HISTORY
 
+2024/1.5 (in development)
+
+  New features:
+
+    * Add \autotagplainoutput and \sectionstructure.
+    * Allow bookmarks that are not associated to structure elements.
+    * The characters ~#% need no longer be escaped in a \hyperlink url.
+
+  Bug fixes:
+
+    * When writing the document structure is disabled, emit a warning instead 
+      of an error for incompatible structure types.
+
 2024/1.4 (5/1/2024)
 
   Breaking changes:
 
-    * Table cells and headers now connect automatically in \automarktable
+    * Table cells and headers now connect automatically in \automarktable.
 
   New features:
 
-    * Add support for pdf/ua
-    * Re-write \hyperlink, adding many options
-    * Add ref and title options to structure elements
-    * New helper macros for footnotes
-    * Add \withpdfresource
+    * Add support for pdf/ua.
+    * Re-write \hyperlink, adding many options.
+    * Add ref and title options to structure elements.
+    * New helper macros for footnotes.
+    * Add \withpdfresource.
 
 2023/1.3 (20/10/2023)
 
   New features:
 
-    * Add \markcolumnspan and \markrowspan
-    * Add \markcolumnhead and \markrowhead
+    * Add \markcolumnspan and \markrowspan.
+    * Add \markcolumnhead and \markrowhead.
 
 
 2023/1.2 (3/3/2023)

Modified: trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.doc
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.doc	2024-03-01 21:45:34 UTC (rev 70310)
+++ trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.doc	2024-03-01 21:45:43 UTC (rev 70311)
@@ -14,8 +14,8 @@
 \else \startmetadata
     author   {Esger Renkema}
     title    {minim-pdf}
-    date     {2024-01-05}
-    version  {2024/1.4}
+    date     {2024-02-25}
+    version  {2024/1.5}
     keywords {LuaTeX; Plain TeX; PDF/A; Tagged PDF; accessibility; a11y;
               hypertext; bookmarks; document outline; associated files}
     stopmetadata
@@ -40,9 +40,16 @@
 With the ⟦name⟧ action, a named destination must be used (see below), while the 
 ⟦user⟧ action will be passed directly to the back-end (as with the pdftex 
 primitive).
+After the ⟦url⟧ action, the characters \Uchar`\~, \# and \% need not be escaped.
+(Of course, this does nothing for already-tokenised text; be aware of this when 
+you wrap ⟦\hyperlink⟧ into another macro.)
+Any spaces after the ⟦<action>⟧ will be ignored.
+
 The ⟦*\hyperlinkstyle⟧ token list can be used so set common (pdf) link 
 attributes; it defaults to ⟦/Border [0 0 0]⟧. The contents of the optional 
 ⟦attr⟧ parameter will be appended to these.
+The ⟦alt⟧ options sets the ⟦/Contents⟧ key that is required by PDF/UA (where it 
+has the purpose of an alt text).
 
 A named destination can be created with ⟦*\nameddestination {...}⟧ (also in 
 horizontal mode, unlike the backend primitive) and if you cannot think of 
@@ -53,20 +60,26 @@
 
 \section Bookmarks %
1
 
-Bookmarks (also known as outlines) can be added with ⟦*\outline [open|closed] 
-[dest {name}] {title}⟧.
+Bookmarks (also known as outlines) can be added with
+⟦*\outline [level n] [open|closed] [dest {name}] {title}⟧.
 Add ⟦open⟧ or ⟦closed⟧ to have the bookmark appear initially open or closed 
-(default), and
+(the default), and
 say ⟦dest {name}⟧ for having it refer to a specific named destination 
 (otherwise, a new one will be created where the ⟦\outline⟧ command appears).
 
-A bookmark is automatically associated with the current structure element and 
-the hierarchy of structure elements determines the nesting of bookmarks. 
-Therefore, if you want nested bookmarks, you \emph{must} precede the ⟦\outline⟧ 
-command with a declaration of the current structure element, even if you have 
-otherwise disabled tagging. See the next chapter on how to do this.
+In the absence of the ⟦level⟧ option, the bookmark is automatically associated 
+with the current structure element and the hierarchy of structure elements 
+determines the nesting of bookmarks. This works even if you have otherwise 
+disabled tagging and is the recommended way of generating outlines.
+(You can find all relevant macros in next chapter under ‘Document structure’ 
+and ‘Structure element aliases’.)
 
+As a fallback, outlines specified with the ⟦level n⟧ option will be inserted at 
+the end of the current outline list at the specified level (${\tt n}≥1$ and 
+need not be contiguous). Both methods can be intertwined, but please use the 
+document structure if you can.
 
+
 \section Page labels %
1
 
 If the page numbers of your document are not a simple sequence starting with~1, 
@@ -201,6 +214,46 @@
 the (excellent) manual of latex’s tagpdf package.
 
 
+\section Quick-start guide % 
1
+
+The minimal setup for producing tagged pdf from plain tex documents is 
+something like the following:
+
+⟦% first update all fonts to TrueType (ttf) or OpenType (otf)
+\input luaotfload.sty
+% ... font redefinitions omitted ...
+\input minim-mp
+\pdfalevel 2a % declare pdf/a conformance, enable tagging
+\autotagplainoutput % update the output routine
+% create section markers and counters
+\sectionstructure { subsection, section, chapter }⟧
+
+You can then update your sectioning macros to look like this:
+
+⟦\def\section#1\par{%
+    % space above
+    \bigskip \goodbreak
+    % structure and outline (this is the new part)
+    \marksection \outline open {#1}
+    % section header
+    \noindent {\bf \the\chapternr.\the\sectionnr. #1}
+    % space below
+    \smallskip \noindent}⟧
+
+Other macros you might have for laying out structural elements, such as tables 
+or lists, should of course also be updated. The rest of this chapter describes 
+the tools you can use.
+
+Please be advised that producing tagged pdf will likely forever remain 
+a fragile and error-prone process.
+You should always validate the resulting pdf.
+An easy-to-use and free validator is \hyperlink alt {The veraPDF website.}
+url {https://verapdf.org/home}veraPDF\endlink.
+For inspecting the document structure, you can use the ⟦pdfinfo⟧ utility that 
+comes with the \hyperlink alt {The Poppler website.}
+url {https://poppler.freedesktop.org/}Poppler\endlink\ pdf library.
+
+
 \section Purpose, limitations and pitfalls %
1
 
 The main purpose of this package is semi-automatically marking up the 
@@ -213,7 +266,7 @@
 tagging can be done without any manual intervantion, it is quite possible and 
 rather easy to generate the wrong document structure, or even cause syntax 
 errors in the resulting pdf code.
-You should always check the result in an external application.
+You should always inspect and validate the result.
 
 This is the full list of limitations, pitfalls and shortcomings:
 \startlist
@@ -223,15 +276,13 @@
 below).
 \item2. The contents of ⟦\localleftbox⟧ and ⟦\localrightbox⟧ must be marked 
 manually, probably as artifact.
-\item3. You must mark page header, page footer and footnote rule yourself; no 
-default is set.
-\item4. There currently is no way of marking xforms or other pdf objects as 
+\item3. There currently is no way of marking xforms or other pdf objects as 
 content items of themselves.
-\item5. The content of xforms (i.e. pdf objects created by  ⟦\useboxresource⟧) 
+\item4. The content of xforms (i.e. pdf objects created by  ⟦\useboxresource⟧) 
 should not contain tagging commands.
-\item6. Likewise, you should be careful with box reuse: it might work, but you 
+\item5. Likewise, you should be careful with box reuse: it might work, but you 
 should check.
-\item7. This package currently only supports pdf~1.7 tagging and is not yet 
+\item6. This package currently only supports pdf~1.7 tagging and is not yet 
 ready for use with pdf~2.0.
 \stoplist
 
@@ -279,7 +330,7 @@
 pdf standard, is not supported by this package. You should set these on the 
 structure element instead.
 
-The begining and ending of a content item can be forced with 
+The beginning and ending of a content item can be forced with 
 ⟦*\startcontentitem⟧ and ⟦*\stopcontentitem⟧, while ⟦*\ensurecontentitem⟧ will 
 only open a new content item if you are currently outside any.
 If you need some part to be a single content item, you can use
@@ -336,17 +387,10 @@
 will have to be closed by an explicit closing tag, as in xml.
 In this case, ⟦\stopelement⟧ and ⟦\ensurestopelement⟧ will be equivalent.
 
-By default, ⟦P⟧ structure elements are inserted automatically at the start of 
-every paragraph. The tag can be changed with ⟦*\nextpartag {Tag}⟧; leaving the 
-argument empty will prevent marking the next paragraph.
-Keep in mind that the reassignment is local: if a paragraph marked with 
-⟦\nextpartag⟧ starts inside a group, it will not reset.
-Auto-marking paragraphs can be (locally) disabled or enabled by saying 
-⟦*\markparagraphsfalse⟧ or ⟦*\markparagraphstrue⟧.
-
 You can query the place in the document structure of any point with 
 ⟦*\showdocumentstructure⟧.
 
+
 \section Structure element aliases %
1
 
 New structure element tags can be created with
@@ -360,6 +404,33 @@
 have actually been used.
 
 
+\section Automatic tagging of paragraphs %
1
+
+By default, ⟦P⟧ structure elements are inserted automatically at the start of 
+every paragraph. The tag can be changed with ⟦*\nextpartag {Tag}⟧; leaving the 
+argument empty will prevent marking the next paragraph.
+Keep in mind that the (internal) reassignment is local: if a paragraph marked 
+with ⟦\nextpartag⟧ starts inside a group, it will not reset.
+Hence, to avoid surprises, you should have ⟦\nextpartag⟧ and the start of your 
+paragraph at the same grouping level.
+
+Useful structure elements for ⟦\nextpartag⟧ include ⟦H⟧ for headings and ⟦LI⟧ 
+for list items. Since minim-pdf produces strongly-structured documents, the 
+tags ⟦H1⟧, ⟦H2⟧, ⟦H3⟧ etc. should not be used.
+
+Please also note that if you add ⟦\hbox⟧es directly to a vertical list
+(this includes ⟦\line⟧, ⟦\centerline⟧ and the like),
+the ⟦\everypar⟧ token list is not inserted and no new paragraph structure element 
+will be opened.
+The contents of the ⟦\hbox⟧ will be added to the current structure element, and 
+this may result in an invalid structure hierarchy (and an error messsage 
+reading ‘Structure type mismatch’).
+You can make your intentions clear by inserting ⟦\startelement{P}⟧ at the 
+appropriate place (see above).
+
+Auto-marking paragraphs can be (locally) disabled or enabled by saying 
+⟦*\markparagraphsfalse⟧ or ⟦*\markparagraphstrue⟧.
+
 \section Manipulating the logical order %
1
 
 With the process outlined above, the logical order of structure elements has to 
@@ -504,7 +575,7 @@
 Cells spanning multiple cells or rows can be marked with 
 ⟦*\markcolumnspan {width}⟧ and ⟦*\markrowspan {height}⟧; these statements may not 
 occur before ⟦\marktablecell⟧. Note that while ⟦\markcolumnspan⟧ properly 
-increases the (internal) column number, ⟦\markcolumnrow⟧ does nothing of the 
+increases the (internal) column number, ⟦\markrowspan⟧ does nothing of the 
 sort (and indeed, no general logic can be given in the latter case). Always proceed 
 with caution when using cells spanning multiple rows, and inspect the resulting 
 structure carefully.
@@ -529,6 +600,46 @@
 around the footnote markers, will insert the proper ⟦Ref⟧, ⟦Note⟧ and ⟦Lbl⟧ 
 tags.
 
+Helper macros for tagging sections can be setup quickly with
+⟦*\sectionstructure { <section list> }⟧. The ⟦<section list>⟧ should be an 
+increasing comma-separated list of section types, e.g.
+⟦{subsection, section, chapter}⟧. This will first reserve the ⟦\count⟧ 
+registers ⟦\subsectionnr⟧ etc, then create the structure aliases ⟦/Subsection⟧ 
+etc. and finally define the helper macros ⟦\marksubsection⟧ etc, which will do 
+the following:
+\startlist
+\item 1. Call ⟦\ensurestopelement⟧ on all lower section types.
+\item 2. Set all lower section number counts to zero.
+\item 3. Increase the current section type number by one.
+\item 4. Call ⟦\startelement⟧ for the current section type.
+\item 5. Set the ⟦\nextpartag⟧ to ⟦H⟧.
+\stoplist
+The proper place for these helper macros is just before the section heading; 
+inbetween those two may come an ⟦\outline⟧ statement (see the previous 
+chapter). You can set the ⟦title⟧ option to the internal ⟦\startelement⟧ 
+statement with an optional argument (e.g.
+⟦\marksection [Section \the\sectionnr]⟧).
+
+\section Tagging the output routine %
1
+
+The command ⟦*\autotagplainoutput⟧ will try and update plain tex’s output routine 
+to produce tagged page artifacts and footnotes.
+It redefines ⟦\makeheadline⟧, ⟦\makefootline⟧, 
+⟦\footnoterule⟧, ⟦\footnote⟧ and ⟦\vfootnote⟧.
+Headline and footline will not be marked as artifacts if their contents equal 
+⟦\hfil⟧; the footnote macros are edited to include the ⟦\marknoteref⟧ and 
+⟦\marknotelbl⟧ macros described above.
+Note that the ⟦\topinsert⟧, ⟦\midinsert⟧ and ⟦\pageinsert⟧ macros are left 
+untouched; you will have to mark those explicitly.
+
+You can make some changes to the affected macros before calling 
+⟦\autotagplainoutput⟧, as it tries to be smart about it.
+Though the redefinitions involve a full expansion,
+most conditionals and common typesetting instructions (⟦\line⟧, ⟦\quad⟧, 
+⟦\strut⟧ etc.) are safe-to-use and will not be expanded.
+If you include custom macros of your own, however, it is wise to have those 
+⟦\protected⟧.
+
 % 
 
 \endmanual

Modified: trunk/Master/texmf-dist/doc/luatex/minim-pdf/minim-pdf.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.lua	2024-03-01 21:45:34 UTC (rev 70310)
+++ trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.lua	2024-03-01 21:45:43 UTC (rev 70311)
@@ -229,7 +229,13 @@
         end
     end
     if not c then
-        alloc.err('Structure type mismatch: %s in %s', se.struct, current.struct)
+        if tagging_enabled() then
+            alloc.err('Structure type mismatch: %s in %s',
+                    pdf_name(se.struct), pdf_name(current.struct))
+        else
+            alloc.msg('Warning (minim-pdf): Structure type mismatch (%s in %s)',
+                    pdf_name(se.struct), pdf_name(current.struct))
+        end
     end
     return c or current
 end
@@ -820,6 +826,13 @@
 
 -- provide the arguments to \pdfextension startlink
 local link_types = { }
+local function make_link_attr(s)
+    local attr = { 'attr {\\csname minim:linkattr\\endcsname' }
+    if s.attr then table.insert(attr, s.attr) end
+    if s.alt or s.contents then insert_formatted(attr, '/Contents %s', pdf_string(s.alt or s.contents)) end
+    table.insert(attr, '}')
+    return attr
+end
 alloc.luadef('hyper:makelink', function()
     local s = options_scanner()
         :argument('alt'):argument('contents') -- same thing
@@ -832,18 +845,32 @@
         userf = link_types.first
     end
     local user = userf()
-    attr = { 'attr {\\csname minim:linkattr\\endcsname' }
-    if s.attr then table.insert(attr, s.attr) end
-    if s.alt or s.contents then insert_formatted(attr, '/Contents %s', pdf_string(s.alt or s.contents)) end
-    insert_formatted(attr, '} user {%s}', user)
+    local attr = make_link_attr(s)
     tex.sprint(table.concat(attr, ' '))
+    tex.sprint('user {')
+    tex.write(user)
+    tex.sprint('}\\ignorespaces')
 end)
 
+local function scan_escaped_argument(chars_to_escape)
+    local stored = { }
+    for char in string.utfvalues(chars_to_escape) do
+        stored[char] = tex.getcatcode(char)
+        tex.setcatcode(char, 12)
+    end
+    local res = token.scan_argument()
+    for char, code in pairs(stored) do
+        tex.setcatcode(char, code)
+    end
+    return res
+end
+
 function link_types.dest()
     return string.format('/Subtype/Link /A <</S/GoTo /D %s>>', pdf_string(token.scan_argument()))
 end
 function link_types.url()
-    return string.format('/Subtype/Link /A <</S/URI /URI %s>>', pdf_string(token.scan_argument()))
+    local url = scan_escaped_argument ('~#$%^&_')
+    return string.format('/Subtype/Link /A <</S/URI /URI %s>>', pdf_string(url))
 end
 
 function link_types.user() return token.scan_argument() end
@@ -855,7 +882,7 @@
 -- 
1 bookmarks (outlines)
 
 -- start with a dummy top-level bookmark
-local bookmarks = { { count = 0 } }
+local bookmarks = { { count = 0, level = 0 } }
 structure[1].bookmark = bookmarks[1]
 
 local function write_bookmarks()
@@ -870,13 +897,13 @@
         ' <</Type /Outlines /First %s 0 R /Last %s 0 R /Count %s >> ',
         bookmarks[2].outline_obj, bookmarks[1].last.outline_obj, #bookmarks - 1))
     -- write bookmark objects
-    for i=2, #bookmarks do
+    for i=2, #bookmarks do -- skip the root (i=1)
         local bm, res = bookmarks[i], { }
         insert_formatted(res, '<< /Title %s\n/Parent %s 0 R /Dest %s', pdf_string(bm.title),
             bm.parent and bm.parent.outline_obj or bookmarks[1].outline_obj, pdf_string(bm.dest))
         if bm.next then insert_formatted(res, '/Next %s 0 R', bm.next.outline_obj) end
         if bm.prev then insert_formatted(res, '/Prev %s 0 R', bm.prev.outline_obj) end
-        if bm.struct and bm.struct.objnum then
+        if bm.struct and bm.struct.objnum then -- false if no structures are written out
             insert_formatted(res, '/SE %s 0 R', bm.struct.objnum)
         end
         if bm.count > 0 then
@@ -888,37 +915,51 @@
 end
 
 function M.add_bookmark(bm)
-    local se = current_structure_element()
-    bm.parent, bm.count = false, 0
-    bm.dest = bm.dest or write_new_dest()
-    se.bookmark, bm.struct = bm, se
-    -- find and update the parent bookmarks
-    local p = se.parent
-    while p do
-        local pbm = p.bookmark
-        if pbm then
-            if not bm.parent then
-                if pbm.last then pbm.last.next = bm end
-                bm.parent, bm.prev = pbm, pbm.last
-                pbm.first, pbm.last = pbm.first or bm, bm
+    local pbm
+    if bm.level then
+        for i = #bookmarks, 1, -1 do
+            pbm = bookmarks[i]
+            if pbm.level < bm.level then
+                break
             end
-            -- update the count until the first closed bookmark
-            pbm.count = pbm.count + 1
-            p = pbm.open and pbm.parent
-        else
-            p = p.parent
         end
+    else
+        local se = current_structure_element()
+        if se.bookmark then
+            return alloc.err('Structure element %s already has a bookmark', pdf_name(se.struct))
+        end
+        se.bookmark, bm.struct = bm, se
+        -- derive parent from strucrure
+        pbm = se.parent
+        while not pbm.bookmark do
+            pbm = pbm.parent
+        end
+        pbm = pbm.bookmark
     end
+    -- initial values; links to other bookmarks
+    bm.parent, bm.count = false, 0
+    bm.dest = bm.dest or write_new_dest()
+    if pbm.last then pbm.last.next = bm end
+    bm.parent, bm.prev = pbm, pbm.last
+    pbm.first, pbm.last = pbm.first or bm, bm
+    bm.level = bm.level or (pbm.level + 1)
+    -- update the count until the first closed bookmarks
+    repeat
+        pbm.count = pbm.count + 1
+        pbm = pbm.open and pbm.parent
+    until not pbm
+    -- append to the list
     table.insert(bookmarks, bm)
 end
 
 alloc.luadef('outline', function()
-    local s = options_scanner()
+    local bm = options_scanner()
         :keyword('open', 'closed')
         :string('dest')
+        :int('level')
         :scan()
-    s.title = token.scan_string()
-    M.add_bookmark(s)
+    bm.title = token.scan_string()
+    M.add_bookmark(bm)
 end, 'protected')
 
 
@@ -987,7 +1028,7 @@
         t.name = t.file or alloc.err('No name specified for embedded file stream')
     end
     t.name = pdf_string(t.name or '(unnamed)')
-    local fs, ef = M.embed_file(t, t.global)
+    local fs, _ = M.embed_file(t, t.global)
     -- where to attach?
     if t.global then
         table.insert(attached_files, { name = t.name, objnum = fs } )

Modified: trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.tex
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.tex	2024-03-01 21:45:34 UTC (rev 70310)
+++ trunk/Master/texmf-dist/tex/luatex/minim-pdf/minim-pdf.tex	2024-03-01 21:45:43 UTC (rev 70311)
@@ -323,6 +323,84 @@
     \markelement{Lbl}{{\stopformulatagging#1}}}
 \def\tagging:ensurestopNote{\ensurestopelement{Note}}
 
+% \sectionstructure { subsection, section, chapter }
+\def\sectionstructure{%
+    \newtoks\tag:sect:resets \tag:sect:resets{}%
+    \splitcommalist\tag:sect:a}
+\def\tag:sect:a#1{\expandafter\tag:sect:b
+    \expandafter{\Uchar\uccode`#1}{#1}}
+\def\tag:sect:b#1#2{% Section section
+    \addstructuretype Sect #1\relax
+    \expandafter\newcount\csname #2nr\endcsname
+    \expandafter\edef\csname mark#2\endcsname{%
+        \noexpand\withoptions[]%
+        \expandafter\noexpand\csname #2:domark\endcsname}%
+    \expandafter\edef\csname #2:domark\endcsname[##1]{%
+        \unexpanded{\ifhmode\errhelp{You should place section markers
+            in the vertical list, before the header.}\errmessage
+            {Section marker in horizontal list}\fi}%
+        \global\advance\expandafter\noexpand
+            \csname #2nr\endcsname1
+        \noexpand\the\expandafter\noexpand
+            \csname #2:resets\endcsname
+        \startelement\noexpand\ifx=##1=\noexpand\else
+            title{##1}\noexpand\fi{#1}%
+        \nextpartag{H}\ignorespaces}%
+    \expandafter\newtoks\csname #2:resets\endcsname
+    \csname #2:resets\endcsname \tag:sect:resets
+    \etoksapp\tag:sect:resets{%
+        \noexpand\ensurestopelement{#1}%
+        \global\expandafter\noexpand\csname#2nr\endcsname0 }}
+
+% tagging the plain output routine
+\begingroup\catcode`\@=11
+\gdef\autotagplainoutput{%
+    \let \vfootnot = \tag:vfootnote
+    \begingroup
+        % these should not be expanded
+        \tag:mkrelax
+            \ifhmode \ifvmode \ifnum \ifdim \ifodd \ifeven
+            \ifcondition \unless \else \fi \next \tmp
+            \strut \strutbox \footstrut
+            \the \number \empty \folio
+            \line \leftline \rightline \centerline
+            \nointerlineskip \offinterlineskip
+            \textindent \narrower \hang \llap \rlap
+            \enspace \thinspace \hidewidth
+            \quad \qquad \enskip
+            \@sf \fo at t \footins
+        \tag:mkrelax
+        % redefine head- and footlines
+        \def\footline{\taggedfootline}%
+        \def\headline{\taggedheadline}%
+        \xdef\makeheadline{\makeheadline}%
+        \xdef\makefootline{\makefootline}%
+        \xdef\footnoterule{\markartifact{Layout}\footnoterule}
+        % redefine vfootnote
+        \def\textindent##1{\noexpand\nextpartag{}%
+            \noexpand\marknotelbl{\noexpand\textindent{##1}}%
+            \noexpand\startelement{P}}%
+        \xdef\vfootnote##1{\vfootnote{##1}}%
+        % redefine footnote
+        \let\vfootnote=\relax \let\textindent=\relax
+        \def\fi##1\@sf{\noexpand\fi\noexpand\marknoteref{##1}\@sf}
+        \xdef\footnote##1{\footnote{##1}}%
+    \endgroup}
+\endgroup
+\def\tag:mkrelax#1{\ifx\tag:mkrelax#1\tag:else
+    \let#1=\relax\expandafter\tag:mkrelax\tag:fi}
+\let\tag:else=\else \let\tag:fi=\fi
+\newtoks \taggedheadline \newtoks \taggedfootline
+\taggedheadline{\tagtoks:nonempty{Pagination /Subtype/Header}\headline}
+\taggedfootline{\tagtoks:nonempty{Pagination /Subtype/Footer}\footline}
+\def\tagtoks:nonempty#1#2{%
+    \edef\tagtoks:tmp{\the#2}%
+    \ifx\tagtoks:tmp\tagtoks:hfil
+        \the#2\else
+        \markartifact{#1}{\the#2}\fi}
+\def\tagtoks:hfil{\hfil}
+
+
 % 
1 tagging formulas
 
 % \autotagformulas
@@ -408,7 +486,7 @@
 % \hyperlink <args> ... \endlink
 %   args: alt {...} attr {...} <type>
 %   type: dest {name} | url {url} | next | prev | first | last
-\protected\def\endlink{\pdfextension endlink\stopelement{Link}\relax}
+\protected\def\endlink{\pdfextension endlink\ensurestopelement{Link}\relax}
 \protected\def\startlink{\startelement{Link}\pdfextension startlink}
 \protected\def\hyperlink{\quitvmode\startlink\hyper:makelink}
 



More information about the tex-live-commits mailing list.