|
From: <mi...@us...> - 2025-03-06 08:41:14
|
Revision: 10017
http://sourceforge.net/p/docutils/code/10017
Author: milde
Date: 2025-03-06 08:41:10 +0000 (Thu, 06 Mar 2025)
Log Message:
-----------
Fix LaTeX docinfo handling of affiliation fields preceding author field.
With "use_latex_docinfo", the content of the bibliographic fields
"address", "contact", and "organization" is attached to the author name.
Reserve the first position for the author name instead of creating an
"author info" list without author if any of these fields appeares before
an "author" or "authors" field.
Modified Paths:
--------------
trunk/docutils/HISTORY.rst
trunk/docutils/docs/ref/doctree.rst
trunk/docutils/docs/ref/rst/restructuredtext.rst
trunk/docutils/docutils/writers/latex2e/__init__.py
trunk/docutils/test/test_writers/test_latex2e_parts.py
Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst 2025-03-06 08:40:49 UTC (rev 10016)
+++ trunk/docutils/HISTORY.rst 2025-03-06 08:41:10 UTC (rev 10017)
@@ -189,6 +189,8 @@
and`LaTeXTranslator.fallbacks`.
- Use <document> "title" attribute in pdfinfo.
- Encode <meta> element content in pdfinfo.
+ - Improve docinfo handling with "use_latex_docinfo".
+ - `LaTeXTranslator.pop_output_collector() now returns the popped list.
.. _reference-label: docs/user/config.html#reference-label
__ docs/user/config.html#stylesheet-latex-writers
Modified: trunk/docutils/docs/ref/doctree.rst
===================================================================
--- trunk/docutils/docs/ref/doctree.rst 2025-03-06 08:40:49 UTC (rev 10016)
+++ trunk/docutils/docs/ref/doctree.rst 2025-03-06 08:41:10 UTC (rev 10017)
@@ -611,7 +611,7 @@
Examples
--------
-In reStructuredText, "authors" is one of the registered
+In reStructuredText, the `"authors" field`_ is one of the registered
`bibliographic fields`_::
Document Title
@@ -631,10 +631,8 @@
<author>
Jane Doe
-In reStructuredText, multiple author's names are separated with
-semicolons (";") or commas (","); semicolons take precedence.
-There is currently no way to represent the author's organization,
-address, or contact in a reStructuredText "Authors" field.
+There is currently no way to represent an individual author's <organization>,
+<address>, or <contact> in a reStructuredText `"authors" field`_.
See `\<docinfo>`_ for a more complete example, including processing
context.
@@ -5221,6 +5219,7 @@
.. _auto-symbol: rst/restructuredtext.html#auto-symbol-footnotes
.. _bibliographic data:
.. _bibliographic fields: rst/restructuredtext.html#bibliographic-fields
+.. _"authors" field: rst/restructuredtext.html#authors
.. _block quote: rst/restructuredtext.html#block-quotes
.. _bullet list: rst/restructuredtext.html#bullet-lists
.. _CSS3 length units: rst/restructuredtext.html#length-units
Modified: trunk/docutils/docs/ref/rst/restructuredtext.rst
===================================================================
--- trunk/docutils/docs/ref/rst/restructuredtext.rst 2025-03-06 08:40:49 UTC (rev 10016)
+++ trunk/docutils/docs/ref/rst/restructuredtext.rst 2025-03-06 08:41:10 UTC (rev 10017)
@@ -1003,12 +1003,12 @@
=================== ================
.. compound::
- The "Authors" field may contain
+ The "_`Authors`" field may contain
* a single paragraph consisting of a list of authors, separated by
``;`` or ``,`` (``;`` is checked first, so ``Doe, Jane; Doe,
- John`` will work.) [#i18n]_
- * multiple paragraphs (one per author) or
+ John`` will work), [#i18n]_
+ * multiple paragraphs (one per author), or
* a bullet list whose elements each contain a single paragraph per author.
In some languages (e.g. Swedish), there is no singular/plural distinction
@@ -1017,6 +1017,11 @@
contains a comma, end it with a semicolon to disambiguate:
``:Författare: Doe, Jane;``.
+ There is currently no way to represent an individual author's
+ organization or contact info in a reStructuredText "Authors" field.
+ However, you may use an "Author" field followed by
+ "Organization", "Address", and/or "Contact" for each author.
+
The "Address" field is for a multi-line surface mailing address.
Newlines and whitespace will be preserved.
Modified: trunk/docutils/docutils/writers/latex2e/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/latex2e/__init__.py 2025-03-06 08:40:49 UTC (rev 10016)
+++ trunk/docutils/docutils/writers/latex2e/__init__.py 2025-03-06 08:41:10 UTC (rev 10017)
@@ -1193,6 +1193,10 @@
literal = False # literal text (block or inline)
alltt = False # inside `alltt` environment
+ # Nodes affected by "use_latex_docinfo" setting:
+ LATEX_DOCINFO_NODES = (nodes.address, nodes.author, nodes.contact,
+ nodes.date, nodes.organization)
+
def __init__(self, document, babel_class=Babel) -> None:
super().__init__(document)
# Reporter
@@ -1298,9 +1302,8 @@
# Title metadata:
self.title_labels = []
self.subtitle_labels = []
- # (if use_latex_docinfo: collects lists of
- # author/organization/contact/address lines)
- self.author_stack = []
+ # with "use_latex_docinfo", we also need
+ self.author_stack = [['']] # first item reserved for author name
self.date = []
# PDF properties:
@@ -1636,12 +1639,14 @@
self.fallbacks['DUclass'] = PreambleCmds.duclass
self.out.append('\\end{DUclass}\n')
- def push_output_collector(self, new_out) -> None:
+ def push_output_collector(self, new_out: list) -> None:
self.out_stack.append(self.out)
self.out = new_out
- def pop_output_collector(self) -> None:
+ def pop_output_collector(self) -> list:
+ old_out = self.out
self.out = self.out_stack.pop()
+ return old_out
def term_postfix(self, node):
"""
@@ -1957,9 +1962,8 @@
DeprecationWarning, stacklevel=2)
if isinstance(node, nodes.address):
self.insert_newline = True # preserve newlines
- if self.use_latex_docinfo and isinstance(
- node, (nodes.address, nodes.author, nodes.contact,
- nodes.date, nodes.organization)):
+ if self.use_latex_docinfo and isinstance(node,
+ self.LATEX_DOCINFO_NODES):
self.push_output_collector([]) # see depart_docinfo_item()
else:
label = self.language_label(node.tagname)
@@ -1973,19 +1977,21 @@
def depart_docinfo_item(self, node) -> None:
self.insert_newline = False # reset change with <address> node
- if self.use_latex_docinfo and isinstance(
- node, (nodes.address, nodes.author, nodes.contact,
- nodes.date, nodes.organization)):
- text = ''.join(self.out)
- self.pop_output_collector()
+ if self.use_latex_docinfo and isinstance(node,
+ self.LATEX_DOCINFO_NODES):
+ # Collect date and author info for use in `self.make_title()`:
+ text = ''.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.
+ if self.author_stack[-1][0]:
+ self.author_stack.append([text])
+ else:
+ self.author_stack[-1][0] = text
else:
- # Attach to the last author. If any of them precedes
- # the first author, put them in a separate "author" group
- # (in lack of better semantics).
- if isinstance(node, nodes.author) or not self.author_stack:
- self.author_stack.append([])
+ # Append affiliation/contact info to current "author info".
self.author_stack[-1].append(text)
else:
if isinstance(node, nodes.address):
@@ -2023,8 +2029,7 @@
if self.pdfinfo:
self.pdfsetup += [r'\hypersetup{'] + self.pdfinfo + ['}']
# * title (including author(s) and date if using "latex_docinfo")
- if self.title or (self.use_latex_docinfo
- and (self.author_stack or self.date)):
+ if self.title or self.date or self.author_stack != [['']]:
self.make_title() # see below
# * bibliography
if self._bibitems:
@@ -2042,11 +2047,12 @@
def make_title(self) -> None:
# Auxiliary function called by `self.depart_document()`.
#
- # Append ``\title``, ``\author``, and ``\date`` to "titledata".
- # (We need all three, even if empty, to prevent errors
- # and/or automatic display of the current date by \maketitle.)
- # Append ``\maketitle`` to "body_pre_docinfo" parts.
- #
+ # The document title is stored in the "titledata" document part.
+ # Date and author info is included with "use_latex_docinfo".
+ # However, we need the ``\title``, ``\author``, and ``\date``
+ # macros even if empty, to prevent errors and/or automatic
+ # display of the current date by ``\maketitle``.
+
# \title
title_arg = [''.join(self.title)] # ensure len == 1
if self.title:
@@ -2057,15 +2063,16 @@
] + self.subtitle_labels
self.titledata.append(r'\title{%s}' % '%\n '.join(title_arg))
# \author
- author_arg = ['\\\\\n'.join(author_entry)
- for author_entry in self.author_stack]
- self.titledata.append(r'\author{%s}' %
- ' \\and\n'.join(author_arg))
+ # author name(s) and optional affiliation and contact info
+ # cf. https://tex.stackexchange.com/a/377030/288060.
+ authors = ['\\\\\n'.join((field for field in author_entry if field))
+ for author_entry in self.author_stack]
+ self.titledata.append(r'\author{%s}' % ' \\and\n'.join(authors))
# \date
self.titledata.append(r'\date{%s}' % ', '.join(self.date))
# \maketitle
- # Must be in the document body. We add it to `body_pre_docinfo`
- # to allow templates to put `titledata` into the document preamble.
+ # Must be in the document body. Append to "body_pre_docinfo" part
+ # so templates may use the "titledata" part in the document preamble.
self.body_pre_docinfo.append('\\maketitle\n')
def append_bibliogaphy(self) -> None:
Modified: trunk/docutils/test/test_writers/test_latex2e_parts.py
===================================================================
--- trunk/docutils/test/test_writers/test_latex2e_parts.py 2025-03-06 08:40:49 UTC (rev 10016)
+++ trunk/docutils/test/test_writers/test_latex2e_parts.py 2025-03-06 08:41:10 UTC (rev 10017)
@@ -687,7 +687,6 @@
\date{}
"""
}],
-
# template
["""\
""",
@@ -694,7 +693,46 @@
{'body': '',
'requirements': '\\usepackage[T1]{fontenc}\n'
}],
+# bibliographic fields
+["""
+:contact: here@home
+:organization: Example & Cie.
+:author: Mr. Smith
+:date: yesterday
+:address: 0231 Abendglanz
+ Milky Way 23 b
+""",
+ {'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={Mr. Smith}\n}\n',
+ 'docinfo': r"""
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Contact}: & \href{mailto:here@home}{here@home} \\
+\textbf{Organization}: & Example \& Cie. \\
+\textbf{Author}: & Mr. Smith \\
+\textbf{Date}: & yesterday \\
+\textbf{Address}: & {\raggedright
+0231 Abendglanz\\
+Milky Way 23 b} \\
+\end{tabularx}
+\end{center}
+""",
+ }],
])
samples['book'] = ({'documentclass': 'book'}, [
@@ -942,7 +980,60 @@
}],
])
+samples['LaTeX docinfo'] = ({'use_latex_docinfo': True}, [
+# bibliographic fields
+["""
+:contact: here@home
+:organization: Example & Cie.
+:author: Mr. Smith
+:date: yesterday
+:address: 0231 Abendglanz
+ Milky Way 23 b
+""",
+ {'pdfsetup': DEFAULT_PARTS['pdfsetup']
+ + '\\hypersetup{\n pdfauthor={Mr. Smith}\n}\n',
+ 'titledata': r"""\title{}
+\author{Mr. Smith\\
+\href{mailto:here@home}{here@home}\\
+Example \& Cie.\\
+0231 Abendglanz\\
+Milky Way 23 b}
+\date{yesterday}
+""",
+ 'body_pre_docinfo': '\\maketitle\n',
+ }],
+# bibliographic fields
+["""
+:keywords: custom, docinfo, field
+""",
+ {'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}
+""",
+ 'docinfo': r"""
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{keywords}: &
+custom, docinfo, field
+\\
+\end{tabularx}
+\end{center}
+""",
+ }],
+])
+
+
samples['embed_stylesheet'] = ({'stylesheet_path': f'{spam},{ham}',
'embed_stylesheet': True,
'warning_stream': ''}, [
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|