refactor(api): Replace inline JS with data-component in rapidoc.html
Remove ~230 lines of inline JavaScript and use the new api-rapidoc TypeScript component via data-component attribute instead.worktree-2025-12-30T19-16-55
parent
15bf7ec3ce
commit
b5cf8967f5
|
|
@ -30,7 +30,7 @@
|
|||
<link rel="alternate" type="application/json" href="{{ $specPathJSON | absURL }}" title="OpenAPI Specification (JSON)" />
|
||||
{{ end }}
|
||||
|
||||
<div class="api-reference-wrapper">
|
||||
<div class="api-reference-wrapper" data-component="api-rapidoc">
|
||||
{{/* RapiDoc component with slot-based customization */}}
|
||||
<rapi-doc
|
||||
id="api-doc"
|
||||
|
|
@ -94,235 +94,6 @@
|
|||
{{/* Load RapiDoc from CDN */}}
|
||||
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
console.log('[RapiDoc] Script loaded');
|
||||
|
||||
// Detect current theme by checking which theme stylesheet is enabled
|
||||
function isDarkTheme() {
|
||||
// Check for enabled dark-theme stylesheet
|
||||
const darkStylesheet = document.querySelector('link[rel*="stylesheet"][title="dark-theme"]:not([disabled])');
|
||||
if (darkStylesheet && !darkStylesheet.disabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: check for data-theme attribute (some pages may use this)
|
||||
if (document.documentElement.dataset.theme === 'dark') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: check localStorage preference
|
||||
try {
|
||||
const stored = localStorage.getItem('defined_style_preference');
|
||||
if (stored) {
|
||||
const prefs = JSON.parse(stored);
|
||||
return prefs.theme === 'dark';
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore localStorage errors
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update RapiDoc theme based on document theme
|
||||
function updateRapiDocTheme() {
|
||||
const rapiDoc = document.getElementById('api-doc');
|
||||
if (!rapiDoc) return;
|
||||
|
||||
const isDark = isDarkTheme();
|
||||
|
||||
if (isDark) {
|
||||
// Match Hugo dark theme: $grey10: #14141F
|
||||
rapiDoc.setAttribute('theme', 'dark');
|
||||
rapiDoc.setAttribute('bg-color', '#14141F');
|
||||
rapiDoc.setAttribute('text-color', '#D4D7DD');
|
||||
rapiDoc.setAttribute('header-color', '#D4D7DD');
|
||||
rapiDoc.setAttribute('primary-color', '#a0a0ff');
|
||||
rapiDoc.setAttribute('nav-bg-color', '#1a1a2a');
|
||||
rapiDoc.setAttribute('nav-text-color', '#D4D7DD');
|
||||
rapiDoc.setAttribute('nav-hover-bg-color', '#252535');
|
||||
rapiDoc.setAttribute('nav-hover-text-color', '#ffffff');
|
||||
rapiDoc.setAttribute('nav-accent-color', '#a0a0ff');
|
||||
rapiDoc.setAttribute('code-theme', 'monokai');
|
||||
} else {
|
||||
// Match Hugo light theme: $g20-white: #FFFFFF
|
||||
rapiDoc.setAttribute('theme', 'light');
|
||||
rapiDoc.setAttribute('bg-color', '#ffffff');
|
||||
rapiDoc.setAttribute('text-color', '#2b2b2b');
|
||||
rapiDoc.setAttribute('header-color', '#020a47');
|
||||
rapiDoc.setAttribute('primary-color', '#020a47');
|
||||
rapiDoc.setAttribute('nav-bg-color', '#f7f8fa');
|
||||
rapiDoc.setAttribute('nav-text-color', '#2b2b2b');
|
||||
rapiDoc.setAttribute('nav-hover-bg-color', '#e8e8f0');
|
||||
rapiDoc.setAttribute('nav-hover-text-color', '#020a47');
|
||||
rapiDoc.setAttribute('nav-accent-color', '#020a47');
|
||||
rapiDoc.setAttribute('code-theme', 'prism');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', updateRapiDocTheme);
|
||||
} else {
|
||||
updateRapiDocTheme();
|
||||
}
|
||||
|
||||
// Set custom CSS properties for input border styling
|
||||
function setInputBorderStyles() {
|
||||
const rapiDoc = document.getElementById('api-doc');
|
||||
if (!rapiDoc) {
|
||||
console.log('[RapiDoc] Element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Set CSS custom property on the rapi-doc element
|
||||
// This will penetrate the shadow DOM
|
||||
rapiDoc.style.setProperty('--border-color', '#00A3FF');
|
||||
console.log('[RapiDoc] Set --border-color to #00A3FF');
|
||||
}
|
||||
|
||||
// Wait for RapiDoc custom element to be fully defined
|
||||
if (customElements && customElements.whenDefined) {
|
||||
customElements.whenDefined('rapi-doc').then(() => {
|
||||
console.log('[RapiDoc] Custom element defined');
|
||||
setInputBorderStyles();
|
||||
// Set again after render
|
||||
setTimeout(setInputBorderStyles, 500);
|
||||
});
|
||||
} else {
|
||||
// Fallback for older browsers
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', setInputBorderStyles);
|
||||
} else {
|
||||
setInputBorderStyles();
|
||||
}
|
||||
setTimeout(setInputBorderStyles, 500);
|
||||
}
|
||||
|
||||
// Watch for stylesheet changes (theme toggles enable/disable stylesheets)
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
// Check if a stylesheet's disabled attribute changed
|
||||
if (mutation.type === 'attributes' &&
|
||||
mutation.target.tagName === 'LINK' &&
|
||||
mutation.target.title &&
|
||||
mutation.target.title.includes('theme')) {
|
||||
updateRapiDocTheme();
|
||||
}
|
||||
// Also watch for data-theme changes as a fallback
|
||||
if (mutation.attributeName === 'data-theme') {
|
||||
updateRapiDocTheme();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Observe the head element for stylesheet changes
|
||||
observer.observe(document.head, {
|
||||
attributes: true,
|
||||
attributeFilter: ['disabled'],
|
||||
subtree: true
|
||||
});
|
||||
|
||||
// Also observe the document element for data-theme changes
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
|
||||
// Hide "Expand all | Collapse all" controls and Overview section inside shadow DOM
|
||||
function hideExpandCollapseControls() {
|
||||
const rapiDoc = document.getElementById('api-doc');
|
||||
if (!rapiDoc) return;
|
||||
|
||||
// Wait for RapiDoc to render, try multiple times
|
||||
let attempts = 0;
|
||||
const maxAttempts = 10;
|
||||
|
||||
const tryHide = function() {
|
||||
attempts++;
|
||||
try {
|
||||
const shadowRoot = rapiDoc.shadowRoot;
|
||||
if (!shadowRoot) {
|
||||
if (attempts < maxAttempts) {
|
||||
setTimeout(tryHide, 500);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Find all elements in shadow DOM and hide those containing "Expand all"
|
||||
const allElements = shadowRoot.querySelectorAll('*');
|
||||
let hiddenCount = 0;
|
||||
|
||||
allElements.forEach(function(element) {
|
||||
const text = element.textContent || '';
|
||||
|
||||
// Check if element contains "Expand all", "Collapse all"
|
||||
if (text.includes('Expand all') || text.includes('Collapse all')) {
|
||||
// Hide the element and its parent containers
|
||||
element.style.display = 'none';
|
||||
if (element.parentElement) {
|
||||
element.parentElement.style.display = 'none';
|
||||
}
|
||||
hiddenCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// Separately target all headings and hide those with "Overview"
|
||||
const headings = shadowRoot.querySelectorAll('h1, h2, h3, h4');
|
||||
headings.forEach(function(heading) {
|
||||
const text = (heading.textContent || '').trim();
|
||||
const innerText = (heading.innerText || '').trim();
|
||||
|
||||
// Log for debugging
|
||||
if (text.includes('Overview') || innerText.includes('Overview')) {
|
||||
console.log('[RapiDoc] Found heading:', heading.tagName, 'with text:', text, 'innerText:', innerText);
|
||||
heading.style.display = 'none';
|
||||
hiddenCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// Also inject CSS as backup to hide Overview sections
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
/* Hide Overview section and headings */
|
||||
.section-gap.section-tag,
|
||||
[id*="overview"],
|
||||
.regular-font.section-gap:empty,
|
||||
h1:empty, h2:empty, h3:empty {
|
||||
display: none !important;
|
||||
}
|
||||
`;
|
||||
shadowRoot.appendChild(style);
|
||||
|
||||
console.log('[RapiDoc] Hidden ' + hiddenCount + ' elements containing expand/collapse text (attempt ' + attempts + ')');
|
||||
|
||||
if (hiddenCount === 0 && attempts < maxAttempts) {
|
||||
// Try again if nothing was hidden
|
||||
setTimeout(tryHide, 500);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[RapiDoc] Could not access shadow DOM:', e);
|
||||
if (attempts < maxAttempts) {
|
||||
setTimeout(tryHide, 500);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(tryHide, 500);
|
||||
}
|
||||
|
||||
// Call after RapiDoc initializes
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', hideExpandCollapseControls);
|
||||
} else {
|
||||
hideExpandCollapseControls();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.api-reference-wrapper {
|
||||
width: 100%;
|
||||
|
|
|
|||
Loading…
Reference in New Issue