* Add Security docs section, SEO improvements, and doc site enhancements - Add Authorization guide covering per-server and per-tool OAuth patterns - Add CSP & CORS guide extracted from Patterns doc - Group both under a new Security section in the documentation nav - Replace CSP & CORS section in Patterns with cross-reference to new guide - Rename doc site title from package name to 'MCP Apps' - Rename 'Modules' nav section to 'API Documentation' - Ensure Security section appears before API Documentation in TOC - Add SEO plugin with JSON-LD structured data (TechArticle/WebPage) - Add per-page meta descriptions from frontmatter - Add description frontmatter to all documentation pages - Add hostedBaseUrl for sitemap.xml generation and canonical URLs - Normalize document page slugs to lowercase hyphenated format - Update compressed navigation and search index data to match new slugs * Add favicons with light/dark mode support - Download favicons from modelcontextprotocol.io (light + dark variants) - Inject favicon link tags into every page with correct relative paths - Support prefers-color-scheme media queries for light/dark mode - Include apple-touch-icon for iOS - Copy favicon assets to output directory during doc build * Fix HTML sanitization in SEO plugin with proper parser Replace regex-based HTML tag stripping with htmlparser2 for extracting plain-text descriptions from rendered pages. * Add custom theme to align with modelcontextprotocol.io styling - Import Inter and JetBrains Mono fonts (matching MCP site) - Override light mode colors: pure white backgrounds, softer gray borders - Override dark mode colors: match MCP site dark background (#0f1117) - Taller header (3.5rem) with backdrop-blur frosted glass effect - Sidebar: adjusted spacing, font size, and hover/active states - Content: increased line-height (1.6), more heading breathing room - Code blocks: JetBrains Mono, subtle border, more padding - Fix CSS load order: custom.css now loads after theme stylesheets * Align sidebar nav styling with modelcontextprotocol.io - Active item: tinted blue background with blue text (matching MCP's primary-color tinted active state) - Non-active items: muted gray text, subtle hover background - Larger border-radius (0.75rem/rounded-xl) matching MCP sidebar - Group headers: semibold with slight letter spacing - Proper dark mode variants for all states * Fix sidebar active item: dark gray background with bold text * Make sidebar active item more prominent: bolder weight, stronger background * Highlight current page in sidebar nav, normalize code font size Inject a small script via the SEO plugin that marks the active sidebar link with a "current" class (TypeDoc doesn't do this natively for document pages). Uses a MutationObserver since the sidebar is populated asynchronously. Pathname comparison strips .html extensions to support clean-URL servers. Also bumps code/pre font-size from 0.85em to 1em so code snippets match the surrounding body text size. * Split styling into dedicated plugin, fix auth terminology, improve breadcrumbs Extract CSS cascade fix, breadcrumb labels, and sidebar nav highlighting from the SEO plugin into a new typedoc-plugin-mcpstyle.mjs to keep concerns separated. Fix authorization doc: use "authorization" consistently instead of mixing with "authentication", link to MCP spec and RFC 9728 for Protected Resource Metadata, remove redundant spec link paragraph. Rename "Documents" nav section to "Getting Started" and add explicit group frontmatter to all doc pages. Breadcrumbs now show the section name instead of duplicating the page title.
53 lines
2.6 KiB
JavaScript
53 lines
2.6 KiB
JavaScript
/**
|
|
* TypeDoc plugin that applies MCP-specific styling tweaks.
|
|
*
|
|
* - Moves custom.css to load last so overrides win the cascade
|
|
* - Replaces breadcrumbs with the document group name (e.g. "Security")
|
|
* - Marks the current sidebar nav link for CSS highlighting
|
|
*/
|
|
|
|
import { Renderer } from "typedoc";
|
|
|
|
/**
|
|
* TypeDoc plugin entry point.
|
|
* @param {import('typedoc').Application} app
|
|
*/
|
|
export function load(app) {
|
|
app.renderer.on(Renderer.EVENT_END_PAGE, (page) => {
|
|
if (!page.contents) return;
|
|
|
|
// Move custom.css to load after all theme stylesheets so overrides win the cascade
|
|
const customCssLink = page.contents.match(
|
|
/<link rel="stylesheet" href="[^"]*custom\.css"\/>/,
|
|
);
|
|
if (customCssLink) {
|
|
page.contents = page.contents.replace(customCssLink[0], "");
|
|
page.contents = page.contents.replace(
|
|
"</head>",
|
|
customCssLink[0] + "\n</head>",
|
|
);
|
|
}
|
|
|
|
// For document pages, replace the breadcrumb with the group name
|
|
// (e.g. "Security", "Getting Started"). The page title is in the H1.
|
|
if (page.model?.isDocument?.() && page.model.frontmatter?.group) {
|
|
const group = String(page.model.frontmatter.group);
|
|
page.contents = page.contents.replace(
|
|
/<ul class="tsd-breadcrumb"[^>]*>.*?<\/ul>/,
|
|
`<ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><span>${group}</span></li></ul>`,
|
|
);
|
|
}
|
|
|
|
// Inject script to mark the current sidebar nav link with a "current" class.
|
|
// TypeDoc does not natively add this class for document pages.
|
|
// The sidebar is populated asynchronously from compressed navigation data,
|
|
// so we use a MutationObserver to detect when links appear.
|
|
// Pathname comparison strips trailing slashes and .html extensions to handle
|
|
// servers with clean-URL mode (e.g. `serve` drops .html).
|
|
const currentNavScript = `<script>(function(){function norm(s){return s.replace(/\\/$/,"").replace(/\\.html$/,"");}function mark(){var p=norm(location.pathname);var links=document.querySelectorAll(".site-menu .tsd-navigation a[href]");for(var i=0;i<links.length;i++){var h=norm(new URL(links[i].href,location.href).pathname);if(h===p){links[i].classList.add("current");return true;}}return false;}function init(){if(!mark()){var c=document.getElementById("tsd-nav-container");if(c){new MutationObserver(function(m,o){if(mark())o.disconnect();}).observe(c,{childList:true,subtree:true});}}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script>`;
|
|
page.contents = page.contents.replace(
|
|
"</body>",
|
|
currentNavScript + "\n</body>",
|
|
);
|
|
});
|
|
}
|