SF.net SVN: docutils:[10063 ] trunk/docutils

milde--- via Docutils-checkins <[email protected]> Sun, 30 Mar 2025 20:13:30 +0000
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 10063
          http://sourceforge.net/p/docutils/code/10063
Author:   milde
Date:     2025-03-30 20:13:30 +0000 (Sun, 30 Mar 2025)
Log Message:
-----------
LaTeX writer: Fix formatting of "authors" bibinfo field.

Collect author names from "author" fields nested in "authors".

With "--use-docutils-docinfo", use one "authors" entry instead of separate
"author" entries for the individual author names.

With "--use-latex-docinfo", print author names as one block
to ensure a common author affiliation is centered under all
author names, not just the last (cf. https://tex.stackexchange.com/a/11656/288060).

Modified Paths:
--------------
    trunk/docutils/HISTORY.rst
    trunk/docutils/docs/user/latex.rst
    trunk/docutils/docutils/writers/latex2e/__init__.py
    trunk/docutils/test/functional/expected/latex_leavevmode.tex
    trunk/docutils/test/functional/expected/latex_memoir.tex
    trunk/docutils/test/functional/expected/standalone_rst_latex.tex
    trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
    trunk/docutils/test/test_writers/test_latex2e_parts.py

Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/HISTORY.rst	2025-03-30 20:13:30 UTC (rev 10063)
@@ -189,7 +189,7 @@
     and`LaTeXTranslator.fallbacks`.
   - Use <document> "title" attribute in pdfinfo.
   - Encode <meta> element content in pdfinfo.
-  - Improve docinfo handling with "use_latex_docinfo".
+  - Improve formatting of docinfo fields.
   - `LaTeXTranslator.pop_output_collector()` now returns the popped list.
 
   .. _reference-label: docs/user/config.html#reference-label

Modified: trunk/docutils/docs/user/latex.rst
===================================================================
--- trunk/docutils/docs/user/latex.rst	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/docs/user/latex.rst	2025-03-30 20:13:30 UTC (rev 10063)
@@ -662,6 +662,32 @@
 See section Templates_ and the `TeX FAQ`_ on how to customize the
 `style of document titles`_.
 
+Example:
+  With `use-latex-docinfo`_, author information and date are typeset
+  as part of the document title instead of the `document info`_ table.
+
+  Paper by three authors, two of them from the same organisation::
+
+    Shop Sketches
+    =============
+
+    :authors: * Mr. Mousebender
+              * Mr. Arthur Wensleydale
+    :organization: Ye National Cheese Emporium
+
+    :author: Hr. Hallmackenreuther
+    :organization: Bettengeschäft
+
+  With ``--use-latex-docinfo``, authors and their affiliations are
+  typeset below the title using the standard LaTeX command ``\author``
+  with a `simple hack for the common affiliation`__. [#]_
+
+.. [#] Unfortunately, author names don't wrap if there are more
+   authors than fit on one line in one "authors" field.
+
+__ https://tex.stackexchange.com/a/11656/288060from
+
+
 .. _section structure: rst/quickref.html#section-structure
 .. _doctitle_xform: config.html#doctitle-xform
 .. _TeX FAQ: https://texfaq.org/

Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py	2025-03-30 20:13:30 UTC (rev 10063)
@@ -1728,17 +1728,24 @@
 
     def visit_author(self, node) -> None:
         self.pdfauthor.append(self.attval(node.astext()))
-        self.visit_docinfo_item(node)
+        if isinstance(node.parent, nodes.authors):
+            # ensure output is one item per <author> element (see depart…)
+            self.push_output_collector([])
+        else:
+            self.visit_docinfo_item(node)
 
     def depart_author(self, node) -> None:
-        self.depart_docinfo_item(node)
+        if isinstance(node.parent, nodes.authors):
+            author_name = self.pop_output_collector()
+            self.out.append(''.join(author_name))
+        else:
+            self.depart_docinfo_item(node)
 
     def visit_authors(self, node) -> None:
-        # not used: visit_author is called anyway for each author.
-        pass
+        self.visit_docinfo_item(node)
 
     def depart_authors(self, node) -> None:
-        pass
+        self.depart_docinfo_item(node)
 
     def visit_block_quote(self, node) -> None:
         self.duclass_open(node)
@@ -1973,16 +1980,33 @@
                 self.out.append('\n  ')
             else:
                 self.out.append(' ')
+            if isinstance(node, nodes.authors):
+                self.push_output_collector([])  # collect author names
 
     def depart_docinfo_item(self, node) -> None:
         if self.use_latex_docinfo and isinstance(node, self.TITLEDATA_NODES):
-            # Collect date and author info for use in `self.make_title()`:
-            text = ''.join(self.pop_output_collector())
+            # Prepare data for use in `self.make_title()`
+            if isinstance(node, nodes.authors):
+                # join author names with "\and" or,
+                # if there is shared author info, with "\quad"
+                # (cf. https://tex.stackexchange.com/a/11656/288060)
+                s = r' \and '
+                for nn in node.findall(include_self=False, descend=False,
+                                       siblings=True):
+                    if isinstance(nn, (nodes.author, nodes.authors)):
+                        break
+                    if isinstance(nn, (nodes.address, nodes.contact,
+                                       nodes.organization)):
+                        s = r' \quad '
+            else:
+                s = ''
+            text = s.join(self.pop_output_collector())
+
             if isinstance(node, nodes.date):
                 self.date.append(text)
-            elif isinstance(node, nodes.author):
-                # Insert author name as first item of an "author info" list.
-                # If author name already set, start a new list.
+            elif isinstance(node, (nodes.author, nodes.authors)):
+                # Insert author name(s) as first item of an "author info" list,
+                # starting a new list if author name already set:
                 if self.author_stack[-1][0]:
                     self.author_stack.append([text])
                 else:
@@ -1993,6 +2017,13 @@
         else:
             if isinstance(node, nodes.address):
                 self.out.append('}')
+            elif isinstance(node, nodes.authors):
+                author_names = self.pop_output_collector()
+                # get last "author separator" that is not in any author name
+                for sep in reversed(self.language_module.author_separators):
+                    if not any(sep in name for name in author_names):
+                        break
+                self.out.append((sep+' ').join(author_names))
             self.out.append(' \\\\\n')
 
     def visit_doctest_block(self, node) -> None:

Modified: trunk/docutils/test/functional/expected/latex_leavevmode.tex
===================================================================
--- trunk/docutils/test/functional/expected/latex_leavevmode.tex	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/test/functional/expected/latex_leavevmode.tex	2025-03-30 20:13:30 UTC (rev 10063)
@@ -162,8 +162,7 @@
 % Docinfo
 \begin{center}
 \begin{tabularx}{\DUdocinfowidth}{lX}
-\textbf{Author}: & Hänsel \\
-\textbf{Author}: & Gretel \\
+\textbf{Authors}: & Hänsel, Gretel \\
 \textbf{Address}: & {\raggedright
 123 Example Street\\
 Example, EX  Canada} \\

Modified: trunk/docutils/test/functional/expected/latex_memoir.tex
===================================================================
--- trunk/docutils/test/functional/expected/latex_memoir.tex	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/test/functional/expected/latex_memoir.tex	2025-03-30 20:13:30 UTC (rev 10063)
@@ -206,9 +206,7 @@
 Example, EX  Canada\\
 A1B 2C3\\
 \href{mailto:[email protected]}{[email protected]} \and
-Me \and
-Myself \and
-I\\
+Me \quad Myself \quad I\\
 humankind}
 \date{Now, or yesterday.  Or maybe even \emph{before} yesterday.}
 

Modified: trunk/docutils/test/functional/expected/standalone_rst_latex.tex
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_latex.tex	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/test/functional/expected/standalone_rst_latex.tex	2025-03-30 20:13:30 UTC (rev 10063)
@@ -215,9 +215,7 @@
 Example, EX  Canada\\
 A1B 2C3} \\
 \textbf{Contact}: & \href{mailto:[email protected]}{[email protected]} \\
-\textbf{Author}: & Me \\
-\textbf{Author}: & Myself \\
-\textbf{Author}: & I \\
+\textbf{Authors}: & Me, Myself, I \\
 \textbf{Organization}: & humankind \\
 \textbf{Date}: & Now, or yesterday.  Or maybe even \emph{before} yesterday. \\
 \textbf{Status}: & This is a “work in progress” \\

Modified: trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_xetex.tex	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/test/functional/expected/standalone_rst_xetex.tex	2025-03-30 20:13:30 UTC (rev 10063)
@@ -82,9 +82,7 @@
 Example, EX  Canada\\
 A1B 2C3} \\
 \textbf{Contact}: & \href{mailto:[email protected]}{[email protected]} \\
-\textbf{Author}: & Me \\
-\textbf{Author}: & Myself \\
-\textbf{Author}: & I \\
+\textbf{Authors}: & Me, Myself, I \\
 \textbf{Organization}: & humankind \\
 \textbf{Date}: & Now, or yesterday.  Or maybe even \emph{before} yesterday. \\
 \textbf{Status}: & This is a “work in progress” \\

Modified: trunk/docutils/test/test_writers/test_latex2e_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_latex2e_parts.py	2025-03-30 20:13:14 UTC (rev 10062)
+++ trunk/docutils/test/test_writers/test_latex2e_parts.py	2025-03-30 20:13:30 UTC (rev 10063)
@@ -733,6 +733,41 @@
 \end{center}
 """,
   }],
+["""
+:authors: * \\A. *Smith*
+          * \\B. Miller
+:organization: Example & Cie.
+:author: C. Baker
+:organization: Another Example
+""",
+ {'requirements': '\\usepackage[T1]{fontenc}\n'
+                  '\\usepackage{tabularx}\n',
+  'fallbacks': r"""
+% Provide a length variable and set default, if it is new
+\providecommand*{\DUprovidelength}[2]{%
+  \ifdefined#1
+  \else
+    \newlength{#1}\setlength{#1}{#2}%
+  \fi
+}
+
+% width of docinfo table
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+""",
+  'pdfsetup': DEFAULT_PARTS['pdfsetup']
+  + '\\hypersetup{\n  pdfauthor={A. Smith; B. Miller; C. Baker}\n}\n',
+  'docinfo': r"""
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Authors}: & A. \emph{Smith}, B. Miller \\
+\textbf{Organization}: & Example \& Cie. \\
+\textbf{Author}: & C. Baker \\
+\textbf{Organization}: & Another Example \\
+\end{tabularx}
+\end{center}
+""",
+  }],
 ])
 
 samples['book'] = ({'documentclass': 'book'}, [
@@ -1002,8 +1037,25 @@
 """,
   'body_pre_docinfo': '\\maketitle\n',
   }],
-# bibliographic fields
 ["""
+:authors: * \\A. *Smith*
+          * \\B. Miller
+:organization: Example & Cie.
+:author: C. Baker
+:organization: Another Example
+""",
+ {'pdfsetup': DEFAULT_PARTS['pdfsetup']
+  + '\\hypersetup{\n  pdfauthor={A. Smith; B. Miller; C. Baker}\n}\n',
+  'titledata': r"""\title{}
+\author{A. \emph{Smith} \quad B. Miller\\
+Example \& Cie. \and
+C. Baker\\
+Another Example}
+\date{}
+""",
+  'body_pre_docinfo': '\\maketitle\n',
+  }],
+["""
 :keywords: custom, docinfo, field
 """,
  {'requirements': '\\usepackage[T1]{fontenc}\n'

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



_______________________________________________
Docutils-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/docutils-checkins