diff --git a/assets/js/components/rapidoc-mini.ts b/assets/js/components/rapidoc-mini.ts index 5e3f63759..fba66fb47 100644 --- a/assets/js/components/rapidoc-mini.ts +++ b/assets/js/components/rapidoc-mini.ts @@ -293,6 +293,127 @@ function createRapiDocElement( return element; } +/** + * Inject custom styles into RapiDoc's shadow DOM + * Removes the top border and reduces whitespace above operations + */ +function injectShadowStyles(element: HTMLElement): void { + const tryInject = (): boolean => { + const shadowRoot = (element as unknown as { shadowRoot: ShadowRoot | null }) + .shadowRoot; + if (!shadowRoot) return false; + + // Check if styles already injected + if (shadowRoot.querySelector('#rapidoc-custom-styles')) return true; + + const style = document.createElement('style'); + style.id = 'rapidoc-custom-styles'; + style.textContent = ` + /* Hide the operation divider line */ + .divider[part="operation-divider"] { + display: none !important; + } + + /* Reduce spacing above operation sections */ + .section-gap { + padding-top: 0 !important; + } + + /* Hide RapiDoc's built-in security section - we show our own */ + /* Target the authorization requirements shown near each operation */ + .api-key, + .api-key-info, + .security-info-button, + [class*="api-key"], + [class*="security-info"], + .m-markdown-small:has(.lock-icon), + div:has(> .lock-icon), + /* Target the section showing "AUTHORIZATIONS:" or similar */ + .req-resp-container > div:first-child:has(svg[style*="lock"]), + /* Target lock icons and their parent containers */ + svg.lock-icon, + .lock-icon, + /* Wide selectors for security-related elements */ + [part="section-operation-security"], + .expanded-endpoint-body > div:first-child:has([class*="lock"]) { + display: none !important; + } + `; + shadowRoot.appendChild(style); + + // Hide security badge elements by examining content + const hideSecurityBadge = () => { + // Find elements containing security-related text and hide their container + const allElements = shadowRoot.querySelectorAll('span, div'); + allElements.forEach((el) => { + const text = el.textContent?.trim(); + // Find leaf elements that contain authorization-related text + if ( + el.children.length === 0 && + (text === 'HTTP Bearer' || + text === 'Bearer' || + text === 'AUTHORIZATIONS:' || + text === 'Authorization' || + text === 'api_token' || + text === 'BearerAuthentication') + ) { + // Walk up the DOM to find a suitable container to hide + // This hides both the text AND any sibling icons (like lock) + let target: HTMLElement = el as HTMLElement; + let parent: HTMLElement | null = el.parentElement; + let depth = 0; + while (parent && depth < 4) { + // Stop at reasonable container boundaries + if ( + parent.classList.contains('expanded-endpoint-body') || + parent.classList.contains('req-resp-container') || + parent.tagName === 'SECTION' + ) { + break; + } + target = parent; + parent = parent.parentElement; + depth++; + } + target.style.display = 'none'; + } + }); + }; + + // Run immediately and after delays for dynamic content + hideSecurityBadge(); + setTimeout(hideSecurityBadge, 300); + setTimeout(hideSecurityBadge, 800); + + // Watch for dynamically added security elements + const observer = new MutationObserver(() => { + hideSecurityBadge(); + }); + observer.observe(shadowRoot, { + childList: true, + subtree: true, + }); + + // Disconnect after 5 seconds to avoid performance issues + setTimeout(() => observer.disconnect(), 5000); + + return true; + }; + + // Try immediately + if (tryInject()) return; + + // Retry a few times as shadow DOM may not be ready + let attempts = 0; + const maxAttempts = 10; + const interval = setInterval(() => { + attempts++; + if (tryInject() || attempts >= maxAttempts) { + clearInterval(interval); + } + }, 100); +} + /** * Watch for theme changes and update RapiDoc element */ @@ -398,6 +519,9 @@ export default async function RapiDocMini({ const rapiDocElement = createRapiDocElement(specUrl, matchPaths, title); component.appendChild(rapiDocElement); + // Inject custom styles into shadow DOM to remove borders/spacing + injectShadowStyles(rapiDocElement); + // Watch for theme changes and return cleanup function return watchThemeChanges(component); } catch (error) { diff --git a/assets/styles/layouts/_api-security-schemes.scss b/assets/styles/layouts/_api-security-schemes.scss index 325ec2fa2..a80acb7fb 100644 --- a/assets/styles/layouts/_api-security-schemes.scss +++ b/assets/styles/layouts/_api-security-schemes.scss @@ -48,7 +48,8 @@ margin: 0; code { - background: $g3-castle; + background: $article-code-bg; + color: $article-code; padding: 0.2em 0.5em; border-radius: 3px; font-size: 0.9em; @@ -78,10 +79,26 @@ // Positioned above RapiDoc, integrates with "Try it" via JavaScript API. //////////////////////////////////////////////////////////////////////////////// +.api-auth-row { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 0.5rem; +} + .api-auth-trigger-wrapper { position: relative; display: inline-block; - margin-bottom: 1rem; +} + +.api-auth-schemes { + font-size: 0.85rem; + color: $g9-mountain; + + .api-auth-label { + font-weight: 400; + opacity: 0.8; + } } .api-auth-trigger { @@ -340,6 +357,10 @@ // Dark theme overrides [data-theme="dark"], html:has(link[title="dark-theme"]:not([disabled])) { + .api-auth-schemes { + color: $g15-platinum; + } + .api-security-schemes { border-top-color: $grey25; @@ -352,10 +373,6 @@ html:has(link[title="dark-theme"]:not([disabled])) { dt { color: $g15-platinum; } - - dd code { - background: $grey20; - } } .scheme-description { diff --git a/layouts/api/single.html b/layouts/api/single.html index 11cb1810d..c9256b8dd 100644 --- a/layouts/api/single.html +++ b/layouts/api/single.html @@ -87,8 +87,10 @@ {{ end }} - {{/* Security Schemes from OpenAPI spec */}} + {{/* Security Schemes from OpenAPI spec (only show if showSecuritySchemes: true) */}} + {{ if .Params.showSecuritySchemes }} {{ partial "api/security-schemes.html" . }} + {{ end }} {{ else }} {{/* Operation Page - RapiDoc with custom slots */}} diff --git a/layouts/partials/api/rapidoc-mini.html b/layouts/partials/api/rapidoc-mini.html index 4ec33c568..7ac783151 100644 --- a/layouts/partials/api/rapidoc-mini.html +++ b/layouts/partials/api/rapidoc-mini.html @@ -41,25 +41,41 @@ {{ end }} -{{/* Auth credentials popover trigger - positioned above the operation */}} -