use nom::*;
use nom::{
IResult,
bytes::complete::{take_while, take_until},
character::complete::{char, newline, multispace0},
sequence::{separated_pair},
error::{ParseError,VerboseError,context}
};
use super::utils::*;
use super::errors::{
ATTRIBUTE_SPACE_BEFORE_ERROR,
ATTRIBUTE_MISSING_EQUAL_ERROR,
ATTRIBUTE_TAG_ERROR,
ATTRIBUTE_VALUE_ERROR,
ATTRIBUTE_MISSING_OPENING_QUOTE_ERROR,
ATTRIBUTE_MISSING_CLOSING_QUOTE_ERROR,
};
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum Attribute {
Class(String),
Event(String),
Custom(String),
Component(String),
}
impl Attribute {
pub fn get_value(attr: &Attribute) -> &String {
match attr {
Attribute::Class(e) => e,
Attribute::Event(e) => e,
Attribute::Custom(e) => e,
Attribute::Component(e) => e,
}
}
}
pub type TagAttributes = Vec<(Attribute, String)>;
pub fn get_denominator(denominator: &str) -> Attribute {
if denominator == "class" {
Attribute::Class(denominator.to_string())
} else if denominator == "component" {
Attribute::Component(denominator.to_string())
} else if denominator.contains("@") {
Attribute::Event(denominator.to_string().replace("@", ""))
} else {
Attribute::Custom(denominator.to_string())
}
}
pub fn attribute_value(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
let (input, _opening_quote) = context(
ATTRIBUTE_MISSING_OPENING_QUOTE_ERROR,
char('`')
)(input)?;
let (input, value) = context(
ATTRIBUTE_VALUE_ERROR,
take_until("`")
)(input)?;
let (input, _opening_quote) = context(
ATTRIBUTE_MISSING_CLOSING_QUOTE_ERROR,
char('`')
)(input)?;
let (input, _newline) = opt!(input, multispace0)?; Ok((input, value))
}
pub fn attribute_tag(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
let (input, denominator) = context(
ATTRIBUTE_TAG_ERROR,
take_while(is_html_value)
)(input)?;
Ok((input, denominator))
}
pub fn html_attribute(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
let (input, _newline) = opt!(input, multispace0)?; let (input, attr) = attribute_tag(input)?;
Ok((input, attr))
}
pub fn attribute(input: &str) -> IResult<&str, (&str, &str), VerboseError<&str>> {
let (input, _newline) = opt!(input, multispace0)?; separated_pair(
html_attribute,
context(ATTRIBUTE_MISSING_EQUAL_ERROR, char('=')),
attribute_value
)(input)
}