mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Allow custom targets in the manpage role (#11825)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
@@ -175,6 +175,10 @@ different style:
|
||||
``:manpage:`ls(1)``` displays :manpage:`ls(1)`. Creates a hyperlink to an
|
||||
external site rendering the manpage if :confval:`manpages_url` is defined.
|
||||
|
||||
.. versionchanged:: 7.3
|
||||
Allow specifying a target with ``<>``, like hyperlinks.
|
||||
For example, ``:manpage:`blah <ls(1)>``` displays :manpage:`blah <ls(1)>`.
|
||||
|
||||
.. rst:role:: menuselection
|
||||
|
||||
Menu selections should be marked using the ``menuselection`` role. This is
|
||||
|
||||
@@ -31,7 +31,6 @@ generic_docroles = {
|
||||
'kbd': nodes.literal,
|
||||
'mailheader': addnodes.literal_emphasis,
|
||||
'makevar': addnodes.literal_strong,
|
||||
'manpage': addnodes.manpage,
|
||||
'mimetype': addnodes.literal_emphasis,
|
||||
'newsgroup': addnodes.literal_emphasis,
|
||||
'program': addnodes.literal_strong, # XXX should be an x-ref
|
||||
@@ -342,6 +341,29 @@ class Abbreviation(SphinxRole):
|
||||
return [nodes.abbreviation(self.rawtext, text, **options)], []
|
||||
|
||||
|
||||
class Manpage(ReferenceRole):
|
||||
_manpage_re = re.compile(r'^(?P<path>(?P<page>.+)[(.](?P<section>[1-9]\w*)?\)?)$')
|
||||
|
||||
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||
manpage = ws_re.sub(' ', self.target)
|
||||
if m := self._manpage_re.match(manpage):
|
||||
info = m.groupdict()
|
||||
else:
|
||||
info = {'path': manpage, 'page': manpage, 'section': ''}
|
||||
|
||||
inner: nodes.Node
|
||||
text = self.title[1:] if self.disabled else self.title
|
||||
if not self.disabled and self.config.manpages_url:
|
||||
uri = self.config.manpages_url.format(**info)
|
||||
inner = nodes.reference('', text, classes=[self.name], refuri=uri)
|
||||
else:
|
||||
inner = nodes.Text(text)
|
||||
node = addnodes.manpage(self.rawtext, '', inner,
|
||||
classes=[self.name], **info)
|
||||
|
||||
return [node], []
|
||||
|
||||
|
||||
# Sphinx provides the `code-block` directive for highlighting code blocks.
|
||||
# Docutils provides the `code` role which in theory can be used similarly by
|
||||
# defining a custom role for a given programming language:
|
||||
@@ -408,6 +430,7 @@ specific_docroles: dict[str, RoleFunction] = {
|
||||
'file': EmphasizedLiteral(),
|
||||
'samp': EmphasizedLiteral(),
|
||||
'abbr': Abbreviation(),
|
||||
'manpage': Manpage(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -397,24 +397,6 @@ class DoctreeReadEvent(SphinxTransform):
|
||||
self.app.emit('doctree-read', self.document)
|
||||
|
||||
|
||||
class ManpageLink(SphinxTransform):
|
||||
"""Find manpage section numbers and names"""
|
||||
|
||||
default_priority = 999
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
for node in self.document.findall(addnodes.manpage):
|
||||
manpage = ' '.join(str(x) for x in node.children if isinstance(x, nodes.Text))
|
||||
pattern = r'^(?P<path>(?P<page>.+)[\(\.](?P<section>[1-9]\w*)?\)?)$'
|
||||
info = {'path': manpage,
|
||||
'page': manpage,
|
||||
'section': ''}
|
||||
r = re.match(pattern, manpage)
|
||||
if r:
|
||||
info = r.groupdict()
|
||||
node.attributes.update(info)
|
||||
|
||||
|
||||
class GlossarySorter(SphinxTransform):
|
||||
"""Sort glossaries that have the ``sorted`` flag."""
|
||||
|
||||
@@ -520,7 +502,6 @@ def setup(app: Sphinx) -> dict[str, Any]:
|
||||
app.add_transform(UnreferencedFootnotesDetector)
|
||||
app.add_transform(SphinxSmartQuotes)
|
||||
app.add_transform(DoctreeReadEvent)
|
||||
app.add_transform(ManpageLink)
|
||||
app.add_transform(GlossarySorter)
|
||||
app.add_transform(ReorderConsecutiveTargetAndIndexNodes)
|
||||
|
||||
|
||||
@@ -846,13 +846,8 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
|
||||
|
||||
def visit_manpage(self, node: Element) -> None:
|
||||
self.visit_literal_emphasis(node)
|
||||
if self.manpages_url:
|
||||
node['refuri'] = self.manpages_url.format(**node.attributes)
|
||||
self.visit_reference(node)
|
||||
|
||||
def depart_manpage(self, node: Element) -> None:
|
||||
if self.manpages_url:
|
||||
self.depart_reference(node)
|
||||
self.depart_literal_emphasis(node)
|
||||
|
||||
# overwritten to add even/odd classes
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
* :manpage:`man(1)`
|
||||
* :manpage:`ls.1`
|
||||
* :manpage:`sphinx`
|
||||
* :manpage:`mailx(1) <bsd-mailx/mailx.1>`
|
||||
* :manpage:`!man(1)`
|
||||
|
||||
@@ -1492,18 +1492,25 @@ def test_html_sidebar(app, status, warning):
|
||||
assert ctx['sidebars'] == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("fname", "expect"), flat_dict({
|
||||
'index.html': [(".//em/a[@href='https://example.com/man.1']", "", True),
|
||||
(".//em/a[@href='https://example.com/ls.1']", "", True),
|
||||
(".//em/a[@href='https://example.com/sphinx.']", "", True)],
|
||||
@pytest.mark.sphinx('html', testroot='manpage_url',
|
||||
confoverrides={'manpages_url': 'https://example.com/{page}.{section}'})
|
||||
def test_html_manpage(app, cached_etree_parse):
|
||||
app.build(force_all=True)
|
||||
|
||||
}))
|
||||
@pytest.mark.sphinx('html', testroot='manpage_url', confoverrides={
|
||||
'manpages_url': 'https://example.com/{page}.{section}'})
|
||||
@pytest.mark.test_params(shared_result='test_build_html_manpage_url')
|
||||
def test_html_manpage(app, cached_etree_parse, fname, expect):
|
||||
app.build()
|
||||
check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect)
|
||||
content = (app.outdir / 'index.html').read_text(encoding='utf8')
|
||||
assert ('<em class="manpage">'
|
||||
'<a class="manpage reference external" href="https://example.com/man.1">man(1)</a>'
|
||||
'</em>') in content
|
||||
assert ('<em class="manpage">'
|
||||
'<a class="manpage reference external" href="https://example.com/ls.1">ls.1</a>'
|
||||
'</em>') in content
|
||||
assert ('<em class="manpage">'
|
||||
'<a class="manpage reference external" href="https://example.com/sphinx.">sphinx</a>'
|
||||
'</em>') in content
|
||||
assert ('<em class="manpage">'
|
||||
'<a class="manpage reference external" href="https://example.com/bsd-mailx/mailx.1">mailx(1)</a>'
|
||||
'</em>') in content
|
||||
assert '<em class="manpage">man(1)</em>' in content
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='toctree-glob',
|
||||
|
||||
Reference in New Issue
Block a user