squidfunk/mkdocs-material

Having two blog posts with matching title and date causes inconsistent navigation

Closed this issue · 6 comments

Context

Blog post uri is built from title and date while blog index rendering iterates posts so duplicated post is rendered twice on blog index while in navigation there is only on uri.

From my perspective having blog posts with matching title and date is valuable. Real world scenario - notifying users on hotfixes with blog and having two hotfixes within same day (it is cleaner to provide details in title and have at least "hotfix 2.17.2" rather than "hotfix" in title but sometimes it is better to inform users fast rather than do it in proper way).

So I'd say it worth handling such cases with changing uri template from [date]/[title] to [date]/[title]-[number] if there are more than one post with given title an date e.g. for the attcahed zip uris may be /blog/2024/09/20/bugfix-release-1/ and /blog/2024/09/20/bugfix-release-2/

Bug description

If there are two blog posts with same title and date, blog index shows two items but both links point to the same post

Related links

Reproduction

blog issue.zip

Steps to reproduce

  1. enable blog plugin with mkdocs.yml
  2. put two files with same title and date to blog/posts :

blogs/posts/post1.md

---
date:
  created: 2024-09-20
tags:
- notes
title: Bugfix Release
---


Bugfix release 2.17.1 is deployed

blogs/posts/post2.md

---
date:
  created: 2024-09-20
tags:
- notes
title: Bugfix Release
---


Bugfix release 2.17.2 is deployed
  1. Launch mkdocs serve

Actual

index page has two records both pointing post from blogs/posts/post2.md

Expected

one of:

  • two blog records on blog index with correct urls for each post
  • one record on index and warning in log stating that one post is lost

Browser

Chrome

Before submitting

Thanks for reporting. We consider this an edge case. With your suggestion, we would need to introduce conditional formatting, since you would not want to append the -1 or -2 numbering on each and every blog post, only on those that have collisions, which is not feasible. Additionally, if you would only append -1 on a blog post once a second one is created, this will change the URL and invalidate incoming links that did not include the -1 before.

However, you can easily solve it in two ways:

Using slug

You can manually set the slug in the front matter for the second post:

---
date:
  created: 2024-09-20
tags:
- notes
title: Bugfix Release
slug: bugfix-release-2
---


Bugfix release 2.17.2 is deployed

If you configured post_url_format as {date}/{slug} (the default), this will only replace the second part, leading to two separately identifiable blog posts with the same title.

Using file

If you use the file placeholder instead of the computed slug. This will always use the original file name, so you can set the file name to the desired value, which will be guaranteed to be unique.

This configuration will also resolve the issue:

plugins:
  - blog:
      post_url_format: "{date}/{file}"

Thus, this issue can be resolved via configuration.

Thx for post_url_format hint, I've missed it somehow in docs. It solves my issue.

You are right - updating uris is overhead.

But guess, having warning in log if collision is detected might be useful - with mkdocs --strict it'd ensure no posts are lost, though it falls into bells and whistles category :)

BTW a side question if you do not mind - is there any reason why blog plugin manipulates with filesystem instead of mkdocs abstraction? I generate posts with plugin and had to apply some hacky approach (described it here ) to overcome blog expectation to have file in docs_dir

But guess, having warning in log if collision is detected might be useful - with mkdocs --strict it'd ensure no posts are lost, though it falls into bells and whistles category :)

Sure, PR appreciated.

BTW a side question if you do not mind - is there any reason why blog plugin manipulates with filesystem instead of mkdocs abstraction? I generate posts with plugin and had to apply some hacky approach (described it mkdocs/mkdocs#2544 (comment) ) to overcome blog expectation to have file in docs_dir

Not sure what you mean, but if you mean MkDocs new File.generated API – the blog plugin predated this feature by a year or two. We can switch to that, but I currently have no bandwidth to do it.

Sure, PR appreciated.

will try to make one.

Not sure what you mean,

I mean the this code:

        # Resolve path relative to docs directory
        docs = os.path.relpath(config.docs_dir)
        path = os.path.relpath(file.abs_src_path, docs)

        # Read contents and metadata immediately
        with open(file.abs_src_path, encoding = "utf-8-sig") as f:
            self.markdown = f.read()

It applies constraint that blog post must have file resolvable with os.path.relpath(file.abs_src_path, docs) (e.g. on windows it will not work if file is created in temp dir that s by default on drive c: while docs_dir is on drive d: ) and can not be just generated from content and registered with on_file of other plugin.

I see. Well, the blog plugin is designed around posts that live in the posts directory. Generating posts was not on our radar and is currently not a priority to optimize for. However, if you can craft a PR to demonstrate how you imagine this to work with changes to the blog plugin that plays well with all of our existing functionality, we might consider it.

ok will have a look, but following form the fast and dirty experiment replacing code above with

self.markdown=file.content_string

does not break anything while lets posts to be generated