You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js项目中从Markdown前置元数据渲染文本与列表?

在Next.js中实现Markdown驱动的动态博客页面(含图片与前置元数据)

一、编写带前置元数据的Markdown文件

你的Markdown文件必须用---包裹YAML格式的前置元数据,把图片和focusAreas列表都纳入其中,示例如下:

---
title: React Native跨平台项目案例
coverImages:
  - https://i.sstatic.net/TiLcHLJj.png
  - https://i.sstatic.net/DdsqRta4.png
focusAreas:
  - Implemented a scalable React Native app with TypeScript for cross-platform support
    - React Navigation for seamless routing
    - Redux Toolkit for state management
    - React Query for data fetching 
    - Styled Components for consistent UI
  - Created reusable UI components
  - Developed personalization engine
---

# 项目背景
这里可以编写博客正文内容,比如项目需求、实现难点、成果总结等...

注意:YAML格式需严格对齐,数组项的-后要加空格,图片地址直接存入coverImages数组即可。

二、Next.js动态页面实现

1. 安装依赖

先安装解析Markdown的工具包:

npm install gray-matter remark remark-html

2. 编写数据读取函数

在项目根目录新建lib/getCaseStudyData.ts,用于读取Markdown文件并解析前置元数据:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';

// Markdown文件存放目录,可根据实际路径调整
const caseStudiesDir = path.join(process.cwd(), 'case-studies');

export async function getCaseStudyData(slug: string) {
  const fullPath = path.join(caseStudiesDir, `${slug}.md`);
  const fileContents = fs.readFileSync(fullPath, 'utf8');

  // 解析前置元数据
  const matterResult = matter(fileContents);

  // 将Markdown正文转换为HTML
  const processedContent = await remark()
    .use(html)
    .process(matterResult.content);
  const contentHtml = processedContent.toString();

  return {
    slug,
    contentHtml,
    frontmatter: matterResult.data as {
      title: string;
      coverImages: string[];
      focusAreas: (string | Record<string, string[]>)[];
    },
  };
}

3. 修改动态页面组件(/[slug]/page.tsx)

修复原列表渲染逻辑,同时添加图片展示功能:

import { getCaseStudyData } from '@/lib/getCaseStudyData';

// 生成静态路径(用于静态站点生成,可选)
export async function generateStaticParams() {
  const fs = require('fs');
  const path = require('path');
  const caseStudiesDir = path.join(process.cwd(), 'case-studies');
  const filenames = fs.readdirSync(caseStudiesDir);

  return filenames.map((filename: string) => ({
    slug: filename.replace('.md', ''),
  }));
}

export default async function CaseStudyPage({ params }: { params: { slug: string } }) {
  const caseStudy = await getCaseStudyData(params.slug);

  const renderList = (items: (string | Record<string, string[]>)[]) => (
    <div className="flex w-5/6 flex-col gap-2 text-[16px] font-[500] leading-7 max-w-[702px]">
      {items.map((item, index) => {
        if (typeof item === 'string') {
          return <p key={index} className="text-[16px] font-[500] leading-7">{item}</p>;
        }
        // 处理嵌套列表:提取主项和子列表
        const mainItem = Object.keys(item)[0];
        const subItems = Object.values(item)[0];
        return (
          <ul key={index} className="list-disc px-5">
            <li>{mainItem}</li>
            {subItems.length > 0 && renderList(subItems)}
          </ul>
        );
      })}
    </div>
  );

  return (
    <div className="max-w-4xl mx-auto p-8">
      <h1 className="text-3xl font-bold mb-6">{caseStudy.frontmatter.title}</h1>
      
      {/* 展示两张图片 */}
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
        {caseStudy.frontmatter.coverImages.map((imgUrl, idx) => (
          <img 
            key={idx} 
            src={imgUrl} 
            alt={`项目截图${idx+1}`} 
            className="w-full h-auto rounded-lg shadow-md"
          />
        ))}
      </div>

      {/* 渲染focusAreas列表 */}
      <h2 className="text-2xl font-semibold mb-4">核心工作内容</h2>
      {renderList(caseStudy.frontmatter.focusAreas)}

      {/* 渲染Markdown正文 */}
      <div className="mt-8 prose max-w-none">
        <div dangerouslySetInnerHTML={{ __html: caseStudy.contentHtml }} />
      </div>
    </div>
  );
}

三、关键修复说明

  1. 原renderList函数未将嵌套列表的主项放入<li>标签,调整后符合HTML语义规范;
  2. 新增图片展示模块,从前置元数据的coverImages数组读取地址,用Grid布局适配移动端与桌面端;
  3. 补充TypeScript类型定义,避免类型报错。

内容的提问来源于stack exchange,提问作者Prongs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:04:55