如何在Astro中结合Prism渲染Contentful中的嵌入代码块?
Astro集成Contentful时代码块渲染问题:自定义带主题的Prism组件
我用Astro搭建了一个集成Contentful的Web开发博客,除代码块外所有功能都正常运行。我在Contentful内容模型中为代码块创建了嵌入条目,返回的nodeType结构如下:
{ nodeType: 'embedded-entry-block', data: { target: { metadata: [Object], sys: [Object], fields: { code: '```html\n<!DOCTYPE html>\n<html>\n<head>\n<title>My First Astro App</title>\n</head>\n <body>\n<h1>Hello, World!</h1>\n</body>\n</html>\n```' } } }, content: [] }
我不清楚如何通过@contentful/rich-text-html-renderer的documentToHtmlString函数,在博客中用带自定义主题的Prism组件渲染代码块。
目前我已经给嵌入条目传了自定义渲染逻辑到documentToHtmlString的配置里,能提取出代码的语言和内容,并且通过@astrojs/prism的runHighlighterWithAstro实现了无样式的代码块显示,代码如下:
--- import { documentToHtmlString } from "@contentful/rich-text-html-renderer"; import { BLOCKS } from "@contentful/rich-text-types"; import ContentLayout from "@layouts/ContentLayout.astro"; import BlogPostMeta from "@components/BlogPostMeta.astro"; import { BlogPost, contentfulClient } from "@lib/contentful"; import { Prism } from "@astrojs/prism"; import { runHighlighterWithAstro } from "@astrojs/prism/dist/highlighter"; export async function getStaticPaths() { const entries = await contentfulClient.getEntries<BlogPost>({ content_type: "blogPost", }); function extractCode(str: string): { lang: string; code: string } | null { const match = str?.match(/```(\w+)\n([\s\S]+)\n```/); if (match) { return { lang: match[1], code: match[2], }; } return null; } const renderOptions = { renderNode: { [BLOCKS.EMBEDDED_ENTRY]: (node: any) => { const { code } = node.data.target.fields; const extractedCode = extractCode(code); if (extractedCode) { const { lang, code } = extractedCode; const { classLanguage, html } = runHighlighterWithAstro(lang, code); return `<pre class=${classLanguage} set:html=${html}></pre>`; } return ""; }, }, }; const pages = entries.items.map((item) => ({ params: { slug: item.fields.slug }, props: { title: item.fields.title, description: item.fields.description, content: documentToHtmlString(item.fields.content, renderOptions), date: new Date(item.fields.date).toLocaleDateString(), }, })); return pages; } const { slug } = Astro.params; if (typeof slug !== "string") { throw Error(`Slug should be a string. Received: ${slug}`); } const { description, content, title, date } = Astro.props; --- <ContentLayout title={title} date={date}> <BlogPostMeta title={title} description={description} publishDate={date} pagePath={`/posts/${slug}`} slot='meta' /> <body> <h1>{title}</h1> <time>{date}</time> <article slot='content' set:html={content} /> </body> </ContentLayout>
我希望使用自己写的CodeBlock组件来渲染带自定义样式的Prism代码块,但因为之前习惯用React,对Astro的机制不太理解,我的CodeBlock组件代码如下:
--- import { Prism } from "@astrojs/prism"; const { language, code } = Astro.props; --- <Prism lang={language} code={code} /> <style is:global>... </style>
内容的提问来源于stack exchange,提问作者Joshua Karp
相关产品推荐
相关产品推荐

