Commits

Anonymous committed 4349898

Add global citations. #1.

  • Participants
  • Parent commits 0e334d8

Comments (0)

Files changed (10)

 New features added
 ------------------
 
+* Markup features:
+
+  - Citations are now global: all citation defined in any file can be
+    referenced from any file.  Citations are collected in a bibliography
+    for LaTeX output.
+
+  - Footnotes are now properly handled in the LaTeX builder: they appear
+    at the location of the footnote reference in text, not at the end of
+    a section.  Thanks to Andrew McNamara for the initial patch.
+
+  - "System Message" warnings are now automatically removed from the
+    built documentation, and only written to stderr.  If you want the
+    old behavior, set the new config value ``keep_warnings`` to True.
+
+  - Glossary entries are now automatically added to the index.
+
+  - Figures with captions can now be referred to like section titles,
+    using the ``:ref:`` role without an explicit link text.
+
+  - Added ``cmember`` role for consistency.
+
 * HTML output and templates:
 
   - Incompatible change: The "root" relation link (top left in the
     can be subclassed to serialize build HTML in a specific format.  The
     ``PickleHTMLBuilder`` is a concrete subclass of it that uses pickle
     as serialization implementation.
-  
+
   - ``JSONHTMLBuilder`` was added as another ``SerializingHTMLBuilder``
     subclass that dumps the generated HTML into JSON files for further
     processing.
     definition links.
 
 * New and changed config values:
-    
+
   - Added support for internationalization in generated text with the
     ``language`` and ``locale_dirs`` config values.  Many thanks to
     language contributors:
 
 * Other changes:
 
-  - Footnotes are now properly handled in the LaTeX builder: they appear
-    at the location of the footnote reference in text, not at the end of
-    a section.  Thanks to Andrew McNamara for the initial patch.
-    
-  - "System Message" warnings are now automatically removed from the
-    built documentation, and only written to stderr.  If you want the
-    old behavior, set the new config value ``keep_warnings`` to True.
-
-  - Glossary entries are now automatically added to the index.
-
-  - Figures with captions can now be referred to like section titles,
-    using the ``:ref:`` role without an explicit link text.
-
   - Added a distutils command `build_sphinx`: When Sphinx is installed,
     you can call ``python setup.py build_sphinx`` for projects that have
     Sphinx documentation, which will build the docs and place them in
   - In quickstart, if the selected root path already contains a Sphinx
     project, complain and abort.
 
-  - Added ``cmember`` role for consistency.
-
 Bugs fixed
 ----------
 

File doc/rest.rst

 Footnotes
 ---------
 
-For footnotes, use ``[#]_`` to mark the footnote location, and add the footnote
-body at the bottom of the document after a "Footnotes" rubric heading, like so::
+For footnotes, use ``[#name]_`` to mark the footnote location, and add the
+footnote body at the bottom of the document after a "Footnotes" rubric heading,
+like so::
 
-   Lorem ipsum [#]_ dolor sit amet ... [#]_
+   Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_
 
    .. rubric:: Footnotes
 
-   .. [#] Text of the first footnote.
-   .. [#] Text of the second footnote.
+   .. [#f1] Text of the first footnote.
+   .. [#f2] Text of the second footnote.
 
-You can also explicitly number the footnotes for better context.
+You can also explicitly number the footnotes (``[1]_``) or use auto-numbered
+footnotes without names (``[#]_``).
+
+
+Citations
+---------
+
+Standard reST citations are supported, with the additional feature that they are
+"global", i.e. all citations can be referenced from all files.  Use them like
+so::
+
+   Lorem ipsum [Ref]_ dolor sit amet.
+
+   .. [Ref] Book or article reference, URL or whatever.
+
+Citation usage is similar to footnote usage, but with a label that is not
+numeric or begins with ``#``.
 
 
 Comments

File sphinx/environment.py

                                                       nodes.doctest_block):
                 node.replace_self(node.children[0])
 
+class CitationReferences(Transform):
+    """
+    Handle citation references before the default docutils transform does.
+    """
+    default_priority = 619
+
+    def apply(self):
+        for citnode in self.document.traverse(nodes.citation_reference):
+            cittext = citnode.astext()
+            refnode = addnodes.pending_xref(cittext, reftype='citation',
+                                            reftarget=cittext)
+            refnode += nodes.Text('[' + cittext + ']')
+            citnode.parent.replace(citnode, refnode)
+
 
 class SphinxStandaloneReader(standalone.Reader):
     """
     Add our own transforms.
     """
-    transforms = [DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks]
+    transforms = [CitationReferences, DefaultSubstitutions, MoveModuleTargets,
+                  HandleCodeBlocks]
 
     def get_transforms(self):
         return standalone.Reader.get_transforms(self) + self.transforms
         self.labels = {}            # labelname -> docname, labelid, sectionname
         self.anonlabels = {}        # labelname -> docname, labelid
         self.reftargets = {}        # (type, name) -> docname, labelid
-                                    # where type is term, token, option, envvar
+                                    # where type is term, token, option, envvar, citation
 
         # Other inventories
         self.indexentries = {}      # docname -> list of
         self.create_title_from(docname, doctree)
         self.note_labels_from(docname, doctree)
         self.note_indexentries_from(docname, doctree)
+        self.note_citations_from(docname, doctree)
         self.build_toc_from(docname, doctree)
 
         # store time of reading, used to find outdated files
         for node in document.traverse(addnodes.index):
             entries.extend(node['entries'])
 
+    def note_citations_from(self, docname, document):
+        for node in document.traverse(nodes.citation):
+            label = node[0].astext()
+            if ('citation', label) in self.reftargets:
+                self.warn(docname, 'duplicate citation %s, ' % label +
+                          'other instance in %s' % self.doc2path(
+                    self.reftargets['citation', label][0]), node.line)
+            self.reftargets['citation', label] = (docname, node['ids'][0])
+
     def note_toctree(self, docname, toctreenode):
         """Note a TOC tree directive in a document and gather information about
            file relations from it."""
                            'meth', 'cfunc', 'cmember', 'cdata', 'ctype', 'cmacro'))
 
     def resolve_references(self, doctree, fromdocname, builder):
-        reftarget_roles = set(('token', 'term', 'option'))
+        reftarget_roles = set(('token', 'term', 'option', 'citation'))
         # add all custom xref types too
         reftarget_roles.update(i[0] for i in additional_xref_types.values())
 
                         if typ == 'term':
                             self.warn(fromdocname, 'term not in glossary: %s' % target,
                                       node.line)
+                        elif typ == 'citation':
+                            self.warn(fromdocname, 'citation not found: %s' % target,
+                                      node.line)
                         newnode = contnode
                     else:
                         newnode = nodes.reference('', '')

File sphinx/texinputs/howto.cls

   \vspace{12pt}
 }  
 
-% Fix the theindex environment to add an entry to the Table of Contents; this is
-% much nicer than just having to jump to the end of the book and flip around,
-% especially with multiple indexes.
-%
-\let\py@OldTheindex=\theindex
-\renewcommand{\theindex}{
-  \clearpage
-  \phantomsection
-  \py@OldTheindex
-  \addcontentsline{toc}{section}{\indexname}
-}
-
 \@ifundefined{fancyhf}{
   \pagestyle{plain}}{
   \pagestyle{normal}}		% start this way; change for

File sphinx/texinputs/manual.cls

 %
 \renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}
 \renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}
-
-% Fix the theindex environment to add an entry to the Table of Contents; this is
-% much nicer than just having to jump to the end of the book and flip around,
-% especially with multiple indexes.
-%
-\let\py@OldTheindex=\theindex
-\renewcommand{\theindex}{
-  \cleardoublepage
-  \phantomsection
-  \py@OldTheindex
-  \addcontentsline{toc}{chapter}{\indexname}
-}

File sphinx/texinputs/sphinx.sty

 }
 
 
+% Fix the index and bibliography environments to add an entry to the Table of
+% Contents; this is much nicer than just having to jump to the end of the book
+% and flip around, especially with multiple indexes.
+%
+\let\py@OldTheindex=\theindex
+\renewcommand{\theindex}{
+  \cleardoublepage
+  \phantomsection
+  \py@OldTheindex
+  \addcontentsline{toc}{chapter}{\indexname}
+}
+
+\let\py@OldThebibliography=\thebibliography
+\renewcommand{\thebibliography}[1]{
+  \cleardoublepage
+  \phantomsection
+  \py@OldThebibliography{1}
+  \addcontentsline{toc}{chapter}{\bibname}
+}
+
 % Include hyperref last.
 \RequirePackage[colorlinks,breaklinks,
                 linkcolor=InnerLinkColor,filecolor=OuterLinkColor,

File sphinx/textwriter.py

     def depart_footnote(self, node):
         self.end_state(first='[%s] ' % self._footnote)
 
+    def visit_citation(self, node):
+        if len(node) and isinstance(node[0], nodes.label):
+            self._citlabel = node[0].astext()
+        else:
+            self._citlabel = ''
+        self.new_state(len(self._citlabel) + 3)
+    def depart_citation(self, node):
+        self.end_state(first='[%s] ' % self._citlabel)
+
     def visit_label(self, node):
         raise nodes.SkipNode
 
         self.add_text('[%s]' % node.astext())
         raise nodes.SkipNode
 
+    def visit_citation_reference(self, node):
+        self.add_text('[%s]' % node.astext())
+        raise nodes.SkipNode
+
     def visit_Text(self, node):
         self.add_text(node.astext())
     def depart_Text(self, node):

File tests/root/contents.txt

 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
+
+References
+==========
+
+.. [Ref1] Reference target.

File tests/root/markup.txt

 
 Stuff [#]_
 
+Reference lookup: [Ref1]_ (defined in another file).
+
 .. seealso::
 
    `Google <http://www.google.com>`_

File tests/test_build.py

     'markup.html': {
         ".//meta[@name='author'][@content='Me']": '',
         ".//meta[@name='keywords'][@content='docs, sphinx']": '',
+        ".//a[@href='contents.html#ref1']": '',
     },
     'desc.html': {
         ".//dt[@id='mod.Cls.meth1']": '',
         ".//dt[@id='errmod.Error']": '',
         ".//a[@href='#mod.Cls']": '',
     },
+    'contents.html': {
+        ".//td[@class='label']": '[Ref1]',
+    },
 }
 
 class NslessParser(ET.XMLParser):