How to add permalinks to tree nodes in Markdown nav file (mkdocs.yml)?

笑着哭i 提交于 2020-02-22 10:12:46

问题


The mkdocs.yml nav file I am working with includes a hierarchical tree of a manuals website with several categories and subcategories the content articles fall into; the tree is absolutely virtual and not based on a folder structure/website path. I am looking for a way to generate permalinks for each of the tree's nodes (categories). If that is impossible with Markdown or its extensions than perhaps html/css elements could be used.

I am very new to Markdown and mkdocs; I googled thoroughly to get a solution but failed to find one.

site_name: My Site
site_dir: docs/guides/
site_url: http://example.net/
docs_dir: 'src'
nav:
  - 'TOP LEVEL CATEGORY':
    - 'BOTTOM LEVEL CATEGORY':
         - Manual 1: 'manuals/Manual1.md'
         - Manual 2: 'manuals/Manual2.md'
    - 'BOTTOM LEVEL 2':
{...}
  - 'TOP LEVEL CATEGORY 2':
{...}

markdown_extensions:
    - smarty
    - toc:
        permalink: True
        separator: "_"
    - sane_lists
    - tables
    - meta
    - fenced_code
    - admonition
    - footnotes

The virtual hierarchical tree with expandable nodes which is built is all right, but I really need to generate permalinks for each category and subcategory, e.g. example.net/docs/guides/toplevelcat/bottomlevelcat or example.net/docs/guides/toplevelcat#bottomlevelcat it does not matter how exactly the links will be organized and whether they are generated automatically or preset manually

the link could lead to an index page with all manuals belonging to the category OR just display the root mysite.net/docs/guides/ page with the required category expanded


回答1:


This is not supported by MkDocs at this time, but may be possible with a custom theme.

In #1042, you can find an attempt at a solution which was ultimately rejected for a number of reasons. That said, you should be able to simulate something similar with a custom theme.

MkDocs does not care if the structure of the nav matches any actual file structure. So you can arrangement the nesting structure however you want. Just make sure the first child of any "section" points at an index file. Perhaps something like this:

nav:
  - 'TOP LEVEL CATEGORY':
    - 'toplevel1/index.md'
    - 'BOTTOM LEVEL CATEGORY':
         - 'bottomlevel1/index.md'
         - Manual 1: 'manuals/Manual1.md'
         - Manual 2: 'manuals/Manual2.md'
    - 'BOTTOM LEVEL 2':
         - 'bottomlevel2/index.md'

Note that each section includes a unique index file. Of course index files must be named index.md so the only way to make them unique is for each one to be in a unique subdirectory. Also notice that there is no title assigned to the index pages. Presumably, the section title will be used.

Then in your theme template you need to check for children and if the first child is an index, use that as the link for that section. Then when looping through the children, be sure to skip the index in the nested level.

Perhaps something like this:

{% if nav|length>1 %}
    <ul>
    {% for nav_item in nav %}
        {% if nav_item.children %}
            <li>{% if nav_item.children[0].is_index %}
                    <a href="{{ nav_item.children[0].url|url }}">{{ nav_item.title }}</a>
                {% else %}
                    {{ nav_item.title }}
                {% endif %}
                <ul>
                {% for nav_item in nav_item.children[1:] %}
                    <li class="{% if nav_item.active%}current{% endif %}">
                        <a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
                    </li>
                {% endfor %}
                </ul>
            </li>
        {% else %}
            <li class="{% if nav_item.active%}current{% endif %}">
                <a href="{{ nav_item.url|url }}">{{ nav_item.title }}</a>
            </li>
        {% endif %}
    {% endfor %}
    </ul>
{% endif %} 

By way of explanation, the above is simply a slightly modified version of the example in the docs. Where the section title was displayed in the original ({{ nav_item.title }}), we instead check if the first child is an index file and, if so, display a link to the index page instead. Of course, we include a fallback for those occasions where there is no index.

{% if nav_item.children[0].is_index %}
    <a href="{{ nav_item.children[0].url|url }}">{{ nav_item.title }}</a>
{% else %}
    {{ nav_item.title }}
{% endif %}

Then when stepping through the children, we want to avoid including the index file. I used {% for nav_item in nav_item.children[1:] %} in my example ([1:] slices the list to exclude the first item), but that assumes there always is an index file. Some other solutions may be better and left as a exercise for the reader. The Jinja documentation may be helpful here.

Also note that the above template only accounts for one level of nesting. A more sophisticated solution would need to be developed to handle multiple nesting levels. For example, you might want to define a Jinja macro, which each level calls recursively.

Also of note is that you don't need to develop a complete custom theme. You might want to instead override a template block of an existing theme which your own custom navigation.



来源:https://stackoverflow.com/questions/54596774/how-to-add-permalinks-to-tree-nodes-in-markdown-nav-file-mkdocs-yml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!