diff --git a/docs/src/components/ModelConfigDropdown/index.jsx b/docs/src/components/ModelConfigDropdown/index.jsx index 7ac7350d25..737f47ec23 100644 --- a/docs/src/components/ModelConfigDropdown/index.jsx +++ b/docs/src/components/ModelConfigDropdown/index.jsx @@ -17,36 +17,77 @@ marked.setOptions({ gfm: true }); * @property {string} yaml Raw YAML for the configuration step. */ +// Render a markdown string to React nodes. Fenced code blocks become Docusaurus +// CodeBlock components (so they get syntax highlighting and a copy button); +// everything else is marked-parsed to HTML. +function renderBlocks(md, keyPrefix) { + if (!md.trim()) return []; + const tokens = marked.lexer(md); + const nodes = []; + let buffer = []; + let idx = 0; + + const flush = () => { + if (buffer.length) { + buffer.links = tokens.links; + nodes.push( +
, + ); + buffer = []; + } + }; + + tokens.forEach((token) => { + if (token.type === "code") { + flush(); + const language = (token.lang || "text").split(/\s+/)[0]; + nodes.push( + + {token.text} + , + ); + } else { + buffer.push(token); + } + }); + flush(); + return nodes; +} + // marked does not understand Docusaurus admonitions (:::warning ... :::), so -// render those blocks ourselves and marked-parse everything around them. +// render those blocks ourselves and render everything around them normally. function renderMarkdown(md) { - if (!md) return ""; + if (!md) return null; const admonition = /:::(\w+)[ \t]*([^\n]*)\n([\s\S]*?)\n:::/g; - let html = ""; + const nodes = []; let lastIndex = 0; let match; + let k = 0; while ((match = admonition.exec(md)) !== null) { - html += marked.parse(md.slice(lastIndex, match.index)); + nodes.push(...renderBlocks(md.slice(lastIndex, match.index), `seg${k}`)); const [, type, title, body] = match; const heading = (title || type).trim(); - html += - `
` + - `
${heading}
` + - marked.parse(body) + - `
`; + nodes.push( +
+
{heading}
+ {renderBlocks(body, `adm${k}`)} +
, + ); lastIndex = admonition.lastIndex; + k++; } - html += marked.parse(md.slice(lastIndex)); - return html; + nodes.push(...renderBlocks(md.slice(lastIndex), `seg${k}`)); + return nodes; } function Markdown({ children }) { - return ( -
- ); + return
{renderMarkdown(children)}
; } function RecommendedBadge() { diff --git a/docs/src/components/ModelConfigDropdown/styles.module.css b/docs/src/components/ModelConfigDropdown/styles.module.css index a26321eff2..06f0333344 100644 --- a/docs/src/components/ModelConfigDropdown/styles.module.css +++ b/docs/src/components/ModelConfigDropdown/styles.module.css @@ -9,8 +9,9 @@ /* --- Dropdown button --- */ .dropdown { - display: block; - width: 100%; + display: inline-block; + width: 360px; + max-width: 100%; text-align: left; border: 1px solid var(--ifm-color-emphasis-400); border-radius: 8px; @@ -71,13 +72,16 @@ display: flex; justify-content: space-between; align-items: center; - padding: 0.75rem 1rem; + gap: 1rem; + padding: 0.8rem 1rem; } /* --- Model menu --- */ .menu { margin-top: 0.25rem; + width: 360px; + max-width: 100%; border: 1px solid var(--ifm-color-emphasis-400); border-radius: 8px; overflow: hidden; @@ -133,6 +137,7 @@ display: flex; align-items: center; gap: 0.5rem; + white-space: nowrap; } .recommendedBadge { @@ -189,10 +194,8 @@ .stepTitle { margin: 0 0 0.75rem 0; - font-size: 0.8rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.5px; + font-size: 1rem; + font-weight: 600; color: var(--ifm-font-color-base); } @@ -220,10 +223,6 @@ font-size: 0.85rem; } -.markdown pre { - font-size: 0.8rem; -} - /* Docusaurus-style admonitions rendered from markdown. */ .admonition {