Lia*_*ock 0 markdown typescript reactjs next.js
我正在尝试在 Next.js 打字稿博客入门示例中使用Kent C Dodds mdx-bundler。它似乎可以正常渲染 JSX 和某些 Markdown,但大多数简单的 Markdown 语法(例如列表和添加空格来创建段落)不起作用。我完全不知道为什么要这样做!
这是我用来测试的示例 mdx 文件:
---
title: "My first post"
description: "testing mdx"
publishedAt: "2021-12-23"
---
Skeleton component:
import {Skeleton} from '../components/Skeleton'
<Skeleton />
# Heading 1
## Heading 2
Heading
============
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Unordered list:
- a
- b
Ordered list:
1. one
2. two
**bold** and *italic* and ***bold italic***
~~strikethrough~~
Horizontal rule:
*******
Blockquote:
> Lorem ipsum dolor sit amet, consectetur adipiscing elit
>
>> Lorem ipsum dolor sit amet, consectetur adipiscing elit
indented code block:
return false;
backtick code block:
\``` (escaped here for stackoverflow)
return true;
\```
Image:

Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
这是api.ts
读取我的 mdx 内容的文件:
import fs from 'fs'
import { format, parseISO } from "date-fns"
import matter from 'gray-matter'
import path from "path"
import glob from 'glob'
import gfmPlugin from 'remark-gfm'
import remarkBreaks from 'remark-breaks'
import { bundleMDX } from "mdx-bundler"
import { PostMeta } from '../types/post'
const ROOT_PATH = process.cwd()
export const POSTS_PATH = path.join(ROOT_PATH, "posts")
export const getAllPostsMeta = () => {
const PATH = path.join(POSTS_PATH)
// Get all file paths in the posts folder (that end with .mdx)
const paths = glob.sync(`${PATH}/**/*.mdx`)
return (
paths
.map((filePath): PostMeta => {
// Get the content of the file
const source = fs.readFileSync(path.join(filePath), "utf8")
// Get the file name without .mdx
const slug = path.basename(filePath).replace(".mdx", "")
// Use gray-matter to extract the post meta from post content
const data = matter(source).data as PostMeta
const publishedAtFormatted = format(
parseISO(data.publishedAt),
"dd MMMM, yyyy",
)
return {
...data,
slug,
publishedAtFormatted,
}
})
// Sort posts by published date
.sort(
(a, b) =>
Number(new Date(b.publishedAt)) - Number(new Date(a.publishedAt)),
)
)
}
// Get content of specific post
export const getPostBySlug = async (slug: string) => {
// Get the content of the file
const source = fs.readFileSync(path.join(POSTS_PATH, `${slug}.mdx`), "utf8")
const { code, frontmatter } = await bundleMDX({
source,
xdmOptions(options) {
options.remarkPlugins = [
...(options?.remarkPlugins ?? []),
gfmPlugin,
remarkBreaks,
]
return options
},
esbuildOptions(options) {
options.target = "esnext"
return options
},
})
const publishedAtFormatted = format(
parseISO(frontmatter.publishedAt),
"dd MMMM, yyyy",
)
const meta = {
...frontmatter,
publishedAtFormatted,
slug,
} as PostMeta
return {
meta,
code,
}
}
Run Code Online (Sandbox Code Playgroud)
这是[slug].tsx
用于渲染所选帖子的文件:
import React from 'react';
import Container from '../../components/container'
import Header from '../../components/header'
import PostHeader from '../../components/post-header'
import Layout from '../../components/layout'
import { format, parseISO } from "date-fns"
import { getMDXComponent } from "mdx-bundler/client"
import { GetStaticProps } from 'next';
import { getPostBySlug, getAllPostsMeta } from '../../lib/api'
import Head from 'next/head'
import type { Post } from "../../types/post"
import SectionSeparator from '../../components/section-separator'
import { WEBSITE_SHORT_URL } from '../../lib/constants';
export const getStaticPaths = () => {
const posts = getAllPostsMeta()
const paths = posts.map(({ slug }) => ({ params: { slug } }))
return {
paths: paths,
// Return 404 page if path is not returned by getStaticPaths
fallback: false,
}
}
export const getStaticProps: GetStaticProps<Post> = async (context) => {
const slug = context.params?.slug as string
const post = await getPostBySlug(slug)
return {
props: {
...post,
publishedAtFormatted: format(
parseISO(post.meta.publishedAt),
"dd MMMM, yyyy",
),
},
}
}
export default function PostPage({ meta, code }: Post) {
const Component = React.useMemo(() => getMDXComponent(code), [code]);
return (
<Layout>
<Container>
<Header />
<article className="mb-32">
<Head>
<title>
{meta.title} | {WEBSITE_SHORT_URL}
</title>
</Head>
<PostHeader
title={meta.title}
coverImage={meta.coverImage}
date={meta.publishedAt}
/>
<div className="max-w-4xl mx-auto">
<Component
components={{
SectionSeparator
}}
/>
</div>
</article>
</Container>
</Layout>
);
}
Run Code Online (Sandbox Code Playgroud)
其他可能有用的东西...
我的 Next.js 文件夹结构:
+-- next/
+-- @types/
+-- components/
+-- lib
| +-- api.ts
+-- node_modules/
+-- pages
| +-- posts
| | +-- [slug].tsx
| +-- _app.tsx
| +-- _document.tsx
| +-- index.tsx
+-- posts
| +-- my-first-post.mdx
+-- public/
+-- styles/
+-- types/
+-- .gitignore
+-- next-env.d.ts
+-- package-lock.json
+-- package.json
+-- postcss.config.js
+-- tailwind.config.js
+-- tsconfig.json
Run Code Online (Sandbox Code Playgroud)
包.json:
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"typecheck": "tsc"
},
"dependencies": {
"@headlessui/react": "^1.4.2",
"@mdx-js/loader": "^1.6.22",
"@next/mdx": "^12.0.7",
"@reduxjs/toolkit": "^1.7.1",
"axios": "^0.24.0",
"classnames": "2.3.1",
"clsx": "^1.1.1",
"date-fns": "2.21.3",
"esbuild": "^0.13.15",
"glob": "^7.2.0",
"gray-matter": "4.0.3",
"mdx-bundler": "^8.0.0",
"next": "latest",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.22.1",
"react-redux": "^7.2.6",
"react-scroll": "^1.8.4",
"react-use": "^17.3.1",
"react-use-scroll-direction": "^0.1.0",
"remark": "13.0.0",
"remark-breaks": "^3.0.2",
"remark-gfm": "^3.0.1",
"remark-html": "~13.0.1",
"typescript": "^4.2.4"
},
"devDependencies": {
"@types/glob": "^7.2.0",
"@types/jest": "^26.0.23",
"@types/node": "^15.6.0",
"@types/react": "^17.0.6",
"@types/react-dom": "^17.0.5",
"@types/react-scroll": "^1.8.3",
"autoprefixer": "^10.2.5",
"postcss": "^8.3.0",
"tailwindcss": "^2.1.2"
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我遇到了同样的问题,我可以使用一个名为 @tailwindcss/typography 的包来修复它。所以首先安装该包。
npm install @tailwindcss/typography
Run Code Online (Sandbox Code Playgroud)
之后,您需要将其作为插件添加到 tailwind 配置文件中
plugins: [
require('@tailwindcss/typography')
],
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,这个博客绝对对我有帮助。这是链接
归档时间: |
|
查看次数: |
2045 次 |
最近记录: |