use crate::scope::DocumentView;
use crate::shape::Shape;
use headwater_doc::Sentence;
use headwater_yaml::Span;
pub const SCENT: &str = "scent";
pub struct Scent {
pub facet: String,
pub span: Span,
pub sentences: Vec<Sentence>,
}
pub fn scent_facet(shape: &Shape) -> Option<String> {
shape.facet_in_role(SCENT).map(|facet| facet.name.clone())
}
impl Scent {
pub fn of(view: &DocumentView<'_>, facet: &str) -> Option<Scent> {
let entry = view.facets().get(facet)?;
let text = entry.value.as_scalar()?.text.as_str();
if text.trim().is_empty() {
return None;
}
let parsed = headwater_doc::body::scan(text, text, 0);
Some(Scent {
facet: facet.to_string(),
span: entry.span,
sentences: parsed.sentences(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shape::{Facet, Shape};
use headwater_yaml::Position;
fn facet(name: &str, role: Option<&str>) -> Facet {
Facet {
name: name.to_string(),
role: role.map(str::to_string),
value_type: None,
required: false,
values: Vec::new(),
stale_after_days: None,
span: Span::new(Position::new(1, 1, 0), Position::new(1, 1, 0)),
}
}
#[test]
fn the_scent_role_names_the_facet_and_the_name_role_does_not() {
let shape = Shape {
facets: vec![facet("title", Some("name")), facet("summary", Some(SCENT))],
..Shape::default()
};
assert_eq!(scent_facet(&shape).as_deref(), Some("summary"));
}
#[test]
fn a_shape_with_no_scent_facet_names_nothing() {
let shape = Shape {
facets: vec![facet("title", Some("name")), facet("owner", None)],
..Shape::default()
};
assert_eq!(scent_facet(&shape), None);
}
}