-
Notifications
You must be signed in to change notification settings - Fork 41
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
Intersphinx support #86
Conversation
Disconnect original `missing-reference` event from `sphinx.ext.intersphinx` to connect our own function. When this event is triggered, we call the original `missing_reference` function and add some extra data (`data-url` and CSS classes) to the node returned by the original function. This data is later used by the transformer to render the node into HTML as we expect.
Would like to use this feature. Will this PR get merged in the near future? |
Hi, @schandrika! I wrote this PR as a POC to understand if it was possible to make the extension work like we thought. However, there is still some work to do here (tests, documentation, QA, etc) and I haven't have the time to work on it unfortunately. You can try installing the extension from this PR in your project and decide by yourself if it's usable or not (without warranty 😄). Doing that test would be good to have some feedback about it from a real documentation project. Note that both projects (original and linked via intersphinx) have to be hosted on Read the Docs for the extension to work. |
Config File is a big document to show as example in the modal.
Hi @schandrika! I pushed some changes to this PR and I updated the documentation. Would you like to install the extension from this branch and let me know if it works for you? I'd be happy to fix any issue that could appear before merging. Thanks! |
It's confusing to use the default browser's behavior when hovering a HTML tag with `title=` attribute and immediately after show the our own modal/tooltip.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great 💯
@@ -139,6 +140,57 @@ def setup_sphinx_tabs(app, config): | |||
app.disconnect(listener_id) | |||
|
|||
|
|||
def setup_intersphinx(app, config): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call this disconnect_intersphinx
or something a bit more explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm following the pattern I've been using already with setup_
as prefix for each requirement.
'path': docpath, | ||
'section': section, | ||
function getEmbedURL(project, version, doc, docpath, section, url) { | ||
if (url) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can detect there is data coming from Intersphinx, I wonder if we could note that in the embed UI? I wanted a Sphinx:
or similar as a context clue about the content when I used the PR build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea to differentiate a link that shows content from another project! We could add an extra class, e.g. intersphinx
, to differentiate these from other regular hoverxref links and do something specific in the frontend for them. I'll open an issue to work on this from the FE as an improvement. For now, I'm going to add the extra class to these nodes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized that Sphinx uses internal
and external
classes to differentiate this. We may want to rely on that directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. I just think it's useful to know where the page is coming from, so maybe just a larger feature later that adds breadcrumbs or something outside the embed frame to give more context to the document.
Co-authored-by: Eric Holscher <25510+ericholscher@users.noreply.github.com>
Co-authored-by: Eric Holscher <25510+ericholscher@users.noreply.github.com>
…nx-hoverxref into humitos/support-intersphinx
tests/examples/intersphinx/conf.py
Outdated
hoverxref_intersphinx = [ | ||
'python', | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be more natural to use readthedocs
for this test instead, since python
is not hosted on RtD at the moment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. It doesn't really affect the test here. It's just a test to check that the backend is generating the HTML tag as we expect. It doesn't really make the request or anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, the client should show a nicer error if the request returns 404 😄
TypeError: can't pickle dict_keys objects
Testing: poliastro/poliastro#1234 |
Hi @humitos, thanks a lot for this exciting feature! I was just testing this out for my project at https://grill.readthedocs.io/ and I can't find a way to make it work. The I am keen on attempting to debug what is happening, but I honestly don't know where to start :( Would somebody help me look in the right direction, please? These are the details I can provide: Where to look in my docsThe part to test the
These links point to 2 separate RTD hosted projects: https://grill-names.readthedocs.io and http://naming.readthedocs.io. Current build logI can confirm that I am building https://readthedocs.org/projects/grill/builds/13878150/ Collecting sphinx-hoverxref@ git+https://github.com/readthedocs/sphinx-hoverxref@humitos/support-intersphinx
Cloning https://github.com/readthedocs/sphinx-hoverxref (to revision humitos/support-intersphinx) to /tmp/pip-install-bvynei4w/sphinx-hoverxref_0bc00bc5ef3f4681b89f14bf61ab9dbc
Running command git clone -q https://github.com/readthedocs/sphinx-hoverxref /tmp/pip-install-bvynei4w/sphinx-hoverxref_0bc00bc5ef3f4681b89f14bf61ab9dbc
Running command git checkout -b humitos/support-intersphinx --track origin/humitos/support-intersphinx
Switched to a new branch 'humitos/support-intersphinx'
Branch 'humitos/support-intersphinx' set up to track remote branch 'humitos/support-intersphinx' from 'origin'. Worth to mention that I am using a custom Collecting sphinx@ git+https://github.com/thegrill/sphinx.git@grill-intersphinx-uniqueref-fix
Cloning https://github.com/thegrill/sphinx.git (to revision grill-intersphinx-uniqueref-fix) to /tmp/pip-install-bvynei4w/sphinx_94e8d8d8613641ecbc3064d807e1914f
Running command git clone -q https://github.com/thegrill/sphinx.git /tmp/pip-install-bvynei4w/sphinx_94e8d8d8613641ecbc3064d807e1914f
Running command git checkout -b grill-intersphinx-uniqueref-fix --track origin/grill-intersphinx-uniqueref-fix
Switched to a new branch 'grill-intersphinx-uniqueref-fix'
Branch 'grill-intersphinx-uniqueref-fix' set up to track remote branch 'grill-intersphinx-uniqueref-fix' from 'origin'. Current configurationThis is the relevant
How to debug?I noticed if I build locally, from sphinx.cmd import build
if __name__=='__main__':
import shutil
try:
shutil.rmtree(r"B:\write\code\git\grill\docs\build")
except FileNotFoundError:
pass
build.build_main([r"B:\write\code\git\grill\docs\source", r"B:\write\code\git\grill\docs\build"]) probably there's a different way :P That was a lot of text, sorry for the book! |
Use Sphinx's internals to check if the object requested belongs to one of the inventories defined by the user under ``hoverxref_interpshinx`` and add hoverxref on the node based on that.
Thanks @chrizzFTD for your feedback and test! I found some issues last week and I was able to fix them between yesterday and today. Could you do your test again using the latest commit from this branch? Note that I changed a config |
@ericholscher I was able to make the feature work as I wanted 😄 --but I had to change some parts of the |
Tested it on poliastro it works! See for example this function https://poliastro--1234.org.readthedocs.build/en/1234/autoapi/poliastro/twobody/orbit/index.html#poliastro.twobody.orbit.Orbit.from_horizons |
Hi @humitos, thanks a lot for the updates! I tested it but my builds started failing; build 13902904 last log is: Click to show logUsing default style (tooltip) for unknown typ (class). Define it in hoverxref_role_types.
Using default style (tooltip) for unknown typ (class). Define it in hoverxref_role_types.
Using default style (tooltip) for unknown typ (class). Define it in hoverxref_role_types.
Using default style (tooltip) for unknown typ (func). Define it in hoverxref_role_types.
_hoverxref attributes: {'class': 'reference external', 'href': 'https://grill-names.readthedocs.io/en/latest/names/CGAssetFile.html#grill.names.CGAssetFile', 'data-url': 'https://grill-names.readthedocs.io/en/latest/names/CGAssetFile.html#grill.names.CGAssetFile'}
Traceback (most recent call last):
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/cmd/build.py", line 280, in build_main
app.build(args.force_all, filenames)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/application.py", line 352, in build
self.builder.build_update()
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 298, in build_update
len(to_build))
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 360, in build
self.write(docnames, list(updated_docnames), method)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 534, in write
self._write_serial(sorted(docnames))
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/builders/__init__.py", line 544, in _write_serial
self.write_doc(docname, doctree)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/builders/html/__init__.py", line 597, in write_doc
self.docwriter.write(doctree, destination)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/writers/__init__.py", line 78, in write
self.translate()
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/writers/html.py", line 71, in translate
self.document.walkabout(visitor)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 227, in walkabout
if child.walkabout(visitor):
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 227, in walkabout
if child.walkabout(visitor):
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 227, in walkabout
if child.walkabout(visitor):
[Previous line repeated 2 more times]
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 219, in walkabout
visitor.dispatch_visit(self)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/util/docutils.py", line 468, in dispatch_visit
method(node)
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/sphinx/ext/inheritance_diagram.py", line 413, in html_visit_inheritance_diagram
urls[child['reftitle']] = child.get('refuri')
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 652, in __getitem__
return self.attributes[key]
KeyError: 'reftitle'
Exception occurred:
File "/home/docs/checkouts/readthedocs.org/user_builds/grill/envs/feature-usd_resources/lib/python3.7/site-packages/docutils/nodes.py", line 652, in __getitem__
return self.attributes[key]
KeyError: 'reftitle'
The full traceback has been saved in /tmp/sphinx-err-5f1wxo8y.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
A bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks! I noticed sphinx-hoverxref/hoverxref/extension.py Lines 246 to 247 in b96f217
Which made a new build from my branch successful and I can see the intersphinx links working with Is there another way to achieve the same outcome for Thanks again! |
Hey @chrizzFTD, thanks a lot for your tests! It's really useful to me. The problem with
I added it as a minor style improvement, but it's not super important. I will remove it for now because it may make more projects break (I'm removing a field that it's expected to exist) and open an issue to find a better solution. |
#86 (comment) There are other extensions that expect `reftitle` to be an attribute in the node. They are doing `node['reftitle']` without checking if it exists first. This happens in `sphinx.ext.inheritance_diagram` which is a built-in extension. So it's preferrable to not modify the node and find another way to remove the browser's tooltip later. See https://github.com/sphinx-doc/sphinx/blob/4.x/sphinx/ext/inheritance_diagram.py#L413
Thanks a lot, @humitos, I can confirm the updates on this branch work fine for me now! 😃 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 💯
@@ -56,8 +56,14 @@ | |||
'readthedocs': ('https://docs.readthedocs.io/en/stable/', None), | |||
'sphinx': ('https://www.sphinx-doc.org/en/master/', None), | |||
} | |||
hoverxref_intersphinx = True | |||
hoverxref_intersphinx_type = 'modal' | |||
hoverxref_intersphinx = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be hoverxref_intersphinx_projects
? The name currently doesn't really explain what the data type inside would be.
It seems that we're overloading it to be "enable and list of projects" -- perhaps that still works with projects
in the name, since having []
projects effectively means disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that we're overloading it to be "enable and list of projects"
Yes.
Should this be
hoverxref_intersphinx_projects
? The name currently doesn't really explain what the data type inside would be.
Hrm, yeah. I'm not super happy with the name either. However, the most correct technical name would be hoverxref_intersphinx_mappings
since it refers to the keys from the intersphinx_mappings
config --but I didn't like it 😞
Co-authored-by: Eric Holscher <25510+ericholscher@users.noreply.github.com>
Similiar to `hoverxref_types` but for each intersphinx mapping.
@chrizzFTD I merged this PR and made a new release. Please, update your requirements and configs to be updated. Thanks for all the testing and help on this! |
no worries, I'll update during the weekend, thanks a lot for this awesome feature, @humitos ! 😃 |
Just an idea of what we can do to support intersphinx in this extension. There are different things to coordinate and decide yet, but I wanted to have something working to see how it could fit.
How it works?
Intersphinx subscribes to
missing-reference
event to use different methods to try to resolve the reference. If it succeed by using one of the intersphinx configurations (fromintersphinx_mapping
config) it returns anodes.reference
. As we can't hook into the middle of that function, we disconnect the original function called onmissing-reference
event and we connect a custom one. There we call the original function and add some extra data (CSS classes anddata-url
) into the node.Small example
It populates the modal with the content of this page https://docs.readthedocs.io/en/stable/config-file/v2.html#search-ranking
ToDo
title=
HTML property?Closes #51
Reference https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
Reference https://github.com/sphinx-doc/sphinx/blob/53c1dff/sphinx/ext/intersphinx.py