导航菜单

  • 1.claudecode
  • 2.claudecode
  • readline
  • iconv-lite
  • mcp
  • skills
  • gray-matter
  • modelcontextprotocol
  • 1. 学前准备:Front Matter 是什么
    • 1.1 YAML现在只需会这些
  • 2. gray-matter 解决什么问题
  • 3. 安装与第一个可运行示例
  • 4. data 与 content 分别怎么用
  • 5. 从文件读取并解析
  • 6. matter.stringify:拼回带 Front Matter 的文本
  • 7. 小练习:模拟加载 SKILL.md
  • 8. 常见误区
    • 8.1 把整文件内容当正文
    • 8.2 期望库自己去读路径
    • 8.3 Front Matter 没有闭合的 ---
  • 9. 知识点速查

1. 学前准备:Front Matter 是什么 #

很多 Markdown 文件最上面有一小段配置,用一对 --- 包起来,下面才是正文。这一段叫 Front Matter(前置元数据),一般用 YAML 写键值对:

---
title: 我的文章
author: 小明
---

正文从这里开始……

对 Node 来说,你需要两件事:

  1. 拆开:上面的 YAML → JavaScript 对象;下面的字符串 → 正文。
  2. 拼回(可选):改完对象后,再生成带 --- 的完整文件。

手写正则容易漏边界情况;gray-matter 帮你完成「拆」和「拼」。

1.1 YAML现在只需会这些 #

写法 含义
name: commit-message 字符串
count: 3 数字
draft: false 布尔值

2. gray-matter 解决什么问题 #

若你写:

const all = fs.readFileSync('SKILL.md', 'utf8');

得到的是一整段字符串,里面既有 --- 里的配置,也有正文。模型或业务逻辑往往只要其中一部分。

gray-matter 调用后返回大致结构:

属性 含义
data Front Matter 解析成的对象
content 去掉头尾后的正文(通常已 trim)

3. 安装与第一个可运行示例 #

在练习目录打开终端(PowerShell 或 CMD):

npm init -y
npm install gray-matter

保存为 01-hello.js,执行 node 01-hello.js:

// 引入 gray-matter;默认导出是一个函数,习惯命名为 matter
const matter = require('gray-matter');

// 模拟磁盘里一整份带 Front Matter 的文本
const raw = `---
title: Hello World
author: 小明
---
这是正文段落。`;

// 解析:拆成 data(元数据)和 content(正文)
const result = matter(raw);

// 打印元数据对象
console.log('data:', result.data);
// 打印正文
console.log('content:', result.content);

说明: matter 既是函数名,也是库的常见叫法;result.data / result.content 是最常用的两个字段。

4. data 与 content 分别怎么用 #

解析完成后:

  • data:当普通对象用,例如 data.title、data.name。
  • content:仍是字符串,可打印、拼接,或交给其它 Markdown 工具。

下面示例演示「取字段 + 判断正文是否为空」。保存为 02-use-fields.js:

// 引入库
const matter = require('gray-matter');

// 模拟 SKILL.md 风格内容
const raw = `---
name: commit-message
description: 根据 git 变更写提交说明
---

1. 先执行 git status。
2. 再写 commit message。
`;

// 解析
const { data, content } = matter(raw);

// 使用元数据(类似 skills.js 里的 meta)
console.log('技能名:', data.name);
// 使用描述
console.log('描述:', data.description);
// 正文行数(按换行粗算)
console.log('正文行数:', content.split('\n').filter(Boolean).length);
// 正文是否为空
console.log('正文为空?', content.trim() === '');

5. 从文件读取并解析 #

真实项目里内容在文件里。下面脚本会先写入示例 demo-post.md,再读取并解析,保证复制即可运行。保存为 03-read-file.js:

// 文件系统
const fs = require('fs');
// 路径拼接
const path = require('path');
// gray-matter
const matter = require('gray-matter');

// 与本脚本同目录的演示文件
const filePath = path.join(__dirname, 'demo-post.md');

// 要写入的完整 Markdown(含 Front Matter)
const seed = `---
title: 第一篇演示文章
date: 2025-01-15
tags:
  - node
  - tutorial
---

你好,这是 **gray-matter** 演示正文。
`;

// 写入演示文件
fs.writeFileSync(filePath, seed, 'utf8');
// 读回 UTF-8 字符串
const fileContent = fs.readFileSync(filePath, 'utf8');
// 解析
const { data, content } = matter(fileContent);

// 输出元数据
console.log('标题:', data.title);
// 输出标签数组(YAML 列表会解析成数组)
console.log('标签:', data.tags);
// 输出正文前 30 个字符
console.log('正文预览:', content.slice(0, 30));

// 演示结束,删除临时文件(可注释掉以保留查看)
fs.unlinkSync(filePath);

要点: gray-matter 不替你做 readFile;标准写法是 fs.readFileSync + matter(字符串)。

6. matter.stringify:拼回带 Front Matter 的文本 #

改完 data 或 content 后,可用 matter.stringify(正文, 元数据对象) 生成完整字符串,再 writeFileSync 写盘。

保存为 04-stringify.js:

// 引入库
const matter = require('gray-matter');
// 引入 fs
const fs = require('fs');
// 引入 path
const path = require('path');

// 正文(不含 Front Matter)
const body = '更新后的正文内容。';
// 要写入头部的元数据
const meta = {
  title: '新标题',
  draft: false,
};

// 拼成 --- 包裹 YAML + 正文的完整字符串
const full = matter.stringify(body, meta);

// 目标路径
const outPath = path.join(__dirname, 'demo-out.md');
// 写入文件
fs.writeFileSync(outPath, full, 'utf8');

// 打印生成结果
console.log('已写入:', outPath);
// 打印文件内容便于对照
console.log('--- 文件内容 ---\n' + full);

// 清理演示文件
fs.unlinkSync(outPath);

7. 小练习:模拟加载 SKILL.md #

读文件 → matter → 取 data.name、data.description 和正文 body。保存为 05-skill-like.js:

// path
const path = require('path');
// fs/promises 异步读写
const fsp = require('fs/promises');
// gray-matter
const matter = require('gray-matter');

// 模拟 .claude/skills/commit-message/SKILL.md 路径
const skillDir = path.join(process.cwd(), '.claude', 'skills', 'commit-message');
// SKILL.md 完整路径
const skillFile = path.join(skillDir, 'SKILL.md');

// SKILL.md 全文
const skillContent = `---
name: commit-message
description: 根据 git 变更生成 commit message
---

1. 执行 git status 与 git diff。
2. 写一行 conventional commits 风格标题。
`;

// 自执行异步函数
(async () => {
  // 创建目录
  await fsp.mkdir(skillDir, { recursive: true });
  // 写入 SKILL.md
  await fsp.writeFile(skillFile, skillContent, 'utf8');

  // 读文件
  const raw = await fsp.readFile(skillFile, 'utf8');
  // 解析 frontmatter
  const { data, content } = matter(raw);

  // 与 skills.js 类似的字段命名
  const name = (data.name || 'commit-message').trim();
  const description = data.description || name;
  const body = content.trim();

  // 打印摘要
  console.log('name:', name);
  console.log('description:', description);
  console.log('body 长度:', body.length);

  // 可选:保留文件供 skills 教程继续用;这里删除以免堆积
  await fsp.rm(skillDir, { recursive: true, force: true });
})().catch((err) => {
  console.error(err);
  process.exit(1);
});

8. 常见误区 #

8.1 把整文件内容当正文 #

若不用 gray-matter,data 里的 name 会解析不到,正文里还会混进 --- 和 YAML。

8.2 期望库自己去读路径 #

matter('/path/to/file.md') 不是读文件路径;应 readFileSync 后再 matter(字符串)。

8.3 Front Matter 没有闭合的 --- #

格式错误时解析可能失败或得到意外结果。写 SKILL.md 时保持:第一行 ---,YAML 块,再一行 ---,然后正文。

9. 知识点速查 #

主题 记住这一句
安装 npm install gray-matter
解析 const { data, content } = matter(字符串)
读文件 matter(fs.readFileSync(path, 'utf8'))
拼回 matter.stringify(正文, 元数据对象)
典型场景 SKILL.md、博客 md、静态站元数据
← 上一节 2.claudecode 下一节 iconv-lite →

访问验证

请输入访问令牌

Token不正确,请重新输入