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
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
extern crate proc_macro;

use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, ItemFn};

mod form;
mod layouts;
mod render;
mod views;

/// Auto load the layouts (askama templates) from `src/views/_layouts` directory.
///
/// Ignores the files whose name do not start with an alphabet.
///
/// # Examples
///
/// ```
/// use reign::prelude::*;
///
/// layouts!();
/// ```
#[proc_macro]
pub fn layouts(_: TokenStream) -> TokenStream {
    layouts::layouts().into()
}

/// Denote an askama template as a layout.
///
/// This template should have a field called `content`.
///
/// # Examples
///
/// ```
/// use reign::prelude::*;
///
/// #[derive(Debug, Layout, Template)]
/// #[template(path = "different_layouts_dir/plain.html")]
/// pub struct Plain {
///     pub content: String,
///     pub title: String,
/// }
/// ```
#[proc_macro_derive(Layout)]
pub fn derive_layout(input: TokenStream) -> TokenStream {
    let input: DeriveInput = parse_macro_input!(input);

    layouts::layout_derive(input).into()
}

/// Auto load the views (askama templates) from `src/views/[input]` directory.
///
/// # Examples
///
/// ```
/// use reign::prelude::*;
///
/// views!(pages);
/// ```
#[proc_macro]
pub fn views(input: TokenStream) -> TokenStream {
    let input: views::Views = parse_macro_input!(input);

    views::views(input).into()
}

#[proc_macro_attribute]
pub fn read_form(_: TokenStream, input: TokenStream) -> TokenStream {
    let item: ItemFn = parse_macro_input!(input);

    form::read_form_attribute(item).into()
}

/// Shorthand notation for rendering a template in a controller action.
///
/// # Examples
///
/// Render the given template using the default application layout (`src/views/_layouts/application.html`)
///
/// ```
/// use reign::view::render;
///
/// pub fn handler(mut state: State) -> (State, Response<Body>) {
///     render!(ViewIndex {})
/// }
/// ```
///
/// Render the given template using a different layout (`src/views/_layouts/different.html`)
///
/// ```
/// use reign::view::render;
///
/// pub fn handler(mut state: State) -> (State, Response<Body>) {
///     render!(ViewIndex {}, Different)
/// }
/// ```
#[proc_macro]
pub fn render(input: TokenStream) -> TokenStream {
    let input: render::Render = parse_macro_input!(input);

    render::render(input).into()
}