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
相关产品推荐
相关产品推荐

