From 78dec65bcccf002332aa9fe9516311d6eb8c570a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 28 Dec 2008 19:44:54 +0100 Subject: [PATCH] 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. --- CHANGES | 4 ++++ doc/markup/inline.rst | 21 ++++++++++++++++++++- sphinx/builders/latex.py | 5 +++-- sphinx/environment.py | 20 +++++++++++++++++++- sphinx/roles.py | 1 + sphinx/writers/latex.py | 9 +++++++++ 6 files changed, 56 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index efbd486e4..6298b494e 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,10 @@ New features added * 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 diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index fc5d08df3..5776c35e1 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -223,7 +223,26 @@ to labels: 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 + ```), the link caption will be the title of the given document. + Other semantic markup --------------------- diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 2301c7ac3..2bcbc0d07 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -50,7 +50,7 @@ class LaTeXBuilder(Builder): if docname not in self.docnames: raise NoUri else: - return '' + return '%' + docname def init_document_data(self): preliminary_document_data = map(list, self.config.latex_documents) @@ -123,12 +123,13 @@ class LaTeXBuilder(Builder): self.warn('%s: toctree contains ref to nonexisting file %r' % (docname, includefile)) else: - sof = addnodes.start_of_file() + sof = addnodes.start_of_file(docname=includefile) sof.children = subtree.children newnodes.append(sof) 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('') diff --git a/sphinx/environment.py b/sphinx/environment.py index cbedad472..d709d6c2d 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -42,7 +42,7 @@ from docutils.transforms import Transform from docutils.transforms.parts 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 = { @@ -1029,6 +1029,24 @@ class BuildEnvironment: if labelid: newnode['refuri'] += '#' + labelid newnode.append(innernode) + 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, ('','','')) diff --git a/sphinx/roles.py b/sphinx/roles.py index 1557085e1..70fca848c 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -235,6 +235,7 @@ specific_docroles = { 'token': xfileref_role, 'term': xfileref_role, 'option': xfileref_role, + 'doc': xfileref_role, 'menuselection': menusel_role, 'file': emph_literal_role, diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 101476f27..226c98cfc 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -238,6 +238,8 @@ class LaTeXTranslator(nodes.NodeVisitor): # ... and all others are the appendices self.body.append('\n\\appendix\n') 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): @@ -260,6 +262,8 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append('\n\\resetcurrentobjects\n') # and also, new footnotes self.footnotestack.append(self.collect_footnotes(node)) + # also add a document target + self.body.append('\\hypertarget{--doc-%s}{}' % node['docname']) def collect_footnotes(self, node): fnotes = {} @@ -932,6 +936,11 @@ class LaTeXTranslator(nodes.NodeVisitor): elif uri.startswith('#'): self.body.append('\\hyperlink{%s}{' % uri[1:]) self.context.append('}') + 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: self.body.append('\\token{')