Rust元数据解析库gray_matter的使用,gray_matter可高效提取和解析Markdown、YAML等文件中的Front Matter数据

Rust元数据解析库gray_matter的使用

gray_matter是一个高效的Rust库,用于从Markdown、YAML等文件中提取和解析Front Matter数据。它是gray-matter的Rust实现版本,支持以下格式的Front Matter解析:

  • TOML
  • YAML
  • JSON

该库还提供了Engine trait接口,允许开发者实现自定义的解析器。

基础用法

添加依赖

首先需要在Cargo.toml中添加依赖:

[dependencies]
gray_matter = "0.3"

基本解析示例

use gray_matter::{Matter, ParsedEntity, Result};
use gray_matter::engine::YAML;
use serde::Deserialize;

const INPUT: &str = r#"---
title: gray-matter-rs
tags:
  - gray-matter
  - rust
---
Some excerpt
---
Other stuff
"#;

fn main() -> Result<()> {
    // 使用YAML引擎创建解析器
    let matter = Matter::<YAML>::new();
    let result: ParsedEntity = matter.parse(INPUT)?;

    // 验证解析结果
    assert_eq!(result.content, "Some excerpt\n---\nOther stuff");
    assert_eq!(result.excerpt, Some("Some excerpt".to_owned()));
    assert_eq!(result.data.as_ref().unwrap()["title"].as_string(), Ok("gray-matter-rs".to_string()));
    assert_eq!(result.data.as_ref().unwrap()["tags"][0].as_string(), Ok("gray-matter".to_string()));
    assert_eq!(result.data.as_ref().unwrap()["tags"][1].as_string(), Ok("rust".to_string()));

    // 将数据反序列化为自定义结构体
    #[derive(Deserialize, Debug)]
    struct FrontMatter {
        title: String,
        tags: Vec<String>
    }

    let result_with_struct = matter.parse::<FrontMatter>(INPUT)?;
    println!("{:?}", result_with_struct.data);
    // 输出: FrontMatter { title: "gray-matter-rs", tags: ["gray-matter", "rust"] }
    Ok(())
}

自定义分隔符

use gray_matter::{Matter, ParsedEntity, Result};
use gray_matter::engine::YAML;
use serde::Deserialize;

fn main() -> Result<()> {
    let mut matter: Matter<YAML> = Matter::new();
    // 设置自定义分隔符
    matter.delimiter = "~~~".to_owned();
    matter.excerpt_delimiter = Some("<!-- endexcerpt -->".to_owned());

    #[derive(Deserialize, Debug)]
    struct FrontMatter {
        abc: String,
    }

    let result: ParsedEntity<FrontMatter> = matter.parse(
        "~~~\nabc: xyz\n~~~\nfoo\nbar\nbaz\n<!-- endexcerpt -->\ncontent",
    )?;

    Ok(())
}

自定义关闭分隔符

use gray_matter::{Matter, ParsedEntity, Result};
use gray_matter::engine::YAML;
use serde::Deserialize;

fn main() -> Result<()> {
    let mut matter: Matter<YAML> = Matter::new();
    // 设置自定义打开和关闭分隔符
    matter.delimiter = "<!--".to_owned();
    matter.close_delimiter = Some("-->".to_owned());
    matter.excerpt_delimiter = Some("<!-- endexcerpt -->".to_owned());

    #[derive(Deserialize, Debug)]
    struct FrontMatter {
        abc: String,
    }

    let result: ParsedEntity<FrontMatter> = matter.parse(
        "<!--\nabc: xyz\n-->\nfoo\nbar\nbaz\n<!-- endexcerpt -->\ncontent",
    )?;

    Ok(())
}

完整示例

下面是一个完整的Markdown文件解析示例:

use gray_matter::{Matter, ParsedEntity, Result};
use gray_matter::engine::YAML;
use serde::Deserialize;

fn main() -> Result<()> {
    // 包含Front Matter的Markdown内容
    const MARKDOWN: &str = r#"---
title: Rust元数据解析
author: 张伟
date: 2023-05-15
categories:
  - 编程
  - Rust
---
这是文章的摘要部分

<!-- endexcerpt -->

这里是文章的正文内容..."#;
    
    // 创建解析器并配置分隔符
    let mut matter = Matter::<YAML>::new();
    matter.delimiter = "---".to_owned();
    matter.close_delimiter = Some("---".to_owned());
    matter.excerpt_delimiter = Some("<!-- endexcerpt -->".to_owned());

    // 定义Front Matter数据结构
    #[derive(Deserialize, Debug)]
    struct ArticleMeta {
        title: String,
        author: String,
        date: String,
        categories: Vec<String>,
    }

    // 解析内容
    let result = matter.parse::<ArticleMeta>(MARKDOWN)?;
    
    // 输出解析结果
    println!("元数据: {:?}", result.data.unwrap());
    println!("正文内容: {}", result.content);
    println!("摘要: {}", result.excerpt.unwrap());
    
    Ok(())
}

这个完整示例展示了如何:

  1. 配置gray_matter解析器
  2. 定义自定义数据结构来反序列化Front Matter
  3. 解析包含Front Matter的Markdown内容
  4. 提取并输出元数据、正文和摘要

你可以根据需要调整解析引擎(TOML/JSON/YAML)或修改分隔符配置以适应不同的文档格式。


1 回复

以下是基于您提供的内容整理的完整示例代码,包含了gray_matter库的主要使用场景:

完整示例代码

// 导入所需库
use gray_matter::{Matter, engine::{YAML, TOML, JSON}};
use serde::Deserialize;
use std::fs;

// 定义用于反序列化的结构体
#[derive(Debug, Deserialize)]
struct Article {
    title: String,
    author: String,
    date: String,
    tags: Vec<String>,
    draft: bool,
}

fn main() {
    // 示例1:基本YAML解析
    let matter = Matter::<YAML>::new();
    let content = r#"---
title: Rust编程入门
author: 张伟
date: 2023-08-15
tags: [rust, 编程, 教程]
draft: false
---
这是文章正文内容..."#;

    let result = matter.parse(content);
    println!("[示例1] 元数据: {:?}", result.data);
    println!("[示例1] 内容: {}\n", result.content);

    // 示例2:反序列化为结构体
    let result = matter.parse_with_struct::<Article>(content).unwrap();
    let article = result.data.unwrap();
    println!("[示例2] 标题: {}", article.title);
    println!("[示例2] 作者: {}", article.author);
    println!("[示例2] 标签: {:?}\n", article.tags);

    // 示例3:处理TOML格式
    let matter_toml = Matter::<TOML>::new();
    let toml_content = r#"+++
title = "TOML格式示例"
+++
正文内容..."#;
    
    let result = matter_toml.parse(toml_content);
    println!("[示例3] TOML解析结果: {:?}\n", result.data);

    // 示例4:自定义分隔符
    let mut custom_matter = Matter::<YAML>::new();
    custom_matter.delimiter = Some("/* * */".to_string());
    
    let custom_content = r#"/* * */
title: 自定义分隔符
/* * */
正文..."#;
    
    let result = custom_matter.parse(custom_content);
    println!("[示例4] 自定义分隔符结果: {:?}\n", result.data);

    // 示例5:从文件读取
    if let Ok(file_content) = fs::read_to_string("example.md") {
        let result = matter.parse(&file_content);
        println!("[示例5] 文件解析结果 - 元数据: {:?}", result.data);
        println!("[示例5] 文件解析结果 - 内容长度: {}\n", result.content.len());
    } else {
        println!("[示例5] 未找到example.md文件\n");
    }

    // 示例6:处理无Front Matter的内容
    let no_frontmatter = "纯文本内容,没有元数据";
    let result = matter.parse(no_frontmatter);
    println!("[示例6] 无FrontMatter时data是否为None: {}", result.data.is_none());
    println!("[示例6] 内容保持不变: {}\n", result.content == no_frontmatter);
}

示例说明

这个完整示例演示了gray_matter库的6个主要使用场景:

  1. 基本YAML解析:解析包含YAML格式Front Matter的字符串
  2. 反序列化为结构体:将元数据解析到自定义的Rust结构体
  3. 处理TOML格式:展示如何使用不同的解析引擎
  4. 自定义分隔符:修改默认的分隔符配置
  5. 从文件读取:读取并解析文件内容
  6. 无Front Matter内容:处理没有元数据的纯文本内容

每个示例都有清晰的输出标记,方便理解每个功能的实际效果。使用时需要根据实际情况:

  1. 创建相应的Markdown文件(如example.md
  2. 添加适当的Cargo.toml依赖
  3. 调整结构体定义以匹配您的元数据格式
回到顶部