blueswen / mkdocs-swagger-ui-tag

A MkDocs plugin supports adding Swagger UI to the page.
https://blueswen.github.io/mkdocs-swagger-ui-tag/
MIT License
79 stars 8 forks source link

Anchor links to API calls #24

Open MakarovYaroslav opened 7 months ago

MakarovYaroslav commented 7 months ago

Hello! Thanks for the cool plugin.

In the typical Swagger UI doc, when you click on a certain API request description, an anchor link to that request appears in the browser URL. This link can then be used to go directly to the desired API request description.

Example: https://petstore.swagger.io/#/store/getInventory

The current version of the plugin doesn't have this functionality (or I'm doing something wrong). Can you improve the plugin?

tabularasa31 commented 5 months ago

+1 very important

SirGrigory commented 3 months ago

+1

Anatoliy057 commented 2 months ago

Hello all who have come across such a need

I wrote a script that adds navigation (works roughly like in the latest swagger implementation). This is certainly not the best solution, but as a temporary measure, until the plugin will not add it out of the box, may will do.

function scroll() {
    let iframe = document.querySelector("iframe")
    let doc = null
    if(iframe == null) {
        doc = document
    } else {
        doc = iframe.contentDocument
    }

    let href = window.location.hash.substring(1).toLowerCase()

    if(href.length == 0) {
        return
    }

    let anchor = doc.getElementById(href)

    if(anchor == null || anchor.getAttribute("is-anchor") != "true") {
        return
    }
    anchor.scrollIntoView({behavior: "smooth", block: "center"})

    let anchor_parent = anchor.parentElement
    let btn = anchor_parent.querySelector(".opblock-control-arrow, .expand-operation")
    if(btn != null) {
        if(!anchor_parent.classList.contains("is-open") && anchor_parent.getAttribute("data-is-open") != "true") {
            btn.click()
        }
    }
}

function setUpAnchors() {
    iframe = document.querySelector("iframe")
    let doc = null
    if(iframe == null) {
        doc = document
    } else {
        doc = iframe.contentDocument
    }

    let refs = doc.querySelectorAll(".opblock-tag, .opblock")
    for(let i = 0; i < refs.length; i++) {
        let ref = refs[i]
        let href = ''
        let anchor = doc.createElement("a")
        if(ref.tagName.toLowerCase().includes("h")) {
            href = ref.id.substring(ref.id.lastIndexOf('-') + 1)
            href = "/" + href[0].toLowerCase() + href.substring(1)
            let lhref = href.toLowerCase()
            anchor.id = lhref
            anchor.href = "#" + lhref
        } else if (ref.tagName.toLowerCase() == "div") {
            href = ref.id.substring(ref.id.indexOf('-') + 1).replace('-', '/')
            href = "/" + href[0].toLowerCase() + href.substring(1)
            let lhref = href.toLowerCase()
            anchor.id = lhref
            anchor.href = "#" + lhref
        }
        anchor.setAttribute('is-anchor', "true")
        ref.appendChild(anchor)

        setUpButtons(ref, href)
    }
}

function setUpButtons(btn, href) {
    btn.addEventListener("click", function(event){
        window.location.href = "#" + href
    });
}

document.querySelector('iframe').onload = function() {
    setTimeout(function() {
        setUpAnchors();
        scroll();
    }, 1000);
}
<swagger-ui src="path/to/openapi.json"/>

<script src="path/to/script.js" defer></script>