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
79
80
81
82
//! # Yew Lmth
//!
//! A macro crate for writing HTML-like syntax, which will be translated into a corresponding `yew::prelude::html!()` macro.
//!
//! ## Syntax
//!
//! ### Tags
//!
//! | `lmth!` syntax        | meaning                         | `html!` syntax              |
//! | --------------------- | ------------------------------- | -------------------------- |
//! | `! { ... }`           | Yew's fragment                  | `<> ... </>`               |
//! | `tag (attrs) { ... }` | Tag with attributes and content | `<tag attrs>{ ... }</tag>` |
//! | `tag (attrs)`         | Void tag with attributes        | `<tag attrs />`            |
//! | `tag { ... }`         | Tag with content                | `<tag>{ ... }</tag>`       |
//! | `tag`                 | Void tag with no attribute      | `<tag />`                  |
//!
//! ### Attributes
//!
//! Attributes are separated by commas: `tag (attr: val, attr: val, ...) { ... }`
//!
//! | `lmth!` syntax  | meaning                                | `html!` syntax  |
//! | --------------- | -------------------------------------- | -------------- |
//! | `attr: expr`    | Attribute with expression as value     | `attr={expr}`  |
//! | `attr: {code}`  | Attribute with code block as value     | `attr={code}`  |
//! | `attr="litstr"` | Attribute with literal string as value | `attr="litstr"`|
//! | `attr`          | Shorthand for `{attr}` in yew          | `{attr}`       |
//!
//! ### Content
//!
//! | `lmth!` syntax  | meaning                   | `html!` syntax     |
//! | --------------- | ------------------------- | ----------------- |
//! | `{code}`        | Code as content           | `{code}`          |
//! | `"litstr"`      | Literal string as content | `"litstr"`        |
//! | `tag ...`       | Tag                       | corresponding tag |
//!

use lmth::{ir::LmthNode, lmth_act};
use proc_macro as pm;
use quote::quote;
use syn::parse_macro_input;

//~ Sub-modules
mod lmth;
#[cfg(test)]
mod tests;

/// Macro for writing HTML-like syntax, which will be translated
/// into a corresponding `yew::prelude::html!()` macro.
///
/// # Example
///
/// ```rust
/// use yew_lmth::lmth;
///
/// lmth! {
///     div (class="container") {
///        h1 { "Hello, world!" }
///        button (onclick: handle_click()) { "Click me!" }
///     }
/// }
///
/// // expands to:
/// // yew::prelude::html! {
/// //     <div class="container">
/// //         <h1>{ "Hello, world!" }</h1>
/// //         <button onclick={handle_click()}>{ "Click me!" }</button>
/// //     </div>
/// // }
/// ```
#[proc_macro]
pub fn lmth(input: pm::TokenStream) -> pm::TokenStream {
    if input.is_empty() {
        return quote! {
            yew::prelude::html! {}
        }
        .into();
    }

    let node = parse_macro_input!(input as LmthNode);

    lmth_act(node).into()
}