Integrate "SmartDefault" as "AutoDefault" macro

This commit is contained in:
Manuel Cillero 2024-02-27 21:57:16 +01:00
parent cb38145bf5
commit 9e4f593dbd
51 changed files with 387 additions and 103 deletions

View file

@ -16,23 +16,28 @@ the [Rust ecosystem](https://lib.rs), such as:
# ⌨️ Code # ⌨️ Code
* PageTop includes code from version [0.11.0](https://github.com/mehcode/config-rs/tree/0.11.0) of PageTop integrates code from various renowned crates to enhance functionality:
[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 incorporates an adapted version of the excellent crate * [**Config (v0.11.0)**](https://github.com/mehcode/config-rs/tree/0.11.0): Includes code from
[maud](https://crates.io/crates/maud) by [Chris Wong](https://crates.io/users/lambda-fairy) [config-rs](https://crates.io/crates/config) by [Ryan Leckey](https://crates.io/users/mehcode),
(version [0.25.0](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud)), to add its chosen for its advantages in reading configuration settings and delegating assignment to safe
functionalities without requiring a reference to `maud` in the `Cargo.toml` file of each project. types, tailored to the specific needs of each package, theme, or application.
* PageTop utilizes the renowned crates [SQLx](https://github.com/launchbadge/sqlx) and * [**Maud (v0.25.0)**](https://github.com/lambda-fairy/maud/tree/v0.25.0/maud): An adapted version
[SeaQuery](https://github.com/SeaQL/sea-query) for database interactions. However, to restrict of the excellent [maud](https://crates.io/crates/maud) crate by
migrations to packages, a modified version of [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 [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 [0.12.8](https://github.com/SeaQL/sea-orm/tree/0.12.8/sea-orm-migration/src)). This modification
into the code. ensures migration processes are confined to specific packages, enhancing modularity and
maintainability.
# 🗚 FIGfonts # 🗚 FIGfonts

View file

@ -47,7 +47,6 @@ itoa = "1.0.10"
nom = "7.1.3" nom = "7.1.3"
once_cell = "1.19.0" once_cell = "1.19.0"
paste = "1.0.14" paste = "1.0.14"
smart-default = "0.7.1"
substring = "1.4.5" substring = "1.4.5"
term_size = "0.3.2" term_size = "0.3.2"
toml = "0.8.10" toml = "0.8.10"

View file

@ -1,4 +1,5 @@
mod maud; mod maud;
mod smart_default;
use concat_string::concat_string; use concat_string::concat_string;
use proc_macro::TokenStream; use proc_macro::TokenStream;
@ -102,8 +103,17 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
output 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)] #[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 input = parse_macro_input!(input as DeriveInput);
let name = &input.ident; let name = &input.ident;

View file

@ -0,0 +1,4 @@
pub mod body_impl;
mod default_attr;
mod util;

View 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(),
))
}
}

View 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))
}
}

View 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)
}

View file

@ -1,6 +1,6 @@
use crate::core::component::{Context, ContextOp}; use crate::core::component::{Context, ContextOp};
use crate::html::{JavaScript, StyleSheet}; use crate::html::{JavaScript, StyleSheet};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
// Context parameters. // Context parameters.
pub const PARAM_BASE_WEIGHT: &str = "base.weight"; pub const PARAM_BASE_WEIGHT: &str = "base.weight";
@ -57,7 +57,7 @@ pub(crate) fn add_base_assets(cx: &mut Context) {
// ************************************************************************************************* // *************************************************************************************************
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum BreakPoint { pub enum BreakPoint {
#[default] #[default]
None, /* Does not apply. Rest initially assume 1 pixel = 0.0625em */ 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 { pub enum ButtonStyle {
#[default] #[default]
Default, Default,
@ -119,7 +119,7 @@ impl ToString for ButtonStyle {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum FontSize { pub enum FontSize {
ExtraLarge, ExtraLarge,
XxLarge, XxLarge,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Block { pub struct Block {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Branding { pub struct Branding {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ButtonTarget { pub enum ButtonTarget {
#[default] #[default]
Default, Default,
@ -11,7 +11,7 @@ pub enum ButtonTarget {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Button { pub struct Button {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -7,7 +7,7 @@ use crate::prelude::*;
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum Direction { pub enum Direction {
#[default] #[default]
Default, Default,
@ -42,7 +42,7 @@ impl ToString for Direction {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum WrapAlign { pub enum WrapAlign {
#[default] #[default]
Default, Default,
@ -65,7 +65,7 @@ impl ToString for WrapAlign {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ContentAlign { pub enum ContentAlign {
#[default] #[default]
Default, Default,
@ -94,7 +94,7 @@ impl ToString for ContentAlign {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ContentJustify { pub enum ContentJustify {
#[default] #[default]
Default, Default,
@ -123,7 +123,7 @@ impl ToString for ContentJustify {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemAlign { pub enum ItemAlign {
#[default] #[default]
Default, Default,
@ -150,7 +150,7 @@ impl ToString for ItemAlign {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum Gap { pub enum Gap {
#[default] #[default]
Default, Default,
@ -175,7 +175,7 @@ impl ToString for Gap {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemGrow { pub enum ItemGrow {
#[default] #[default]
Default, Default,
@ -210,7 +210,7 @@ impl ToString for ItemGrow {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemShrink { pub enum ItemShrink {
#[default] #[default]
Default, Default,
@ -245,7 +245,7 @@ impl ToString for ItemShrink {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemSize { pub enum ItemSize {
#[default] #[default]
Default, Default,
@ -284,7 +284,7 @@ impl ToString for ItemSize {
// ************************************************************************************************* // *************************************************************************************************
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemOffset { pub enum ItemOffset {
#[default] #[default]
Default, Default,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Container { pub struct Container {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Item { pub struct Item {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ActionButtonType { pub enum ActionButtonType {
#[default] #[default]
Submit, Submit,
@ -18,7 +18,7 @@ impl ToString for ActionButtonType {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct ActionButton { pub struct ActionButton {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Date { pub struct Date {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum FormMethod { pub enum FormMethod {
#[default] #[default]
Post, Post,
@ -8,7 +8,7 @@ pub enum FormMethod {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Form { pub struct Form {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Hidden { pub struct Hidden {
weight: Weight, weight: Weight,
name : OptionName, name : OptionName,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum InputType { pub enum InputType {
#[default] #[default]
Textfield, Textfield,
@ -12,7 +12,7 @@ pub enum InputType {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Input { pub struct Input {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum HeadingType { pub enum HeadingType {
#[default] #[default]
H1, H1,
@ -11,7 +11,7 @@ pub enum HeadingType {
H6, H6,
} }
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum HeadingSize { pub enum HeadingSize {
ExtraLarge, ExtraLarge,
XxLarge, XxLarge,
@ -39,7 +39,7 @@ impl ToString for HeadingSize {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Heading { pub struct Heading {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Html(Markup); pub struct Html(Markup);
impl ComponentTrait for Html { impl ComponentTrait for Html {

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Icon { pub struct Icon {
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
const IMG_FLUID: &str = "pt-img__fluid"; const IMG_FLUID: &str = "pt-img__fluid";
const IMG_FIXED: &str = "pt-img__fixed"; const IMG_FIXED: &str = "pt-img__fixed";
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ImageSize { pub enum ImageSize {
#[default] #[default]
Auto, Auto,
@ -14,7 +14,7 @@ pub enum ImageSize {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Image { pub struct Image {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -5,7 +5,7 @@ use super::Submenu;
type Content = ArcTypedComponent<Html>; type Content = ArcTypedComponent<Html>;
type SubmenuItems = ArcTypedComponent<Submenu>; type SubmenuItems = ArcTypedComponent<Submenu>;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ElementType { pub enum ElementType {
#[default] #[default]
Void, Void,
@ -16,7 +16,7 @@ pub enum ElementType {
// Element. // Element.
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Element { pub struct Element {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use super::Element; use super::Element;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Group { pub struct Group {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -7,7 +7,7 @@ type Content = ArcTypedComponent<Html>;
type SubmenuItems = ArcTypedComponent<Submenu>; type SubmenuItems = ArcTypedComponent<Submenu>;
type MegamenuGroups = ArcTypedComponent<Megamenu>; type MegamenuGroups = ArcTypedComponent<Megamenu>;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum ItemType { pub enum ItemType {
#[default] #[default]
Void, Void,
@ -22,7 +22,7 @@ pub enum ItemType {
// Item. // Item.
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Item { pub struct Item {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use super::Group; use super::Group;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Megamenu { pub struct Megamenu {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use super::Item; use super::Item;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Menu { pub struct Menu {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -3,7 +3,7 @@ use crate::prelude::*;
use super::Item; use super::Item;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Submenu { pub struct Submenu {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,7 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Paragraph { pub struct Paragraph {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -11,7 +11,7 @@ pub enum PoweredByLogo {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct PoweredBy { pub struct PoweredBy {
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Translate(L10n); pub struct Translate(L10n);
impl ComponentTrait for Translate { impl ComponentTrait for Translate {

View file

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum WrapperType { pub enum WrapperType {
#[default] #[default]
Container, Container,
@ -11,7 +11,7 @@ pub enum WrapperType {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(ComponentClasses, SmartDefault)] #[derive(AutoDefault, ComponentClasses)]
pub struct Wrapper { pub struct Wrapper {
id : OptionId, id : OptionId,
weight : Weight, weight : Weight,

View file

@ -1,11 +1,11 @@
use crate::core::action::ActionTrait; use crate::core::action::ActionTrait;
use crate::SmartDefault; use crate::AutoDefault;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
pub type Action = Box<dyn ActionTrait>; pub type Action = Box<dyn ActionTrait>;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct ActionsList(Arc<RwLock<Vec<Action>>>); pub struct ActionsList(Arc<RwLock<Vec<Action>>>);
impl ActionsList { impl ActionsList {

View file

@ -1,9 +1,9 @@
use crate::core::component::Context; use crate::core::component::Context;
use crate::SmartDefault; use crate::AutoDefault;
pub type FnIsRenderable = fn(cx: &Context) -> bool; pub type FnIsRenderable = fn(cx: &Context) -> bool;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Renderable { pub struct Renderable {
#[default(_code = "render_always")] #[default(_code = "render_always")]
pub check: FnIsRenderable, pub check: FnIsRenderable,

View file

@ -1,6 +1,6 @@
use crate::core::component::{AnyComponents, ArcAnyComponent, ArcAnyOp}; use crate::core::component::{AnyComponents, ArcAnyComponent, ArcAnyOp};
use crate::core::theme::ThemeRef; use crate::core::theme::ThemeRef;
use crate::{LazyStatic, SmartDefault, TypeId}; use crate::{AutoDefault, LazyStatic, TypeId};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::RwLock; use std::sync::RwLock;
@ -11,7 +11,7 @@ static THEME_REGIONS: LazyStatic<RwLock<HashMap<TypeId, ComponentsInRegions>>> =
static COMMON_REGIONS: LazyStatic<RwLock<ComponentsInRegions>> = static COMMON_REGIONS: LazyStatic<RwLock<ComponentsInRegions>> =
LazyStatic::new(|| RwLock::new(ComponentsInRegions::default())); LazyStatic::new(|| RwLock::new(ComponentsInRegions::default()));
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct ComponentsInRegions(HashMap<&'static str, AnyComponents>); pub struct ComponentsInRegions(HashMap<&'static str, AnyComponents>);
impl ComponentsInRegions { impl ComponentsInRegions {

View file

@ -4,7 +4,7 @@ pub mod javascript;
pub mod stylesheet; pub mod stylesheet;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
pub trait AssetsTrait { pub trait AssetsTrait {
fn path(&self) -> &str; fn path(&self) -> &str;
@ -14,7 +14,7 @@ pub trait AssetsTrait {
fn prepare(&self) -> Markup; fn prepare(&self) -> Markup;
} }
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Assets<T>(Vec<T>); pub struct Assets<T>(Vec<T>);
impl<T: AssetsTrait> Assets<T> { impl<T: AssetsTrait> Assets<T> {

View file

@ -1,9 +1,9 @@
use crate::html::assets::AssetsTrait; use crate::html::assets::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct HeadScript { pub struct HeadScript {
path : String, path : String,
code : String, code : String,

View file

@ -1,9 +1,9 @@
use crate::html::assets::AssetsTrait; use crate::html::assets::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct HeadStyles { pub struct HeadStyles {
path : String, path : String,
styles: String, styles: String,

View file

@ -1,6 +1,6 @@
use crate::html::assets::AssetsTrait; use crate::html::assets::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
#[derive(Default, Eq, PartialEq)] #[derive(Default, Eq, PartialEq)]
pub enum ModeJS { pub enum ModeJS {
@ -11,7 +11,7 @@ pub enum ModeJS {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct JavaScript { pub struct JavaScript {
path : String, path : String,
prefix : &'static str, prefix : &'static str,

View file

@ -1,6 +1,6 @@
use crate::html::assets::AssetsTrait; use crate::html::assets::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::{SmartDefault, Weight}; use crate::{AutoDefault, Weight};
pub enum TargetMedia { pub enum TargetMedia {
Default, Default,
@ -10,7 +10,7 @@ pub enum TargetMedia {
} }
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct StyleSheet { pub struct StyleSheet {
path : String, path : String,
prefix : &'static str, prefix : &'static str,

View file

@ -1,7 +1,7 @@
use crate::html::{html, Markup}; use crate::html::{html, Markup};
use crate::SmartDefault; use crate::AutoDefault;
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct Favicon(Vec<Markup>); pub struct Favicon(Vec<Markup>);
impl Favicon { impl Favicon {

View file

@ -9,7 +9,7 @@
//! **OptionClasses** assumes that the order of the classes is irrelevant //! **OptionClasses** assumes that the order of the classes is irrelevant
//! (<https://stackoverflow.com/a/1321712>), and duplicate classes will not be allowed. //! (<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 { pub enum ClassesOp {
Add, Add,
@ -20,7 +20,7 @@ pub enum ClassesOp {
Set, Set,
} }
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct OptionClasses(Vec<String>); pub struct OptionClasses(Vec<String>);
impl OptionClasses { impl OptionClasses {

View file

@ -1,6 +1,6 @@
use crate::{fn_with, SmartDefault}; use crate::{fn_with, AutoDefault};
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct OptionId(Option<String>); pub struct OptionId(Option<String>);
impl OptionId { impl OptionId {

View file

@ -1,6 +1,6 @@
use crate::{fn_with, SmartDefault}; use crate::{fn_with, AutoDefault};
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct OptionName(Option<String>); pub struct OptionName(Option<String>);
impl OptionName { impl OptionName {

View file

@ -1,6 +1,6 @@
use crate::{fn_with, SmartDefault}; use crate::{fn_with, AutoDefault};
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct OptionString(Option<String>); pub struct OptionString(Option<String>);
impl OptionString { impl OptionString {

View file

@ -1,8 +1,8 @@
use crate::html::Markup; use crate::html::Markup;
use crate::locale::{L10n, LanguageIdentifier}; use crate::locale::{L10n, LanguageIdentifier};
use crate::{fn_with, SmartDefault}; use crate::{fn_with, AutoDefault};
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct OptionTranslated(L10n); pub struct OptionTranslated(L10n);
impl OptionTranslated { impl OptionTranslated {

View file

@ -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 // 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 // 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. // About viewport: If the browser window size is 50cm wide, 1vw = 0.5cm.
#[rustfmt::skip] #[rustfmt::skip]
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub enum Value { pub enum Value {
#[default] #[default]
None, None,

View file

@ -81,10 +81,7 @@ pub use concat_string::concat_string;
/// Enables flexible identifier concatenation in macros, allowing new items with pasted identifiers. /// Enables flexible identifier concatenation in macros, allowing new items with pasted identifiers.
pub use paste::paste; pub use paste::paste;
/// Custom derive for automatically implementing the [Default] trait with customized default values. pub use pagetop_macros::{fn_with, main, test, AutoDefault, ComponentClasses};
pub use smart_default::SmartDefault;
pub use pagetop_macros::{fn_with, main, test, ComponentClasses};
// ************************************************************************************************* // *************************************************************************************************
// GLOBAL. // GLOBAL.

View file

@ -87,7 +87,7 @@
//! ``` //! ```
use crate::html::{Markup, PreEscaped}; 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 fluent_templates;
pub use unic_langid::LanguageIdentifier; pub use unic_langid::LanguageIdentifier;
@ -164,7 +164,7 @@ macro_rules! static_locales {
}; };
} }
#[derive(SmartDefault)] #[derive(AutoDefault)]
enum L10nOp { enum L10nOp {
#[default] #[default]
None, None,
@ -172,7 +172,7 @@ enum L10nOp {
Translate(String), Translate(String),
} }
#[derive(SmartDefault)] #[derive(AutoDefault)]
pub struct L10n { pub struct L10n {
op: L10nOp, op: L10nOp,
locales: Option<&'static Locales>, locales: Option<&'static Locales>,

View file

@ -1,14 +1,13 @@
//! The PageTop Prelude. //! The PageTop Prelude.
// Re-exported macros and derives. // 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. // Global.
pub use crate::{HashMapResources, LazyStatic, TypeId, Weight}; pub use crate::{HashMapResources, LazyStatic, TypeId, Weight};
// Functions and macro helpers. // Functions and macro helpers.
pub use crate::util; pub use crate::util;
pub use crate::{kv, ComponentClasses};
// MACROS. // MACROS.
@ -20,6 +19,8 @@ pub use crate::static_locales;
pub use crate::{service_for_static_files, static_files}; pub use crate::{service_for_static_files, static_files};
// crate::core::actions // crate::core::actions
pub use crate::actions; pub use crate::actions;
// crate::util
pub use crate::kv;
// API. // API.