1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! `basecoat-macros` — the `rsx!` proc-macro for basecoat-rs.
//!
//! # Usage
//!
//! ```rust,ignore
//! use basecoat_macros::rsx;
//!
//! let markup = rsx! { <Button variant="primary">"Click me"</Button> };
//! ```
//!
//! See `SYNTAX.md` in this crate for the full language specification.
//!
//! # Crate architecture
//!
//! - `parse` — rstml → internal `RsxNode` AST.
//! - `emit` — `RsxNode` AST → `proc_macro2::TokenStream`.
//! - `props` — static tables: known typed setters per component, void element
//! list, PascalCase → snake_case conversion.
//!
//! The emitted code calls:
//! - `::basecoat_core::*` for prop types.
//! - `::basecoat_components::*` for component functions.
//! - `::basecoat_macros_rt::escape_text` / `escape_attr` for runtime escaping.
use TokenStream;
use TokenStream as TokenStream2;
/// JSX-like template macro that emits pre-rendered HTML as
/// `::basecoat_core::Markup`.
///
/// See `crates/basecoat-macros/SYNTAX.md` for the full syntax specification
/// and worked examples.
///
/// # Quick reference
///
/// - **PascalCase tags** call `::basecoat_components::the_fn(Props::builder()..build())`.
/// - **lowercase tags** emit raw HTML strings.
/// - `<>...</>` is a fragment (children concatenated, no wrapper element).
/// - `attr="literal"` — compile-time-escaped value.
/// - `attr={expr}` — runtime-escaped via `::basecoat_macros_rt`.
/// - No control-flow tags — use `{ if ... }` / `{ iter.map(...) }` inside `{}`.
///
/// # Example
///
/// ```rust,ignore
/// let name = "World";
/// let markup = rsx! {
/// <div class="greeting">
/// <span>"Hello, "</span>
/// {name}
/// </div>
/// };
/// assert!(markup.to_string().contains("Hello,"));
/// ```