Skip to content
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

👌 IMPROVE: Allow for heading anchor links in docutils #678

Merged
merged 2 commits into from
Jan 11, 2023

Conversation

chrisjsewell
Copy link
Member

This aligns the treatment of [](#target) style links for docutils with sphinx, such that they are linked to a heading slug.

The core behaviour for sphinx is not changed,
except that failed reference resolution
now emits a myst.xref_missing warning (as opposed to a std.ref one), with a clearer warning message. Also on failure, the reference is still created,
for people who wish to suppress the warning (see e.g. #677)

This is another step towards executablebooks/myst-enhancement-proposals#10

This aligns the treatment of `[](#target)` style links for docutils with sphinx,
such that they are linked to a heading slug.

The core behaviour for sphinx is not changed,
except that failed reference resolution
now emits a `myst.xref_missing` warning (as opposed to a `std.ref` one), with a clearer warning message.
Also on failure, the reference is still created,
for people who wish to suppress the warning (see e.g. #677)

This is another step towards executablebooks/myst-enhancement-proposals#10
@codecov
Copy link

codecov bot commented Jan 10, 2023

Codecov Report

Base: 89.58% // Head: 89.66% // Increases project coverage by +0.07% 🎉

Coverage data is based on head (919209b) compared to base (797af5f).
Patch coverage: 90.38% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #678      +/-   ##
==========================================
+ Coverage   89.58%   89.66%   +0.07%     
==========================================
  Files          23       23              
  Lines        2544     2573      +29     
==========================================
+ Hits         2279     2307      +28     
- Misses        265      266       +1     
Flag Coverage Δ
pytests 89.66% <90.38%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
myst_parser/config/main.py 88.42% <ø> (ø)
myst_parser/sphinx_ext/myst_refs.py 89.04% <86.95%> (-1.47%) ⬇️
myst_parser/mdit_to_docutils/base.py 92.81% <90.69%> (-0.11%) ⬇️
myst_parser/mdit_to_docutils/sphinx_.py 97.61% <100.00%> (+2.88%) ⬆️
myst_parser/warnings_.py 95.91% <100.00%> (+0.08%) ⬆️
myst_parser/parsers/docutils_.py 83.46% <0.00%> (+1.57%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@chrisjsewell
Copy link
Member Author

chrisjsewell commented Jan 10, 2023

@choldgraf @rowanc1 if you could review this asap please; it is the final commit before a new version can be released.

Hopefully you can see from the recent commits, the point of these is to facilitate moving towards an implementation for executablebooks/myst-enhancement-proposals#10; implementing the things that are not yet breaking backwards compatibility.

Obviously, that PR is essentially useless if what it stipulates can't actually be implemented, in a robust way

Copy link
Member

@choldgraf choldgraf left a comment

Choose a reason for hiding this comment

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

This looks good to me - I think the behavior you describe here is what others expect in markdown link behavior anyway. One quick question but I don't think it needs to block the PR if you want to get a release out quickly.

@@ -255,7 +255,8 @@ By default, MyST will resolve link destinations according to the following rules
3. Destinations which point to a local file path are treated as links to that file.
- The path must be relative and in [POSIX format](https://en.wikipedia.org/wiki/Path_(computing)#POSIX_and_Unix_paths) (i.e. `/` separators).
- If the path is to another source file in the project (e.g. a `.md` or `.rst` file),
then the link will be to the initial heading in that file.
then the link will be to the initial heading in that file or,
if the path is appended by a `#target`, to the heading "slug" in that file.
Copy link
Member

Choose a reason for hiding this comment

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

What happens if #target is also defined as a section label as well? E.g. if there's content like:

(target)=
## Some section

Some text

## Target

Some other text, and a ref to [](#target).

And does the behavior change at all if instead the reference was [](myfile.md#target)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Firstly, to note, this behaviour is intended to change with executablebooks/myst-enhancement-proposals#10 (to search for more things), but currently:

For both #target and myfile.md#target the ONLY targets that are searched for are myst-anchor slugs, e.g. in your example #target will NOT be found, and #some-section would be found ONLY if myst_heading_anchors=1 (or greater) is set.

Here is where these slugs are computed and stored (when a heading is encountered):

# add possible reference slug, this may be different to the standard name above,
# and does not have to be normalised, so we treat it separately
if "id" in token.attrs:

Then, for references of the form #target, these can be "immediately" resolved, at the end of the document parse:

def _render_finalise(self) -> None:
"""Finalise the render of the document."""
# attempt to replace id_link references with internal links
for refnode in findall(self.document)(nodes.reference):

For references of the form myfile.md#target, we need to wait until all documents have been parsed, and so these are resolved in a post-transform:

def resolve_myst_ref_doc(self, node: pending_xref):
"""Resolve a reference, from a markdown link, to another document,
optionally with a target id within that document.

Copy link
Member

Choose a reason for hiding this comment

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

ah ok - I thought this was implementing that part of the MEP, but if this is just a step forward in anticipation of the MEP, I think we should just merge it as-is

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought this was implementing that part of the MEP,

yeh, no because obviously that could start breaking peoples projects, so that needs to be done with great care 😅 (and ideally provide them a way to migrate)

With executablebooks/myst-enhancement-proposals#10, we would like #target to search through essentially all targets on that page (and possibly all pages); headings, figures, tables, equations, ...

  1. You need a systematic way to do this
  2. and you need to allow for a way to filter on ambiguous target names, i.e. by specifying the domain and/or object type (similar to the new inv:key:domain:type#name links)

In #613 I have kind of achieved this, but it does involve some "patching" of sphinx's code, for example they do some weird stuff with creating latex labels, which I guess does introduce a bit more potential maintenance burden.

@chrisjsewell
Copy link
Member Author

This looks good to me

thanks!

@chrisjsewell chrisjsewell merged commit 8daa00b into master Jan 11, 2023
@chrisjsewell chrisjsewell deleted the docutils-anchors branch January 11, 2023 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants