refactor: convert MarkdownContent to server component, remove context
This commit is contained in:
@@ -1,15 +1,8 @@
|
|||||||
"use client";
|
import React from "react";
|
||||||
|
|
||||||
import React, { createContext, useContext } from "react";
|
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import type { Components } from "react-markdown";
|
import type { Components } from "react-markdown";
|
||||||
import type { Element } from "hast";
|
import type { Element } from "hast";
|
||||||
|
|
||||||
// Lets the `code` renderer know it's inside a `pre` block vs. inline.
|
|
||||||
// React renders parent-to-child, so the Provider in `pre` is active
|
|
||||||
// when `code` renders inside it.
|
|
||||||
const InsidePreContext = createContext(false);
|
|
||||||
|
|
||||||
function GoldDot() {
|
function GoldDot() {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
@@ -72,40 +65,6 @@ function extractHastText(node: Element): string {
|
|||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function CodeRenderer({ children }: { children?: React.ReactNode }) {
|
|
||||||
const insidePre = useContext(InsidePreContext);
|
|
||||||
|
|
||||||
if (insidePre) {
|
|
||||||
return (
|
|
||||||
<code
|
|
||||||
style={{
|
|
||||||
fontFamily: "var(--font-mono, 'Geist Mono', monospace)",
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
color: "#e2e8f0",
|
|
||||||
lineHeight: 1.65,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</code>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<code
|
|
||||||
style={{
|
|
||||||
background: "rgba(250, 204, 21, 0.1)",
|
|
||||||
border: "1px solid rgba(250, 204, 21, 0.3)",
|
|
||||||
borderRadius: 5,
|
|
||||||
padding: "1px 7px",
|
|
||||||
color: "#fde68a",
|
|
||||||
fontFamily: "var(--font-mono, 'Geist Mono', monospace)",
|
|
||||||
fontSize: "0.875em",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</code>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const components: Components = {
|
const components: Components = {
|
||||||
h1: ({ children }) => (
|
h1: ({ children }) => (
|
||||||
@@ -286,10 +245,15 @@ const components: Components = {
|
|||||||
<em style={{ color: "#e2e8f0", fontStyle: "italic" }}>{children}</em>
|
<em style={{ color: "#e2e8f0", fontStyle: "italic" }}>{children}</em>
|
||||||
),
|
),
|
||||||
|
|
||||||
// `pre` wraps `code` for fenced code blocks. The Provider lets the
|
// `pre` reads code text directly from the HAST node so `code` renderer
|
||||||
// nested `code` renderer know it's in a block context (not inline).
|
// is only ever called for inline code — no client-side context needed.
|
||||||
pre: ({ children }) => (
|
pre: ({ node }) => {
|
||||||
<InsidePreContext.Provider value={true}>
|
const codeEl = node?.children?.[0] as Element | undefined;
|
||||||
|
const codeText = (codeEl?.children ?? [])
|
||||||
|
.filter((c): c is { type: "text"; value: string } => c.type === "text")
|
||||||
|
.map((c) => c.value)
|
||||||
|
.join("");
|
||||||
|
return (
|
||||||
<pre
|
<pre
|
||||||
style={{
|
style={{
|
||||||
background: "rgba(255, 255, 255, 0.04)",
|
background: "rgba(255, 255, 255, 0.04)",
|
||||||
@@ -301,12 +265,36 @@ const components: Components = {
|
|||||||
margin: "0 0 1.25rem 0",
|
margin: "0 0 1.25rem 0",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
<code
|
||||||
|
style={{
|
||||||
|
fontFamily: "var(--font-mono, 'Geist Mono', monospace)",
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
color: "#e2e8f0",
|
||||||
|
lineHeight: 1.65,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{codeText}
|
||||||
|
</code>
|
||||||
</pre>
|
</pre>
|
||||||
</InsidePreContext.Provider>
|
);
|
||||||
),
|
},
|
||||||
|
|
||||||
code: CodeRenderer,
|
// Always inline — block code is handled entirely by the `pre` renderer above.
|
||||||
|
code: ({ children }) => (
|
||||||
|
<code
|
||||||
|
style={{
|
||||||
|
background: "rgba(250, 204, 21, 0.1)",
|
||||||
|
border: "1px solid rgba(250, 204, 21, 0.3)",
|
||||||
|
borderRadius: 5,
|
||||||
|
padding: "1px 7px",
|
||||||
|
color: "#fde68a",
|
||||||
|
fontFamily: "var(--font-mono, 'Geist Mono', monospace)",
|
||||||
|
fontSize: "0.875em",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MarkdownContent({ content }: { content: string }) {
|
export default function MarkdownContent({ content }: { content: string }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user