➖ Integrate "SmartDefault" as "AutoDefault" macro
This commit is contained in:
parent
cb38145bf5
commit
9e4f593dbd
51 changed files with 387 additions and 103 deletions
33
CREDITS.md
33
CREDITS.md
|
|
@ -16,23 +16,28 @@ the [Rust ecosystem](https://lib.rs), such as:
|
|||
|
||||
# ⌨️ Code
|
||||
|
||||
* PageTop includes code from version [0.11.0](https://github.com/mehcode/config-rs/tree/0.11.0) of
|
||||
[config](https://crates.io/crates/config) by [Ryan Leckey](https://crates.io/users/mehcode). This
|
||||
inclusion provides advantages over its more modern versions for reading configuration settings and
|
||||
delegating their assignment to safe types according to the requirements of each package, theme, or
|
||||
application.
|
||||
PageTop integrates code from various renowned crates to enhance functionality:
|
||||
|
||||
* PageTop incorporates an adapted version of the excellent crate
|
||||
[maud](https://crates.io/crates/maud) by [Chris Wong](https://crates.io/users/lambda-fairy)
|
||||
(version [0.25.0](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud)), to add its
|
||||
functionalities without requiring a reference to `maud` in the `Cargo.toml` file of each project.
|
||||
* [**Config (v0.11.0)**](https://github.com/mehcode/config-rs/tree/0.11.0): Includes code from
|
||||
[config-rs](https://crates.io/crates/config) by [Ryan Leckey](https://crates.io/users/mehcode),
|
||||
chosen for its advantages in reading configuration settings and delegating assignment to safe
|
||||
types, tailored to the specific needs of each package, theme, or application.
|
||||
|
||||
* PageTop utilizes the renowned crates [SQLx](https://github.com/launchbadge/sqlx) and
|
||||
[SeaQuery](https://github.com/SeaQL/sea-query) for database interactions. However, to restrict
|
||||
migrations to packages, a modified version of
|
||||
* [**Maud (v0.25.0)**](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud): An adapted version
|
||||
of the excellent [maud](https://crates.io/crates/maud) crate by
|
||||
[Chris Wong](https://crates.io/users/lambda-fairy) is incorporated to leverage its functionalities without requiring a reference to `maud` in the `Cargo.toml` files.
|
||||
|
||||
* **SmartDefault (v0.7.1)**: Embedded [SmartDefault](https://crates.io/crates/smart_default) by
|
||||
[Jane Doe](https://crates.io/users/jane-doe) as `AutoDefault`to simplify the documentation of
|
||||
Default implementations and also removes the need to explicitly list `smart_default` in the
|
||||
`Cargo.toml` files.
|
||||
|
||||
* **Database Operations**: PageTop employs [SQLx](https://github.com/launchbadge/sqlx) and
|
||||
[SeaQuery](https://github.com/SeaQL/sea-query), complemented by a custom version of
|
||||
[SeaORM Migration](https://github.com/SeaQL/sea-orm/tree/master/sea-orm-migration) (version
|
||||
[0.12.8](https://github.com/SeaQL/sea-orm/tree/0.12.8/sea-orm-migration/src)) has been integrated
|
||||
into the code.
|
||||
[0.12.8](https://github.com/SeaQL/sea-orm/tree/0.12.8/sea-orm-migration/src)). This modification
|
||||
ensures migration processes are confined to specific packages, enhancing modularity and
|
||||
maintainability.
|
||||
|
||||
|
||||
# 🗚 FIGfonts
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ itoa = "1.0.10"
|
|||
nom = "7.1.3"
|
||||
once_cell = "1.19.0"
|
||||
paste = "1.0.14"
|
||||
smart-default = "0.7.1"
|
||||
substring = "1.4.5"
|
||||
term_size = "0.3.2"
|
||||
toml = "0.8.10"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
mod maud;
|
||||
mod smart_default;
|
||||
|
||||
use concat_string::concat_string;
|
||||
use proc_macro::TokenStream;
|
||||
|
|
@ -102,8 +103,17 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
|||
output
|
||||
}
|
||||
|
||||
#[proc_macro_derive(AutoDefault, attributes(default))]
|
||||
pub fn derive_auto_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
match smart_default::body_impl::impl_my_derive(&input) {
|
||||
Ok(output) => output.into(),
|
||||
Err(error) => error.to_compile_error().into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ComponentClasses)]
|
||||
pub fn component_classes_derive(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_component_classes(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let name = &input.ident;
|
||||
|
||||
|
|
|
|||
4
helpers/pagetop-macros/src/smart_default.rs
Normal file
4
helpers/pagetop-macros/src/smart_default.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub mod body_impl;
|
||||
|
||||
mod default_attr;
|
||||
mod util;
|
||||
158
helpers/pagetop-macros/src/smart_default/body_impl.rs
Normal file
158
helpers/pagetop-macros/src/smart_default/body_impl.rs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
use proc_macro2::TokenStream;
|
||||
|
||||
use quote::quote;
|
||||
use syn::parse::Error;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::DeriveInput;
|
||||
|
||||
use crate::smart_default::default_attr::{ConversionStrategy, DefaultAttr};
|
||||
use crate::smart_default::util::find_only;
|
||||
|
||||
pub fn impl_my_derive(input: &DeriveInput) -> Result<TokenStream, Error> {
|
||||
let name = &input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
let (default_expr, doc) = match input.data {
|
||||
syn::Data::Struct(ref body) => {
|
||||
let (body_assignment, _doc) = default_body_tt(&body.fields)?;
|
||||
(
|
||||
quote! {
|
||||
#name #body_assignment
|
||||
},
|
||||
format!("Returns a `{}` default.", name),
|
||||
)
|
||||
}
|
||||
syn::Data::Enum(ref body) => {
|
||||
let default_variant = find_only(body.variants.iter(), |variant| {
|
||||
if let Some(meta) = DefaultAttr::find_in_attributes(&variant.attrs)? {
|
||||
if meta.code.is_none() {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(Error::new(
|
||||
meta.code.span(),
|
||||
"Attribute #[default] on variants should have no value",
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})?
|
||||
.ok_or_else(|| Error::new(input.span(), "No default variant"))?;
|
||||
let default_variant_name = &default_variant.ident;
|
||||
let (body_assignment, _doc) = default_body_tt(&default_variant.fields)?;
|
||||
(
|
||||
quote! {
|
||||
#name :: #default_variant_name #body_assignment
|
||||
},
|
||||
format!("Returns a `{}::{}` default.", name, default_variant_name),
|
||||
)
|
||||
}
|
||||
syn::Data::Union(_) => {
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
Ok(quote! {
|
||||
#[automatically_derived]
|
||||
impl #impl_generics Default for #name #ty_generics #where_clause {
|
||||
#[doc = #doc]
|
||||
fn default() -> Self {
|
||||
#default_expr
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Return a token-tree for the default "body" - the part after the name that contains the values.
|
||||
/// That is, the `{ ... }` part for structs, the `(...)` part for tuples, and nothing for units.
|
||||
fn default_body_tt(body: &syn::Fields) -> Result<(TokenStream, String), Error> {
|
||||
let mut doc = String::new();
|
||||
use std::fmt::Write;
|
||||
let body_tt = match body {
|
||||
syn::Fields::Named(ref fields) => {
|
||||
doc.push_str(" {");
|
||||
let result = {
|
||||
let field_assignments = fields
|
||||
.named
|
||||
.iter()
|
||||
.map(|field| {
|
||||
let field_name = field.ident.as_ref();
|
||||
let (default_value, default_doc) = field_default_expr_and_doc(field)?;
|
||||
write!(
|
||||
&mut doc,
|
||||
"\n {}: {},",
|
||||
field_name.expect("field value in struct is empty"),
|
||||
default_doc
|
||||
)
|
||||
.unwrap();
|
||||
// let default_value = default_value.into_token_stream();
|
||||
Ok(quote! { #field_name : #default_value })
|
||||
})
|
||||
.collect::<Result<Vec<_>, Error>>()?;
|
||||
quote! {
|
||||
{
|
||||
#( #field_assignments ),*
|
||||
}
|
||||
}
|
||||
};
|
||||
if doc.ends_with(',') {
|
||||
doc.pop();
|
||||
doc.push('\n');
|
||||
};
|
||||
doc.push('}');
|
||||
result
|
||||
}
|
||||
syn::Fields::Unnamed(ref fields) => {
|
||||
doc.push('(');
|
||||
let result = {
|
||||
let field_assignments = fields
|
||||
.unnamed
|
||||
.iter()
|
||||
.map(|field| {
|
||||
let (default_value, default_doc) = field_default_expr_and_doc(field)?;
|
||||
write!(&mut doc, "{}, ", default_doc).unwrap();
|
||||
Ok(default_value)
|
||||
})
|
||||
.collect::<Result<Vec<TokenStream>, Error>>()?;
|
||||
quote! {
|
||||
(
|
||||
#( #field_assignments ),*
|
||||
)
|
||||
}
|
||||
};
|
||||
if doc.ends_with(", ") {
|
||||
doc.pop();
|
||||
doc.pop();
|
||||
};
|
||||
doc.push(')');
|
||||
result
|
||||
}
|
||||
&syn::Fields::Unit => quote! {},
|
||||
};
|
||||
Ok((body_tt, doc))
|
||||
}
|
||||
|
||||
/// Return a default expression for a field based on it's `#[default = "..."]` attribute. Panic
|
||||
/// if there is more than one, of if there is a `#[default]` attribute without value.
|
||||
fn field_default_expr_and_doc(field: &syn::Field) -> Result<(TokenStream, String), Error> {
|
||||
if let Some(default_attr) = DefaultAttr::find_in_attributes(&field.attrs)? {
|
||||
let conversion_strategy = default_attr.conversion_strategy();
|
||||
let field_value = default_attr.code.ok_or_else(|| {
|
||||
Error::new(field.span(), "Expected #[default = ...] or #[default(...)]")
|
||||
})?;
|
||||
|
||||
let field_value = match conversion_strategy {
|
||||
ConversionStrategy::NoConversion => field_value,
|
||||
ConversionStrategy::Into => quote!((#field_value).into()),
|
||||
};
|
||||
|
||||
let field_doc = format!("{}", field_value);
|
||||
Ok((field_value, field_doc))
|
||||
} else {
|
||||
Ok((
|
||||
quote! {
|
||||
Default::default()
|
||||
},
|
||||
"Default::default()".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
89
helpers/pagetop-macros/src/smart_default/default_attr.rs
Normal file
89
helpers/pagetop-macros/src/smart_default/default_attr.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::ToTokens;
|
||||
use syn::{parse::Error, MetaNameValue};
|
||||
|
||||
use crate::smart_default::util::find_only;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ConversionStrategy {
|
||||
NoConversion,
|
||||
Into,
|
||||
}
|
||||
|
||||
pub struct DefaultAttr {
|
||||
pub code: Option<TokenStream>,
|
||||
conversion_strategy: Option<ConversionStrategy>,
|
||||
}
|
||||
|
||||
impl DefaultAttr {
|
||||
pub fn find_in_attributes(attrs: &[syn::Attribute]) -> Result<Option<Self>, Error> {
|
||||
if let Some(default_attr) =
|
||||
find_only(attrs.iter(), |attr| Ok(attr.path().is_ident("default")))?
|
||||
{
|
||||
match &default_attr.meta {
|
||||
syn::Meta::Path(_) => Ok(Some(Self {
|
||||
code: None,
|
||||
conversion_strategy: None,
|
||||
})),
|
||||
syn::Meta::List(meta) => {
|
||||
// If the meta contains exactly (_code = "...") take the string literal as the
|
||||
// expression
|
||||
if let Ok(ParseCodeHack(code_hack)) = syn::parse(meta.tokens.clone().into()) {
|
||||
Ok(Some(Self {
|
||||
code: Some(code_hack),
|
||||
conversion_strategy: Some(ConversionStrategy::NoConversion),
|
||||
}))
|
||||
} else {
|
||||
Ok(Some(Self {
|
||||
code: Some(meta.tokens.clone()),
|
||||
conversion_strategy: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
syn::Meta::NameValue(MetaNameValue { value, .. }) => Ok(Some(Self {
|
||||
code: Some(value.into_token_stream()),
|
||||
conversion_strategy: None,
|
||||
})),
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn conversion_strategy(&self) -> ConversionStrategy {
|
||||
if let Some(conversion_strategy) = self.conversion_strategy {
|
||||
// Conversion strategy already set
|
||||
return conversion_strategy;
|
||||
}
|
||||
let code = if let Some(code) = &self.code {
|
||||
code
|
||||
} else {
|
||||
// #[default] - so no conversion (`Default::default()` already has the correct type)
|
||||
return ConversionStrategy::NoConversion;
|
||||
};
|
||||
match syn::parse::<syn::Lit>(code.clone().into()) {
|
||||
Ok(syn::Lit::Str(_)) | Ok(syn::Lit::ByteStr(_)) => {
|
||||
// A string literal - so we need a conversion in case we need to make it a `String`
|
||||
return ConversionStrategy::Into;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Not handled by one of the rules, so we don't convert it to avoid causing trouble
|
||||
ConversionStrategy::NoConversion
|
||||
}
|
||||
}
|
||||
|
||||
struct ParseCodeHack(TokenStream);
|
||||
|
||||
impl syn::parse::Parse for ParseCodeHack {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let ident: syn::Ident = input.parse()?;
|
||||
if ident != "_code" {
|
||||
return Err(Error::new(ident.span(), "Expected `_code`"));
|
||||
}
|
||||
input.parse::<syn::token::Eq>()?;
|
||||
let code: syn::LitStr = input.parse()?;
|
||||
let code: TokenStream = code.parse()?;
|
||||
Ok(ParseCodeHack(code))
|
||||
}
|
||||
}
|
||||
21
helpers/pagetop-macros/src/smart_default/util.rs
Normal file
21
helpers/pagetop-macros/src/smart_default/util.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use syn::parse::Error;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
/// Return the value that fulfills the predicate if there is one in the slice. Panic if there is
|
||||
/// more than one.
|
||||
pub fn find_only<T, F>(iter: impl Iterator<Item = T>, pred: F) -> Result<Option<T>, Error>
|
||||
where
|
||||
T: Spanned,
|
||||
F: Fn(&T) -> Result<bool, Error>,
|
||||
{
|
||||
let mut result = None;
|
||||
for item in iter {
|
||||
if pred(&item)? {
|
||||
if result.is_some() {
|
||||
return Err(Error::new(item.span(), "Multiple defaults"));
|
||||
}
|
||||
result = Some(item);
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::core::component::{Context, ContextOp};
|
||||
use crate::html::{JavaScript, StyleSheet};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
// Context parameters.
|
||||
pub const PARAM_BASE_WEIGHT: &str = "base.weight";
|
||||
|
|
@ -57,7 +57,7 @@ pub(crate) fn add_base_assets(cx: &mut Context) {
|
|||
// *************************************************************************************************
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum BreakPoint {
|
||||
#[default]
|
||||
None, /* Does not apply. Rest initially assume 1 pixel = 0.0625em */
|
||||
|
|
@ -88,7 +88,7 @@ impl ToString for BreakPoint {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ButtonStyle {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -119,7 +119,7 @@ impl ToString for ButtonStyle {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum FontSize {
|
||||
ExtraLarge,
|
||||
XxLarge,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Block {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Branding {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ButtonTarget {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -11,7 +11,7 @@ pub enum ButtonTarget {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Button {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::prelude::*;
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum Direction {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -42,7 +42,7 @@ impl ToString for Direction {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum WrapAlign {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -65,7 +65,7 @@ impl ToString for WrapAlign {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ContentAlign {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -94,7 +94,7 @@ impl ToString for ContentAlign {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ContentJustify {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -123,7 +123,7 @@ impl ToString for ContentJustify {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemAlign {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -150,7 +150,7 @@ impl ToString for ItemAlign {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum Gap {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -175,7 +175,7 @@ impl ToString for Gap {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemGrow {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -210,7 +210,7 @@ impl ToString for ItemGrow {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemShrink {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -245,7 +245,7 @@ impl ToString for ItemShrink {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemSize {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
@ -284,7 +284,7 @@ impl ToString for ItemSize {
|
|||
|
||||
// *************************************************************************************************
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemOffset {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Container {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Item {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ActionButtonType {
|
||||
#[default]
|
||||
Submit,
|
||||
|
|
@ -18,7 +18,7 @@ impl ToString for ActionButtonType {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct ActionButton {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Date {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum FormMethod {
|
||||
#[default]
|
||||
Post,
|
||||
|
|
@ -8,7 +8,7 @@ pub enum FormMethod {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Form {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Hidden {
|
||||
weight: Weight,
|
||||
name : OptionName,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum InputType {
|
||||
#[default]
|
||||
Textfield,
|
||||
|
|
@ -12,7 +12,7 @@ pub enum InputType {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Input {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum HeadingType {
|
||||
#[default]
|
||||
H1,
|
||||
|
|
@ -11,7 +11,7 @@ pub enum HeadingType {
|
|||
H6,
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum HeadingSize {
|
||||
ExtraLarge,
|
||||
XxLarge,
|
||||
|
|
@ -39,7 +39,7 @@ impl ToString for HeadingSize {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Heading {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Html(Markup);
|
||||
|
||||
impl ComponentTrait for Html {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Icon {
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||
const IMG_FLUID: &str = "pt-img__fluid";
|
||||
const IMG_FIXED: &str = "pt-img__fixed";
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ImageSize {
|
||||
#[default]
|
||||
Auto,
|
||||
|
|
@ -14,7 +14,7 @@ pub enum ImageSize {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Image {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use super::Submenu;
|
|||
type Content = ArcTypedComponent<Html>;
|
||||
type SubmenuItems = ArcTypedComponent<Submenu>;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ElementType {
|
||||
#[default]
|
||||
Void,
|
||||
|
|
@ -16,7 +16,7 @@ pub enum ElementType {
|
|||
// Element.
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Element {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||
use super::Element;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Group {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ type Content = ArcTypedComponent<Html>;
|
|||
type SubmenuItems = ArcTypedComponent<Submenu>;
|
||||
type MegamenuGroups = ArcTypedComponent<Megamenu>;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum ItemType {
|
||||
#[default]
|
||||
Void,
|
||||
|
|
@ -22,7 +22,7 @@ pub enum ItemType {
|
|||
// Item.
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Item {
|
||||
weight : Weight,
|
||||
renderable : Renderable,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||
use super::Group;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Megamenu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||
use super::Item;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Menu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::prelude::*;
|
|||
use super::Item;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Submenu {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Paragraph {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub enum PoweredByLogo {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct PoweredBy {
|
||||
weight : Weight,
|
||||
renderable: Renderable,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Translate(L10n);
|
||||
|
||||
impl ComponentTrait for Translate {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum WrapperType {
|
||||
#[default]
|
||||
Container,
|
||||
|
|
@ -11,7 +11,7 @@ pub enum WrapperType {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(ComponentClasses, SmartDefault)]
|
||||
#[derive(AutoDefault, ComponentClasses)]
|
||||
pub struct Wrapper {
|
||||
id : OptionId,
|
||||
weight : Weight,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::core::action::ActionTrait;
|
||||
use crate::SmartDefault;
|
||||
use crate::AutoDefault;
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub type Action = Box<dyn ActionTrait>;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct ActionsList(Arc<RwLock<Vec<Action>>>);
|
||||
|
||||
impl ActionsList {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::core::component::Context;
|
||||
use crate::SmartDefault;
|
||||
use crate::AutoDefault;
|
||||
|
||||
pub type FnIsRenderable = fn(cx: &Context) -> bool;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Renderable {
|
||||
#[default(_code = "render_always")]
|
||||
pub check: FnIsRenderable,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::core::component::{AnyComponents, ArcAnyComponent, ArcAnyOp};
|
||||
use crate::core::theme::ThemeRef;
|
||||
use crate::{LazyStatic, SmartDefault, TypeId};
|
||||
use crate::{AutoDefault, LazyStatic, TypeId};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::RwLock;
|
||||
|
|
@ -11,7 +11,7 @@ static THEME_REGIONS: LazyStatic<RwLock<HashMap<TypeId, ComponentsInRegions>>> =
|
|||
static COMMON_REGIONS: LazyStatic<RwLock<ComponentsInRegions>> =
|
||||
LazyStatic::new(|| RwLock::new(ComponentsInRegions::default()));
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct ComponentsInRegions(HashMap<&'static str, AnyComponents>);
|
||||
|
||||
impl ComponentsInRegions {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ pub mod javascript;
|
|||
pub mod stylesheet;
|
||||
|
||||
use crate::html::{html, Markup};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
pub trait AssetsTrait {
|
||||
fn path(&self) -> &str;
|
||||
|
|
@ -14,7 +14,7 @@ pub trait AssetsTrait {
|
|||
fn prepare(&self) -> Markup;
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Assets<T>(Vec<T>);
|
||||
|
||||
impl<T: AssetsTrait> Assets<T> {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::html::assets::AssetsTrait;
|
||||
use crate::html::{html, Markup};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct HeadScript {
|
||||
path : String,
|
||||
code : String,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use crate::html::assets::AssetsTrait;
|
||||
use crate::html::{html, Markup};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct HeadStyles {
|
||||
path : String,
|
||||
styles: String,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::html::assets::AssetsTrait;
|
||||
use crate::html::{html, Markup};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
#[derive(Default, Eq, PartialEq)]
|
||||
pub enum ModeJS {
|
||||
|
|
@ -11,7 +11,7 @@ pub enum ModeJS {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct JavaScript {
|
||||
path : String,
|
||||
prefix : &'static str,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::html::assets::AssetsTrait;
|
||||
use crate::html::{html, Markup};
|
||||
use crate::{SmartDefault, Weight};
|
||||
use crate::{AutoDefault, Weight};
|
||||
|
||||
pub enum TargetMedia {
|
||||
Default,
|
||||
|
|
@ -10,7 +10,7 @@ pub enum TargetMedia {
|
|||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct StyleSheet {
|
||||
path : String,
|
||||
prefix : &'static str,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::html::{html, Markup};
|
||||
use crate::SmartDefault;
|
||||
use crate::AutoDefault;
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct Favicon(Vec<Markup>);
|
||||
|
||||
impl Favicon {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
//! **OptionClasses** assumes that the order of the classes is irrelevant
|
||||
//! (<https://stackoverflow.com/a/1321712>), and duplicate classes will not be allowed.
|
||||
|
||||
use crate::{fn_with, SmartDefault};
|
||||
use crate::{fn_with, AutoDefault};
|
||||
|
||||
pub enum ClassesOp {
|
||||
Add,
|
||||
|
|
@ -20,7 +20,7 @@ pub enum ClassesOp {
|
|||
Set,
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct OptionClasses(Vec<String>);
|
||||
|
||||
impl OptionClasses {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{fn_with, SmartDefault};
|
||||
use crate::{fn_with, AutoDefault};
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct OptionId(Option<String>);
|
||||
|
||||
impl OptionId {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{fn_with, SmartDefault};
|
||||
use crate::{fn_with, AutoDefault};
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct OptionName(Option<String>);
|
||||
|
||||
impl OptionName {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{fn_with, SmartDefault};
|
||||
use crate::{fn_with, AutoDefault};
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct OptionString(Option<String>);
|
||||
|
||||
impl OptionString {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::html::Markup;
|
||||
use crate::locale::{L10n, LanguageIdentifier};
|
||||
use crate::{fn_with, SmartDefault};
|
||||
use crate::{fn_with, AutoDefault};
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct OptionTranslated(L10n);
|
||||
|
||||
impl OptionTranslated {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{concat_string, SmartDefault};
|
||||
use crate::{concat_string, AutoDefault};
|
||||
|
||||
// About pixels: Pixels (px) are relative to the viewing device. For low-dpi devices, 1px is one
|
||||
// device pixel (dot) of the display. For printers and high resolution screens 1px implies multiple
|
||||
|
|
@ -10,7 +10,7 @@ use crate::{concat_string, SmartDefault};
|
|||
// About viewport: If the browser window size is 50cm wide, 1vw = 0.5cm.
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub enum Value {
|
||||
#[default]
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -81,10 +81,7 @@ pub use concat_string::concat_string;
|
|||
/// Enables flexible identifier concatenation in macros, allowing new items with pasted identifiers.
|
||||
pub use paste::paste;
|
||||
|
||||
/// Custom derive for automatically implementing the [Default] trait with customized default values.
|
||||
pub use smart_default::SmartDefault;
|
||||
|
||||
pub use pagetop_macros::{fn_with, main, test, ComponentClasses};
|
||||
pub use pagetop_macros::{fn_with, main, test, AutoDefault, ComponentClasses};
|
||||
|
||||
// *************************************************************************************************
|
||||
// GLOBAL.
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@
|
|||
//! ```
|
||||
|
||||
use crate::html::{Markup, PreEscaped};
|
||||
use crate::{config, kv, LazyStatic, SmartDefault, LOCALES_PAGETOP};
|
||||
use crate::{config, kv, AutoDefault, LazyStatic, LOCALES_PAGETOP};
|
||||
|
||||
pub use fluent_templates;
|
||||
pub use unic_langid::LanguageIdentifier;
|
||||
|
|
@ -164,7 +164,7 @@ macro_rules! static_locales {
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
enum L10nOp {
|
||||
#[default]
|
||||
None,
|
||||
|
|
@ -172,7 +172,7 @@ enum L10nOp {
|
|||
Translate(String),
|
||||
}
|
||||
|
||||
#[derive(SmartDefault)]
|
||||
#[derive(AutoDefault)]
|
||||
pub struct L10n {
|
||||
op: L10nOp,
|
||||
locales: Option<&'static Locales>,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
//! The PageTop Prelude.
|
||||
|
||||
// Re-exported macros and derives.
|
||||
pub use crate::{concat_string, fn_with, html, main, paste, test, SmartDefault};
|
||||
pub use crate::{concat_string, fn_with, html, main, paste, test, AutoDefault, ComponentClasses};
|
||||
|
||||
// Global.
|
||||
pub use crate::{HashMapResources, LazyStatic, TypeId, Weight};
|
||||
|
||||
// Functions and macro helpers.
|
||||
pub use crate::util;
|
||||
pub use crate::{kv, ComponentClasses};
|
||||
|
||||
// MACROS.
|
||||
|
||||
|
|
@ -20,6 +19,8 @@ pub use crate::static_locales;
|
|||
pub use crate::{service_for_static_files, static_files};
|
||||
// crate::core::actions
|
||||
pub use crate::actions;
|
||||
// crate::util
|
||||
pub use crate::kv;
|
||||
|
||||
// API.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue