MDX 渲染器 - Gatsby 网站 - <li>、<pre> 和 <code> 标签未渲染

Posted

技术标签:

【中文标题】MDX 渲染器 - Gatsby 网站 - <li>、<pre> 和 <code> 标签未渲染【英文标题】:MDX renderer - Gatsby Site - <li>, <pre> and <code> tags not rendering 【发布时间】:2021-05-04 21:49:08 【问题描述】:

我试图弄清楚为什么我必须在 gatsby-browser.js 中指定所有 html 标记,以便 MDXrenderer 了解如何设置 HTML 标记的样式。

内容来自 GraphCMS 通过 GraphQL 查询。

我一直在研究其他 gatsby 项目,其中未设置规范,但它们正确呈现 HTML 标记。

我能够定位大多数 HTML 标签,但我无法弄清楚我的“ul”和“li”标签是如何呈现的。例如,我可以定位它们并应用颜色,但在查看时它仍然看起来像页面上的“p”标签。虽然如果您检查元素,它确实会显示“ul”和“li”标签。

请看下面的例子:

Webpage with inspection

这是我的 gatsby-node.js 文件:

const path = require("path")

exports.createPages = async ( actions:  createPage , graphql ) => 
  const  data  = await graphql(
    `
      
        pages: allGraphCmsPage 
          nodes 
            id
            content 
              markdownNode 
                childMdx 
                  body
                
              
            
            seo 
              description
              image 
                url
              
              keywords
              title
            
            slug
            subtitle
            title
          
        
        posts: allGraphCmsPost(sort:  fields: date, order: ASC ) 
          edges 
            nextPost: next 
              slug
              title
            
            page: node 
              id
              author 
                id
                name
                title
              
              content 
                markdownNode 
                  childMdx 
                    body
                  
                
              
              date: formattedDate
              excerpt
              seo 
                description
                image 
                  url
                
                keywords
                title
              
              slug
              title
            
            previousPost: previous 
              slug
              title
            
          
        
      
    `
  )

  if (data.errors) throw data.errors

  data.posts.edges.forEach(( nextPost, page, previousPost ) => 
    createPage(
      component: path.resolve("./src/templates/article-post.tsx"),
      context: 
        id: page.id,
        page,
        previousPost,
        nextPost,
      ,
      path: `/articles/$page.slug`,
    )
  )

  data.pages.nodes.forEach(page => 
    createPage(
      component: path.resolve("./src/templates/default-page.tsx"),
      context: 
        page,
      ,
      path: `/$page.slug`,
    )
  )


exports.createResolvers = ( createResolvers ) => 
  const resolvers = 
    GraphCMS_Post: 
      formattedDate: 
        type: "String",
        resolve: source => 
          const date = new Date(source.date)

          return new Intl.DateTimeFormat("en-US", 
            weekday: "long",
            year: "numeric",
            month: "long",
            day: "numeric",
          ).format(date)
        ,
      ,
    ,
  

  createResolvers(resolvers)


这是我的 gatsby-config.js 文件:

require("dotenv").config()

const path = require("path")

module.exports = 
  siteMetadata: 
    title: `Code Shape`,
    description: `Learn to create great things.`,
    author: `@codeshape`,
  ,
  plugins: [
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `images`,
        path: `$__dirname/static/images/icons`,
      ,
    ,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `images`,
        path: `$__dirname/static/images/logos`,
      ,
    ,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `images`,
        path: `$__dirname/static/images/profiles`,
      ,
    ,
    
      resolve: `gatsby-source-filesystem`,
      options: 
        name: `posts`,
        path: `$__dirname/src/posts/`,
      ,
    ,
    
      resolve: "gatsby-plugin-page-creator",
      options: 
        path: `$__dirname/src/posts`,
      ,
    ,
    `gatsby-plugin-mdx`,
    
      resolve: "gatsby-source-graphcms",
      options: 
        endpoint: process.env.GRAPHCMS_ENDPOINT,
        token: process.env.GRAPHCMS_TOKEN,
        buildMarkdownNodes: true,
        downloadLocalImages: true,
      ,
    ,
    `gatsby-plugin-styled-components`,
    `gatsby-plugin-react-helmet`,
    "gatsby-transformer-sharp",
    "gatsby-plugin-sharp",
  ],


这是我的 gatsby-browser.js 文件:

import React from "react"
import  MDXProvider  from "@mdx-js/react"
import Layout from "./src/components/layout/layout"

/* eslint-disable */
const components = 
  wrapper: ( children ) => <>children</>,
  h1: props => (
    <h1 style= fontSize: "60px", fontWeight: "bold"  ...props />
  ),
  h2: props => (
    <h2 style= fontSize: "40px", fontWeight: "bold"  ...props />
  ),
  h3: props => (
    <h3 style= fontSize: "30px", fontWeight: "bold"  ...props />
  ),
  h4: props => (
    <h4 style= fontSize: "20px", fontWeight: "bold"  ...props />
  ),
  p: props => <p style= fontSize: "16px", lineHeight: 1.6  ...props />,
  strong: props => (
    <strong style= fontWeight: "900", lineHeight: 1.6  ...props />
  ),
  img: props => <img style= width: "100%"  ...props />,
  pre: props => 
    const className = props.children.props.className || ""
    const matches = className.match(/language-(?<lang>.*)/)
    return (
      <Highlight
        ...defaultProps
        code=props.children.props.children
        language=
          matches && matches.groups && matches.groups.lang
            ? matches.groups.lang
            : ""
        
      >
        ( className, style, tokens, getLineProps, getTokenProps ) => (
          <pre className=className style=style>
            tokens.map((line, i) => (
              <div ...getLineProps( line, key: i )>
                line.map((token, key) => (
                  <span ...getTokenProps( token, key ) />
                ))
              </div>
            ))
          </pre>
        )
      </Highlight>
    )
  ,


const wrapPageElement = ( element, props ) => (
  <Layout ...props>element</Layout>
)

const wrapRootElement = ( element ) => (
  <MDXProvider components=components>element</MDXProvider>
)

export  wrapPageElement, wrapRootElement 

这是我的 article-post.tsx 文件的模板:

import React from "react"
import  graphql, Link  from "gatsby"
import Img from "gatsby-image"
import  MDXRenderer  from "gatsby-plugin-mdx"
import styled from "styled-components"
import 
  BodyMain,
  Caption,
  H1,
  MediumText,
 from "../components/styles/TextStyles"
import ReactDisqusComments from "react-disqus-comments"
import LazyLoad from "react-lazy-load"

export const pageQuery = graphql`
  fragment AssetFields on GraphCMS_Asset 
    id
    localFile 
      childImageSharp 
        fluid(maxWidth: 600) 
          ...GatsbyImageSharpFluid
        
      
    
  

  query ArticlePostQuery($id: String!) 
    authorImage: graphCmsAsset(
      authorAvatar: 
        elemMatch:  posts:  elemMatch:  id:  in: [$id]    
      
    ) 
      ...AssetFields
    
    coverImage: graphCmsAsset(
      coverImagePost:  elemMatch:  id:  eq: $id   
    ) 
      ...AssetFields
    
  
`

export default function ArticlePostTemplate(
  data:  authorImage, coverImage ,
  pageContext:  nextPost, page, previousPost ,
) 
  return (
    <Wrapper>
      <Header>
        <PublishDate>page.date</PublishDate>
        <PageTitle>page.title</PageTitle>
      </Header>
      <InformationWrapper>
        <AuthorWrapper>
          <AuthorAvatar>
            <Img
              fluid=authorImage.localFile.childImageSharp.fluid
              fadeIn=false
              className="Image"
            />
          </AuthorAvatar>
          <AuthorTextWrapper>
            <AuthorName>page.author.name</AuthorName>
            <AuthorTitle>page.author.title</AuthorTitle>
          </AuthorTextWrapper>
        </AuthorWrapper>
      </InformationWrapper>
      <ContentWrapper>
        <Img
          fluid=coverImage.localFile.childImageSharp.fluid
          fadeIn=false
          className="CoverImage"
        />
        <MDXRenderer>page.content.markdownNode.childMdx.body</MDXRenderer>
      </ContentWrapper>
      <Navigation>
        (nextPost || previousPost) && (
          <div>
            <hr className="Divider" />
            nextPost && (
              <div>
                <h2>Next Post</h2>
                <div>
                  <Link to=`/articles/$nextPost.slug`>
                    nextPost.title
                  </Link>
                </div>
                <hr className="Divider" />
              </div>
            )
            previousPost && (
              <div>
                <h2>Previous Post</h2>
                <div>
                  <Link to=`/articles/$previousPost.slug`>
                    previousPost.title
                  </Link>
                </div>
                <hr className="Divider" />
              </div>
            )
          </div>
        )
        <div>
          <Link to="/articles/" className="">
            &larr; Back to the blog
          </Link>
        </div>
      </Navigation>
      <LazyLoad offsetTop=400>
        <ReactDisqusComments
          shortname="codeshape"
          identifier=page.id
          title=page.title
          url=page.url
          category_id=page.category_id
        />
      </LazyLoad>
    </Wrapper>
  )


const Wrapper = styled.div`
  margin: 1.875rem;
  display: grid;
  grid-gap: 1.875rem;
`

const Header = styled.div`
  text-align: center;
  margin: 0 auto;
`

const PublishDate = styled(BodyMain)`
  color: #757372;
`

const PageTitle = styled(H1)``

const InformationWrapper = styled.div`
  display: grid;
  align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
`

const ContentWrapper = styled.div`
  display: grid;
  grid-gap: 1rem;
  margin: 0 auto;
  max-width: 80rem;

  .CoverImage 
    border-radius: 1.25rem;
    object-fit: cover;
  
`

const AuthorWrapper = styled.div`
  margin: 0 auto;
  padding: 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-template-columns: auto auto;
  width: 20rem;
  justify-content: center;
  align-content: center;
`

const AuthorAvatar = styled.div`
  .Image 
    border-radius: 50%;
    border: 3px solid white;
    width: 4rem;
  
`

const AuthorTextWrapper = styled.div`
  display: grid;
  justify-content: center;
  align-content: center;
`

const AuthorName = styled(MediumText)`
  font-weight: 900;
`

const AuthorTitle = styled(Caption)`
  color: #757372;
`

const Navigation = styled.div`
  margin: 0 auto;
  text-align: center;
  padding: 1.875rem;
  display: grid;
  grid-gap: 1rem;
  width: 18rem;

  .Divider 
    color: #757372;
    line-height: 3rem;
  
`

package.json 文件中的依赖关系:

    "@mdx-js/mdx": "^1.6.22",
    "@mdx-js/react": "^1.6.22",
    "@types/react-helmet": "^6.1.0",
    "@types/styled-components": "^5.1.4",
    "autoprefixer": "^10.2.3",
    "babel-plugin-styled-components": "^1.12.0",
    "gatsby": "^2.28.0",
    "gatsby-image": "^2.10.0",
    "gatsby-plugin-manifest": "^2.8.0",
    "gatsby-plugin-mdx": "^1.9.0",
    "gatsby-plugin-offline": "^3.6.0",
    "gatsby-plugin-react-helmet": "^3.6.0",
    "gatsby-plugin-sharp": "^2.13.4",
    "gatsby-plugin-styled-components": "^3.9.0",
    "gatsby-source-filesystem": "^2.7.0",
    "gatsby-source-graphcms": "^2.2.0",
    "gatsby-transformer-sharp": "^2.11.0",
    "prop-types": "^15.7.2",
    "react": "^16.14.0",
    "react-disqus-comments": "^1.4.0",
    "react-dom": "^16.14.0",
    "react-helmet": "^6.1.0",
    "react-lazy-load": "^3.1.13",
    "styled-components": "^5.2.1"
  ,

您能帮我解决我需要做什么才能让 MDXrenderer 工作吗?我仍然需要弄清楚列表和代码块是如何呈现的。

【问题讨论】:

【参考方案1】:

您完全是在解决这个问题。您无需在gatsby-browser.js 中创建实例即可“让 MDX 理解”。您的 MDX 工作正常,因为您正在渲染 &lt;ul&gt;&lt;li&gt;。您只是缺少样式。

在您分享的屏幕截图中,可以看到以下内容:

Inherited from ul
ol, ul 
   list-style: none;

这会使您的列表“看起来像 &lt;p&gt;”。

您只需向它们添加正确的样式或删除重置样式。默认情况下,&lt;ul&gt; 具有:

display: block; 
list-style-type: disc; 
margin-top: 1em; 
margin-bottom: 1 em; 
margin-left: 0; 
margin-right: 0; 
padding-left: 40px;

还有&lt;li&gt;

display: list-item; 

恢复默认样式后,您的列表标签将保持原样。

【讨论】:

感谢您指出这一点。这是一个很大的帮助。有时它很简单,我必须学习如何更好地隔离它。再次感谢:) 不客气。它发生在每个人身上 :) 如果问题已经解决,请考虑接受/支持答案以关闭问题。

以上是关于MDX 渲染器 - Gatsby 网站 - <li>、<pre> 和 <code> 标签未渲染的主要内容,如果未能解决你的问题,请参考以下文章

生产 Gatsby 博客未在 MDX 文件中呈现 TailwindCSS 类

MDX 中的 Gatsby 静态图像(gatsby-plugin-image)

使用 MDX 在 Gatsby 博客中添加 featuresImage

使用 Gatsby mdx.slug 的重复页面

Gif 打破了 Gatsby 网站的响应能力

连接两个 gatsby 节点