Merge pull request #8599 from tk0miya/6550_html_permalinks_icon

Close #6550: html: Allow to use HTML permalink texts
This commit is contained in:
Takeshi KOMIYA 2021-01-24 14:30:06 +09:00 committed by GitHub
commit becf8f43be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 23 deletions

View File

@ -8,6 +8,8 @@ Incompatible changes
--------------------
* Update Underscore.js to 1.12.0
* #6550: html: The config variable ``html_add_permalinks`` is replaced by
:confval:`html_permalinks` and :confval:`html_permalinks_icon`
Deprecated
----------
@ -22,6 +24,8 @@ Deprecated
* ``sphinx.ext.autodoc.importer.get_module_members()``
* ``sphinx.ext.autosummary.generate._simple_info()``
* ``sphinx.ext.autosummary.generate._simple_warn()``
* ``sphinx.writers.html.HTMLTranslator.permalink_text``
* ``sphinx.writers.html5.HTML5Translator.permalink_text``
Features added
--------------
@ -37,6 +41,8 @@ Features added
* #6241: html: Allow to add JS/CSS files to the specific page when an extension
calls ``app.add_js_file()`` or ``app.add_css_file()`` on
:event:`html-page-context` event
* #6550: html: Allow to use HTML permalink texts via
:confval:`html_permalinks_icon`
* #8649: imgconverter: Skip availability check if builder supports the image
type
* #8573: napoleon: Allow to change the style of custom sections using
@ -53,7 +59,6 @@ Features added
* C++, also hyperlink operator overloads in expressions and alias declarations.
* #8247: Allow production lists to refer to tokens from other production groups
Bugs fixed
----------

View File

@ -71,6 +71,16 @@ The following is a list of deprecated interfaces.
- 5.0
- :ref:`logging-api`
* - ``sphinx.writers.html.HTMLTranslator.permalink_text``
- 3.5
- 5.0
- :confval:`html_permalinks_icon`
* - ``sphinx.writers.html5.HTML5Translator.permalink_text``
- 3.5
- 5.0
- :confval:`html_permalinks_icon`
* - The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()``
- 3.4
- 5.0

View File

@ -1133,6 +1133,23 @@ that use Sphinx's HTMLWriter class.
This can now be a string to select the actual text of the link.
Previously, only boolean values were accepted.
.. deprecated:: 3.5
This has been replaced by :confval:`html_permalinks`
.. confval:: html_permalinks
If true, Sphinx will add "permalinks" for each heading and description
environment. Default: ``True``.
.. versionadded:: 3.5
.. confval:: html_permalinks_icon
A text for permalinks for each heading and description environment. HTML
tags are allowed. Default: a paragraph sign; ````
.. versionadded:: 3.5
.. confval:: html_sidebars
Custom sidebar templates, must be a dictionary that maps document names to

View File

@ -1205,6 +1205,16 @@ def validate_html_favicon(app: Sphinx, config: Config) -> None:
config.html_favicon = None # type: ignore
def migrate_html_add_permalinks(app: Sphinx, config: Config) -> None:
"""Migrate html_add_permalinks to html_permalinks*."""
if config.html_add_permalinks:
if (isinstance(config.html_add_permalinks, bool) and
config.html_add_permalinks is False):
config.html_permalinks = False # type: ignore
else:
config.html_permalinks_icon = html.escape(config.html_add_permalinks) # type: ignore # NOQA
# for compatibility
import sphinxcontrib.serializinghtml # NOQA
@ -1235,7 +1245,9 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('html_sidebars', {}, 'html')
app.add_config_value('html_additional_pages', {}, 'html')
app.add_config_value('html_domain_indices', True, 'html', [list])
app.add_config_value('html_add_permalinks', '', 'html')
app.add_config_value('html_add_permalinks', None, 'html')
app.add_config_value('html_permalinks', True, 'html')
app.add_config_value('html_permalinks_icon', '', 'html')
app.add_config_value('html_use_index', True, 'html')
app.add_config_value('html_split_index', False, 'html')
app.add_config_value('html_copy_source', True, 'html')
@ -1267,6 +1279,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
# event handlers
app.connect('config-inited', convert_html_css_files, priority=800)
app.connect('config-inited', convert_html_js_files, priority=800)
app.connect('config-inited', migrate_html_add_permalinks, priority=800)
app.connect('config-inited', validate_html_extra_path, priority=800)
app.connect('config-inited', validate_html_static_path, priority=800)
app.connect('config-inited', validate_html_logo, priority=800)

View File

@ -22,7 +22,7 @@ from docutils.writers.html4css1 import Writer
from sphinx import addnodes
from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.locale import _, __, admonitionlabels
from sphinx.util import logging
from sphinx.util.docutils import SphinxTranslator
@ -100,11 +100,6 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
self.docnames = [self.builder.current_docname] # for singlehtml builder
self.manpages_url = self.config.manpages_url
self.protect_literal_text = 0
self.permalink_text = self.config.html_add_permalinks
# support backwards-compatible setting to a bool
if not isinstance(self.permalink_text, str):
self.permalink_text = '' if self.permalink_text else ''
self.permalink_text = self.encode(self.permalink_text)
self.secnumber_suffix = self.config.html_secnumber_suffix
self.param_separator = ''
self.optional_param_level = 0
@ -333,9 +328,10 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
append_fignumber(figtype, node['ids'][0])
def add_permalink_ref(self, node: Element, title: str) -> None:
if node['ids'] and self.permalink_text and self.builder.add_permalinks:
if node['ids'] and self.config.html_permalinks and self.builder.add_permalinks:
format = '<a class="headerlink" href="#%s" title="%s">%s</a>'
self.body.append(format % (node['ids'][0], title, self.permalink_text))
self.body.append(format % (node['ids'][0], title,
self.config.html_permalinks_icon))
def generate_targets_for_listing(self, node: Element) -> None:
"""Generate hyperlink targets for listings.
@ -410,7 +406,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def depart_title(self, node: Element) -> None:
close_tag = self.context[-1]
if (self.permalink_text and self.builder.add_permalinks and
if (self.config.html_permalinks and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']):
# add permalink anchor
if close_tag.startswith('</h'):
@ -420,7 +416,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
node.parent['ids'][0] +
'title="%s">%s' % (
_('Permalink to this headline'),
self.permalink_text))
self.config.html_permalinks_icon))
elif isinstance(node.parent, nodes.table):
self.body.append('</span>')
self.add_permalink_ref(node.parent, _('Permalink to this table'))
@ -838,3 +834,9 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
def unknown_visit(self, node: Node) -> None:
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
@property
def permalink_text(self) -> str:
warnings.warn('HTMLTranslator.permalink_text is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.config.html_permalinks_icon

View File

@ -20,7 +20,7 @@ from docutils.writers.html5_polyglot import HTMLTranslator as BaseTranslator
from sphinx import addnodes
from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.locale import _, __, admonitionlabels
from sphinx.util import logging
from sphinx.util.docutils import SphinxTranslator
@ -71,11 +71,6 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
self.docnames = [self.builder.current_docname] # for singlehtml builder
self.manpages_url = self.config.manpages_url
self.protect_literal_text = 0
self.permalink_text = self.config.html_add_permalinks
# support backwards-compatible setting to a bool
if not isinstance(self.permalink_text, str):
self.permalink_text = '' if self.permalink_text else ''
self.permalink_text = self.encode(self.permalink_text)
self.secnumber_suffix = self.config.html_secnumber_suffix
self.param_separator = ''
self.optional_param_level = 0
@ -304,9 +299,10 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
append_fignumber(figtype, node['ids'][0])
def add_permalink_ref(self, node: Element, title: str) -> None:
if node['ids'] and self.permalink_text and self.builder.add_permalinks:
if node['ids'] and self.config.html_permalinks and self.builder.add_permalinks:
format = '<a class="headerlink" href="#%s" title="%s">%s</a>'
self.body.append(format % (node['ids'][0], title, self.permalink_text))
self.body.append(format % (node['ids'][0], title,
self.config.html_permalinks_icon))
# overwritten
def visit_bullet_list(self, node: Element) -> None:
@ -361,8 +357,8 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def depart_title(self, node: Element) -> None:
close_tag = self.context[-1]
if (self.permalink_text and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']):
if (self.config.html_permalinks and self.builder.add_permalinks and
node.parent.hasattr('ids') and node.parent['ids']):
# add permalink anchor
if close_tag.startswith('</h'):
self.add_permalink_ref(node.parent, _('Permalink to this headline'))
@ -371,7 +367,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
node.parent['ids'][0] +
'title="%s">%s' % (
_('Permalink to this headline'),
self.permalink_text))
self.config.html_permalinks_icon))
elif isinstance(node.parent, nodes.table):
self.body.append('</span>')
self.add_permalink_ref(node.parent, _('Permalink to this table'))
@ -786,3 +782,9 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
def unknown_visit(self, node: Node) -> None:
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
@property
def permalink_text(self) -> str:
warnings.warn('HTMLTranslator.permalink_text is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.config.html_permalinks_icon

View File

@ -1665,3 +1665,23 @@ def test_highlight_options_old(app):
location=ANY, opts={})
assert call_args[2] == call(ANY, 'java', force=False, linenos=False,
location=ANY, opts={})
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'html_permalinks': False})
def test_html_permalink_disable(app):
app.build()
content = (app.outdir / 'index.html').read_text()
assert '<h1>The basic Sphinx documentation for testing</h1>' in content
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'html_permalinks_icon': '<span>[PERMALINK]</span>'})
def test_html_permalink_icon(app):
app.build()
content = (app.outdir / 'index.html').read_text()
assert ('<h1>The basic Sphinx documentation for testing<a class="headerlink" '
'href="#the-basic-sphinx-documentation-for-testing" '
'title="Permalink to this headline"><span>[PERMALINK]</span></a></h1>' in content)