squidfunk / mkdocs-material

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

Support Custom icons/emoji format for navigation #2318

Closed Andre601 closed 3 years ago

Andre601 commented 3 years ago

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

Description

It would be awesome, if it was doable to use both emojis and the pymdownx.emojis Icons in the navigation-section of the mkdocs.yml file. Right now does it not render those in the nav, limiting us a bit

Use Cases

This is useful for when you want to show icons in the nav to indicate certain things, such as the logo to a social media page, or - like in my case - indicate an external page with a external-link icon.

Screenshots / Mockups

squidfunk commented 3 years ago

Unfortunately, we can't do anything about that, as navigation is core-MkDocs and not compatible with our icon integration. The same goes for the table of contents.

Andre601 commented 3 years ago

Good to know... I assume making a plugin for this could maybe fix it? Otherwise, will I probably open an issue on MkDocs to request the options that either extensions or plugins should be able to alter those things.

squidfunk commented 3 years ago

You can use literal emoji code points, but not the :...: syntax. I don't know if it's possible to hook into the nav generation, maybe @facelessuser has an idea?

facelessuser commented 3 years ago

https://python-markdown.github.io/extensions/toc/#custom-labels

Andre601 commented 3 years ago

https://python-markdown.github.io/extensions/toc/#custom-labels

This seems to only apply to the ToC, no?

facelessuser commented 3 years ago

This seems to only apply to the ToC, no?

Yes, this applies to TOC navigation, but not document page navigation.

polarathene commented 3 years ago

Upstream response was that it's not something that belongs in upstream, but something a theme is perfectly capable of supporting: https://github.com/mkdocs/mkdocs/issues/2311#issuecomment-785386132

An alternative approach that might work is CSS, but that's a bit detached from the nav label and a bit more difficult to manage/target nav items (eg when nav is modified could break it if relying on list order for targeting).

A project I'm migrating docs for has had a request for external links to indicate that they're external (and I guess they should additionally have attribute to open a new tab instead of navigate away from docs). They also want to use the FA external link icon for this purpose.

For external links at least, it's probably easier to implement, by detecting a third-party link in the nav? Then just adding a class might be sufficient and CSS can assign the external link icon to each. Probably want to additionally modify the HTML though to add that attribute for opening a new tab.

squidfunk commented 3 years ago

We can't do anything about it in Material for MkDocs, as we're only rendering what's there. IMHO, things would have to be solved in a plugin (for navigation) or extension (for table of contents).

polarathene commented 3 years ago

We can't do anything about it in Material for MkDocs, as we're only rendering what's there.

I thought you're using JS to manipulate client-side and possibly some additions (or included third-party plugins/extensions) that do modifications at build?

Seems like something that could be handled via JS without an issue, but I understand why you may be reluctant to pursue that, especially if demand for it is low from the community/insiders.

squidfunk commented 3 years ago

We're using JavaScript only to enhance the application and where it's absolutely necessary. If you disable JavaScript, you will see that basically, 80% of the theme will look the same. Features as search and instant loading that are interactive won't work obviously. This is one of the core values of Material for MkDocs - it should even work on slow Internet connections (i.e. emerging markets). Handling this via JS would mean that we would need to load the complete icon and emoji index which currently weights 577k - that's 5 times the whole JavaScript + CSS payload. Furthermore, this would need to block rendering, or we would introduce content shift. Therefore it's barely a solution. Unfortunately, this really needs to be solved upstream.

polarathene commented 3 years ago

This is one of the core values of Material for MkDocs - it should even work on slow Internet connections (i.e. emerging markets).

I'm not familiar with the build pipeline. In JS web dev land, it's not uncommon for SSGs to have a build step that uses JS to build/pre-render page content that on the frontend client becomes interactive with JS if available. Gatsby has established a reputation for doing that fairly well, along with Next.js, both React based.

I assume python is used for the build step, and that it would be possible to add some logic here, but if that's out of the scope of mkdocs-material that's fine.

As for those with JS disabled, it's a nice-to-have but that wouldn't be reason enough to completely dismiss such a feature.

For slower connections there are solutions for that too, but perhaps I'm too used to modern web dev and you're limited to what you can do here with MkDocs. A single glyph shouldn't be a major concern however.

Handling this via JS would mean that we would need to load the complete icon and emoji index which currently weights 577k - that's 5 times the whole JavaScript + CSS payload.

Apart from a build step filtering this to be a non-issue, there are other ways around that.

However, the interest for just treating external links with a different behaviour (open new tab instead of change the existing page) and include a glyph to make these items distinct from relative/internal links seems like a fair and common feature.

Furthermore, this would need to block rendering, or we would introduce content shift. Therefore it's barely a solution. Unfortunately, this really needs to be solved upstream.

I don't see why that'd be the case tbh. Depends on how you approach it.

waylan commented 3 years ago

For external links at least, it's probably easier to implement, by detecting a third-party link in the nav?

This should be rather simple to do as external links are different Python objects (mkdocs.structure.nav.Link) than internal links (mkdocs.structure.pages.Page). A simple if statement in the template should be able to provide different output much like is already done for nav sections. All three types of objects include the same three attributes: is_section, is_page and is_link, only one of which is ever True. See the documentation.

polarathene commented 3 years ago

Made a basic implementation:

Screenshot_20210303_174827

Screenshot_20210303_174644


Originally I tried inlining the SVG via background-image, but this prevented being able to modify/inherit the colour.

// SVG via CSS var defined wherever would be relevant:
// --md-nav-icon--external: svg-load("octicons/link-external-16.svg");

// _tabs.scss: `&__link{}`
&-external::after {
  content: "";
  /* sets an position/scale followed by SVG */
  background: center/70% no-repeat var(--md-nav-icon--external);
  /* Required for visibility */
  padding-left: 1rem;
}

I considered the mask-image approach that's been used already by @squidfunk but I know how he feels about maintenance and complicating things. There seems to be some non-DRY usage of that mask-image technique, which could probably be refactored to leverage SCSS features, but I opted out of exploring this route.

Instead I figured the usual approach with font icon glyphs instead of SVGs might be more appropriate. I realize @squidfunk is probably opposed to including complete fonts wastefully, so I just extracted the external link glyph into it's own web font (woff) file.

This could bundle multiple glyphs if appropriate (might be useful for heading permalink icon?), here's basic CSS for re-creating the solution:

// _icons.scss
// Just place the font in the `material` theme location, could use a CSS var or a user could override the file if they want to use different glyph(s)
@font-face {
  font-family: 'external-link';
  src: url('/assets/fonts/external-link.woff') format('woff');
}

// Avoids repeating the style or requiring sibling class by matching any class with the prefix:
[class*='md-glyph--']:before {
  display: inline-block;
  font-family: 'external-link';
  /* At least for this glyph, it's too big by default, may be better suited below or handled when generating the font */
  font-size: 80%;
}

.md-glyph {
  // If more icons were bundled, just add the glyph modifier and set `content` to it's mapping (eg "A" or "\0041")
  &--external-link:before { content:'\0041'; }
}

Then the Jinja templates with the info @waylan provided:

<!-- tabs-item.html#L52 -->
<a href="{{ nav_item.url | url }}" class="{{ class }} {{ 'md-glyph--external-link' if nav_item.is_link }}">
<!-- nav-item.html#131 -->
<a href="{{ nav_item.url | url }}" class="md-nav__link {{ 'md-glyph--external-link' if nav_item.is_link }}">

As I'm not familiar with the code base, it's possible I've missed something there. The woff is 1KB in weight, I did no effort to optimize that and used an online web generator instead of putting something proper together with NodeJS or similar.

You could add to your build a way to either extract font glyphs or build a font from SVG inputs, or just include the pre-built font like I have and if anyone wants to change that, they just swap the file or change the path to their own font.

I can PR these changes if you're interested. I don't have time to contribute anything more extensive (like refactoring your SCSS or adding a font generator to your build pipeline.

polarathene commented 3 years ago

One other option, is just adding a class only and expecting all users that want this to provide the additional CSS and font file themselves. This would be inconvenient, but probably the most acceptable option for @squidfunk if he's opposed to any solution mentioned in my prior comment.

With the font loaded, then CSS can be used to target external links like this:

Generic selector ```css /* my-third-party.css */ /* Any link element with an `href` attribute starting with `http` that isn't (eg `github.com`) add the external link icon. */ a[href^="http"]:not([href*="github.com"])::before { display: inline-block; font-family: 'external-link'; font-size: 80%; content: '\0041'; } ``` Note: This will require multiple `:not()` or more explicit hostname to match. Otherwise you'll find stuff like the github link or twitter announcement (from the `mkdocs-material` demo) pre-pending this glyph icon which is obviously undesirable.

EDIT: Just noticed the MkDocs nav URLs are relative href values, so third-party CSS can probably make do with this slightly more verbose approach without a class to target:


/* my-third-party.css */
/* tab or nav sidebar with non-relative links will pre-pend an icon from the given font-family */
.md-tabs__link[href^="http"]::before, .md-nav__link[href^="http"]::before {
  display: inline-block;
  font-family: 'external-link';
  font-size: 80%;
  content: '\0041';
}
squidfunk commented 3 years ago

Your last EDIT is the way to go 👍 no additional code necessary. We shouldn’t re-introduce web fonts, as the SVG approach is superior.

Andre601 commented 3 years ago

Your last EDIT is the way to go 👍 no additional code necessary. We shouldn’t re-introduce web fonts, as the SVG approach is superior.

Not quite sure how the last one even is different? Like from the looks of it would you still need to add a own font-family for it? Like I have a somewhat hard time to understand this entire thing now, so if someone could give me a dumbed-down version of this (Where the icon would also be after the text) would I be happy about it...

squidfunk commented 3 years ago

Yes, I meant there is nothing we need to add (additional CSS classes) to the theme to make this (add an icon to external links) work. You still need to bring your own webfont or SVG via mask-image, thus customize it.Custom Admonitions give a start how the mask-image approach can be pulled off 😊

polarathene commented 3 years ago

Like from the looks of it would you still need to add a own font-family for it?

Yes, you must provide your own font file and font-family CSS similar to what the earlier post had. Most font generators will produce this for you, but their icon CSS is class based like the earlier example, so you need to add a class to use them.

You can pull in all of an existing font like FontAwesome, but it will be weighty vs a single glyph font like I created. Honestly it's lightweight that it's something I think this theme should be open to including, with a simple toggle to enable, but I'm familiar enough with how this project is maintained to know what the outcome was likely to be.

Users that want this will have to be familiar with provisioning a custom font, or the wasteful usage of a full icon font, in addition to adding the custom CSS.

if someone could give me a dumbed-down version of this (Where the icon would also be after the text) would I be happy about it...

The icon is prepended to the nav or tab item text, just like the screenshots show.

You could change this to append instead, switch the ::before to ::after in the CSS. I added comments in the CSS snippets to help explain what was going on a bit better for users less comfortable with CSS (or this approach in general).

It will offset your text as if the font icon was included in the text itself, so you shouldn't have any layout issues occur.

~I have not tested it against other features like Instant Navigation from this theme. That is known to rewrite URLs, but I only investigated it's impact on <script> elements. @squidfunk can confirm if it will also rewrite the href of the nav <a> elements too.~ (EDIT: Instant Nav should be fine, href seems to remain relative)

squidfunk commented 3 years ago

[...] that's been used already by @squidfunk but I know how he feels about maintenance and complicating things.

[...] but I'm familiar enough with how this project is maintained to know what the outcome was likely to be.

This is a problem that happens when @squidfunk won't even consider @waylan advice on how to detect page links from external links (just a Jinja template condition in two places to add a class that can be targeted).

I must kindly remind you again to adhere to the code of conduct. This is your second warning (first one was here).


I haven't read a compelling reason why we need that template switch. It's perfectly achievable with a few lines of CSS. In fact, the CSS-only solution is superior, because some authors also want to add external link symbols to the body copy which is generated from Markdown, and we can't add/inject switches there. Authors would be required to add the respective CSS class via attribute list on every external link on their own.

Detecting external links should be done entirely in CSS (here scoped to all links a for simplicity):

a[href^="http"] {
  ...
}

The great thing is, you can also detect different protocols like for example mailto:, to render an envelope symbol:

a[href^="mailto"] {
  ...
}
polarathene commented 3 years ago

Custom Admonitions give a start how the mask-image approach can be pulled off :blush:

As I relayed earlier, the mask-image approach wasn't working well for me. I was referencing your implementation for prev/next nav buttons at the bottom of a page though, the admonition example kinda works but needs adjustments otherwise:

Screenshot_20210303_205130 Screenshot_20210303_205151 Screenshot_20210303_205215 Screenshot_20210303_205309

This is due to using left to offset with position: absolute. Most notable is the nav tabs as all tabs are displaying the icon, but they've all been offset to the same location. Also the icons aren't clipped when you scroll down to the bottom of a page and the sidebar or toc is scrollable, the icons will overflow.


For the benefit of others that want to use the mask-image approach, you don't need to reference a font and unlike the background-image referencing an SVG, you can inherit the text colour with this approach:

Screenshot_20210303_211709

Screenshot_20210303_212111

Screenshot_20210303_212159 Screenshot_20210303_212244

/* Add this to your custom CSS file wrapped with an appropriate selector like discussed above */
content: "";
background-color: currentColor; /* inherit the relevant colour to match the text label */
padding-right: 0.6rem; /* width for SVG to fit into, affects scaling */
margin-right: 0.1rem; /* offset gap between icon and link label */
mask-position-y: 30%; /* vertically adjust Y position of icon to better place it */
mask-repeat: no-repeat;
mask-size: contain;
/* Add the SVG below (this one is the font-awesome external-link SVG sourced from `mkdocs-material/material/.icons/fontawesome/solid/external-link-alt.svg`) */
/* make sure it's encoded properly: https://yoksel.github.io/url-encoder/ */ 
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M432 320h-32a16 16 0 0 0-16 16v112H64V128h144a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16H48a48 48 0 0 0-48 48v352a48 48 0 0 0 48 48h352a48 48 0 0 0 48-48V336a16 16 0 0 0-16-16zM488 0H360c-21.37 0-32.05 25.91-17 41l35.73 35.73L135 320.37a24 24 0 0 0 0 34L157.67 377a24 24 0 0 0 34 0l243.61-243.68L471 169c15 15 41 4.5 41-17V24a24 24 0 0 0-24-24z'/%3E%3C/svg%3E");

Bit more CSS and a little more fragile (doesn't scale with font size), but it might not be an issue for you. (EDIT: changing to em units instead of rem resolves that, eg padding-right: 0.8em; margin-right: 0.2em;)

polarathene commented 3 years ago

Detecting external links should be done entirely in CSS (here scoped to all links a for simplicity):

I covered this in the collapsed "Generic Selector" example. But you have to be careful as it can lead to unexpected targets like your twitter and github links in the Nav/announcement section on your project docs page.

That requires being more specific, often by maintaining a potentially long list of exclusions or inclusions as I mentioned.

I haven't read a compelling reason why we need that template switch. It's perfectly achievable with a few lines of CSS.

It has some minor benefits. I was advocating more towards upstream enablement via config, but perhaps I misunderstood the demographic of your users that you explained to me earlier.

I felt it's a common enough feature to centralize availability in upstream(this project) at least to a point that minimizes the expectations of a user to implement it, such as some documentation snippet at the very least.

Long version: You don't. Often you don't need CSS classes to target elements, and you can get more creative. I'm sure you understand the merits of having a specific class to target though. > In fact, the CSS-only solution is superior, because some authors also want to add external link symbols to the body copy which is generated from Markdown, and we can't add/inject switches there. That would be *some* authors. You can apply that rationale for plenty of things. Just like only *some* would be interested in marking external links just for the nav (where it's less obvious from a UI) vs the document/article content. The proposal here was however you want to implement that, to support so upstream out of the box, via some feature option if you wanted to. This is a lot more accessible for your users than the usual "go figure it out yourself" approach. As you've mentioned in a prior discussion, most of your user base aren't web developers and they're not comfortable with CSS; yet I wouldn't be surprised if some of those users have seen links with an icon on other sites and would like that distinction in their nav sidebar/tabs specifically. Instead of the project helping them out for achieving such, it encourages the opposite. I assume it won't be added to the docs to assist those users, perhaps they'll manage to stumble upon this issue and I'd have been helpful to them. If you do document it, and believe that users wanting such a feature will be comfortable dealing with CSS targeting `href` attribute and chaining a bunch of `:not()` filters and such, great. As for the addition of arbitrary links elsewhere in the document, sure that's a fair point as some users probably would like a feature supporting that too. If you added this feature for nav links, I imagine the response to a user requesting broader support would be that it is out of scope among other reasons, but we didn't make it that far either.

Just for clarity, since this message will more than likely risk another CoC warning being issued. I fully understand that you aren't interested in making this an upstream feature. I don't care either way as it's a non-issue for me personally, but I do care about your community and I had them in mind.

Please forgive me if you feel my communication has been in any manner insulting, unprofessional, disrespectful, etc.


I must kindly remind you again to adhere to the code of conduct. This is your second warning (first one was here).

The first warning I asked for clarification but heard nothing back.

Long version: This warning, I'm being accused of violating your code of conduct because I said that you weren't interested in making identification of external links in nav tabs/sidebar better via a conditional that adds a class? (the other quotes being accurate about your stance on maintaining / developing this project) I realize communication via text doesn't have tone to accompany it, nor body language... but I meant no negative association to those statements. I apologize if you've taken them the wrong way. I've only tried to be helpful towards your community, going out of my way to volunteer time to assist others that you dismissed. Frankly, I'm tired of being treated this way by you with our interactions. I've tried to be open and helpful, and almost every time you've shut me down (the bug report on source maps is one of the few I recall as positive). I have an open PR that's small but intended for the benefit of others. Can you forgive me from my experiences so far that I don't feel welcomed to contribute to this community, or that my efforts in the majority of cases will end in rejection as they have been multiple times now; despite trying to be accommodating and adapt to your style of maintainership.

I'll take this 2nd warning as a sign that I should step away from this community. The sensitivity and misunderstandings of those whom enforce it is far too easy to trip over accidentally. While I have not contributed much to the community thus far, I'd rather not have anymore of my time and efforts disrespected; especially when it involves being threatened punishment for citing honest observations that someone in a position of authority disapproves of.

victorbnl commented 3 years ago

As a (dirty) workaround, I put the icon somewhere in the page, then inspect the element and copy the HTML of the span .twemoji, then I put it directly in the title:

# <span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"></path></svg></span> Downloads

It won't work directly, you then need to fix some things in CSS

nav .twemoji {
    display: inline-flex;
    height: 1.125em;
    width: 1.125em;
    fill: currentColor;
    vertical-align: text-top;
}
sugatoray commented 2 years ago

An Alternative: Fixed :fire: -- quick-and-dirty solution

Another way of simply adding an icon to the navigation (while keeping the formatting correct for both the tabs and the nav-bar) is as follows:

# file: mkdocs.yml

extra_javascript:
  ## for: fontawesome (use your own fontawesome kit)
  - https://kit.fontawesome.com/1a2b3c4d5e.js # fontawesome-kit

nav: 
  # - Research: # instead of this use the following line
  - "<p><i class='fas fa-flask'>&nbsp;</i> Research</p>":
    - Paper2009: papers/paper2009.md
    - Paper2012: papers/paper2012.md 
    - Paper2019: papers/paper2019.md

Granted, this makes the nav items a bit harder to read; but you can quickly get a dirty solution like this working. And may be later on if you have enough time and motivation, you could consider writing a plugin or contribute directly to mkdocs-material.

The fix here uses two things:

Sample Output:

This is how it would look like then (this is not the same code as the code-block above, but it uses the same logic/fix).

After (without the problem: left-nav-bar)

With - "<p><i class='fab fa-stack-exchange'>&nbsp;</i> Teaching</p>": as the section.

image

Before (with problem: see left-nav-bar)

With - "<i class='fab fa-stack-exchange'></i> Teaching": as the section.

image

cc: @squidfunk @polarathene @Andre601

squidfunk commented 2 years ago

Update: navigation icons are now available.

youngdjn commented 9 months ago

Is there a way to use the navigation icons feature for nav tabs that are not associated with a MkDocs page (i.e., those that link to an external URL)?

Andre601 commented 9 months ago

You can make a redirect page and define a icon there. Example: https://codeberg.org/Andre601/AdvancedServerList/src/branch/master/docs/api/javadocs.md?display=source

Material for MkDocs provides the redirect.html template already.

polarathene commented 7 months ago

Sorry to chime in here, I know we don't get along 😅

This is mostly for the benefit of others dropping in here and to raise awareness to you and anyone else working on the project.

TL;DR:


Quoted context > Your last EDIT is the way to go 👍 no additional code necessary. > (**EDIT:** Instant Nav should be fine, `href` seems to remain relative) > > * If it does this, relative urls become absolute and the third-party CSS will not work, every nav and tab link will render the external-link icon. > > Detecting external links should be done entirely in CSS (here scoped to all links a for simplicity): > > I covered this in the collapsed "Generic Selector" example. But you have to be careful as it can lead to unexpected targets like your twitter and github links in the Nav/announcement section on your project docs page. > > That requires being more specific, often by maintaining a potentially long list of exclusions or inclusions as I mentioned. > > > I haven't read a compelling reason why we need that template switch. It's perfectly achievable with a few lines of CSS. > > It has some minor benefits. I was advocating more towards upstream enablement via config, but perhaps I misunderstood the demographic of your users that you explained to me earlier. > > I felt it's a common enough feature to centralize availability in upstream(this project) at least to a point that minimizes the expectations of a user to implement it, such as some documentation snippet at the very least.

FWIW, this concern raised a while back just recently happened and broke the rendering of the approach I had suggested and was endorsed over adding official support.

I didn't expect the breakage to be introduced in a point release, but it was from 9.5.5, probably here.

Relative linkage was dropped, and I assume that's intentional given the changelog, so I don't know how you'd want to approach fixing the unintentional breakage here.

image

CSS workaround (awkward)

From the looks of it, I can workaround that with a less generic CSS rule:

.md-tabs__link[href]:not([href*="docker-mailserver.github.io"])::before, .md-nav__link[href]:not([href*="docker-mailserver.github.io"])::before

But that requires modification to support builds on deployment vs preview builds (different domains).

Alternatives

Alternatively, there is the other suggested approaches:

I don't make any money where I use mkdocs-material, so unfortunately I can't justify insiders in my circumstances.

Tip - Discoverability

The actual name is not "Navigation Icon", it's only discoverable via the "Reference" tab, or realizing the sidebar "Reference" is also a page link, then noticing the "Setting the page icon" on the right-sidebar or scrolling down that reference main page.

One might think it'd be worthwhile to be discoverable from the navigation settings page, where there is no mention of icon. An example for a common enough case of marking an external link for added accessibility reasons would be nice to document, even if that's to convey to the reader that they cannot just provide an external nav link, but must add a markdown file to redirect to the external link to get the icon.

What is endorsed now?

Perhaps the endorsed approach for marking external links in nav items is now the awkward approach with Navigation Icons and markdown file redirect workaround?

I haven't read a compelling reason why we need that template switch. It's perfectly achievable with a few lines of CSS. In fact, the CSS-only solution is superior

The CSS approach was justification for disregarding another request for this support officially. Where this article was endorsed as an example by @squidfunk on twitter for how to approach it.

However, like my examples shared here prior to that article being written, both depended upon href attribute matching to differentiate from the relative links. Something that is no longer compatible going forward?

squidfunk commented 7 months ago

Thanks for your view on this.

I didn't expect the breakage to be introduced in a point release, but it was from 9.5.5, probably here.

So, first of all, you're talking about a customization, which is not considered public API surface, thus not a breaking change. If we would declare this a breaking change, we could only release major versions, because every change might be a breaking change, as we cannot possibly anticipate how authors customize the theme. Not economical, nor maintainable for us. We try to warn authors about changes to templates in our changelog though, none of which happened here.

Relative linkage was dropped, and I assume that's intentional given the changelog, so I don't know how you'd want to approach fixing the unintentional breakage here.

This is only the case if you enable navigation.instant and it is done in the browser, meaning that HTML files are not touched, thus internal/external links are still detectable during build. We fixed all known bugs in instant navigation in 9.5.5, and making links absolute upon instant navigation is an absolute must, or things might break in certain situations. Especially on slow connections, which we tested with extensively, not replacing links sometimes led to wrong navigation, e.g.:

  1. User navigates to ./foo, URL changes immediately (read instant navigation code why this cannot be avoided)
  2. Browser hasn't finished loading, but user now navigates to ./bar. If we would leave links relative, the resolved location would be ./foo/bar now, which is incorrect.

This is one of the main reasons I decided to make links absolute upon replacement of the document after instant navigation, as it now means that links are now always correct, regardless of connectivity. Additionally, if navigation fails completely for some reason, the application will try to navigate to the page regularly. All of this makes it necessary to canonicalize links before replacement. I invite you to study the instant navigation code, the reasoning is very heavily documented.

While I won't invest time to further discuss this change back and forth, because it is pointless given the bugs that desperately needed to be fixed, here are some workarounds:

  1. Disable navigation.instant (simplest)
  2. Use the external links feature of the privacy plugin to add a custom property, or use rel=noopener to detect, as noted – yes it is currently reserved to sponsors, but this is the canonical way we recommend. What you ask is by no means a critical feature, but optional, so it's perfectly fine to, for now, only provide this to sponsors.
  3. Write a tiny script that detects links that go to the same URL and adds a CSS class.
  4. Write a tiny hook that detects relative links and add a CSS class for styling.

It's unfortunate that $13k monthly isn't sufficient for such a feature.

Okay. I'm going to explain it once and for all. You might not be aware of the fact that $13k a month is not what's going on my bank account. In fact, you can read in our sponsorship FAQ how we use funds. In short: sponsoring several upstream projects, sponsoring several MkDocs plugin maintainers, paying individuals that we add to our core team (we started to build a team), and taxes (a huge fraction, and yes, we also have to pay them). From the rest, I put bread on my table and dare to go on a vacation from time to time. I hope that is okay for you. Material for MkDocs currently is my day job, and we try to grow a sustainable ecosystem around it, adding more (wo)man power to cope with the increasing demand for change requests and user support, a large fraction notably by users that do not financially support us.

I'm going to leave it here and lock this thread now, because I've clearly explained the reasoning behind it and gave several possible workarounds. Please respect that. Thank you.