use swc_core::{ecma::{ast::{Expr, Pat}, atoms::{JsWord, Atom}}, common::Span};
pub type FervidAtom = Atom;
#[macro_export]
macro_rules! fervid_atom {
($lit: literal) => {
fervid_core::FervidAtom::from($lit)
};
}
#[derive(Debug, Clone)]
pub enum Node {
Element(ElementNode),
Text(FervidAtom, Span),
Interpolation(Interpolation),
Comment(FervidAtom, Span),
ConditionalSeq(ConditionalNodeSequence),
}
#[derive(Debug, Clone)]
pub struct ElementNode {
pub kind: ElementKind,
pub starting_tag: StartingTag,
pub children: Vec<Node>,
pub template_scope: u32,
pub patch_hints: PatchHints,
pub span: Span
}
#[derive(Debug, Clone, Copy, Default)]
pub enum ElementKind {
Builtin(BuiltinType),
#[default]
Element,
Component,
}
#[derive(Debug, Clone, Copy)]
pub enum BuiltinType {
Component,
KeepAlive,
Slot,
Suspense,
Teleport,
Transition,
TransitionGroup,
}
#[derive(Debug, Clone)]
pub struct ConditionalNodeSequence {
pub if_node: Box<Conditional>,
pub else_if_nodes: Vec<Conditional>,
pub else_node: Option<Box<ElementNode>>,
}
#[derive(Debug, Clone)]
pub struct Conditional {
pub condition: Expr,
pub node: ElementNode,
}
#[derive(Debug, Clone)]
pub struct Interpolation {
pub value: Box<Expr>,
pub template_scope: u32,
pub patch_flag: bool,
pub span: Span
}
#[derive(Debug, Clone)]
pub struct StartingTag {
pub tag_name: FervidAtom,
pub attributes: Vec<AttributeOrBinding>,
pub directives: Option<Box<VueDirectives>>,
}
#[derive(Debug, Clone)]
pub enum AttributeOrBinding {
RegularAttribute { name: FervidAtom, value: FervidAtom, span: Span },
VBind(VBindDirective),
VOn(VOnDirective),
}
#[derive(Debug, Clone)]
pub enum StrOrExpr {
Str(FervidAtom),
Expr(Box<Expr>),
}
impl<'s> From<&'s str> for StrOrExpr {
fn from(value: &'s str) -> StrOrExpr {
StrOrExpr::Str(FervidAtom::from(value))
}
}
#[derive(Debug, Default, Clone)]
pub struct PatchHints {
pub flags: PatchFlagsSet,
pub props: Vec<JsWord>,
pub should_use_block: bool
}
flagset::flags! {
#[derive(Default)]
pub enum PatchFlags: i32 {
Text = 1,
Class = 1 << 1,
Style = 1 << 2,
Props = 1 << 3,
FullProps = 1 << 4,
NeedHydration = 1 << 5,
StableFragment = 1 << 6,
KeyedFragment = 1 << 7,
UnkeyedFragment = 1 << 8,
#[default]
NeedPatch = 1 << 9,
DynamicSlots = 1 << 10,
DevRootFragment = 1 << 11,
Hoisted = -1,
Bail = -2,
}
}
pub type PatchFlagsSet = flagset::FlagSet<PatchFlags>;
#[derive(Clone, Debug, Default)]
pub struct VueDirectives {
pub custom: Vec<VCustomDirective>,
pub v_cloak: Option<()>,
pub v_else: Option<()>,
pub v_else_if: Option<Box<Expr>>,
pub v_for: Option<VForDirective>,
pub v_html: Option<Box<Expr>>,
pub v_if: Option<Box<Expr>>,
pub v_memo: Option<Box<Expr>>,
pub v_model: Vec<VModelDirective>,
pub v_once: Option<()>,
pub v_pre: Option<()>,
pub v_show: Option<Box<Expr>>,
pub v_slot: Option<VSlotDirective>,
pub v_text: Option<Box<Expr>>,
}
#[derive(Clone, Debug)]
pub struct VForDirective {
pub iterable: Box<Expr>,
pub itervar: Box<Expr>,
pub patch_flags: PatchFlagsSet,
pub span: Span
}
#[derive(Clone, Debug)]
pub struct VOnDirective {
pub event: Option<StrOrExpr>,
pub handler: Option<Box<Expr>>,
pub modifiers: Vec<FervidAtom>,
pub span: Span
}
#[derive(Clone, Debug)]
pub struct VBindDirective {
pub argument: Option<StrOrExpr>,
pub value: Box<Expr>,
pub is_camel: bool,
pub is_prop: bool,
pub is_attr: bool,
pub span: Span
}
#[derive(Clone, Debug)]
pub struct VModelDirective {
pub argument: Option<StrOrExpr>,
pub value: Box<Expr>,
pub update_handler: Option<Box<Expr>>,
pub modifiers: Vec<FervidAtom>,
pub span: Span
}
#[derive(Clone, Debug)]
pub struct VSlotDirective {
pub slot_name: Option<StrOrExpr>,
pub value: Option<Box<Pat>>,
}
#[derive(Debug, Default, Clone)]
pub struct VCustomDirective {
pub name: FervidAtom,
pub argument: Option<StrOrExpr>,
pub modifiers: Vec<FervidAtom>,
pub value: Option<Box<Expr>>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BindingTypes {
Data,
Props,
PropsAliased,
SetupLet,
SetupConst,
SetupReactiveConst,
SetupMaybeRef,
SetupRef,
Options,
LiteralConst,
Component,
Imported,
TemplateLocal,
JsGlobal,
Unresolved,
}
#[derive(Debug, Default)]
pub enum TemplateGenerationMode {
Inline,
#[default]
RenderFn
}