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 {