jimporter / mike

Manage multiple versions of your MkDocs-powered documentation via Git
BSD 3-Clause "New" or "Revised" License
536 stars 47 forks source link

Can mike add a banner for old doc versions? #26

Closed JulioV closed 3 years ago

JulioV commented 3 years ago

Can mike add a banner to let users know that they are looking at an old version of the docs (similar to readthedocs)? If not, what would be a good way to implement this functionality?

EDIT: Maybe by outputting the banner as a markdown file which can be injected on a template block depending on the theme (e.g. mkdocs-material announcement bar)?

jimporter commented 3 years ago

It should be pretty straightforward to customize the extra CSS/JS to do this. For the mkdocs theme, you'd just need to check if the current version is the most recent somewhere in here, and then maybe set an attribute on the <body> tag that your CSS does something with:

https://github.com/jimporter/mike/blob/fbb05bbd9f11c1fea2bec1621dce23640203aece/mike/themes/mkdocs/js/version-select.js#L45-L73

Of course, themes that have built-in support for mike could do something similar internally.

Broadly speaking, I consider mike to be feature complete (at least for the time being), so I'm not sure I'd want to add something like this to the repo. Ideally, themes that want to do more-advanced things like this can handle that on their end so that mike can remain focused on managing the files in your gh-pages branch.

JulioV commented 3 years ago

Thank you for the pointers! For anyone bumping into this issue and using the material-theme + its mike plugin I solved this problem by extending the theme and adding the following JS and CSS. Note that this relies on having a mike alias called latest.

window.addEventListener("DOMContentLoaded", function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", window.location + "../versions.json");
    xhr.onload = function() {
      var versions = JSON.parse(this.responseText);
      latest_version = ""
      for(id in versions)
          if(versions[id]["aliases"].length > 0 && versions[id]["aliases"].includes("latest")) 
              latest_version = "/" + versions[id].version + "/"
      if(!window.location.pathname.includes("/latest/") && (latest_version.length > 0 && !window.location.pathname.includes(latest_version)))
          document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>You are seeing the docs for a previous version of RAPIDS, <a href='" + window.location.href + "latest/'>click here to go to the latest</a></div>"
    };
    xhr.send();
  });
div[data-md-component=announce] {
    background-color: rgba(255,145,0,.1);
}
div[data-md-component=announce]>div#announce-msg{
    color: var(--md-admonition-fg-color);
    font-size: .8rem;
    text-align: center;
    margin: 15px;
}
div[data-md-component=announce]>div#announce-msg>a{
    color: var(--md-typeset-a-color);
    text-decoration: underline;
}
jimporter commented 3 years ago

@JulioV It might be worth filing an issue with the mkdocs-material project to suggest this if you haven't already. I'd be happy to help provide guidance on ways to determine what version is the "latest", although I don't think I'd have time to write a full patch.

One thing to note: if you also host pre-release docs, they'd get the warning message (I think). To handle this, you could get the index of the "latest" docs, and anything with a smaller index is a pre-release. Whether you'd want to hide the message entirely or just show a different message in that case is up to you though. :) (For a mkdocs-material patch, I could see that being a configurable option.)

JulioV commented 3 years ago

@jimporter could you add some pointers to the best way to implement this feature in this material theme issue? https://github.com/squidfunk/mkdocs-material/issues/2084 Much appreciated, thanks!

miguno commented 3 years ago

FWIW here is adapted JavaScript of https://github.com/jimporter/mike/issues/26#issuecomment-730043664 that I am using:

// Show warning banner when displaying old content versions
window.addEventListener("DOMContentLoaded", function() {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/versions.json");
    xhr.onload = function() {
        var versions = JSON.parse(this.responseText);
        latest_version = ""
        for (id in versions) {
            if (versions[id]["aliases"].length > 0 && versions[id]["aliases"].includes("latest")) {
                latest_version = "/" + versions[id].version + "/";
            }
        }
        if (!window.location.pathname.includes("/latest/") && (latest_version.length > 0 && !window.location.pathname.includes(latest_version))) {
            document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>This documentation is for a previous version. We recommend you <a href='/latest/'>use the latest</a>.</div>";
        }
    };
    xhr.send();
});

The main change is the use of absolute links (/versions.json, /latest/) instead of relative links (../versions.json, window.location.href + "latest/") so that the warning keeps being displayed, even when the visitor enters deeper into the page hierarchy. In the original JavaScript above, the warning would be displayed on the page/1.2/ but not for the page /1.2/foo.