socketry_markdown/mdast/frontmatter.rs
1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::unist::Position;
5use alloc::string::String;
6
7/// Language-agnostic frontmatter with an opaque format hint.
8///
9/// The contents are raw text: the Markdown parser does not interpret the
10/// named language. Untagged `---` and `+++` forms retain their legacy `Yaml`
11/// and `Toml` nodes; tagged forms and language-tagged code fences use this node.
12#[derive(Clone, Debug, Eq, PartialEq)]
13#[cfg_attr(
14 feature = "serde",
15 derive(serde::Serialize, serde::Deserialize),
16 serde(rename_all = "camelCase")
17)]
18pub struct Frontmatter {
19 /// Raw content between the fence lines, including its trailing line ending.
20 pub value: String,
21 /// The whole info string, with surrounding spaces and tabs removed.
22 /// Escapes and character references remain literal, as in Markly.
23 pub info: String,
24 /// Opening fence marker: a backtick, tilde, dash, or plus.
25 pub fence: char,
26 /// Number of opening fence markers. Serialization may lengthen the fence
27 /// to keep edited content from closing it prematurely.
28 pub fence_length: usize,
29 /// Number of closing fence markers. Closing code fences can be longer
30 /// than their opening fence.
31 pub closing_fence_length: usize,
32 /// Source position, including the fences.
33 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
34 pub position: Option<Position>,
35}
36
37impl Frontmatter {
38 /// Return the first ASCII-whitespace-separated word as a format or language hint.
39 /// The parser does not validate or interpret this hint.
40 #[must_use]
41 pub fn language(&self) -> Option<&str> {
42 self.info.split_ascii_whitespace().next()
43 }
44}