squidfunk / mkdocs-material

Documentation that simply works
https://squidfunk.github.io/mkdocs-material/
MIT License
19.96k stars 3.46k forks source link

🏷️ Tags plugin 2.0 – now available #6517

Closed squidfunk closed 8 months ago

squidfunk commented 8 months ago

[!NOTE] The new tags plugin is available as of 9.5.3+insiders-4.48.0

Hello everyone,

We're currently rethinking the tags plugin, transforming it into something much more powerful with the help of your feedback. Here's a sneak peek into the progress we've made and the innovations on the horizon:

Coming very soon

These enhancements aim to transform the tags plugin into a more powerful, flexible, and user-friendly tool, enhancing the overall documentation experience on MkDocs. We're excited to see how these features will be utilized to create more dynamic and interconnected content. Your feedback and ideas are always welcome as we continue to improve the MkDocs ecosystem.

Feel free to share anything that's on your mind.

ccoenen commented 8 months ago

I have a few tags set up for the usual tag things (public-facing organisation of similar things). But I also have a set of tags that I only use for organisation, kind of like what you describe. Let me explain:

together, they give me a nav tree like this, all emoji and numbers you see here are added automatically. None of this shows up in production (in fact, half of the articles pictured here are still being written and don't show up in production at all. Only the :heavy_check_mark: articles go live). internal development nav tree of fediverse.jetzt

alexvoss commented 8 months ago

@Guts, thought you should be aware of this and we should think about how this might impact the RSS plugin. Could open up some new opportunities? Anything (more) from your side / the side of users of the RSS plugin to help shape this functionality?

per1234 commented 8 months ago

I would love to see support for "nested tags"/"hierarchical tags", similar to what was requested in https://github.com/squidfunk/mkdocs-material/issues/4839

My source content has this format:

---
tags:
  - foo/pippo
---

# Some Page

[...]
---
tags:
  - foo/pluto
---

# Another Page

[...]

Currently, this results in a tag index structure like:

The intention is a structure like this:

This slash-separated nested tag format (which was specified in https://github.com/squidfunk/mkdocs-material/issues/4839) is an established convention. Examples of where it is already in use:

squidfunk commented 8 months ago

What happens if I use the tags foo, foo/pluto and pluto? How do they relate? Are hierarchical tags a tree or a graph, i.e., are relations uni- or bidirectional?

alexvoss commented 8 months ago

In Obsidian, something that is tagged #foo/pluto gets found by a search for #foo but not when I search for #pluto (there is one page tagged with only #pluto). Consequently, there is a tag tree in the UI:

image

Obsidian also has a graph view for the pages. When I filter for #foo, I get this:

image

The green dots are the tags and the white ones the pages that contain them. You can see that here a distinction is made between #foo and #foo/pluto. There is no connection between the two tags, which I find a bit surprising.

squidfunk commented 8 months ago

Thanks for the clarification! Creating this issue already paid off by collecting additional use cases. We'll see how we can make nested tags work. IMHO, there should definitely be a relation, but I agree that it should be trees, as we already have the tags graph itself.

Guts commented 8 months ago

@Guts, thought you should be aware of this and we should think about how this might impact the RSS plugin. Could open up some new opportunities? Anything (more) from your side / the side of users of the RSS plugin to help shape this functionality?

Thanks for the ping @alexvoss!

On the RSS plugin side, we mainly refer to the YAML frontmatter (mkdocs.page.meta) to define the feed items categories as defined in RSS specification. User has to specify in categories option which YAML key/s the plugin should use as item's keywords/tags/category (default to None).

See the related section in plugin's documentation: https://guts.github.io/mkdocs-rss-plugin/configuration/#categories-item-categories

On the Material theme side, the documentation make some recomendations about how to use this option (https://squidfunk.github.io/mkdocs-material/setup/setting-up-a-blog/#rss) by defining tags and categories

To sum up: for now there is no direct relationship between Material tags plugin and RSS plugin.

squidfunk commented 8 months ago

I second @Guts – the RSS plugin and the tags plugin are two plugins that both consume front matter properties, but for different purposes.

Guts commented 8 months ago

Now, if I put aside my role as the main developer and maintainer of the RSS plugin, I find these evolutions exciting. On the whole, I always find the design or refactoring phases, or the major evolution of bricks that are already widely used, really interesting.
Tags is typically a common feature hiding huge stakes for end-user experience.

Every innovation mentioned in the description seems very good to me. If I have to say something to challenge the collective idéation:

alexvoss commented 8 months ago

@Guts, it might matter to you how the hierarchical tags are implemented. The RSS standard defines them as slash-separated.

squidfunk commented 8 months ago

Hierarchical tags will be an implementation detail of the tags plugin. As long as the RSS plugin consumes tags from metadata and not from the tags plugin instance, it doesn't matter how hierarchical tags are implemented. If it decides to consume them from the tags plugin, this is of course different, but I think this doesn't make sense to do.

Now, if I put aside my role as the main developer and maintainer of the RSS plugin, I find these evolutions exciting. On the whole, I always find the design or refactoring phases, or the major evolution of bricks that are already widely used, really interesting.

We will put significant effort in making the transitioning phase as simple as possible. Hierarchical tags will be opt-in, the separator will be configurable (defaulting to /). The obsolete tags_file and tags_extra_files (now replaced with inline comments) will receive proper deprecation paths and continue to work until the next major version. We'll also make sure that the tags plugin works the same between the community version and Insiders.

I'm a big fan of semantic web and I would like to see more of schemas to be automatically generated in documentation websites. Here, why not about the keywords or DefinedTerm?

Could you expand on this a little? Should the tags plugin generate a schema for the concrete tags used by the author, or how would you imagine this to work?

why not propose an old-school words cloud? or something approaching. I've recently started something with wordcloud and a mask inspired from the graphical elements of the website (in the spirit of social cards). Was "just for the fun"; now I'm questioning myself if it would land on the homepage 😅. Seriously, with the mentioned tags.json file, it would be really easier to make some things like this :).

That's essentially just another rendering of a tags index and will definitely be possible to pull off with the new architecture. We might provide a default renderer for this as well. tags.json will definitely be a part of the new plugin.

alexvoss commented 8 months ago

Hierarchical tags will be an implementation detail of the tags plugin.

They are not hidden, though. The way they are done will filter through to the RSS feed via mkdocs-rss-plugin. Slashes by default are good in that respect.

Configurable is also good, though perhaps it might be good to mention that using things other than slashes could break some RSS-reader behaviour? That is, if RSS-readers are doing anything meaningful with the categories - I just checked mine (Reeder) and it does not seem to, which is a bit surprising and disappointing. Does anyone know a reader that allows filtering/grouping by the RSS category?

squidfunk commented 8 months ago

We're still in ideation and prototyping phase, once we have everything ready, we should check what we should document, but currently it'd be premature documentation (cough) ☺️

Guts commented 8 months ago

Does anyone know a reader that allows filtering/grouping by the RSS category?

Thunderbird?

squidfunk commented 8 months ago

Progress! Here's a quick demo of what you'll be able to do in the coming days:

https://github.com/squidfunk/mkdocs-material/assets/932156/bf71d694-8a10-4135-b79c-a6f4d20db8e8

Define listing using inline syntax:

<!-- material/tags { include: [foo/a, foo/b], scope: true } -->

Define listing using block syntax:

<!--
  material/tags
    include:
      - foo/a, 
      - foo/b
    scope: true
-->

Reference a pre-defined listing:

<!-- material/tags bar -->

This makes tags much more flexible already, as you can now allow your users to "hop" through your documentation by cleverly chaining tags indexes. I'm still working on the other things described in my OP, and need to clean up the mess I made – so many levels of indirections, so I'll need a few days still, but I love how this is turning out.

I'll post here when I got a first clean draft in Insiders which you can install and play with on your machine ☺️ Those of you who're not sponsors yet: you can support the project and make this feature happen faster by sponsoring @squidfunk! Additionally, you can build this feature with us, together, influencing precisely how it will turn out in the end!

alexvoss commented 8 months ago

@squidfunk - cannot watch the video?

image
squidfunk commented 8 months ago

Weird – does the one on Twitter work (it's the same)? https://twitter.com/squidfunk/status/1736761608666255866

alexvoss commented 8 months ago

Yes, it does. A MIME type issue rather than an encoding one? This is on a Mac and on Linux - aha, the common factor here is Firefox. Safari works fine on the Mac.

squidfunk commented 8 months ago

Not sure why this is the case. I need to improve my screen recording setup.

alexvoss commented 8 months ago

Did you replace the video? Because now I closed the tab and came back to it after a while - the video is working, same browser. Perhaps GitHub re-encodes uploaded videos and the pipeline took a bit of time? In any case, seems fine now.

squidfunk commented 8 months ago

And I just finished a first prototype of the hierarchical renderings of the tags index. It's not beautiful, yet, but we're getting there. I'm first focusing on functionality and we'll improve the styling once we got it working:

Bildschirm­foto 2023-12-19 um 13 43 09

Pages are tagged as follow:

This shows the following properties:

I still need to clean up all the mess I made, hope to finish the prototype today or tomorrow!

squidfunk commented 8 months ago

Next update: shadow tags. Now, tags can be hidden when rendering listings and pages, but they will still exist in the tags structure and be marked as hidden. This allows for creating listings that are solely meant for temporary collecting and tagging pages or blog posts (e.g. for todos). In this example, tags starting with _ are marked as shadow tags:

Bildschirm­foto 2023-12-21 um 12 34 10

Tags can be marked as shadow tags by adding them to the explicit shadow_tags list, or by prefix or suffix. Same as for the blog post draft state, tags can be rendered during mkdocs serve and removed during mkdocs build. In the screenshot above, they're rendered during mkdocs serve.

squidfunk commented 8 months ago

And the first version is available! https://github.com/squidfunk/mkdocs-material-insiders/pull/76

The PR implements almost all of the features proposed in my OP. I've adjusted the OP with check lists what is already implemented. I've also opened a PR on our examples repository demonstrating the three greatest new features: scoped listings, tag hierarchies and shadow tags.

No more tags_file and tags_extra_files settings (will be kept for downward compatibility, of course) – using the tags plugin is now much, much easier and much more flexible. You can render listings (= tags indexes) anywhere.

I recommend to check out the examples. As a quick idea, here's the new annotated configuration of the plugin – most settings are quite self explanatory. All commented settings are new. I'll add documentation in the coming days, but the brave of you can already give it a spin:

class TagsConfig(Config):
    enabled = Type(bool, default = True)

    # Settings for filtering
    filters = SubConfig(FilterConfig)

    # Settings for tags
    tags = Type(bool, default = True)
    tags_slugify = Type(Callable, default = slugify(case = "lower"))
    tags_slugify_separator = Type(str, default = "-")
    tags_slugify_format = Type(str, default = "tag:{slug}") # slug is now passed through this format string
    tags_hierarchy = Type(bool, default = False) # hierarchical tags are disabled by default
    tags_hierarchy_separator = Type(str, default = "/") # you can configure the hierarchy separator
    tags_sort_by = Type(Callable, default = tag_name)
    tags_sort_reverse = Type(bool, default = False)
    tags_name_property = Type(str, default = "tags") # name of the front matter property in Markdown
    tags_name_variable = Type(str, default = "tags") # name of the template variable for tags in pages
    tags_allowed = TagSet()

    # Settings for listings
    listings = Type(bool, default = True) # whether listings should be rendered (= tag indexes)
    listings_map = DictOfItems(SubConfig(ListingConfig), default = {}) # pre-defined listings
    listings_sort_by = Type(Callable, default = item_title) # sort function for pages under a tag
    listings_sort_reverse = Type(bool, default = False)
    listings_tags_sort_by = Type(Callable, default = tag_name) # sort function for tags in listings
    listings_tags_sort_reverse = Type(bool, default = False)

    # Settings for shadow tags
    shadow = Type(bool, default = False) # whether to render shadow tags or remove them
    shadow_on_serve = Type(bool, default = True) # when serving, enabled rendering of shadow tags
    shadow_tags = TagSet() # these tags should be considered shadow tags
    shadow_tags_prefix = Type(str, default = "") # tags starting with this string are shadow tags
    shadow_tags_suffix = Type(str, default = "") # tags ending with this string are shadow tags

I'm so happy how this turned out – the tags plugin is infinitely more powerful and I can't wait what use cases we can solve with this beast. I've wanted to give the tags plugin a rewrite for a year now, and @alexvoss motivated me to give it a go. Our examples repository will host a pretty complex and comprehensive tags index, so this is definitely use case no 0.

squidfunk commented 8 months ago

The new tags plugin was released as part of 9.5.3+insiders-4.48.0. This is a HUGE release 🥳

We'll keep this issue open until we finished to update our documentation. We want to provide more use cases and case studies how the new tags plugin can help you, so quite some stuff to write, but the brave of you can already give it a spin 🚀 It should be downward compatible, albeit print warning messages if you're using tags_file and tags_extra_files – those are now deprecated and no longer necessary. Just use the inline syntax as mentioned in https://github.com/squidfunk/mkdocs-material/issues/6517#issuecomment-1860689219

This took significant effort, but the result is just wow. The tags plugin was the first plugin that I wrote several years ago, and it was quite dated. The capabilities now are on a whole new level. In fact, I know of no other SSGs that have such a powerful tags plugin, allowing you to place customizable listings basically everywhere. It should now also align more nicely with the capabilities of Obsidian.

All of this was only made possible by our awesome sponsors ❤️ Sponsorships are allowing me to push this project further and further, creating one of the simplest yet most powerful frameworks for writing documentation.

squidfunk commented 8 months ago

Documentation was added in https://github.com/squidfunk/mkdocs-material/commit/fee72372fb9f7a209f18f11c56fc1447cf68843d.

The documentation barely touches what the new plugin is capable of. We will use the tags plugin as the first patient for restructuring our setup guide into usage-centric guides with examples and starter templates. A first draft for a structure with some diagrams is in #6556. I imagine that we create a new section that evolves around the topic of structuring a documentation project with Material for MkDocs. This section should accompany our users on their journey from starting out with a single Markdown file up to several thousand files. This includes the usage of the following features and plugins:

We'll continue to work on this in #6556.

squidfunk commented 8 months ago

I'm closing this issue for now. In the coming weeks, we add more examples and better documentation on the plugin, so users can better understand what can now be done with it. Since this will be part of a much larger rewrite, it doesn't make sense to keep this open, as there's already a lot of information packed in this issue, which will be distilled into better documentation.

If you have feedback on the new plugin, you can post it here.