Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Bugfix thumbnail text formatting #1005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

alexisthual
Copy link
Contributor

@alexisthual alexisthual commented Sep 19, 2022

Closes #1002 and #998.

Regarding the unsanitized text, I saw in gen_rst.py that:

  1. thumbnail tooltip text was sanitized but thumbnail title wasn't
  2. sanitizing function is hand-made and missed some cases

I checked thumbnail tooltips from nilearn and mne-python to add some missing cases to the sanitizing function. I think this PR, at least partially, now fixes both issues, but feel free to add more cases to the sanitizing function!

Regarding the "redundant title", @mgeier I agree with you that we can get rid of the uninformative <img /> alt description, so I did it in this PR.
However, I don't have much control over the rest of the thumbnail: the <p><a><span>...</span></a></p> is here for the sole purpose of having the thumbnail behave like an HTML link. As it's handled by sphinx I don't think I can customize its output, which is the reason why it is hidden. Eventually, the <div class="sphx-glr-thumbnail-title">...</div> is needed to display the title properly.

Comment on lines 218 to 221
# :term:`the term` --> the term
string = re.sub(r':term:`(.*)`', r'\1', string)
# :ref:`the ref` --> the ref
string = re.sub(r':ref:`(.*)`', r'\1', string)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many possible roles here, so perhaps we want something more like

Suggested change
# :term:`the term` --> the term
string = re.sub(r':term:`(.*)`', r'\1', string)
# :ref:`the ref` --> the ref
string = re.sub(r':ref:`(.*)`', r'\1', string)
# :role:`the thing` --> the thing
string = re.sub(r':[a-z]+:`([^`]+)`', r'\1', string)

Note the generalization of the :role: and also the exclusion of any backticks within the captured group -- otherwise something like this would probably be an issue because regex is greedy:

:meth:`a.B` and :meth:`a.C`

I think would collapse to something bad like:

a.b` and :meth:`a.C

As another issue, people can also do

:meth:`My method <a.B>`

but we could deal with that later/in another PR unless you're keen to work on more regex :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I think this works:

:[a-z]+:`([^`<>]+)( <[^`<>]+>)?`

On https://regex101.com/ it replaces

:meth:`MyMethod <a.B>` and :meth:`a.C`

with

MyMethod and a.C

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, that's much better :) I added it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to implement a (subset of a) docutils parser by hand. Why not use existing code? Doesn't Sphinx have some functionality like this?

As a concrete example what can go wrong when doing it manually: did you know that the role name can also be used as a suffix?
https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#interpreted-text

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed it would be good to use something built in if we can.

In the meantime I'd rather not let the perfect be the enemy of the good here. In years of looking through intersphinx refs I've seen hundreds or thousands of prefixes and no postfixes. It's not saying they don't exist, but again, perfect being the enemy of the good... I'd assume YAGNI on trying to catch every variant here if we do indeed need to start with our own parsing.

And I'm okay with merging this imperfect/manual version as-is, with a follow-up PR to improve it. This already improves on what we have I think.

Comment on lines 106 to 141
# check used and unused
if has_graphviz:
assert 'alt="API unused entries graph"' in content
if sphinx_app.config.sphinx_gallery_conf['show_api_usage']:
assert 'alt="sphinx_gallery usage graph"' in content
else:
assert 'alt="sphinx_gallery usage graph"' not in content
# check graph output
assert 'src="_images/graphviz-' in content
else:
assert 'alt="API unused entries graph"' not in content
assert 'alt="sphinx_gallery usage graph"' not in content
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These used to check that the correct images were there. Instead of deleting these lines (presumably because the alt is gone?), could you look for correct file names instead?

# *string* --> string
string = re.sub(r'\*([^\*]*)\*', r'\1', string)
# `link text <url>`_ --> link text
string = re.sub(r'`(.*) <.*>`\_', r'\1', string)
Copy link
Contributor

@larsoner larsoner Sep 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also need adjustments like

[^`<>]+

instead of the .* inside the group, similar to below

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and links can be anonymous with two trailing underscores, so maybe

Suggested change
string = re.sub(r'`(.*) <.*>`\_', r'\1', string)
string = re.sub(r'`([^`<>]+) <[^`<>]>`\_\_?', r'\1', string)

@larsoner
Copy link
Contributor

Isn't regex fun? 😆

@@ -265,7 +265,7 @@ def identify_names(script_blocks, global_variables=None, node=''):
.. only:: html

.. image:: /{thumbnail}
:alt: {title}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might have missed this but why are we removing the alt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the current alt is simply the gallery item's title, #998 suggested to remove it because redundant information will be spoken when using a screen reader 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to check the title is still read out?

@@ -21,7 +21,7 @@
.. only:: html

.. image:: /fake_dir/images/thumb/sphx_glr_test_file_thumb.png
:alt: test title
:alt:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not remove the :alt: altogether if we are not using it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, the alt is required:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#value

Practically speaking, it makes a big difference for screen readers (AFAIK, but I'm not really a user myself): with alt="", the image is ignored by screen readers, without the alt attribute, the screen reader will try to provide some information, maybe the file name of the image, which really wouldn't be very helpful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay this still seems like a regression -- the alt seems important for screen readers.

@alexisthual WDYT about keeping it, but setting the display: None for the alt in our CSS? That would remove the visual redundancy on mouseover, but keep screen readers working, right?

@mgeier
Copy link
Contributor

mgeier commented Oct 9, 2022

As it's handled by sphinx I don't think I can customize its output, which is the reason why it is hidden.

But as a Sphinx extension you can generate arbitrary HTML, right?
Or you could create the appropriate docutils nodes which are then turned into the desired HTML.
I don't understand why you use the detour via reST markup, doesn't that just make it harder?

@larsoner
Copy link
Contributor

larsoner commented Oct 9, 2022

I don't understand why you use the detour via reST markup, doesn't that just make it harder?

One reason is that I think way more people understand and can work with reST markup than can work with docutils nodes. In this sense sticking with reST is perhaps more maintainable. But if someone with docutils expertise and experience can come up with a better and still maintainable/understandable solution that would be great!

README.rst Outdated
in a proper conda environment:

```
pip install -r requirements.txt -r dev-requirements.txt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that (partially) redundant to what was mentioned above in the section "Install as a Sphinx-Gallery developer"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed this one and agree -- will push a commit to fix

@alexisthual
Copy link
Contributor Author

I gave this PR some more thoughts and effort.

It's not trivial to replace links generated by sphinx directives with manually generated links. I think sphinx deduces at build time a relative path going from the generated file with a ref directive to the reference's target, which is hard to do in _thumbnail_div() (I think I could replace relative links with absolute ones if I had a simple way of assessing the documentation's base url, but I couldn't find this in sphinx).

Moreover, I'm afraid that changing all this HTML/CSS could eventually break of lot of things (especially if we don't generate the exact same URLs). I won't have that much bandwidth to work on this in the coming weeks, and I think @mgeier wanted this to be merged soon, but I feel like we need to get this right the first time or it could have dramatic effects haha 😄

@larsoner
Copy link
Contributor

@alexisthual should we merge this as is to remove the redundancy for now at least then, or no?

@alexisthual
Copy link
Contributor Author

alexisthual commented Oct 24, 2022

So far, this PR:

  • sanitizes thumbnail titles
  • removes the alt in thumbnail images

I think it could use one last review, but otherwise it's probably good to go!

Besides, changing the HTML/CSS structure of thumbnails would be useful, but I don't have the bandwidth now to test these changes thoroughly. I'm not saying it's not doable though, and maybe someone more used to sphinx could find an elegant solution!

@mgeier
Copy link
Contributor

mgeier commented Oct 24, 2022

Thanks for the update @alexisthual!

I think @mgeier wanted this to be merged soon

I'm not in a hurry at all. I prefer a good solution to a fast solution.

I agree that the current state of this PR is a nice incremental improvement, and as far as I'm concerned there's nothing speaking against merging it (except for my comment above about the documentation: #1005 (comment)).

However, I think the generated HTML is still awkward and bloated, and most of the CSS is for working around that awkwardness.

Regarding the implementation in nbsphinx, I don't think it makes sense for me to copy the awkward HTML and fetch CSS from Sphinx Gallery with all those work-arounds.
It would make more sense for me to generate good HTML myself and then manually include much less CSS in nbsphinx (which users can still override if they want).

So if Sphinx Gallery produces nice HTML and lean CSS, I'm happy to keep compatibility in nbsphinx, but if not, I think I'll switch to a custom HTML+CSS solution that won't be compatible with SG anymore.

@mgeier
Copy link
Contributor

mgeier commented Jan 21, 2023

FYI: I'm currently working on spatialaudio/nbsphinx#706, which uses custom HTML/CSS and does not use Sphinx Gallery anymore.

CSS comparison

Sphinx Gallery:

.sphx-glr-thumbnails {
  width: 100%;
  margin: 0px 0px 20px 0px;

  /* align thumbnails on a grid */
  justify-content: space-between;
  display: grid;
  /* each grid column should be at least 160px (this will determine
  the actual number of columns) and then take as much of the
  remaining width as possible */
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 15px;
}
.sphx-glr-thumbnails .toctree-wrapper {
  /* hide empty toctree divs added to the DOM
  by sphinx even though the toctree is hidden
  (they would fill grid places with empty divs) */
  display: none;
}
.sphx-glr-thumbcontainer {
  background: transparent;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
  box-shadow: 0 0 10px var(--sg-thumb-box-shadow-color);

  /* useful to absolutely position link in div */
  position: relative;

  /* thumbnail width should include padding and borders
  and take all available space */
  box-sizing: border-box;
  width: 100%;
  padding: 10px;
  border: 1px solid transparent;

  /* align content in thumbnail */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
}
.sphx-glr-thumbcontainer p {
  position: absolute;
  top: 0;
  left: 0;
}
.sphx-glr-thumbcontainer p,
.sphx-glr-thumbcontainer p a {
  /* link should cover the whole thumbnail div */
  width: 100%;
  height: 100%;
}
.sphx-glr-thumbcontainer p a span {
  /* text within link should be masked
  (we are just interested in the href) */
  display: none;
}
.sphx-glr-thumbcontainer:hover {
  border: 1px solid;
  border-color: var(--sg-thumb-hover-border);
  cursor: pointer;
}
.sphx-glr-thumbcontainer a.internal {
  bottom: 0;
  display: block;
  left: 0;
  box-sizing: border-box;
  padding: 150px 10px 0;
  position: absolute;
  right: 0;
  top: 0;
}
/* Next one is to avoid Sphinx traditional theme to cover all the
thumbnail with its default link Background color */
.sphx-glr-thumbcontainer a.internal:hover {
  background-color: transparent;
}

.sphx-glr-thumbcontainer p {
  margin: 0 0 0.1em 0;
}
.sphx-glr-thumbcontainer .figure {
  margin: 10px;
  width: 160px;
}
.sphx-glr-thumbcontainer img {
  display: inline;
  max-height: 112px;
  max-width: 160px;
}
.sphx-glr-thumbcontainer[tooltip]:hover:after {
  background: var(--sg-tooltip-background);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  color: var(--sg-tooltip-foreground);
  content: attr(tooltip);
  padding: 10px;
  z-index: 98;
  width: 100%;
  height: 100%;
  position: absolute;
  pointer-events: none;
  top: 0;
  box-sizing: border-box;
  overflow: hidden;
  backdrop-filter: blur(3px);
}

proposed for nbsphinx in spatialaudio/nbsphinx#706:

.nbsphinx-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 10px;
    margin-top: 1em;
    margin-bottom: 1em;
}

.nbsphinx-gallery > a {
    padding: 5px;
    border: 1px dotted currentColor;
    border-radius: 2px;
    text-align: center;
}

.nbsphinx-gallery > a:hover {
    border-style: solid;
}

.nbsphinx-gallery img {
    max-width: 100%;
    max-height: 100%;
}

.nbsphinx-gallery > a > div:first-child {
    display: flex;
    align-items: start;
    justify-content: center;
    height: 120px;
    margin-bottom: 5px;
}

@larsoner
Copy link
Contributor

larsoner commented Mar 8, 2023

Sounds like alt-as-blank is the way to go here since the contents are elsewhere / redundant for screen readers. I'll fix the conflict and mark for merge when green, then cut 0.12

@larsoner larsoner enabled auto-merge (squash) March 8, 2023 18:21
@larsoner larsoner merged commit 3825d9f into sphinx-gallery:master Mar 8, 2023
@larsoner larsoner added the bug label Mar 8, 2023
StefRe added a commit to StefRe/matplotlib that referenced this pull request Mar 19, 2023
Sphinx Gallery 0.11.0 left RST formatting characters in the thumbnail
titles. This was fixed in version 0.12.2 for most cases by
github.com/sphinx-gallery/sphinx-gallery/pull/1005, which doesn't
cover default roles. So to restore the previous behavior we need
to explicitely a role.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Thumbnail title regression since 0.11.0
4 participants