From messing around with Gutenberg for an hour or so, one of the features I'm missing (or can't seem to find documentation for) is a "breadcrumbs"-like navigation.
For example, if I have:
.
โโโ _index.md
โโโ section_a
โย ย โโโ subsection_aa
โย ย โย ย โโโ _index.md
โย ย โย ย โโโ subsection_page.md
โย ย โโโ _index.md
โย ย โโโ section_page.md
โย ย โโโ antother_page.md
โโโ section_b
โโโ _index.md
and I'm on site.com/section_a/subsection_aa/subsection_page/, I'd like to be able to create a navbar at the top like:
home > section_a > subsection_aa > subsection_page title
Or if I'm on site.com/section_a/subsection_aa/ itself, I might see:
home > section_a > subsection_aa title
It seems like {{section.components}} might get me close, but I would like to be able to fetch full data about the parent (and grandparent, etc.) so that I can get their permalink, title, and so on.
Is there a neat trick that I could do to build this, or maybe something I'm missing that would allow me to build this?
Thanks!
Taking a look at how this works under the hood a little, I think if we could add "parent" to the serialization of Section and Page somehow, we'd be closer to getting this to work.
From looking at what {{ __tera_context }} gives you, that might just give you infinite data, though...
Maybe if this hypothetical "parent" field only gave you the path of the immediate parent, and if there was a more generic get_page/get_section that worked for any URL, you could write some sort of recursive macro to build a breadcrumb navigation.
I could see the "parent" field being relatively useful for other purposes too, either way.
Sounds like a good idea to add the parent section for those cases, I'll take a PR!
Another way is to have a root field, an array of all top level sections.
Or we could provide some lineage or breadcrumbs array (of pairs of url => title) that would allow with tera built-in filters (first and last) to walk the breadcrumbs in the direction you like, or just get the parent section as requested in #350. If the array doesn't contain the current page but just the parents, it can be generated once per section (not once per page).
Does more of the parent content/metadata need to be exposed? Keeping it minimal (url/title) will be nice for memory usage but maybe there's use cases i'm not thinking of?
Does more of the parent content/metadata need to be exposed? Keeping it minimal (url/title) will be nice for memory usage but maybe there's use cases i'm not thinking of?
I'm thinking that that should be good enough -- at least for this feature. It might be nice to have additional information about the parent, but that doesn't necessarily need to happen with this issue/request.
I've thought it through a little more. Do we really need to expose the permalink? I think page/section titles would be enough, given that we can use relative URLs to go up in the folder hierarchy. Like go to parent section with <a href=".">, one section up with <a href="..">, two sections up with <a href="../.."> etc.. If some people actually need complete permalinks for some setup, this is also achievable by splitting the current page permalink with '/' and rejoining without the last part of the path.
So given an array of titles for ancestors we could just do something like:
{% set depth = page.ancestors | length %}
{% for ancestor in page.ancestors %}
<a href="{% if loop.last %}.{% else %}{% set level = depth - loop.index0 %}{{ "../" | repeat(times=level) }}{% endif %}" title="{{ ancestor }}">{{ ancestor }}</a>
{% endfor %}
โโโ Yes i know there's no repeat filter in the templates. Maybe it would be nice to have one though :)
So do you agree with me only titles are important for breadcrumbs? That is, unless some people want to expose actual Page/Section instances for the complete ancestry.
Not 100% related but what about https://github.com/Keats/gutenberg/issues/480
That would make breadcrumbs fairly easy to build
Titles are important but it needs to work across languages once i18n is in so that's another hurdle
See #484 that adds parent_section that should make breadcrumbs pretty easy to add @paulcmal
Oh yeah sorry, forgot to reply earlier. I'll check it out, sounds like it should be good though!
Having thought about it a bit, I don't think it would actually solve the issue of breadcrumbs because it would go from parent to root but breadcrumbs are displayed from root to parent and you can't append to an array in Tera. Maybe having the full list of ancestors paths would be better.
I believe to have nice breadcrumbs, pages and section need to have a list of parent sections, from root to parent. I'm not sure whether to include the index section in that list though as it will always be the first in the array. parents could be called ancestors, whatever is the clearest.
Ideally, it would look like:
<ul class="breadcrumbs">
{% for parent in page.parents %}
{% set s = get_section(path=parent, include_pages=false) %}
<li><a href="{{s.permalink}}">{{s.title}}</a></li>
{% endfor %}
</ul>
The parameter include_pages of get_section doesn't exist yet but is an easy addition to make it faster for those usecases where you only need the section metadata.
A page/section can still get the parent section by doing {{ page.parents | last }} when needed.
Any thoughts @paulcmal @crsaracco @happycoder97 ?
Sounds good. :+1:
A small suggestion.. I think get_section_metadata(path=parent) or get_section(path=parent, metadata_only=true) is better than get_section(path=parent, include_pages=false)
How is the navbar on the left in https://www.getgutenberg.io/documentation/ implemented?
I like metadata_only, I'll go with that.
How is the navbar on the left in https://www.getgutenberg.io/documentation/ implemented?
https://github.com/Keats/gutenberg/blob/master/docs/templates/documentation.html#L9-L24
It's all in the next branch
The parameter include_pages of get_section doesn't exist yet but is an easy addition to make it faster for those usecases where you only need the section metadata.
That's an elegant solution to the performance issue indeed! But what do you think about the "optimization" i proposed here? I think just having the titles would match 90% of usecases (while being lighter than having to reparse the whole sections).
Maybe the best of both world would be to have the parents as a map of titles โ paths, so one could simply loop through the titles when simply building breadcrumbs (using ../ form links), or get_section on the path when needed for advanced use-cases. What do you think?
A page/section can still get the parent section by doing {{ page.parents | last }} when needed.
Nice :)
But what do you think about the "optimization" i proposed here? I think just having the titles would match 90% of usecases (while being lighter than having to reparse the whole sections).
You never know what people might want so sending all the metadata is safer. The difference in terms of perf for sending all the metadata and only the title is pretty small.
Most helpful comment
It's all in the
nextbranch