Georg Brandl avatar Georg Brandl committed ab1f780

Due to popular demand, added a ``:doc:`` role which directly
links to another document without the need of creating a
label to which a ``:ref:`` could link to.

Comments (0)

Files changed (6)

 * Markup:
+  - Due to popular demand, added a ``:doc:`` role which directly
+    links to another document without the need of creating a
+    label to which a ``:ref:`` could link to.
   - The ``toctree`` directive now supports a ``:hidden:`` flag,
     which will prevent links from being generated in place of
     the directive -- this allows you to define your document


 Using :role:`ref` is advised over standard reStructuredText links to sections
 (like ```Section title`_``) because it works across files, when section headings
 are changed, and for all builders that support cross-references.
+Cross-referencing documents
+.. versionadded:: 0.6
+There is also a way to directly link to documents:
+.. role:: doc
+   Link to the specified document; the document name can be specified in
+   absolute or relative fashion.  For example, if the reference
+   ``:doc:`parrot``` occurs in the document ``sketches/index``, then the link
+   refers to ``sketches/parrot``.  If the reference is ``:doc:`/people``` or
+   ``:doc:`../people```, the link refers to ``people``.
+   If no explicit link text is given (like usual: ``:doc:`Monty Python members
+   </people>```), the link caption will be the title of the given document.
 Other semantic markup


         if docname not in self.docnames:
             raise NoUri
-            return ''
+            return '%' + docname
     def init_document_data(self):
         preliminary_document_data = map(list, self.config.latex_documents)
                         self.warn('%s: toctree contains ref to nonexisting file %r' %
                                   (docname, includefile))
-                        sof = addnodes.start_of_file()
+                        sof = addnodes.start_of_file(docname=includefile)
                         sof.children = subtree.children
                 toctreenode.parent.replace(toctreenode, newnodes)
             return tree
         tree = self.env.get_doctree(indexfile)
+        tree['docname'] = indexfile
         if toctree_only:
             # extract toctree nodes from the tree and put them in a fresh document
             new_tree = new_document('<latex output>')


 from import ContentsFilter
 from sphinx import addnodes
-from sphinx.util import get_matching_docs, SEP, ustrftime
+from sphinx.util import get_matching_docs, SEP, ustrftime, docname_join
 from sphinx.directives import additional_xref_types
 default_settings = {
                             if labelid:
                                 newnode['refuri'] += '#' + labelid
+                elif typ == 'doc':
+                    # directly reference to document by source name; can be absolute
+                    # or relative
+                    docname = docname_join(fromdocname, target)
+                    if docname not in self.all_docs:
+                        newnode = doctree.reporter.system_message(
+                            2, 'unknown document: %s' % docname)
+                    else:
+                        if node['refcaption']:
+                            # reference with explicit title
+                            caption = node.astext()
+                        else:
+                            caption = self.titles[docname].astext()
+                        innernode = nodes.emphasis(caption, caption)
+                        newnode = nodes.reference('', '')
+                        newnode['refuri'] = builder.get_relative_uri(
+                            fromdocname, docname)
+                        newnode.append(innernode)
                 elif typ == 'keyword':
                     # keywords are referenced by named labels
                     docname, labelid, _ = self.labels.get(target, ('','',''))
     'token': xfileref_role,
     'term': xfileref_role,
     'option': xfileref_role,
+    'doc': xfileref_role,
     'menuselection': menusel_role,
     'file': emph_literal_role,


             # ... and all others are the appendices
             self.first_document = -1
+        if 'docname' in node:
+            self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
         # "- 1" because the level is increased before the title is visited
         self.sectionlevel = self.top_sectionlevel - 1
     def depart_document(self, node):
         # and also, new footnotes
+        # also add a document target
+        self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
     def collect_footnotes(self, node):
         fnotes = {}
         elif uri.startswith('#'):
             self.body.append('\\hyperlink{%s}{' % uri[1:])
+        elif uri.startswith('%'):
+            hashindex = uri.find('#')
+            targetname = (hashindex == -1) and '--doc-' + uri[1:] or uri[hashindex+1:]
+            self.body.append('\\hyperlink{%s}{' % targetname)
+            self.context.append('}')
         elif uri.startswith('@token'):
             if self.in_production_list:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.