fralau / mkdocs-macros-plugin

Create richer and more beautiful pages in MkDocs, by using variables and calls to macros in the markdown code.
https://mkdocs-macros-plugin.readthedocs.io
Other
321 stars 50 forks source link

TOC does not show headings from an included markdown file #122

Closed alanlivio closed 2 years ago

alanlivio commented 2 years ago

TOC does not show headings from an included markdown file

To reproduce, run:

mkdocs new test
cd test
cat >> mkdocs.yml  <<EOL
plugins:
  - search
  - macros
theme:
  name: material
EOL
cp docs/index.md docs/index-copy.md
echo -e "\n{% include 'index-copy.md' %}'" >> docs/index.md
mkdocs serve

You can see the missing TOC in the image:

image

fralau commented 2 years ago

Interesting study case 🤔

The bash sequence you gave doesn't run, so I had to correct it. For others who will read this: in summary the index page is using the jinja2 directive {% include index-copy.md %} to read another file which is basically a copy of itself (without any further include). The result is that the Table of Contents on the top right of the page is broken.

WHAT happened?

This is not an mkdocs-macros issue. ~I would also not consider it as an issue of mkdocs-material.~ It is connected to HTML syntax and the way the mkdocs-material themplate is building a TOC (table of contents).

It is a question of how mkdocs will define a page title (see documentation here under 'title'):

  1. A title defined in the nav configuration setting for a document.
  2. A title defined in the title meta-data key of a document.
  3. A level 1 Markdown header on the first line of the document body. Please note that Setext-style headers are not supported.
  4. The filename of a document.

Let's forget 1 and 2 for the moment, since they don't apply here, and let's concentrate on 3 and 4.

Bottomline is that, unless you do something special, mkdocs considers a level 1 header as the title of a page.

This phrase defines a level 1 header in the included file (index-copy.md):

# Welcome to MkDocs

mkdocs will render your TOC correctly as long as there is one and only one title on a markdown page. If you put more than 1 header of that level (the second instance of Welcome to Mkdocs), there are now two titles for the same page. Then what should mkdocs be expected to do? It doesn't know and is thus getting badly confused.

Correction

Now suppose you modified the statement in the included file as:

## Welcome to MkDocs2

so it's no longer a title.

What would one get on the main page, when it is served?

Table of contents

Aha! Now there is only one level 1 header, hence one title in the main page, and mkdocs is back to its sensible self.

There is an interesting side effect to that change: now the title of the second page is Index Copy!

Second page

How come? Simple: since the second page does not have a markdown title (level 1), mkdocs falls back on the file name (point 4)! This correspond to mkdocs official documentation.

So it's all explained.

Conclusion

The problem is HTML in the end (only one <h1> tag allowed in the HTML that will be produced). The material theme reacts in that way (see @squidfunk's explanation below).

You'll be safe as long as you respect this golden rule 🙇

One Title (per page) to rule them all, One Title to find them; One Title to compile them all and out to the light serve them.

I'm putting @waylan (mkdocs) in copy, for info on my philosophical musings on this very simple example, but rich in teachings.

Perhaps it might be interesting to speculate if mkdocs could ~resolve its own quandary in a more elegant way~ prevent this issue altogether, e.g. by ~ignoring the second title... or~ simply crashing with the error "More than 1 markdown level 1 heading on the same page"!

squidfunk commented 2 years ago

Note that only one h1 heading per document is a deliberate design decision of Material for MkDocs, not MkDocs. If multiple h1 are found, the table of contents is reset to the last one found. Why? Because it's not valid HTML to provide more than one h1 per document, section or article tag, and the page is rendered inside an article tag. For this reason, it's invalid HTML and this is why it is not supported.

Other themes may or may not exhibit the same behavior.

alanlivio commented 2 years ago

Thanks, both @fralau and @squidfunk. It was very rich feedback. Sorry, @fralau by the typo on 'index-copy.md'.

fralau commented 2 years ago

Thanks @squidfunk for this concise and enlightening note!

nejch commented 2 years ago

Just adding this in case someone stumbles across this in the future as I was debugging it for a colleague :) macros_info() generates its own h1 heading and will lead to the same behavior when there's another h1 heading in the file.

I'm fairly sure https://github.com/fralau/mkdocs_macros_plugin/blob/master/test/module_dir/docs/environment.md would also be affected if run with material. Not really an issue as no one will have that in production but just in case people get confused.

fralau commented 2 years ago

@nejch Thanks a lot! I turned your remark into a new issue.