Repository: sphinx-gallery/sphinx-gallery

Issue:
ENH: remove API crossrefs from hover text
Currently if the first sentence of an example/tutorial/whatever contains an API cross-ref, the hover text can end up looking like this:

![Screenshot_2019-05-28_11-33-48](https://user-images.githubusercontent.com/1810515/58506751-989da580-813c-11e9-915d-f827ce715a82.png)

Enhancement would be to add a regex to the hover text generator that would strip out the cross-reference-generating text and leave just the class/function/method/attribute name. Ideally would be smart enough to behave the same way the cross-refs do w/r/t the presence of the leading `~`.

Comments:

Patch:
diff --git a/sphinx_gallery/backreferences.py b/sphinx_gallery/backreferences.py
index ab1b204..4c44d49 100644
--- a/sphinx_gallery/backreferences.py
+++ b/sphinx_gallery/backreferences.py
@@ -196,7 +196,7 @@ BACKREF_THUMBNAIL_TEMPLATE = THUMBNAIL_TEMPLATE + """
 
 def _thumbnail_div(target_dir, src_dir, fname, snippet, is_backref=False,
                    check=True):
-    """Generates RST to place a thumbnail in a gallery"""
+    """Generate RST to place a thumbnail in a gallery."""
     thumb, _ = _find_image_ext(
         os.path.join(target_dir, 'images', 'thumb',
                      'sphx_glr_%s_thumb.png' % fname[:-3]))
diff --git a/sphinx_gallery/gen_rst.py b/sphinx_gallery/gen_rst.py
index 0bf420a..45991d4 100644
--- a/sphinx_gallery/gen_rst.py
+++ b/sphinx_gallery/gen_rst.py
@@ -196,9 +196,31 @@ def codestr2rst(codestr, lang='python', lineno=None):
     return code_directive + indented_block
 
 
-def extract_intro_and_title(filename, docstring):
-    """ Extract the first paragraph of module-level docstring. max:95 char"""
+def _regroup(x):
+    x = x.groups()
+    return x[0] + x[1].split('.')[-1] + x[2]
+
+
+def _sanitize_rst(string):
+    """Use regex to remove at least some sphinx directives."""
+    # :class:`a.b.c <thing here>`, :ref:`abc <thing here>` --> thing here
+    p, e = r'(\s|^):[^:\s]+:`', r'`(\W|$)'
+    string = re.sub(p + r'\S+\s*<([^>`]+)>' + e, r'\1\2\3', string)
+    # :class:`~a.b.c` --> c
+    string = re.sub(p + r'~([^`]+)' + e, _regroup, string)
+    # :class:`a.b.c` --> a.b.c
+    string = re.sub(p + r'([^`]+)' + e, r'\1\2\3', string)
+
+    # ``whatever thing`` --> whatever thing
+    p = r'(\s|^)`'
+    string = re.sub(p + r'`([^`]+)`' + e, r'\1\2\3', string)
+    # `whatever thing` --> whatever thing
+    string = re.sub(p + r'([^`]+)' + e, r'\1\2\3', string)
+    return string
 
+
+def extract_intro_and_title(filename, docstring):
+    """Extract and clean the first paragraph of module-level docstring."""
     # lstrip is just in case docstring has a '\n\n' at the beginning
     paragraphs = docstring.lstrip().split('\n\n')
     # remove comments and other syntax like `.. _link:`
@@ -223,9 +245,9 @@ def extract_intro_and_title(filename, docstring):
     intro_paragraph = title if len(paragraphs) < 2 else paragraphs[1]
     # Concatenate all lines of the first paragraph and truncate at 95 chars
     intro = re.sub('\n', ' ', intro_paragraph)
+    intro = _sanitize_rst(intro)
     if len(intro) > 95:
         intro = intro[:95] + '...'
-
     return intro, title
 
 
@@ -709,7 +731,6 @@ def generate_file_rst(fname, target_dir, src_dir, gallery_conf):
             for label, content, line_number in script_blocks
         ]
 
-
     output_blocks, time_elapsed = execute_script(script_blocks,
                                                  script_vars,
                                                  gallery_conf)


Test patch:
diff --git a/sphinx_gallery/tests/test_backreferences.py b/sphinx_gallery/tests/test_backreferences.py
index 1b15dfe..f150fb2 100644
--- a/sphinx_gallery/tests/test_backreferences.py
+++ b/sphinx_gallery/tests/test_backreferences.py
@@ -8,21 +8,13 @@ from __future__ import division, absolute_import, print_function
 
 import pytest
 import sphinx_gallery.backreferences as sg
+from sphinx_gallery.gen_rst import _sanitize_rst
 
 
-def test_thumbnail_div():
-    """Test if the thumbnail div generates the correct string"""
-
-    with pytest.raises(RuntimeError, match='internal sphinx-gallery thumb'):
-        html_div = sg._thumbnail_div('fake_dir', '', 'test_file.py',
-                                     '<"test">')
-    html_div = sg._thumbnail_div('fake_dir', '', 'test_file.py',
-                                 '<"test">', check=False)
-
-    reference = r"""
+REFERENCE = r"""
 .. raw:: html
 
-    <div class="sphx-glr-thumbcontainer" tooltip="&lt;&quot;test&quot;&gt;">
+    <div class="sphx-glr-thumbcontainer" tooltip="{0}">
 
 .. only:: html
 
@@ -32,44 +24,45 @@ def test_thumbnail_div():
 
 .. raw:: html
 
-    </div>
+    </div>{1}
 """
 
-    assert html_div == reference
-
-
-def test_backref_thumbnail_div():
-    """Test if the thumbnail div generates the correct string"""
-
-    html_div = sg._thumbnail_div('fake_dir', '',
-                                 'test_file.py', 'test formating',
-                                 is_backref=True, check=False)
-
-    reference = """
-.. raw:: html
-
-    <div class="sphx-glr-thumbcontainer" tooltip="test formating">
-
-.. only:: html
-
-    .. figure:: /fake_dir/images/thumb/sphx_glr_test_file_thumb.png
-
-        :ref:`sphx_glr_fake_dir_test_file.py`
-
-.. raw:: html
 
-    </div>
+@pytest.mark.parametrize('content, tooltip, is_backref', [
+    # HTML sanitizing
+    ('<"test">', '&lt;&quot;test&quot;&gt;', False),
+    # backref support
+    ('test formating', 'test formating', True),
+    # RST sanitizing
+    ('1 :class:`~a.b`. 2 :class:`a.b` 3 :ref:`whatever <better name>`',
+     '1 b. 2 a.b 3 better name', False),
+    ('use :meth:`mne.io.Raw.plot_psd` to',
+     'use mne.io.Raw.plot_psd to', False),
+    ('`this` and ``that``; and `these things` and ``those things``',
+     'this and that; and these things and those things', False),
+])
+def test_thumbnail_div(content, tooltip, is_backref):
+    """Test if the thumbnail div generates the correct string."""
+    with pytest.raises(RuntimeError, match='internal sphinx-gallery thumb'):
+        html_div = sg._thumbnail_div('fake_dir', '', 'test_file.py',
+                                     '<"test">')
+    content = _sanitize_rst(content)
+    html_div = sg._thumbnail_div('fake_dir', '', 'test_file.py',
+                                 content, is_backref=is_backref, check=False)
+    if is_backref:
+        extra = """
 
 .. only:: not html
 
-    * :ref:`sphx_glr_fake_dir_test_file.py`
-"""
-
+    * :ref:`sphx_glr_fake_dir_test_file.py`"""
+    else:
+        extra = ''
+    reference = REFERENCE.format(tooltip, extra)
     assert html_div == reference
 
 
 def test_identify_names(unicode_sample):
-
+    """Test name identification."""
     expected = {
         'os.path.join':
             {'name': 'join', 'module': 'os.path', 'module_short': 'os.path'},
@@ -88,6 +81,7 @@ def test_identify_names(unicode_sample):
 
 
 def test_identify_names2(tmpdir):
+    """Test more name identification."""
     code_str = b"""
 '''
 Title
@@ -103,7 +97,8 @@ print(c)
 e.HelloWorld().f.g
 """
     expected = {'c': {'name': 'c', 'module': 'a.b', 'module_short': 'a.b'},
-                'e.HelloWorld': {'name': 'HelloWorld', 'module': 'd', 'module_short': 'd'}}
+                'e.HelloWorld': {'name': 'HelloWorld', 'module': 'd',
+                                 'module_short': 'd'}}
 
     fname = tmpdir.join("indentify_names.py")
     fname.write(code_str, 'wb')