mod source_location;
use core::fmt;
use core::option;
use crate::define_environment::EnvSpec;
use crate::define_function::FunctionSpec;
use crate::parser::parse_node::NodeType;
pub use source_location::{LexerInterface, SourceLocation};
use strum::AsRefStr;
use strum::Display;
use strum::EnumCount;
use strum::EnumIter;
use strum::EnumString;
mod parse_error;
pub use parse_error::ErrorLocationProvider;
pub use parse_error::ParseError;
use strum::FromRepr;
mod tokens;
pub use crate::symbols::Mode;
pub use tokens::Token;
mod settings;
pub use settings::{
OutputFormat, Settings, StrictFunction, StrictMode, StrictReturn, StrictSetting, TrustContext,
TrustFunction, TrustSetting,
};
pub use source_location::SourceRangeRef;
#[derive(
EnumIter, Debug, Copy, AsRefStr, PartialEq, Eq, Hash, Clone, Display, EnumCount, FromRepr,
)]
#[strum(serialize_all = "kebab-case")]
#[repr(u8)]
pub enum CssProperty {
BackgroundColor,
BorderBottomWidth,
BorderColor,
BorderRightStyle,
BorderRightWidth,
BorderTopWidth,
BorderStyle,
BorderWidth,
Bottom,
Color,
Height,
Left,
Margin,
MarginLeft,
MarginRight,
MarginTop,
MinWidth,
PaddingLeft,
Position,
TextShadow,
Top,
Width,
VerticalAlign,
}
#[derive(Clone, PartialEq, Eq, Default)]
pub struct CssStyle {
map: [Option<String>; CssProperty::COUNT],
}
impl fmt::Debug for CssStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use strum::IntoEnumIterator as _;
let mut ds = f.debug_struct("CssStyle");
for (property, value) in CssProperty::iter().zip(self.map.iter()) {
if let Some(value) = value {
ds.field(property.as_ref(), value);
}
}
ds.finish()
}
}
pub struct CssStyleIter<'a> {
index: usize,
data: &'a [Option<String>; CssProperty::COUNT],
}
impl<'a> Iterator for CssStyleIter<'a> {
type Item = (CssProperty, &'a String);
fn next(&mut self) -> Option<Self::Item> {
while self.index < CssProperty::COUNT {
let idx = self.index;
self.index += 1;
if let Some(v) = &self.data[idx]
&& let Some(prop) = CssProperty::from_repr(idx as u8)
{
return Some((prop, v));
}
}
None
}
}
impl<'a> IntoIterator for &'a CssStyle {
type Item = (CssProperty, &'a String);
type IntoIter = CssStyleIter<'a>;
fn into_iter(self) -> Self::IntoIter {
CssStyleIter {
index: 0,
data: &self.map,
}
}
}
impl CssStyle {
pub fn insert(&mut self, property: CssProperty, value: String) {
self.map[property as usize] = Some(value);
}
pub fn extend(&mut self, other: &Self) {
for (i, value) in other.map.iter().enumerate() {
if let Some(value) = value {
self.map[i] = Some(value.clone());
}
}
}
#[inline]
#[must_use]
pub const fn contains_key(&self, property: CssProperty) -> bool {
self.map[property as usize].is_some()
}
#[inline]
#[must_use]
pub fn get(&self, property: CssProperty) -> Option<&str> {
self.map[property as usize].as_deref()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.map.iter().all(option::Option::is_none)
}
#[must_use]
pub fn iter(&self) -> CssStyleIter<'_> {
self.into_iter()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArgType {
Color,
Size,
Url,
Raw,
Original,
Hbox,
Primitive,
Mode(Mode),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, AsRefStr)]
#[strum(serialize_all = "lowercase")]
pub enum StyleVariant {
Text,
Display,
Script,
ScriptScript,
}
#[derive(Debug, Clone, PartialEq, Eq, EnumString, AsRefStr)]
pub enum BreakToken {
#[strum(serialize = "]")]
RightBracket,
#[strum(serialize = "}")]
RightBrace,
#[strum(serialize = "\\endgroup")]
EndGroup,
#[strum(serialize = "$")]
Dollar,
#[strum(serialize = "\\)")]
RightParen,
#[strum(serialize = "\\\\")]
DoubleBackslash,
#[strum(serialize = "\\end")]
End,
#[strum(serialize = "EOF")]
Eof,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FontVariant {
Bold,
BoldItalic,
BoldSansSerif,
DoubleStruck,
Fraktur,
Italic,
Monospace,
Normal,
SansSerif,
SansSerifBoldItalic,
SansSerifItalic,
Script,
}
pub trait Spec {
fn num_args(&self) -> usize;
fn num_optional_args(&self) -> usize;
fn arg_types(&self) -> Option<&Vec<ArgType>>;
fn primitive(&self) -> bool;
fn node_type(&self) -> Option<&NodeType>;
}
impl Spec for FunctionSpec {
fn num_args(&self) -> usize {
self.num_args
}
fn num_optional_args(&self) -> usize {
self.num_optional_args
}
fn arg_types(&self) -> Option<&Vec<ArgType>> {
self.arg_types.as_ref()
}
fn primitive(&self) -> bool {
self.primitive
}
fn node_type(&self) -> Option<&NodeType> {
self.node_type.as_ref()
}
}
impl Spec for EnvSpec {
fn num_args(&self) -> usize {
self.num_args
}
fn num_optional_args(&self) -> usize {
self.num_optional_args
}
fn arg_types(&self) -> Option<&Vec<ArgType>> {
self.arg_types.as_ref()
}
fn primitive(&self) -> bool {
false
}
fn node_type(&self) -> Option<&NodeType> {
Some(&self.node_type)
}
}