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

Customisable navigation #16

Open
pradyunsg opened this issue Apr 28, 2021 · 12 comments
Open

Customisable navigation #16

pradyunsg opened this issue Apr 28, 2021 · 12 comments
Labels
type: discussion Discussion of general questions, ideas, design, etc.

Comments

@pradyunsg
Copy link
Owner

pradyunsg commented Apr 28, 2021

One of the things that came up in #11 is handling navigational needs for themes that might want to do something with their toctree, beyond just presenting all of it in a single nested list.

Sphinx doesn't provide anything for this out-of-the-box. I'm wondering if this theme should just implement our flavor of sphinx-doc/sphinx#6676, with the intention of upstreaming it at some point. The use of this parse-html-and-give-python-objects would be an opt-in for the themes, but in exchange for that overhead, this theme would provide components that provide (1) good sidebar-only navigation or (2) good navbar + sidebar navigation.

/cc @choldgraf @jorisvandenbossche

@pradyunsg pradyunsg added the type: discussion Discussion of general questions, ideas, design, etc. label Apr 28, 2021
@pradyunsg
Copy link
Owner Author

My only questions here are that I notice that pydata-sphinx-theme used to do such parsing, and does not anymore. What were the reasons to move away from doing this?

@choldgraf
Copy link
Contributor

Well we still do parse the toc html directly, and then modify it, we just use beautifulsoup to do the parsing because it’s easy to work with. Did you have something else in mind? This seems like a good idea to me in my opinion (and is necessary if folks want to have a top bar navigation with a sidebar that starts at level 2)

@schettino72
Copy link

Hi guys. Glad to see this initiative. I am the author of sphinx-press-theme [1], not done a good job maintaining it so far...
Anyway, if I understand you guys correctly I face this problem of handling the TOC.
Instead of parsing HTML I build a "dict" version directly from docutils data [2].

[1] https://github.com/schettino72/sphinx_press_theme
[2] https://github.com/schettino72/sphinx_press_theme/blob/master/sphinx_press_theme/__init__.py#L11

@jpmckinney
Copy link

jpmckinney commented May 14, 2021

I've been experimenting, and I think you can get a navbar with just this:

from sphinx.environment.adapters.toctree import TocTree

def navbar_toc(app, pagename, templatename, context, doctree):
    """
    The :data:`sphinx:toctree` template variable provided by Sphinx is a callable that returns TOC entries as a bullet
    list. This function instead provides a ``navbar_toc`` template variable for the top-level TOC entries as a list of
    dicts with "link" and "title" keys.
    """

    toc = TocTree(app.env).get_toctree_for(pagename, app.builder, True, titles_only=True, maxdepth=1)

    context["navbar_toc"] = [{"link": ref["refuri"], "title": ref.astext()} for ref in toc.traverse(nodes.reference)]

Then in your template you can do:

          {%- for item in navbar_toc %}
          <a class="navbar__item navbar__link" href="{{ item.link }}">{{ item.title }}</a>
          {%- endfor %}

It'll ignore any caption. If the user puts external links in the toctree, they will appear (I figure this behavior is correct).

This avoids parsing and editing HTML.

@pradyunsg
Copy link
Owner Author

I want to preserve the captions.

I think I'm going to just add a {"caption": ...} element to the structure that @jpmckinney described above.

@jpmckinney
Copy link

😎 The captions are easy to get from toc.

Note: Only top-level caption(s) are returned by get_toctree_for. Getting all captions of all sub-trees requires rewriting Sphinx's get_toctree_for to patch the for subtocnode in toc.traverse(addnodes.toctree) loop.

@pradyunsg
Copy link
Owner Author

pradyunsg commented May 24, 2021

The captions are easy to get from toc.

What I meant by "caption" is stuff like "Development" in the sidebar of https://pradyunsg.me/furo/. Are you referring to the same thing?

@jpmckinney
Copy link

jpmckinney commented May 24, 2021

Yes. To avoid confusion, I mean the toc variable in my code snippet, which will include the top-level caption nodes (which are either docutils nodes.caption or nodes.title depending on the Sphinx version – in any case, they are in the same position within the tree of nodes). By "all captions of all sub-trees", I mean if there's a toctree with a caption on a page that is linked from the toctree of the root_doc / master_doc page, then that caption is not included in the tree of nodes.

@pradyunsg
Copy link
Owner Author

I've been playing with this today, which resulted in #25. It borrows a bit from @schettino72's post above, a bit from how Sphinx does things internally and from https://github.com/executablebooks/sphinx-external-toc as well.

I really don't like the data structure I've ended up with though, and feedback on how to improve things would be very much welcome!

@choldgraf
Copy link
Contributor

Cc @AakashGfude who was going to start looking into the basic ng theme and @damianavila who is starting to do some work on the pydata theme.

@pradyunsg
Copy link
Owner Author

So, I've been looking into this as part of working on Lutra, and I've concluded that it's actually easier to just work with the docutils nodes that Sphinx renders, within Python as part of page-context.

docutils_node_tree = TocTree(builder.env).get_toctree_for(docname, builder, collapse=True, titles_only=True)
what_sphinx_provides_as_toctree_retval = builder.render_partial(docutils_node_tree)["fragment"]

I'm leaning toward documenting this, and making it clearer how a theme author can transform this into HTML that works for their theme.

See https://github.com/pradyunsg/lutra/blob/b4b1ddd83e742885d1bfb69367d16bf3c3b03ab7/src/lutra/navigation.py for examples. It doesn't implement collapsing navigation, but that would be easy-enough with this.

@pradyunsg
Copy link
Owner Author

pradyunsg commented Jun 27, 2022

If folks are in agreement, I'm inclined to:

  1. close this issue
  2. file a follow up issue as a documentation task, to document that structure with examples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: discussion Discussion of general questions, ideas, design, etc.
Projects
None yet
Development

No branches or pull requests

4 participants