lib.rs 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. extern crate proc_macro;
  2. use crate::parser::HtmlParser;
  3. use crate::tag::Tag;
  4. use syn::parse::{Parse, ParseStream, Result};
  5. use syn::parse_macro_input;
  6. mod parser;
  7. mod tag;
  8. /// Used to generate VirtualNode's from a TokenStream.
  9. ///
  10. /// html! { <div> Welcome to the html! procedural macro! </div> }
  11. #[proc_macro]
  12. pub fn html(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  13. let parsed = parse_macro_input!(input as Html);
  14. let mut html_parser = HtmlParser::new();
  15. let parsed_tags_len = parsed.tags.len();
  16. // Iterate over all of our parsed tags and push them into our HtmlParser one by one.
  17. //
  18. // As we go out HtmlParser will maintain some heuristics about what we've done so far
  19. // since that will sometimes inform how to parse the next token.
  20. for (idx, tag) in parsed.tags.iter().enumerate() {
  21. let mut next_tag = None;
  22. if parsed_tags_len - 1 > idx {
  23. next_tag = Some(&parsed.tags[idx + 1])
  24. }
  25. html_parser.push_tag(tag, next_tag);
  26. }
  27. html_parser.finish().into()
  28. }
  29. #[derive(Debug)]
  30. struct Html {
  31. tags: Vec<Tag>,
  32. }
  33. impl Parse for Html {
  34. fn parse(input: ParseStream) -> Result<Self> {
  35. let mut tags = Vec::new();
  36. while !input.is_empty() {
  37. let tag: Tag = input.parse()?;
  38. tags.push(tag);
  39. }
  40. Ok(Html { tags })
  41. }
  42. }