use super::{check, get_checked, Error, FunctionMap};
use crate::css::{BadSelector, Selectors, Value};
use crate::sass::Name;
use crate::Scope;
use std::convert::{TryFrom, TryInto};
pub fn create_module() -> Scope {
let mut f = Scope::builtin_module("sass:selector");
def_va!(f, append(selectors), |s| {
get_selectors(s, name!(selectors))?
.into_iter()
.try_fold(Selectors::root(), |base, ext| base.append(ext))
.map(Into::into)
});
def_va!(f, nest(selectors), |s| {
let mut v = get_selectors(s, name!(selectors))?.into_iter();
let first = v.next().unwrap().css_ok()?;
Ok(v.fold(first, |b, e| e.inside(&b)).into())
});
def!(f, parse(selector), |s| {
Ok(get_checked(s, name!(selector), parse_selectors_x)?.into())
});
f
}
fn get_selectors(s: &Scope, name: Name) -> Result<Vec<Selectors>, Error> {
Ok(get_checked(s, name, check::va_list_nonempty)?
.into_iter()
.map(|v| v.try_into())
.collect::<Result<_, BadSelector>>()?)
}
pub fn expose(m: &Scope, global: &mut FunctionMap) {
for (gname, lname) in &[
(name!(selector_append), name!(append)),
(name!(selector_nest), name!(nest)),
(name!(selector_parse), name!(parse)),
] {
global.insert(gname.clone(), m.get_lfunction(lname));
}
}
fn parse_selectors_x(v: Value) -> Result<Selectors, String> {
Selectors::try_from(v)
.and_then(|s| s.css_ok())
.map_err(|e| e.to_string())
}