wayver's git archive


an obsidian renderer
git clone https://git.wayver.dev/sable

sable-frontmatter/src/toml.rs@main

raw
Date Commit Message Author Files + -
2026-02-23 01:55 initial mvp wayverd 139 17808 0
...

1//! Parse TOML frontmatter
2
3use miette::{SourceOffset, SourceSpan};
4
5use crate::{Metadata, parse_simple};
6
7/// TOML parse error
8#[derive(Debug, miette::Diagnostic, thiserror::Error)]
9#[error("failed to deserialize toml frontmatter")]
10pub struct Error {
11    /// The 'source' of the frontmatter.
12    #[source_code]
13    src: String,
14    /// The location where [`serde_toml`] failed to parse.
15    #[label("{err}")]
16    location: Option<SourceSpan>,
17
18    /// The error emitted.
19    #[source]
20    err: Box<serde_toml::de::Error>,
21}
22
23/// Locates start and end `+++` and attempts to parse the contents.
24///
25/// # Errors
26///
27/// This will fail if the contents is not valid TOML.
28pub fn parse(data: &str) -> Result<(Option<Metadata>, &str), Error> {
29    let (frontmatter, contents) = match parse_simple(data, "---") {
30        (Some(frontmatter), contents) => (frontmatter, contents),
31        (None, contents) => return Ok((None, contents)),
32    };
33
34    let parsed = match serde_toml::from_str(frontmatter) {
35        Ok(parsed) => parsed,
36        Err(err) => {
37            return Err(Error {
38                src: frontmatter.to_string(),
39                location: err.span().map(|span| {
40                    SourceSpan::new(SourceOffset::from(span.start), span.end - span.start)
41                }),
42                err: Box::new(err),
43            });
44        }
45    };
46
47    Ok((Some(parsed), contents))
48}
49