Next.js13中用GFM扩展转MD到MDAST树时出现inTable错误
解决Next.js 13中mdast-util-from-markdown结合GFM扩展的报错问题
问题概况
在Next.js 13项目中,尝试通过mdast-util-from-markdown搭配GFM扩展将.md文件转换为MDAST树(JSON格式)时,出现两个问题:
- VSCode中提示TypeScript错误
- 浏览器端Next.js抛出
Cannot set properties of undefined (setting 'inTable')异常
移除fromMarkdown的扩展配置后,普通Markdown可正常转换,但GFM语法(如表格、任务列表等)无法被识别。
报错原因
代码中对fromMarkdown的参数传递存在错误:fromMarkdown的函数签名为fromMarkdown(value: string, options?: Options),第二个参数应为配置选项对象,但你额外传入了'utf8'作为第二个参数,导致配置选项被挤到第三个参数,GFM扩展的初始化逻辑无法正确读取配置,进而引发内部状态(如inTable所属的上下文)未被正确创建的错误。
同时,原代码直接将包含frontmatter的完整文件内容传入fromMarkdown,会导致frontmatter部分被错误转换。
解决方案
- 移除多余的
'utf8'参数,因为fs.readFileSync已经以utf8编码读取了文件内容,fromMarkdown接收的是字符串类型,无需重复指定编码。 - 将
matterResult.content(仅文章主体内容)传入fromMarkdown,避免转换frontmatter部分。 - 引入MDAST的
Root类型,替换any以获得正确的TypeScript类型提示。
修正后的完整代码
"use server" import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; import { fromMarkdown } from "mdast-util-from-markdown" import { gfm } from 'micromark-extension-gfm' import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm' import type { Root } from 'mdast' const postsDirectory = path.join(process.cwd(), 'blogposts'); type BlogPost = { id: string; title: string; date: string; published: string; } export async function getPostDataToEdit(id: string) { const fullPath = path.join(postsDirectory, `${id}.md`); const fileContents = fs.readFileSync(fullPath, 'utf8'); const matterResult = matter(fileContents); const tree: Root = fromMarkdown(matterResult.content, { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] }) const blogPost: BlogPost & { body: Root } = { id, title: matterResult.data.title, date: matterResult.data.date, published: matterResult.data.published ? "Published" : "Draft", body: tree, } return blogPost; }
额外说明
- 替换
fileContents为matterResult.content后,只会转换Markdown文章的主体部分,frontmatter将由gray-matter单独处理,符合预期逻辑。 - 使用
Root类型代替any,可以在开发过程中获得更准确的类型检查和代码提示,减少潜在的TypeScript错误。
内容的提问来源于stack exchange,提问作者Nicolás Jorge Vera
相关产品推荐
相关产品推荐

