iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0

前面花了兩篇解決了圖片顯示的問題,接下來來解決文章顯示的問題
現在我們是用 Sanity 預設的 text 型別,並且在裡面存放 markdown 格式的內容,渲染到畫面的時候基本就是像現在這樣,不管是在 Sanity 裡面還是 Next 前端頁面都一樣,完全沒有排版。

import {defineType, defineField} from 'sanity'
import {getImageDimensions, getExtension} from '@sanity/asset-utils'

export default defineType({
  name: 'blogPost',
  title: 'Blog Post',
  type: 'document',
  // ...
  fields: [
    // ...
    defineField({
      name: 'content',
      title: '內容',
      type: 'text',
      validation: (rule) => rule.required(),
    }),
    // ...
  ],
})

https://ithelp.ithome.com.tw/upload/images/20240928/20101989jHb0BsooBN.png

https://ithelp.ithome.com.tw/upload/images/20240928/20101989Lmt9A0vptg.png


sanity-plugin-markdown

一開始先來解決 Sanity 資料欄位問題,現在使用的是 text 型別,但 Markdown 這種被廣泛使用的撞格式有沒有那種專門的型別呢?

答案是有的,就是 sanity-plugin-markdown
使用上也非常簡單,npm 下載套件後再引入 plugin 後就有markdown 這個型別可以使用了。

npm 下載套件:

npm install --save sanity-plugin-markdown

sanity.config.ts 中加入 plugin:

import {markdownSchema} from 'sanity-plugin-markdown'

export default defineConfig({
  // ...
	plugins: [
		structureTool(),
		visionTool(),
		markdownSchema() // 加入 plugin
	],
	// ...
})

最後在型別上改成 markdown,就完成了。

defineField({
  name: 'content',
  title: '內容',
  type: 'markdown',
  validation: (rule) => rule.required(),
}),

https://ithelp.ithome.com.tw/upload/images/20240928/20101989orKw8Vf4sN.png

這樣一來在 Sanity 那端,就有基本的排版跟工具列可以用了。


Next.js 顯示 Markdown 內容

在 Next.js 前端顯示 Markdown 內容選用的 react-markdown, remark-gfm, rehype-highlight, github-markdown-css

功能分別是:

  • react-markdown - 將 Markdown 字串轉換為 html 標籤 ( 基本顯示 )
  • remark-gfm - 支援 Github spec 的 markdown 格式
  • rehype-highlight - 用於顯示 <code></code> 的內容,有一些基本樣式。
  • github-markdown-css - markdown 的樣式主題

這邊就不展開講 unified, remark, rehype 這些了,比較不是這裡的重點。

在 Next.js 建立一個叫 MarkdownBlock 的 Component:

// app/components/MarkdownBlock.tsx
import ReactMarkdown from "react-markdown";

import remarkGfm from "remark-gfm";
import rehypeHighlight from "rehype-highlight";
import "github-markdown-css/github-markdown-dark.css";

export default function MarkdownBlock({
  content,
}: Readonly<{ content: string }>) {
  return (
    <ReactMarkdown
      className="markdown-body"
      remarkPlugins={[remarkGfm]}
      rehypePlugins={[rehypeHighlight]}
    >
      {content}
    </ReactMarkdown>
  );
}

接著引入就可以直接使用了~~

// ...

export default async function Post({ params }: { params: { slug: string } }) {
  // ...

  return (
    <div className="post max-w-screen-md p-5">
	    {/* ...  */}
      <MarkdownBlock content={post.content} />
    </div>
  );
}

https://ithelp.ithome.com.tw/upload/images/20240928/20101989umjXdgbSeQ.png

這樣內容就都出來了~


上一篇
Day 13 - @Sanity/image-url + Next.js
下一篇
Day 15 - Contentful 內容轉移到 Sanity
系列文
用 Sanity 跟 Nextjs 重寫個人部落格30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言