micronaut-openapi icon indicating copy to clipboard operation
micronaut-openapi copied to clipboard

Override templates to add branding

Open mariogarcia opened this issue 3 years ago • 4 comments

Feature description

Hi

First of all, thanks for all the great work.

The use case I'm trying to achieve is to add a brand logo in the generated rapidoc page. I think it makes sense to have some branding, specially when a company, for example, wants to expose its REST API in a sandbox for developers, you'd normally see at least the company's logo.

Taking a look to the rapidoc documentation it seems that the only way of adding a header logo is to add some tags inside the rapidoc tag. The actual micronaut-openapi-rapidoc documentation only allows me to add attributes to the rapidoc tag but I didn't see anything on how to add a custom tag. Here some examples:

Adding a logo Adding custom HTML

Is there any way to do this at the moment ?

Versions:

  • micronaut-core: 2.5.4
  • micronaut-openapi:2.4.0
  • jdk 11.0.11
  • Linux

mariogarcia avatar Aug 15 '21 16:08 mariogarcia

There are two approaches:

  • Allow to pass more parameters/options to be included in the <rapi-doc>xxxx</rapi-doc> tags
  • Allow to have a custom template on the project instead of using the one in this library.

For the second approach I've tried to have my own custom template in a test application but when trying to read the file here https://github.com/micronaut-projects/micronaut-openapi/blob/530914d46848340f5992469c49faf700d7e6d258/openapi/src/main/java/io/micronaut/openapi/view/OpenApiViewConfig.java#L145 it was always null.

As a workaround you could have your custom "expanded" template (the one generated by Micronaut OpenAPI) in a directory in your application like template/index.html with the logo or any other customization you want. Then create the following Gradle task:

task copyCustomRapidocTemplate(type: Copy) {
    from "template/index.html"
    into "build/classes/java/main/META-INF/swagger/views/rapidoc/"
    include '**/*.html'
}

classes {
    dependsOn(copyCustomRapidocTemplate)
}

With that, when running the application or packaging it as a fatjar, the copyCustomRapidocTemplate will be executed and will replace the index.html create by Micronaut with your own custom one. Of course you need to make sure your index.html has everything defined properly (tags, rapidoc options,...).

ilopmar avatar Aug 16 '21 11:08 ilopmar

How can we add Logo and company name for swagger documentation?

anandjaisy avatar Aug 17 '21 11:08 anandjaisy

@anandjaisy following the same workaround I explained but using the swagger-ui index.html file generated in your project instead of the rapidoc one.

ilopmar avatar Aug 17 '21 11:08 ilopmar

For rapidoc I did as @ilopmar mentioned,

I created the following template index.html (see below) and put it in the templates path directory in my project root dir so that the micronaut-openapi could pick it up from there and use it at runtime.

<!doctype html>
<!-- Important: must specify, else rendering will be effected -->
<html>
<head>
    <title>my-api-1.0.0</title>
    <!-- Important: The Custom element uses utf8 characters -->
    <meta charset='utf-8' />
    <meta name='viewport' content='width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes' />
    <script src='https://unpkg.com/rapidoc/dist/rapidoc-min.js'></script>
    <style>
        .index-header {
            display: flex;
            align-content: space-between;
        }

        .index-header .logo {
          align-self: center;
          margin-left: auto;
        }

        .index-header h2 {
            margin-bottom: 0;
        }
    </style>
</head>
<body>
    <rapi-doc id='rapidoc' layout="row" sort-tags="true" sort-endpoints-by="method" show-header="false" theme="dark">
        <div slot="nav-logo" class="index-header">
            <div class="title">
                <h2>MYAPP</h2>
                <p>An Incredible APP!</p>
            </div>
            <div class="logo">
                <object data="/rapidoc/toolbox.svg" type="image/svg+xml" width="70"></object>
            </div>
        </div>
    </rapi-doc>
    <script>
            const extract = function(v) {
                    return decodeURIComponent(v.replace(/(?:(?:^|.*;\s*)contextPath\s*\=\s*([^;]*).*$)|^.*$/, "$1"));
                },
                cookie = extract(document.cookie),
                contextPath = cookie === '' ? extract(window.location.search.substring(1)) : cookie,
                rapidoc = document.getElementById('rapidoc');
            if (contextPath !== '') {
                rapidoc.addEventListener('spec-loaded', e => {
                    e.detail.tags.forEach(tag => tag.paths.forEach(path => path.path = contextPath + path.path));
                    rapidoc.requestUpdate();
                });
            }
            rapidoc.setAttribute('spec-url', contextPath + '/swagger/my-api-1.0.0.yml');

        </script>
</body>
</html>

There are parts that would be different in your use case of course. The only things I added were:

  • <style/> content
  • All tags inside <rapi-doc/>
  • Added an image at the same directory as the template
<object data="/rapidoc/toolbox.svg" type="image/svg+xml" width="70"></object>

To make the image available at runtime you should put the toolbox.svg file in the same directory you put your index.html template and modify the copy script to include everything in the template's directory:

task copyCustomRapidocTemplate(type: Copy) {
    from "template"
    into "build/classes/java/main/META-INF/swagger/views/rapidoc/"
    include '**/*.*' // NOW IT INCLUDES THE IMAGE AS WELL!!!
}

classes {
    dependsOn(copyCustomRapidocTemplate)
}

mariogarcia avatar Aug 17 '21 14:08 mariogarcia

@graemerocher Could you close this issue? It fixed in version 4.8.0

altro3 avatar Dec 07 '22 21:12 altro3