squidfunk / mkdocs-material

Documentation that simply works

Home Page:https://squidfunk.github.io/mkdocs-material/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[`tags` plugin] Feature suggestion: multiple tag listings (files) & tag sets

twardoch opened this issue · comments

Contribution guidelines

I want to suggest an idea and checked that ...

  • ... to my best knowledge, my idea wouldn't break something for other users
  • ... the documentation does not mention anything about my idea
  • ... there are no open or closed issues that are related to my idea

Description

In addition or as an alternative to the global tags file, larger documentation projects would hugely benefit from specialized tag listings that could be placed anywhere in the documentation.

I imagine it as follows:

  1. The metadata of any .md file in the docs can include a tags_index entry.
  2. The presence of the tags_index entry is mutually exclusive with the tags metadata entry.
  3. The tags_index entry has a list of dictionaries with the following keys:
  • where: PLACEHOLDER (optional): the placeholder which should be replaced by the tag listing, default is [TAGS], must be specified if more than one tag listings is specified
  • show: RE_TAGSET (optional): a regex that defines the tags to be included in the tag listing, if absent, all tags will be listed
  • hide: RE_TAGSET (optional): a regex that defines the tags to be omitted from the tag listing, if absent, no tags will be omitted

For example, a tutorials.md for could look like this:

---
tags_index: 
   - where: "[TAGS:tutbeg]"
      show: "^tutbeg:.*"
   - where: "[TAGS:tutadv]"
      show: "^tutadv:.*"
---

# Tutorials

## Tutorials for beginners

[TAGS:tutbeg]

## Advanced tutorials

[TAGS:tutadv]

If the plugin finds a .md with the tags_index metadata key, it treats it as one of the tags files where it will put the tag listing(s) in the 2nd pass.

Then, in the 2nd pass, it goes through all the tags files.

In each one, it goes through the list of tag listing discussions (the where, show and hide keys).

In the current document, it finds the placeholder specified in where, and replaces it with the tag listing specified by the showhide set.

If show is not given, it considers all available tags. If it is given, it considers the subset of the available tags matched by the regex.

Then, if hide is not given, that's it. If hide is given, it removes the tags matched by the regex from the considered set.

Finally, it replaces the placeholder with the tag listing of each considered tag (tag "bubble" with the links to the pages).

That's all.

Use Cases

I believe this may be simple to implement, would still allow simple use of the tags_file config key but that config key could now be optional.

There are many use cases. Obviously more complex documentations, where a specialized tag index could serve as a kind of table of contents for a particular portion of the docs.

Or a better categorization (grouping) of tags on the listing instead of purely alphabetical. Thanks to the user of regex, the plugin would not impose a particular syntax for the tag "namespaces".

Screenshots / Mockups

No response

An alternative simpler implementation should still allow for multiple tags files. Here, a tags_files plugin config key would take a dictionary where the filenames would be keys and values would be tag identifiers, those used for the icons. Each tags file would then use the simple [TAGS] marker and there would be only one tag listing per such file permitted.

Users could use pymdownx.snippets or other such plugin to build more complex listings.

Thanks for suggesting. The problem with the first approach you mentioned is that we'll end up with different syntaxes in Markdown files which add more complexity for authors and maintainers. This would mean that we would need to adjust the built-in search plugin, which also uses the tags metadata.

However, what might work is the following idea: we allow to specify a list of files under tags_file, e.g.:

plugins:
  - tags
      tags_file:
        - category-1.md
        - category-2.md

Then, we allow specifying which tags to render as part of the [TAGS] marker. This would allow placing the marker anywhere in each Markdown file that is listed under tags_file. If no marker is present, all tags are rendered, which is the current behavior. The tags could be specified as such:

# Category 1

[TAGS foo-1 foo-2 foo-3]

# Category 2

[TAGS bar-1 bar-2 bar-3]

We could also allow simple wildcards (no regexes), something like:

[TAGS foo-*]

Alternatively, we could of course also follow your second idea, something like:

plugins:
  - tags
      tags_file:
        category-1.md:
          - foo-1
          - foo-2
          - foo-3
        category-2.md:
          - bar-*

However, I'd first be interested what other users think, so I'm all for letting this issue sit for some time and see if it is useful to anyone. My guess is that it might be rather edge-casey. You can also solve this problem by dividing your project into multiple MkDocs projects, which might be a better idea.

Multiple projects won't work, because I’d also like to share tags! :) For example, I have a regular book-type manual, a tutorials section, and an encyclopedic reference section.

In each of these sections, I have documents that talk about some functionalities of the app: kerning, drawing, hinting, the eraser tool, the rectangle tool etc. So I'd assign "global" tags to those documents, and I'd like a global tags file.

But for example within the tutorial articles, I'd like to also assign tut-* tags like tut-kerning, tut-hinting etc. that I'd then like to list in a tags file specific to the tutorials section.

I would also love to have small page lists for a few tags somewhere near the opening page of a big chapter — for example in the big chapter on kerning, I’d like to be able to have a kerning-tags.md page that has maybe only the list of pages with one tag (or a few), so a narrow scope.

Because I may have a TOC page (and nav) in that chapter, sure, but I'll also have kerning-related stuff in other parts of the documentation like in the tutorials.

The main point is that the big alphabetical list of tags is nice as a global index, but the ability to have a few separate pages would make it truly useful.

I might fork & extend your plugin myself, but I fear it would the become out of sync with your wonderful upstream development. :)

I like your simplified idea. Using simple wildcards in the plugin config would work. Or even using the identifiers used for icons.

Or even using the identifiers used for icons.

That's also a pretty nifty idea, now that we have them! So, that I understand correctly: allowing to provide multiple pages under tags_file, saying to the plugin "please look for [TAGS] markers inside those files and render them", together with linking identifiers either to [TAGS] markers (e.g. [TAGS id-1 id-2]) or in mkdocs.yml would work for you, right? You could then render subsets of tags on arbitrary pages, which as I understand is what you requested.

Yes! I have a feeling that if we list the tags files in mkdocs.yml, then that would be the right place to define the scope as well. The [TAGS id-1 id-2] solution is somehow a bit less clean (I feel), because, well, those ids are "data" (not markup, not text, and not styling). So they shouldn't pollute the Markdown if they don't have to :)

We specify the tags for each page in the YAML front matter, and we specify the "icon IDs" in the mkdocs.yaml. So I feel that the selection should also be in some YAML. Esp. if we just use the "icon IDs" — then it's easier to manage everything related to these IDs in mkdocs.yaml.

And this way, that data is automatically structured, while the extended [TAGS id-1 id-2] marker would have to be extra parsed.

Plus using just YAML would ensure better i18n compatibility of the IDs. Maybe someone wants to use ] as part of the ID (who knows), or some other Unicode chars.

Let YAML deal with that — not some custom marker parser :)

You're right, mkdocs.yml is probably the best idea.

Maybe someone wants to use ] as part of the ID (who knows), or some other Unicode chars.

That's currently not supported, because we use these identifiers for CSS classes to link icons to tags. It's possible in theory, but we have to escape them, then. Currently, only alpha-numeric identifiers are supported:

Bildschirmfoto 2022-05-01 um 13 41 16

I'll investigate in the coming weeks how hard it will be to add this functionality. Your idea of using the identifiers was pretty great because we can use the existing infrastructure and semantics. My gut feeling tells me it shouldn't be too hard.

And: no need for wildcards (at least for me). The IDs already provide a tag grouping mechanism.

Another conceptual thing that needs some thought before this can be tackled: where should tags be linked? If the user clicks on a tag, and this tag is included in two indexes, where should the user be taken? Note that MkDocs has no immediate concept of hierarchy – all Markdown files are processed equally. Hierarchy is only reflected in the navigation that can be arbitrarily structured.

Good point.

I think the tags_file config key (or its default) should still be kept as a single-file entry. That would work as the “bidirectional ” index (all tags, and links both from and to). No tag id filtering should be allowed there.

The optional dictionary could be in a 2nd config key like tags_files (or more expressively tags_extra_files), and those would be used strictly for the additional indexes with tag id filtering. But they would only link from it, no other pages would automatically link to them.

Of course an author could make manual links to those pages, to a particular tag, from within a document — but that’s outside the scope of the plug-in.

Hello, i am from the Project BetonQuest and we now have an issue with tags, where we thought about an solution. Now then we found this issue, and this would exactly fit out requirements, where we use the same tag in different contexts.

We would love to see this implemented.

@squidfunk I’ve made a CLI tool md_tags_auto which uses NLP techniques to automatically generate MkDocs Material-compatible tags and write them into the YAML metadata of the Markdown files: https://github.com/twardoch/markdownlp

The tool might theoretically be also made into an MkDocs plugin but I’m not sure if it’s worth it, because it’s slow. But it works well.

@twardoch @Wolf2323 I've got a working prototype for multiple tags indexes ready. Expect it to land in the coming weeks!

Support for multiple tags indexes added in squidfunk/mkdocs-material-insiders@2010e0d.

Released as part of 8.3.9+insiders-4.20.0. Documentation is here.

Please see the announcement in #6517.