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

Building hidden pages #699

Closed
jhamman opened this Issue Jul 27, 2015 · 50 comments

Comments

Projects
@jhamman

jhamman commented Jul 27, 2015

Is it possible to tell mkdocs to build pages but not have them show up in the side bar? If it is possible, an example of how to do this in the documentation would be great.

I asked this question here as well: https://groups.google.com/forum/#!topic/mkdocs/ILW9-SIdERs

@keelii

This comment has been minimized.

keelii commented Jul 27, 2015

I have the same question
mkdocs only build specified .md files in yml. Sometimes i use relative path to reference md file, but it not working for me .

if there is a glob pattern to set, It would be better ^!^ :

mdFiles: docs/*/*.md

@jhamman jhamman referenced this issue Jul 27, 2015

Merged

VIC website hosted on Read-the-docs #229

9 of 9 tasks complete
@waylan

This comment has been minimized.

Member

waylan commented Jul 27, 2015

No this is not possible as this time. I am not aware that it is on the road-map either, although I am not the one to make such a decision. I would suggest that if such a feature was to be implemented, it would use the page meta-data to define a page as "hidden" (perhaps by adding a hidden: true key-value pair to the meta-data for the page). Then, when building the nav, it would simply be skipped.

@jhamman

This comment has been minimized.

jhamman commented Jul 27, 2015

Thanks @waylan - Good to know.

Any thoughts on how difficult this feature would be to add? The hidden: true api is exactly what I was envisioning.

@tomchristie tomchristie referenced this issue Jul 27, 2015

Closed

Internal refactoring. #689

1 of 15 tasks complete
@robodude666

This comment has been minimized.

robodude666 commented Jul 29, 2015

I've ran across this same exact issue a few weeks ago, and adopted the same method that Docker used for their docs (they recently adopted Hugo):

  • Set the Page Title in the mkdocs.yml file to a special value (they used HIDDEN).
  • Update the Template to not include a pages with the above special value.

It feels very hacky, but it's working well enough for me right now. The docs base I'm maintaining is far smaller than Docker's so it's OK for now. I can imagine if you have a larger documentation base it might get annoying to maintain.

@waylan From trying to figure out how to get around this limitation, and reading older issues people opened on this topic it doesn't seem to be something that plans to be supported by mkdocs; and I would agree. mkdocs is intended to be used for simple documentation. Having dozens of hidden pages to be used for links only is a step above simple. Personally, I'd rather see this handled via a extension once API support is added.

@waylan

This comment has been minimized.

Member

waylan commented Jul 29, 2015

According to a recent edit to the first comment on #689 this is addressed by the work there. That said, it is not clear to me how or when that work will be merged in.

In any event, I agree that this seems more like a feature for a plugin API.

@jhamman

This comment has been minimized.

jhamman commented Jul 29, 2015

Thanks for the input @robodude666 and @waylan. I went ahead and modified the read-the-docs theme to exclude nav items == 'hidden'. That seems to be working locally and on read-the-docs.

This solution came from @martinzugnoni and works like a charm, albeit a bit hackish...

This is the original "base.html" file:
https://github.com/mkdocs/mkdocs/blob/master/mkdocs/themes/readthedocs/base.html

mkdocs.yml

# Pages not available to end users
- 'hidden': 'internal_endpoints.md'

base.html

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
        <ul class="current">
          {% for nav_item in nav %}
            {% if nav_item.title != "hidden" %}               <=== this is the important line
              <li>{% include "toc.html" %}<li>
            {% endif %}
          {% endfor %}
        </ul>
      </div>

Given that this was pretty easy to implement, and has nothing to do with the complexity of the site, I would still like to see this become part of the larger package.

@d0ugal

This comment has been minimized.

Member

d0ugal commented Jul 30, 2015

Neat, good to see that you found a work around for this. I would like to see this work with the Markdown metadata. For example, you might add "hidden: true" to the top of the file and then it will be excluded from the nav. I am not sure how #689 is looking to add this. @tomchristie?

@tomchristie

This comment has been minimized.

Contributor

tomchristie commented Jul 30, 2015

Rather than having to include them in the nav with 'hidden' it'd make more sense to just build all .md pages irrespective of if they're in 'pages' or not.

I am not sure how #689 is looking to add this

At the moment that'd build all md files, and warn if any of them are not in pages. For this behavior we'd simply want to turn that warning off.

@robodude666

This comment has been minimized.

robodude666 commented Jul 31, 2015

@tomchristie If pages is being used by a project I'd rather see mkdocs warn when a page is built but not in pages, and then add the ability to list only the filename/globs w/o a name.

For example:

pages:
- 'Introduction': 'index.md'
- 'User Guide': 'user-guide.md'
- 'About': 'about.md'
- hidden_file.md
- hidden/folder/*.md
- extension/generated/apis/*.md

This makes it explicit that these files are intended to be hidden, as no title is given to them (title can be extracted from filename/metadata in these cases).

It'll also help catch cases where the author or contributor creates a new file but forgets to update pages. This way they'll get a warning, which they can explicitly silence by adding it to the pages list.

It also makes it possible for extensions to generate pages that will be included, though albeit extensions would probably have access to modify the pages config...

@waylan

This comment has been minimized.

Member

waylan commented Aug 3, 2015

This makes it explicit that these files are intended to be hidden, as no title is given to them (title can be extracted from filename/metadata in these cases).

My preference would be to always define the Title in the meta-data and never in the config. But according to the above proposal, that would make all my pages "hidden" which is not what I want.

All "hidden" means is that the page is excluded from the nav menu. Interestingly, if no pages config is provided, all pages are auto-discovered and included in the nav menu. All the pages config gives you is a clear way to define order and nesting of the nav menu (I see the ability to define a title as a convenient side effect). It would follow quite naturally then, that any pages not listed in the pages config would then not be listed in the nav menu. As #689 gives us this already (albeit with a warning), I don't see much room for improvement.

@robodude666

This comment has been minimized.

robodude666 commented Aug 3, 2015

My preference would be to always define the Title in the meta-data and never in the config.

I would agree with you, as I don't personally like my recommendation of excluding the title; it was just a simply example to illustrate explicitly hiding pages without having to add a whole bunch of new config options. If we would rather have a boolean flag in the metadata of a page, that would be fine too.

As #689 gives us this already (albeit with a warning), I don't see much room for improvement.

The improvement I'm suggesting is to only give warnings for pages that weren't explicitly hidden. If I have 100 API docs that I'm trying to hide from the navigation I don't want to see 100 warnings when I build my docs. That will make the warnings meaningless if I'm always going to ignore them as it makes it very easy for an important warning to go unnoticed.

@waylan

This comment has been minimized.

Member

waylan commented Aug 3, 2015

I don't want to see 100 warnings when I build my docs.

Right, and as @tomchristie stated, those warnings should be able to be turned off. I assumed that that was clear and didn't restate it. Sounds like we are on the same page here.

@robodude666

This comment has been minimized.

robodude666 commented Aug 4, 2015

I'm trying to point out that they should only be turned off for specific pages, not all. If I mark 5 pages as hidden, and create a new *.md file I should get 1 warning. If that's understood then I'm okay 😄.

@dmehra

This comment has been minimized.

dmehra commented Nov 18, 2015

I found the same need to hide pages from the sidebar nav, as our docs have ~200 pages, and we don't want all of them present in the sidebar menu (if collapsible nav were available per #588, that may remove the need for hiding, or perhaps still not).

What I ended up doing (in a custom theme override of toc.html) is this, inspired by comment #699 (comment) above, but replacing the word hidden with underscores ________ so it's easy to see in my mkdocs.yml which pages are hidden, it looks like this:

pages:
- Concepts:
   - 'Overview': 'concepts/overview.md'
   - '________': 'concepts/quick_ref.md'
   - '________': 'concepts/hello_world.md'
- Modules:
  - 'String': 'modules/string.md'
  - '________': 'modules/string_intro.md'

This is the salient part of my toc.html:

  {% if nav_item.title != "________" %}
    <li class="toctree-l1 {% if nav_item.active%}current{%endif%}">
        <a class="{% if nav_item.active%}current{%endif%}" href="{{ nav_item.url }}">{{ nav_item.title }}</a>
...
    </li>
  {% endif %}
{% endif %}

The reason I prefer this approach to using markdown metadata is that I'd rather specify what is hidden or included in the same place where I'm organizing the menu layout. If it had to be in the metadata, it would be spread across individual markdown files. That would be useful if I didn't have to list out all the pages in mkdocs.yml, but that only works if pages is omitted altogether, in which case I cannot control the menu layout at all (undesired for my project with lots of files and structure).

If you'd like the underscores hack upstream in readthedocs theme, I'm happy to put up a 2-line PR (plus documentation). Perhaps by now there is a better solution for what I'm doing, if so please advise. I couldn't tell what behavior would be delivered by the referenced #689.

@jberkel

This comment has been minimized.

jberkel commented Nov 18, 2015

@dmehra a bit more flexible approach is simply to check for a title beginning with '_':

{% if not nav_item.title.startswith("_") %}
pages:
- Concepts:
   - 'Overview': 'concepts/overview.md'
   - '_QuickRef': 'concepts/quick_ref.md'

This way you can easily enable / disable headings, and you don't need to count the number of "_" used.

@robodude666

This comment has been minimized.

robodude666 commented Nov 19, 2015

@jberkel That's a great idea! Certainly less ambiguous than having a whole bunch of **HIDDEN** titles in your pages.

This got me thinking... What if mkdocs "borrows" from Python, and any *.md filenames that started with a _ or __ were "hidden" and not published in the toc (unless a flag is disabled in the yml config)?

This allows users who don't use pages and rely on mkdoc's self-discovery to maintain hidden pages, while allowing users of pages to specify pages without voodoo hacks.

@dmehra

This comment has been minimized.

dmehra commented Nov 19, 2015

I am using @jberkel title.startswith("_") successfully in my custom scheme right now. The _*.md filename based idea by @robodude666 is interesting, it would avoid having to maintain a long list of ____ Page Title XYZ entries in mkdocs.yml; however to make the pages appear/disappear in the sidebar, one would have to rename the files, as opposed to editing in a single config file. I think the top-down vs bottom-up specification comes down to a personal preference, so perhaps supporting both ways (with a config flag) is worthwhile.

@shichao-an

This comment has been minimized.

shichao-an commented Jan 14, 2016

My workaround is to hack the nav.html template by adding the following line somewhere in the very beginning:

{% set hidden_titles = ["foo", "bar"] %}

Then, the nav for loop is something like this:

...
{% for nav_item in nav %}
  {% if nav_item.title not in hidden_titles %}
...

This does not affect the naming structure of your pages and you can restore the hidden pages by removing them from the hidden_titles anytime you want.

@slackmoehrle

This comment has been minimized.

slackmoehrle commented Jan 29, 2016

+1 for the ideas. Thanks everyone. This was what I needed.

@slackmoehrle

This comment has been minimized.

slackmoehrle commented Jan 29, 2016

@waylan So I have:

- 'Editors & Tools':
      - 'Studio': 'editors_and_tools/studio.md'
      - '________': 'editors_and_tools/Workspace_Overview/en.md'

and in nav.html:

<!-- Expanded navigation -->
        <div class="navbar-collapse collapse">
            {% if include_nav %}
                <!-- Main navigation -->
                <ul class="nav navbar-nav">
                {% for nav_item in nav %}

                  {% if nav_item.title != "________" %}

                      {% if nav_item.children %}
                          <li class="dropdown{% if nav_item.active %} active{% endif %}">
                              <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ nav_item.title }} <b class="caret"></b></a>
                              <ul class="dropdown-menu">
                              {% for nav_item in nav_item.children %}
                                  {% include "nav-sub.html" %}
                              {% endfor %}
                              </ul>
                          </li>
                      {% else %}
                          <li {% if nav_item.active %}class="active"{% endif %}>
                              <a href="{{ nav_item.url }}">{{ nav_item.title }}</a>
                          </li>
                      {% endif %}

                  {% endif %}

                {% endfor %}
                </ul>
            {% endif %}

but when I deploy, I still see items with ________

I also tried: {% if not nav_item.title.startswith("_") %} too

What mistake did I make?

@shichao-an

This comment has been minimized.

shichao-an commented Jan 29, 2016

@slackmoehrle

I think nav_item.title refers to upper-level titles, e.g. 'Editors & Tools'.

________ is in nav_item.children.

You need to put the if inside {% for nav_item in nav_item.children %}

@dmehra

This comment has been minimized.

dmehra commented Jan 29, 2016

If I correctly remember (set up mkdocs a few months ago, works great!) nav.html is for the main page navigation. What you want to modify is toc.html because that controls the left pane menu. Here is mine, using if not nav_item.title.startswith("_"):

{% if nav_item.children %}
    <ul class="subnav">
    <li><span>{{ nav_item.title }}</span></li>

        {% for nav_item in nav_item.children %}
            {% include 'toc.html' %}
        {% endfor %}
    </ul>
{% else %}
  {% if not nav_item.title.startswith("_") %}
    <li class="toctree-l1 {% if nav_item.active%}current{%endif%}">
        <a class="{% if nav_item.active%}current{%endif%}" href="{{ nav_item.url }}">{{ nav_item.title }}</a>
<!-- Removed the subsection list that duplicates subsection title in most cases -->
    </li>
  {% endif %}
{% endif %}
@slackmoehrle

This comment has been minimized.

slackmoehrle commented Jan 29, 2016

@dmehra I am trying to modify both the left hand pane and the menu navigation so that pages with "________" don't appear at all, anywhere. They are just linked to in other docs.

@slackmoehrle

This comment has been minimized.

slackmoehrle commented Jan 29, 2016

@shichao-an Thank you. It works as it should. I appreciate your reply very much.

@gsouf

This comment has been minimized.

gsouf commented Mar 24, 2016

Instead of finding workaround, it there a plan to make it a native feature ?

@waylan

This comment has been minimized.

Member

waylan commented Jan 4, 2018

The code is currently in my private repo and incomplete at this time. The short answer is that before taking any action, MkDocs will walk the docs_dir and compile a list of all files. Any files in that list which are not Markdown files (based on file extension) will be copied to the site_dir. Any Markdown files (based on file extension) will be rendered as pages regardless of whether they are included in the pages config or not. The pages config will simply provide the user with a way to customize the site navigation. In fact, pages may even be renamed to nav to make that clear (with pages as an alias for at least a couple versions to provide a smooth transition). Whether the nav alias happens or not (haven't discussed or decided yet), the config would be auto-populated if not defined, so most users would not see any difference in behavior.

Of course, as any pages not listed in the config will still be rendered, but will not be linked to in the nav, they will be "hidden" pages and the user will need to provide their own links to such pages.

@brandongc

This comment has been minimized.

Contributor

brandongc commented Jan 4, 2018

Thank you for the explanation. This sounds almost identical to what I would consider ideal behavior.

Any files in that list which are not Markdown files (based on file extension) will be copied to the site_dir.

Can this clause be made optional (bold emphasis mine)?

"Hidden" pages in this case may be legitimate "raw" media files I want to link to in my documentation.

@waylan

This comment has been minimized.

Member

waylan commented Jan 4, 2018

Any files in that list which are not Markdown files (based on file extension) will be copied to the site_dir.

Can this clause be made optional (bold emphasis mine)?

No, that would require a new config setting (exclude_pages?), which we are not interested in adding. If you want to add something like that, that should be done via a Plugin. I suppose a generic "exclude pages" plugin may even make for a useful third-party plugin, although I expect a "draft" plugin would be more popular (where the meta data of a page may define a page's publish/draft status). In fact, if we were going to implement anything of the sort, I'd be inclined to do the later. However, as this time, I'm leaving both to be addressed by third party plugins. If such a plugin becomes wildly popular, then we will reconsider.

@majkinetor

This comment has been minimized.

majkinetor commented Jan 16, 2018

This is highly needed - its typical to have pages that should be accessed only by knowing the link (for instance application help for administrators) and hidden from the navbar so that regular users can't see them for both overloading and security reasons.

@froschdesign

This comment has been minimized.

froschdesign commented Jan 17, 2018

@majkinetor

…and security reasons.

If you hide something, that's no security!

@majkinetor

This comment has been minimized.

majkinetor commented Jan 17, 2018

That depends on the context. Hidding is often enough - can u guess my secret gist link?

@majkinetor

This comment has been minimized.

majkinetor commented Jan 17, 2018

Besides, you can configure web server to ask for auth on specific pages/dirs.

But you need to have files, hence the request.

@gsouf

This comment has been minimized.

gsouf commented Jan 17, 2018

Not sure that's the subject of the ticket

@waylan

This comment has been minimized.

Member

waylan commented Jan 17, 2018

Ok, let's keep the conversation on topic please. As it stands, this feature is definitely going to be added and more "me too" comments will only add to the noise. As stated in a previous comment, it is a work in progress. We are volunteers working on this in our spare time and more noise here doesn't give us more spare time.

weierophinney added a commit to weierophinney/zf-mkdoc-theme that referenced this issue Jan 17, 2018

Allow "hidden" pages
This is a hack learned from the mkdocs issue tracker:

- mkdocs/mkdocs#699 (comment)

Essentially, with this in place, if a page _title_ begins with `_`, it
will not be included in the navigation.

Additionally, this patch goes a step further, and the rendered markdown
of such pages is injected only into the `<head>` section of the built
document, with no other content. This allows for a very quick redirect,
with no content present to index.

This is useful when you want to preserve link continuity. The old page
can continue to exist, but no pages on the site will reference it, which
means that search engines will eventually stop crawling it.

The stated recommendation in the README is to replace the contents of
that page with JS and/or a meta refresh in order to force a redirect
once loaded; most search engines will notice these and honor them,
removing the page from their search results.

froschdesign added a commit to froschdesign/zf-mkdoc-theme that referenced this issue Jan 27, 2018

Allow "hidden" pages
This is a hack learned from the mkdocs issue tracker:

- mkdocs/mkdocs#699 (comment)

Essentially, with this in place, if a page _title_ begins with `_`, it
will not be included in the navigation.

Additionally, this patch goes a step further, and the rendered markdown
of such pages is injected only into the `<head>` section of the built
document, with no other content. This allows for a very quick redirect,
with no content present to index.

This is useful when you want to preserve link continuity. The old page
can continue to exist, but no pages on the site will reference it, which
means that search engines will eventually stop crawling it.

The stated recommendation in the README is to replace the contents of
that page with JS and/or a meta refresh in order to force a redirect
once loaded; most search engines will notice these and honor them,
removing the page from their search results.

@waylan waylan added this to To do in Pages Refactor Feb 5, 2018

@waylan waylan referenced this issue Mar 4, 2018

Closed

build all md #1424

weierophinney added a commit to froschdesign/zf-mkdoc-theme that referenced this issue Apr 4, 2018

Allow "hidden" pages
This is a hack learned from the mkdocs issue tracker:

- mkdocs/mkdocs#699 (comment)

Essentially, with this in place, if a page _title_ begins with `_`, it
will not be included in the navigation.

Additionally, this patch goes a step further, and the rendered markdown
of such pages is injected only into the `<head>` section of the built
document, with no other content. This allows for a very quick redirect,
with no content present to index.

This is useful when you want to preserve link continuity. The old page
can continue to exist, but no pages on the site will reference it, which
means that search engines will eventually stop crawling it.

The stated recommendation in the README is to replace the contents of
that page with JS and/or a meta refresh in order to force a redirect
once loaded; most search engines will notice these and honor them,
removing the page from their search results.

ikit added a commit to REGOVAR/Regovar that referenced this issue May 9, 2018

Update mkdocs.yml
thanks to mkdocs/mkdocs#699 for tips

@waylan waylan moved this from To do to In progress in Pages Refactor Jun 3, 2018

@waylan waylan referenced this issue Jun 8, 2018

Merged

Pages Refactor #1504

@waylan waylan closed this in 34ef3ca Jun 28, 2018

Pages Refactor automation moved this from In progress to Done Jun 28, 2018

melo added a commit to melo/docker-mkdocs-alpine that referenced this issue Jul 1, 2018

Add fix for toc.html partial from the Material template:
This will skip menu entries if they start with a “_”

See mkdocs/mkdocs#699 (comment)
for details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment