Compare commits
5 Commits
7b6eba8ca5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 403620396b | |||
| d6052a624e | |||
| b4a8898f9b | |||
| 6be8c58d03 | |||
| fe59a1e444 |
78
src/lib.rs
78
src/lib.rs
@@ -3,7 +3,6 @@ use paste::paste;
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::parse::{Parse, ParseStream, Result};
|
use syn::parse::{Parse, ParseStream, Result};
|
||||||
use syn::punctuated::Punctuated;
|
|
||||||
use syn::{Expr, Ident, Token, parse_macro_input};
|
use syn::{Expr, Ident, Token, parse_macro_input};
|
||||||
|
|
||||||
macro_rules! generate_headings {
|
macro_rules! generate_headings {
|
||||||
@@ -54,25 +53,69 @@ impl Parse for Argument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct BaseElement {
|
struct BaseElement {
|
||||||
value: Expr,
|
values: Vec<Expr>,
|
||||||
params: Punctuated<Property, Token![,]>,
|
params: Vec<Property>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BaseElement {
|
impl Parse for BaseElement {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
let value: Expr = input.parse()?;
|
let mut values = Vec::new();
|
||||||
let _ = input.parse::<Token![,]>();
|
let mut params = Vec::new();
|
||||||
let params: Punctuated<Property, Token![,]> = Punctuated::parse_terminated(input)?;
|
while !input.is_empty() {
|
||||||
Ok(BaseElement { value, params })
|
if input.peek(Ident) && input.peek2(Token![=]) {
|
||||||
|
let property: Property = input.parse()?;
|
||||||
|
params.push(property);
|
||||||
|
} else {
|
||||||
|
let value: Expr = input.parse()?;
|
||||||
|
values.push(value);
|
||||||
|
}
|
||||||
|
if input.peek(Token![,]) {
|
||||||
|
input.parse::<Token![,]>()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(BaseElement { values, params })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heading(level: &str, item: TokenStream) -> TokenStream {
|
/// # HTML Paragraph element
|
||||||
let BaseElement { value, params } = parse_macro_input!(item as BaseElement);
|
/// # Usage:
|
||||||
|
/// ```rust
|
||||||
|
/// use web_macro::paragraph;
|
||||||
|
/// let single_line = paragraph!("This is my lovely text to be displayed", id="title", class="small blue");
|
||||||
|
/// let multi_line = paragraph!(
|
||||||
|
/// "This is my lovely text to be displayed",
|
||||||
|
/// "This is another line that constitutes my paragraph",
|
||||||
|
/// id="title",
|
||||||
|
/// class="small blue"
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
/// # Notes:
|
||||||
|
/// - This element supports child insertions, see usage.
|
||||||
|
/// - Adding multiple children will **not** insert _\<br\>_
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn paragraph(input: TokenStream) -> TokenStream {
|
||||||
|
base("p", input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn division(input: TokenStream) -> TokenStream {
|
||||||
|
base("div", input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base(elem: &str, item: TokenStream) -> TokenStream {
|
||||||
|
let BaseElement { values, params } = parse_macro_input!(item as BaseElement);
|
||||||
|
let values = values.iter();
|
||||||
|
let formated_values = if values.len() > 1 {
|
||||||
|
let mut s = "\n".to_string();
|
||||||
|
s.push_str("{}\n".repeat(values.len()).as_str());
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
"{}".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
let expanded = match params.is_empty() {
|
let expanded = match params.is_empty() {
|
||||||
false => {
|
false => {
|
||||||
let mut values = Vec::new();
|
let mut options_values = Vec::new();
|
||||||
|
|
||||||
let formated_names = params
|
let formated_names = params
|
||||||
.iter()
|
.iter()
|
||||||
@@ -80,18 +123,23 @@ fn heading(level: &str, item: TokenStream) -> TokenStream {
|
|||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
let format_string = format!("<h{} {formated_names}>{{}}</h{}>", level, level);
|
let format_string =
|
||||||
|
format!("<{} {formated_names}>{}</{}>", elem, formated_values, elem);
|
||||||
|
|
||||||
for property in params {
|
for property in params {
|
||||||
values.push(property.value);
|
options_values.push(property.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
quote!(format!(#format_string, #(#values), *, #value))
|
quote!(format!(#format_string, #(#options_values), *, #(#values), *))
|
||||||
}
|
}
|
||||||
true => {
|
true => {
|
||||||
let format_string = format!("<h{}>{{}}</h{}>", level, level);
|
let format_string = format!("<{}>{}</{}>", elem, formated_values, elem);
|
||||||
quote!(format!(#format_string, #value))
|
quote!(format!(#format_string, #(#values), *))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
TokenStream::from(expanded)
|
TokenStream::from(expanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn heading(level: &str, item: TokenStream) -> TokenStream {
|
||||||
|
base(format!("h{level}").as_str(), item)
|
||||||
|
}
|
||||||
|
|||||||
29
tests/tests_divisions.rs
Normal file
29
tests/tests_divisions.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use web_macro::{division, heading1};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base() {
|
||||||
|
assert_eq!("<div>test</div>", division!("test"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_elements() {
|
||||||
|
assert_eq!(
|
||||||
|
"<div>\n<h1>one</h1>\n<h1>two</h1>\n</div>",
|
||||||
|
division!(heading1!("one"), heading1!("two"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_elements_with_options() {
|
||||||
|
assert_eq!(
|
||||||
|
"<div id=\"division_id\">\n<h1>one</h1>\n<h1 class=\"tiny\">two</h1>\n</div>",
|
||||||
|
division!(
|
||||||
|
heading1!("one"),
|
||||||
|
heading1!("two", class = "tiny"),
|
||||||
|
id = "division_id"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
tests/tests_paragraphs.rs
Normal file
13
tests/tests_paragraphs.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use web_macro::paragraph;
|
||||||
|
#[test]
|
||||||
|
fn test_base() {
|
||||||
|
assert_eq!("<p>test</p>", paragraph!("test"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_params() {
|
||||||
|
assert_eq!("<p id=\"oui\">test</p>", paragraph!("test", id = "oui"))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user