You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sanity代码块样式冲突求助:标题与代码块样式互斥

Sanity博客标题与代码块样式冲突问题解决

问题说明

在使用Sanity构建博客时遇到样式冲突:

  • 为h1~h6配置自定义样式后,code块会消失
  • 单独设置code块样式时,标题等元素无法应用自定义样式

使用技术栈:@sanity/block-content-to-react、SyntaxHighlighter、highlight.js

核心渲染代码

<BlockContent
    className="blog__body"
    dataset={import.meta.env.VITE_SANITY_DATASET}
    projectId={import.meta.env.VITE_SANITY_PROJECT_ID}
    blocks={blog.body}
    serializers={serializers}
/>

序列化配置

const serializers = {
    types: {
        code: CodeBlock,
    },
    block: (props) => {
        switch (props.node.style) {
            case "h1":
                return <Heading1>{props.children}</Heading1>;
            case "h2":
                return <Heading2>{props.children}</Heading2>;
            case "h3":
                return <Heading3>{props.children}</Heading3>;
            case "h4":
                return <Heading4>{props.children}</Heading4>;
            case "h5":
                return <Heading5>{props.children}</Heading5>;
            case "h6":
                return <Heading6>{props.children}</Heading6>;
            default:
                return <NormalText>{props.children}</NormalText>;
        }
    },
    listItem: (props) => {
        switch (props.node.listItem) {
            case "bullet":
                return <UnorderedList>{props.children}</UnorderedList>;
            case "number":
                return <OrderedList>{props.children}</OrderedList>;
            default:
                return <li>{props.children}</li>;
        }
    },
    marks: {
        link: Link,
    },
};

数据获取代码

const { slug } = useParams();
const [blog, setBlog] = useState(null);
const publishedTime = timeDifference(
    new Date(),
    new Date(blog?.publishedAt)
);

useEffect(() => {
    client
        .fetch(
            `*[_type == "post" && slug.current == $slug]{
                _id,
                title,
                body,
                publishedAt,
                categories[]->{ 
                    title
                },
                author->{ 
                    name,
                    avatar
                },
                publishedAt,
                mainImage{
                    asset->{ 
                        _id,
                        url
                    },
                    alt
                },
            }[0]`,
            { slug }
        )
        .then((data) => {
            if (data.length === 0) {
                console.error(`No post found with slug "${slug}"`);
                return;
            }
            setBlog(data);
        })
        .catch(console.error);
}, [slug]);

代码块组件

function CodeBlock({ node }) {
    return (
        <SyntaxHighlighter
            language="javascript"
            style={atomDark}
            showLineNumbers
        >
            {node.code}
        </SyntaxHighlighter>
    );
}

解决方案

问题根源在于block序列化器优先级高于types序列化器:code类型节点会被block序列化器的默认分支转换成NormalText,导致types中的CodeBlock无法生效。

修改序列化配置,在block序列化器中先排除code类型节点,让types序列化器处理code块:

const serializers = {
    types: {
        code: CodeBlock,
    },
    block: (props) => {
        // 先判断是否为code类型节点,交给types序列化器处理
        if (props.node._type === 'code') {
            return null;
        }
        
        switch (props.node.style) {
            case "h1":
                return <Heading1>{props.children}</Heading1>;
            case "h2":
                return <Heading2>{props.children}</Heading2>;
            case "h3":
                return <Heading3>{props.children}</Heading3>;
            case "h4":
                return <Heading4>{props.children}</Heading4>;
            case "h5":
                return <Heading5>{props.children}</Heading5>;
            case "h6":
                return <Heading6>{props.children}</Heading6>;
            default:
                return <NormalText>{props.children}</NormalText>;
        }
    },
    listItem: (props) => {
        switch (props.node.listItem) {
            case "bullet":
                return <UnorderedList>{props.children}</UnorderedList>;
            case "number":
                return <OrderedList>{props.children}</OrderedList>;
            default:
                return <li>{props.children}</li>;
        }
    },
    marks: {
        link: Link,
    },
};

修改后,标题会正常应用自定义组件样式,code块也会被CodeBlock组件正确渲染,解决冲突问题。

内容的提问来源于stack exchange,提问作者Aryan Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:43:21