// =============================================================================
// Markdown AST Types
// =============================================================================
///|
/// Markdown node types
pub(all) enum MdNode {
/// Heading with level (1-6)
Heading(level~ : Int, children~ : Array[MdNode], id~ : String)
/// Paragraph
Paragraph(children~ : Array[MdNode])
/// Plain text
Text(String)
/// Bold text
Bold(children~ : Array[MdNode])
/// Italic text
Italic(children~ : Array[MdNode])
/// Inline code
Code(String)
/// Code block with language
CodeBlock(lang~ : String, code~ : String)
/// Link
Link(href~ : String, title~ : String, children~ : Array[MdNode])
/// Image
Image(src~ : String, alt~ : String, title~ : String)
/// Unordered or ordered list
List(ordered~ : Bool, items~ : Array[Array[MdNode]])
/// Blockquote
Blockquote(children~ : Array[MdNode])
/// Table
Table(headers~ : Array[MdNode], rows~ : Array[Array[MdNode]])
/// Raw HTML
Html(String)
/// Island component directive (legacy)
Island(IslandEmbed)
/// Web Component custom element
Component(ComponentEmbed)
/// JSX component from MDX (before conversion to WebComponent)
JsxComponent(JsxComponentEmbed)
/// Horizontal rule
ThematicBreak
/// Line break
LineBreak
}
// =============================================================================
// Island/Component Embedding Types
// =============================================================================
///|
/// Island embedding in markdown (legacy, prefer ComponentEmbed)
pub(all) struct IslandEmbed {
/// Island component name
name : String
/// Props as JSON string
props : String
/// Hydration trigger
trigger : @luna.Trigger
/// Whether to render server-side (default: false, client-only placeholder)
ssr : Bool
}
///|
/// Default Island embed
pub fn IslandEmbed::new(name : String) -> IslandEmbed {
{ name, props: "{}", trigger: @luna.TriggerType::Load, ssr: false }
}
///|
/// Web Component embedding in markdown
/// Custom elements (names containing `-`) are registered via customElements.define
pub(all) struct ComponentEmbed {
/// Custom element tag name (e.g., "my-counter", "foo-bar")
tag : String
/// HTML attributes as key-value pairs
attrs : Array[(String, String)]
/// Inner HTML content
content : String
/// Hydration trigger
trigger : @luna.Trigger
}
///|
/// Default Component embed
pub fn ComponentEmbed::new(tag : String) -> ComponentEmbed {
{ tag, attrs: [], content: "", trigger: @luna.TriggerType::Load }
}
// =============================================================================
// MDX Types
// =============================================================================
///|
/// JSX component embedding in MDX
/// Before rendering, converted to ComponentEmbed (WebComponent)
pub(all) struct JsxComponentEmbed {
/// JSX component tag name (e.g., "Button", "Counter")
tag : String
/// Attributes with typed values
attrs : Array[(String, MdxAttrValue)]
/// Inner content (raw string, may contain nested elements)
children : String
/// Whether self-closing ()
self_closing : Bool
/// CLS optimization hints
cls_hints : ClsHints?
}
///|
/// Default JSX component embed
pub fn JsxComponentEmbed::new(tag : String) -> JsxComponentEmbed {
{ tag, attrs: [], children: "", self_closing: false, cls_hints: None }
}
///|
/// MDX attribute value types
pub(all) enum MdxAttrValue {
/// String literal: prop="value" or prop='value'
StringLiteral(String)
/// Expression: prop={expression}
Expression(String)
/// Boolean: prop (true when present)
Boolean
} derive(Eq, Debug)
///|
/// CLS (Cumulative Layout Shift) optimization hints
/// Used to prevent layout shifts when components load
pub(all) struct ClsHints {
/// Expected width (CSS value, e.g., "200px", "100%")
width : String?
/// Expected height (CSS value, e.g., "100px", "auto")
height : String?
} derive(Eq, Debug)
///|
/// Default CLS hints (no hints)
pub fn ClsHints::new() -> ClsHints {
{ width: None, height: None }
}