Repository: bevyengine/bevy
File: tools/export-content/src/app.rs (Rust)

Code before:

#[derive(Deserialize, Debug)]
struct Metadata {
    title: String,
    authors: Option<Vec<String>>,
    pull_requests: Vec<u32>,
}

#[derive(Debug)]
enum Entry {
    Section { title: String },
    File { metadata: Metadata, content: String },
}

impl Entry {
    fn as_list_entry(&'_ self) -> ListItem<'_> {
        match self {
            Entry::Section { title } => ListItem::new(title.as_str()).underlined().fg(Color::Blue),
            Entry::File { metadata, .. } => ListItem::new(metadata.title.as_str()),
        }
    }
}

/// Loads release content from files in the specified directory
fn load_content(dir: path::PathBuf, kind: &'static str) -> Result<Vec<Entry>> {
    let re = Regex::new(r"(?s)^---\s*\n(.*?)\n---\n(.*)").unwrap();

    let mut entries = vec![];

    for dir_entry in fs::read_dir(dir)
        .into_diagnostic()
        .wrap_err("unable to read directory")?
    {
        let dir_entry = dir_entry
            .into_diagnostic()
            .wrap_err(format!("unable to access {} file", kind))?;

        // Skip directories
        if !dir_entry.path().is_file() {
            continue;
        }
        // Skip files with invalid names
        let Ok(file_name) = dir_entry.file_name().into_string() else {
            continue;
        };
        // Skip hidden files (like .gitkeep or .DS_Store)
        if file_name.starts_with(".") {
            continue;
        }

        let file_content = fs::read_to_string(&dir_entry.path())

Review comment (suggestion):
The Regex has problems on window, where lineendings are temporarily converted to \r\n. Also in my opinion, groups should be named unless there is a reason not to. Makes it much clearer for the reader what the intention is. Of course, the naming is nitpick only, no blocker.
```rs
let re = Regex::new(r"(?s)^---\s*\n(?<frontmatter>.*?)\s*\n---\s*\n(?<content>.*)").unwrap();
```

Code after:
struct Metadata {
    title: String,
    authors: Option<Vec<String>>,
    pull_requests: Vec<u32>,
}

#[derive(Debug)]
enum Entry {
    Section { title: String },
    File { metadata: Metadata, content: String },
}

impl Entry {
    fn as_list_entry(&'_ self) -> ListItem<'_> {
        match self {
            Entry::Section { title } => ListItem::new(title.as_str()).underlined().fg(Color::Blue),
            Entry::File { metadata, .. } => ListItem::new(metadata.title.as_str()),
        }
    }
}

/// Loads release content from files in the specified directory
fn load_content(dir: path::PathBuf, kind: &'static str) -> Result<Vec<Entry>> {
    let re = Regex::new(r"(?s)^---\s*\n(?<frontmatter>.*?)\s*\n---\s*\n(?<content>.*)").unwrap();

    let mut entries = vec![];

    for dir_entry in fs::read_dir(dir)
        .into_diagnostic()
        .wrap_err("unable to read directory")?
    {
        let dir_entry = dir_entry
            .into_diagnostic()
            .wrap_err(format!("unable to access {} file", kind))?;

        // Skip directories
        if !dir_entry.path().is_file() {
            continue;
        }
        // Skip files with invalid names
        let Ok(file_name) = dir_entry.file_name().into_string() else {
            continue;
        };
        // Skip hidden files (like .gitkeep or .DS_Store)
        if file_name.starts_with(".") {
            continue;
        }

        let file_content = fs::read_to_string(dir_entry.path())
            .into_diagnostic()
            .wrap_err(format!("unable to read {} file", kind))?;