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.
This commit is contained in:
Georg Brandl 2008-12-28 19:44:54 +01:00
parent a2363c0751
commit 78dec65bcc
6 changed files with 56 additions and 4 deletions

View File

@ -17,6 +17,10 @@ New features added
* Markup: * 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, - The ``toctree`` directive now supports a ``:hidden:`` flag,
which will prevent links from being generated in place of which will prevent links from being generated in place of
the directive -- this allows you to define your document the directive -- this allows you to define your document

View File

@ -223,7 +223,26 @@ to labels:
Using :role:`ref` is advised over standard reStructuredText links to sections Using :role:`ref` is advised over standard reStructuredText links to sections
(like ```Section title`_``) because it works across files, when section headings (like ```Section title`_``) because it works across files, when section headings
are changed, and for all builders that support cross-references. 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 Other semantic markup
--------------------- ---------------------

View File

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

View File

@ -42,7 +42,7 @@ from docutils.transforms import Transform
from docutils.transforms.parts import ContentsFilter from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes 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 from sphinx.directives import additional_xref_types
default_settings = { default_settings = {
@ -1029,6 +1029,24 @@ class BuildEnvironment:
if labelid: if labelid:
newnode['refuri'] += '#' + labelid newnode['refuri'] += '#' + labelid
newnode.append(innernode) 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': elif typ == 'keyword':
# keywords are referenced by named labels # keywords are referenced by named labels
docname, labelid, _ = self.labels.get(target, ('','','')) docname, labelid, _ = self.labels.get(target, ('','',''))

View File

@ -235,6 +235,7 @@ specific_docroles = {
'token': xfileref_role, 'token': xfileref_role,
'term': xfileref_role, 'term': xfileref_role,
'option': xfileref_role, 'option': xfileref_role,
'doc': xfileref_role,
'menuselection': menusel_role, 'menuselection': menusel_role,
'file': emph_literal_role, 'file': emph_literal_role,

View File

@ -238,6 +238,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
# ... and all others are the appendices # ... and all others are the appendices
self.body.append('\n\\appendix\n') self.body.append('\n\\appendix\n')
self.first_document = -1 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 # "- 1" because the level is increased before the title is visited
self.sectionlevel = self.top_sectionlevel - 1 self.sectionlevel = self.top_sectionlevel - 1
def depart_document(self, node): def depart_document(self, node):
@ -260,6 +262,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\n\\resetcurrentobjects\n') self.body.append('\n\\resetcurrentobjects\n')
# and also, new footnotes # and also, new footnotes
self.footnotestack.append(self.collect_footnotes(node)) 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): def collect_footnotes(self, node):
fnotes = {} fnotes = {}
@ -932,6 +936,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
elif uri.startswith('#'): elif uri.startswith('#'):
self.body.append('\\hyperlink{%s}{' % uri[1:]) self.body.append('\\hyperlink{%s}{' % uri[1:])
self.context.append('}') 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'): elif uri.startswith('@token'):
if self.in_production_list: if self.in_production_list:
self.body.append('\\token{') self.body.append('\\token{')