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

Idea: Option to generate TOC in pages using placeholder? #39

Closed
Andre601 opened this issue Feb 7, 2021 · 14 comments
Closed

Idea: Option to generate TOC in pages using placeholder? #39

Andre601 opened this issue Feb 7, 2021 · 14 comments

Comments

@Andre601
Copy link

Andre601 commented Feb 7, 2021

Not sure if this would be either out of scope, or even impossible to implement, but how about having a way to generate a TOC inside a page, by using a specific placeholder for it?

Example

The following structure is present:

docs/
├ index.md
├ assets/
│  ├ css/ # Some CSS assets
│  │  └ ...
│  └ img/ # Some images
│     └ ...
└ posts/
   ├ index.md # Content shown below
   ├ post1.md
   ├ post2.md
   └ archive/
      └ post3.md

I now set up a .pages.yml file in assets to ignore the folder and one in posts with the following structure:

title: Posts
nav:
- My Posts: index.md
- ...

Finally, do I add the following to my index.md:

# My Posts
Below can you find a list of all posts I made so far.

## Pages
{nav} <!-- Just an example. Not sure how the placeholder should look like -->

The {nav} placeholder would now take all pages it can find in the posts directory and also go through any additional directories found there. It will however skip the file it is used in.

Once it has all pages, will it generate a list that could look like this:

# My Posts
Below can you find a list of all posts I made so far.

## Pages
- [Post1](post1.md)
- [Post2](post2.md)
- [Archived](archive)
  - [Post3](archive/post3.md)

It would take the names to display from either the nav-section in the .pages file, or from the pages themself.

Why?

This plugin is useful for when you want to have the nav updated without needing to always set it yourself, but won't obviously work for when you have a manual nav inside a specific file.

For me is that the case with a blog I have. While I no longer need to update the nav myself do I always have to update the list in the index.md of my posts directory, which is frustrating sometimes.

Having a way to automate this using a placeholder or similar would really help a lot.

I hope this is somewhat doable.

@lukasgeiter
Copy link
Owner

That's an interesting idea. However, I think it is indeed outside of the scope of this plugin. The good news is that since awesome-pages simply modifies the existing MkDocs nav structure, building a new plugin on top of it shouldn't be too hard. In fact I already put together a little prototype which seems to work quite well:

from mkdocs.plugins import BasePlugin
from mkdocs.utils import normalize_url


class InlineNavigationPlugin(BasePlugin):

    def on_nav(self, nav, config, files):
        self.nav = nav

    def on_post_page(self, output, page, config):
        if '{nav}' in output:
            children = page.parent.children if page.parent else self.nav.items
            siblings = [child for child in children if child != page]
            return output.replace('{nav}', self._format_links(siblings, page, config))

    def _format_links(self, items, page, config):
        result = '<ul>'

        for item in items:
            result += '<li>'

            if item.is_section:
                result += item.title
                result += self._format_links(item.children, page, config)
            else:
                url = normalize_url(item.url, page)
                result += f'<a href="{url}">{item.title}</a>'

            result += '</li>'

        result += '</ul>'

        return result

I won't be publishing this as a package - I've already got enough on my hands. But feel free to use the code, modify it or even publish it as a plugin yourself. Refer to the MkDocs documentation on developing plugins.

@Andre601
Copy link
Author

Andre601 commented Feb 22, 2021

Okay thanks.

What would be the easiest setup to import this using pip?
I recall pip having a git+ option to directly retrieve the data from a Git repository if I understood it correctly. But I'm not 100% sure what the required info is for everything to work.

I quickly created a github repository with some basic setup:
https://github.com/Andre601/mkdocs-pagenav-generator

@lukasgeiter
Copy link
Owner

Yeah you should be able to just install from a git repo:

pip install git+https://github.com/Andre601/mkdocs-pagenav-generator.git

@Andre601
Copy link
Author

Seems to not work.
I get the error that "pagenav-generator" isn't installed.

The setup.py should be correct as aI have a pagenav-generator = mkdocs_pagenav_generator.plugin:NavGeneratorPlugin which does exist in the repository

@lukasgeiter
Copy link
Owner

You're missing the packages argument in setup.py. For example:

packages=find_packages(exclude=['*.tests', '*.tests.*'])

@Andre601
Copy link
Author

Andre601 commented Feb 27, 2021

Still not working.
Same error: "Config value: 'plugins'. Error: The "pagenav-generator" plugin is not installed"

I did add the packages part:
https://github.com/Andre601/mkdocs-pagenav-generator/blob/main/setup.py#L23

@lukasgeiter
Copy link
Owner

Strange, I get a different error:

ModuleNotFoundError: No module named 'mkdocs_pagenav_generator'

What you're definitely still missing is an empty __init__.py file in the mkdocs_pagenav_generator folder. This marks it as a python module and should fix the error I am seeing.

@Andre601
Copy link
Author

Andre601 commented Mar 1, 2021

Still getting the same issue.
What about you?
Also, maybe your mkdocs.yml is different? Or how you download the file? I use a requirements.txt and netlify for build previews

EDIT: I'm dumb! I have a typo. pagenav-generaor instead of pagenav-generator

@Andre601
Copy link
Author

Andre601 commented Mar 1, 2021

Yes!

The system works! Thank you so much for the assistance here (And the code of course!). It works nicely.

EDIT: Added it to the mkdocs plugins page on their wiki. Of course with proper credit.
image

@Andre601
Copy link
Author

Andre601 commented Mar 1, 2021

One last question:
If I want to show a live demo of the plugin alongside the raw doc stuff, how could I exclude the entire docs folder, mkdocs.yml, requirements.txt and .github folder from any download in the setup.py?

I assume I add all the folders and files to the packages=find_packages(exclude=['*.tests', '*.tests.*']) but I'm not sure about the pattern to use here...

@lukasgeiter
Copy link
Owner

One last question:
If I want to show a live demo of the plugin alongside the raw doc stuff, how could I exclude the entire docs folder, mkdocs.yml, requirements.txt and .github folder from any download in the setup.py?

I don't know. All unnecessary files get removed from my package when I publish it to PyPI. No idea how it would work when installing from a git repo.


Another thing: The plugin does not actually depend on awesome-pages. It also works with the navigation that MkDocs produces out of the box.

@oprypin
Copy link

oprypin commented Mar 9, 2021

FYI https://github.com/oprypin/mkdocs-literate-nav is a more direct approach to this. The end result is the same: you get both an actual nav and also have it displayed as part of the page. The difference is that the approach is opposite: you write the nav as part of the page in the first place.

@Andre601
Copy link
Author

Andre601 commented Mar 9, 2021

FYI https://github.com/oprypin/mkdocs-literate-nav is a more direct approach to this. The end result is the same: you get both an actual nav and also have it displayed as part of the page. The difference is that the approach is opposite: you write the nav as part of the page in the first place.

Yeah and that's the issue.
As soon as I add a new page will I need to add it to the other page.
With this can I just add a newpage and done

@oprypin
Copy link

oprypin commented Mar 9, 2021

If you will never care about the order of those posts, and will not care about browseability of that page on GitHub, sure.

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

No branches or pull requests

3 participants