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

MDX renderer - Gatsby Site - <li>, <pre> and <code> tags not rendering

我想弄清楚为什么我必须在 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 }

这是我文章的模板-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 工作吗?我仍然需要弄清楚列表和代码块是如何呈现的。

你把这个问题完全矫枉过正了。您不需要在 gatsby-browser.js 中创建一个实例来“让 MDX 理解”。您的 MDX 运行良好,因为您正在渲染 <ul><li>。您只是缺少样式。

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

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

这会使您的列表“看起来像 <p>”。

您只需要为它们添加正确的样式或删除重置样式。默认情况下,<ul> 有:

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

<li>:

display: list-item; 

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