yew_alt_html/lib.rs
1//! Alternative macro for building Html in Yew.
2//!
3//! This crate experiments on creating a macro that would be easier to use.
4//! For this, the [`html!` syntax](https://yew.rs/docs/concepts/html)
5//! that was a bit cumbersome to use
6//! is replaced by direct usage of values in `ah!`.
7//!
8//! Following problems should be solved by this crate:
9//!
10//! - Having to use `{}` inside tags even when values are simple literals.
11//! - Having to wrap attributes in `{}`
12//! (mind that shorthand still uses `{ variable }`).
13//! - Having to repeat generics (Yew-only) and tag names
14//! (not very HTML to omit, but still neat to have considered)
15//! when closing tags.
16//! - Having to use fragment `<></>` when using multiple nodes in the macro root.
17//! - Not being able to use `match` just like `if`.
18//! - Cumbersome `{ for ... }` notation.
19//!
20//! ## Example
21//!
22//! ```rust
23//! use yew::prelude::*;
24//! use yew_alt_html::ah;
25//!
26//! enum LoadState {
27//! Loading,
28//! Failed,
29//! Loaded,
30//! }
31//!
32//! #[function_component]
33//! pub fn App() -> Html {
34//! let name = "Yew";
35//! let italic_style = "font-style: italic";
36//!
37//! use LoadState::*;
38//! let state = Loaded;
39//! let items = vec![1, 2, 3];
40//! ah! {
41//! <h1 style=italic_style>"Hello " name "!"</>
42//! match state {
43//! Loading => "Loading...",
44//! Failed => "Load failed!",
45//! Loaded => <p>"Welcome to "<code>"yew-alt-html"</>"!"</>,
46//! }
47//! <ul>
48//! for item in items {
49//! <li>item</>
50//! }
51//! </>
52//! }
53//! }
54//! ```
55
56mod content;
57mod logic;
58mod reader;
59
60#[macro_use]
61mod util;
62
63#[macro_use]
64mod tt;
65
66use proc_macro::*;
67pub(crate) use tt_call_macro;
68pub(crate) use tt_path;
69pub(crate) use tt_stream;
70
71use self::logic::errors::InvalidSyntax;
72use self::logic::read_children;
73use self::reader::TokenReader;
74
75macro_rules! impl_proc_macro {
76 ($($name:ident -> $yew_name:ident),* $(,)?) => {
77 $(#[proc_macro]
78 pub fn $name(item: TokenStream) -> TokenStream {
79 let reader = TokenReader::from(item);
80
81 match read_children::<read_children::InBlock>(reader) {
82 Ok(children) => tt_call_macro!(::yew::$yew_name!(children)),
83 Err(InvalidSyntax(e, span)) => tt::compile_error(e, span),
84 }
85 })*
86 };
87}
88
89impl_proc_macro!(ah -> html, ah_nested -> html_nested);