@@ -43,6 +43,8 @@ pub enum HtmlNode<'a> {
4343 Text ( Box < ' a , HtmlText < ' a > > ) ,
4444 /// An element node.
4545 Element ( Box < ' a , HtmlElement < ' a > > ) ,
46+ /// A selectorless component node.
47+ Component ( Box < ' a , HtmlComponent < ' a > > ) ,
4648 /// An attribute node.
4749 Attribute ( Box < ' a , HtmlAttribute < ' a > > ) ,
4850 /// A comment node.
@@ -65,6 +67,7 @@ impl<'a> HtmlNode<'a> {
6567 match self {
6668 HtmlNode :: Text ( t) => t. span ,
6769 HtmlNode :: Element ( e) => e. span ,
70+ HtmlNode :: Component ( c) => c. span ,
6871 HtmlNode :: Attribute ( a) => a. span ,
6972 HtmlNode :: Comment ( c) => c. span ,
7073 HtmlNode :: Expansion ( e) => e. span ,
@@ -123,6 +126,35 @@ pub struct HtmlElement<'a> {
123126 pub is_void : bool ,
124127}
125128
129+ /// A selectorless component in the HTML AST.
130+ ///
131+ /// This represents a component used with selectorless syntax: `<MyComp>` or `<MyComp:button>`.
132+ /// This is a first-class node type that matches Angular's Component AST node.
133+ #[ derive( Debug ) ]
134+ pub struct HtmlComponent < ' a > {
135+ /// The component class name (e.g., "MyComp").
136+ pub component_name : Atom < ' a > ,
137+ /// The HTML tag name (e.g., "button" in `<MyComp:button>`).
138+ /// None for component-only syntax like `<MyComp>`.
139+ pub tag_name : Option < Atom < ' a > > ,
140+ /// The full qualified name (e.g., "MyComp:svg:rect").
141+ pub full_name : Atom < ' a > ,
142+ /// The element attributes.
143+ pub attrs : Vec < ' a , HtmlAttribute < ' a > > ,
144+ /// Selectorless directives (e.g., @Dir).
145+ pub directives : Vec < ' a , HtmlDirective < ' a > > ,
146+ /// The child nodes.
147+ pub children : Vec < ' a , HtmlNode < ' a > > ,
148+ /// Whether this component was explicitly self-closing (e.g., `<MyComp/>`).
149+ pub is_self_closing : bool ,
150+ /// The source span.
151+ pub span : Span ,
152+ /// The start tag source span.
153+ pub start_span : Span ,
154+ /// The end tag source span (None for self-closing/incomplete components).
155+ pub end_span : Option < Span > ,
156+ }
157+
126158/// A selectorless directive in the HTML AST (e.g., @Dir or @Dir(attr="value")).
127159#[ derive( Debug ) ]
128160pub struct HtmlDirective < ' a > {
@@ -309,6 +341,11 @@ pub trait Visitor<'a>: Sized {
309341 visit_element ( self , element) ;
310342 }
311343
344+ /// Called when visiting a component node.
345+ fn visit_component ( & mut self , component : & HtmlComponent < ' a > ) {
346+ visit_component ( self , component) ;
347+ }
348+
312349 /// Called when visiting an attribute node.
313350 fn visit_attribute ( & mut self , _attr : & HtmlAttribute < ' a > ) { }
314351
@@ -341,6 +378,7 @@ pub trait Visitor<'a>: Sized {
341378 match node {
342379 HtmlNode :: Text ( text) => self . visit_text ( text) ,
343380 HtmlNode :: Element ( element) => self . visit_element ( element) ,
381+ HtmlNode :: Component ( component) => self . visit_component ( component) ,
344382 HtmlNode :: Attribute ( attr) => self . visit_attribute ( attr) ,
345383 HtmlNode :: Comment ( comment) => self . visit_comment ( comment) ,
346384 HtmlNode :: Expansion ( expansion) => self . visit_expansion ( expansion) ,
@@ -368,6 +406,15 @@ pub fn visit_element<'a, V: Visitor<'a>>(visitor: &mut V, element: &HtmlElement<
368406 visit_all ( visitor, & element. children ) ;
369407}
370408
409+ /// Default traversal for a component node.
410+ /// Visits attributes and children.
411+ pub fn visit_component < ' a , V : Visitor < ' a > > ( visitor : & mut V , component : & HtmlComponent < ' a > ) {
412+ for attr in & component. attrs {
413+ visitor. visit_attribute ( attr) ;
414+ }
415+ visit_all ( visitor, & component. children ) ;
416+ }
417+
371418/// Default traversal for an expansion node.
372419/// Visits all cases.
373420pub fn visit_expansion < ' a , V : Visitor < ' a > > ( visitor : & mut V , expansion : & HtmlExpansion < ' a > ) {
@@ -416,6 +463,7 @@ where
416463 match node {
417464 HtmlNode :: Text ( text) => self . visit_text ( text) ,
418465 HtmlNode :: Element ( element) => self . visit_element ( element) ,
466+ HtmlNode :: Component ( component) => self . visit_component ( component) ,
419467 HtmlNode :: Attribute ( attr) => self . visit_attribute ( attr) ,
420468 HtmlNode :: Comment ( comment) => self . visit_comment ( comment) ,
421469 HtmlNode :: Expansion ( expansion) => self . visit_expansion ( expansion) ,
0 commit comments