pinner 0.0.1

A CLI utility to hash-pin GitHub Actions
Documentation
<style>
#version-selector {
    padding: 10px 15px;
    border-bottom: 1px solid #454545;
    margin-bottom: 10px;
    font-size: 0.85em;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
#version-selector label {
    color: #888;
    font-weight: 600;
    white-space: nowrap;
    margin-right: 10px;
}
#version-selector select {
    background: #353535;
    color: #eee;
    border: 1px solid #454545;
    border-radius: 4px;
    padding: 2px 5px;
    cursor: pointer;
    outline: none;
    flex-grow: 1;
    max-width: 120px;
}
#version-selector select:hover {
    border-color: #666;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
    var pathParts = window.location.pathname.split("/");
    var versionIndex = -1;
    
    // Find the version segment (latest or vX.Y.Z)
    for (var i = 0; i < pathParts.length; i++) {
        if (pathParts[i] === "latest" || pathParts[i].match(/^v\d+/)) {
            versionIndex = i;
            break;
        }
    }

    if (versionIndex === -1) return;

    var currentVersion = pathParts[versionIndex];
    // Ensure rootPath is absolute (starts with /) and includes the repo name if hosted on gh-pages
    // For pinner, it might be /pinner/ or just /
    var rootPath = pathParts.slice(0, versionIndex).join("/") + "/";
    if (!rootPath.startsWith("/")) rootPath = "/" + rootPath;
    
    fetch(rootPath + "versions.json")
        .then(response => response.json())
        .then(versions => {
            var selectorDiv = document.createElement("div");
            selectorDiv.id = "version-selector";
            
            var label = document.createElement("label");
            label.innerHTML = "Version: ";
            selectorDiv.appendChild(label);
            
            var select = document.createElement("select");
            versions.forEach(function(v) {
                var option = document.createElement("option");
                option.value = v;
                option.text = v;
                if (v === currentVersion) {
                    option.selected = true;
                }
                select.appendChild(option);
            });
            
            select.onchange = function() {
                var newVersion = this.value;
                var currentPath = pathParts.slice(versionIndex + 1).join("/");
                window.location.href = rootPath + newVersion + "/" + currentPath;
            };
            
            selectorDiv.appendChild(select);
            
            function injectSelector() {
                var sidebarCrate = document.querySelector(".sidebar .location") || document.querySelector(".sidebar-elems .location");
                if (sidebarCrate) {
                    sidebarCrate.after(selectorDiv);
                    return true;
                }
                return false;
            }

            if (!injectSelector()) {
                var sidebar = document.querySelector(".sidebar");
                if (sidebar) {
                    sidebar.prepend(selectorDiv);
                } else {
                    document.body.insertBefore(selectorDiv, document.body.firstChild);
                }
            }
        })
        .catch(err => console.error("Could not load versions.json", err));
});
</script>