use serde::{Deserialize, Serialize};
use super::HyphenationStyle;
use crate::String;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AttributeHyphenationConfig {
Style(HyphenationStyle),
Options(AttributeHyphenationOptions),
}
impl AttributeHyphenationConfig {
pub fn style(&self) -> HyphenationStyle {
match self {
Self::Style(style) => *style,
Self::Options(options) => options.style,
}
}
pub fn ignore(&self) -> Option<&[String]> {
match self {
Self::Style(_) => None,
Self::Options(options) => Some(&options.ignore),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(try_from = "RawOptions")]
pub struct AttributeHyphenationOptions {
pub style: HyphenationStyle,
pub ignore: Vec<String>,
}
impl Default for AttributeHyphenationOptions {
fn default() -> Self {
Self {
style: HyphenationStyle::Always,
ignore: Vec::new(),
}
}
}
impl AttributeHyphenationOptions {
pub fn validate(&self) -> Result<(), &'static str> {
for (index, entry) in self.ignore.iter().enumerate() {
if entry.chars().all(is_ecmascript_whitespace) {
return Err("ignore entries must not be blank");
}
if entry.ends_with(":exit") {
return Err("ignore entries must not end with :exit");
}
if self
.ignore
.iter()
.take(index)
.any(|previous| previous == entry)
{
return Err("ignore entries must be unique");
}
}
Ok(())
}
}
#[derive(Deserialize)]
#[serde(default, deny_unknown_fields)]
struct RawOptions {
style: HyphenationStyle,
ignore: Vec<String>,
}
impl Default for RawOptions {
fn default() -> Self {
Self {
style: HyphenationStyle::Always,
ignore: Vec::new(),
}
}
}
impl TryFrom<RawOptions> for AttributeHyphenationOptions {
type Error = &'static str;
fn try_from(raw: RawOptions) -> Result<Self, Self::Error> {
let options = Self {
style: raw.style,
ignore: raw.ignore,
};
options.validate()?;
Ok(options)
}
}
fn is_ecmascript_whitespace(character: char) -> bool {
matches!(
character,
'\u{0009}'..='\u{000d}'
| '\u{0020}'
| '\u{00a0}'
| '\u{1680}'
| '\u{2000}'..='\u{200a}'
| '\u{2028}'
| '\u{2029}'
| '\u{202f}'
| '\u{205f}'
| '\u{3000}'
| '\u{feff}'
)
}
#[cfg(test)]
mod tests;