use crate::store::node::Node;
pub const VERSE_TYPES: &[(&str, &str, &str, &str)] = &[
("para:verse-line", "‖ ", "verse line", "\n"),
("para:verse-stanza", "♩ ", "verse stanza", "// stanza 1\n"),
("para:verse-couplet", "‗ ", "verse couplet", "\n\n"),
("para:verse-tercet", "⁚ ", "verse tercet", "\n\n\n"),
("para:verse-quatrain", "⁛ ", "verse quatrain", "\n\n\n\n"),
("para:verse-translation", "⇄ ", "verse translation", "\n"),
];
pub fn verse_glyph(node: &Node) -> Option<&'static str> {
let tag = node.tags.iter().find(|t| t.starts_with("para:verse-"))?;
VERSE_TYPES.iter().find(|(t, ..)| *t == tag.as_str()).map(|(_, glyph, ..)| *glyph)
}
pub fn is_verse_paragraph(node: &Node) -> bool {
node.tags.iter().any(|t| t.starts_with("para:verse-"))
}
#[cfg(test)]
mod tests {
use super::*;
fn para(tags: &[&str]) -> Node {
serde_json::from_value(serde_json::json!({
"id": uuid::Uuid::nil(), "kind": "paragraph", "title": "p", "slug": "p",
"path": [], "parent_id": null, "order": 1, "file": null,
"modified_at": "2026-01-01T00:00:00Z",
"tags": tags,
}))
.expect("test node")
}
#[test]
fn glyph_resolves_every_registered_type() {
for (tag, glyph, ..) in VERSE_TYPES {
assert_eq!(verse_glyph(¶(&[tag])), Some(*glyph));
}
}
#[test]
fn is_verse_paragraph_gates_on_the_verse_prefix() {
assert!(is_verse_paragraph(¶(&["para:verse-stanza"])));
assert!(is_verse_paragraph(¶(&["draft", "para:verse-line"])));
assert!(!is_verse_paragraph(¶(&["para:code"])));
assert!(!is_verse_paragraph(¶(&[])));
}
#[test]
fn non_verse_gets_no_glyph() {
assert_eq!(verse_glyph(¶(&["para:code"])), None);
assert_eq!(verse_glyph(¶(&[])), None);
}
}