From 9e4f593dbd20f780a514ec8e925ccb24ecee5cc0 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Tue, 27 Feb 2024 21:57:16 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9E=96=20Integrate=20"SmartDefault"=20as=20"?= =?UTF-8?q?AutoDefault"=20macro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CREDITS.md | 33 ++-- Cargo.toml | 1 - helpers/pagetop-macros/src/lib.rs | 12 +- helpers/pagetop-macros/src/smart_default.rs | 4 + .../src/smart_default/body_impl.rs | 158 ++++++++++++++++++ .../src/smart_default/default_attr.rs | 89 ++++++++++ .../pagetop-macros/src/smart_default/util.rs | 21 +++ src/base/component.rs | 8 +- src/base/component/block.rs | 2 +- src/base/component/branding.rs | 2 +- src/base/component/button.rs | 4 +- src/base/component/flex.rs | 20 +-- src/base/component/flex/container.rs | 2 +- src/base/component/flex/item.rs | 2 +- src/base/component/form/action_button.rs | 4 +- src/base/component/form/date.rs | 2 +- src/base/component/form/form_main.rs | 4 +- src/base/component/form/hidden.rs | 2 +- src/base/component/form/input.rs | 4 +- src/base/component/heading.rs | 6 +- src/base/component/html.rs | 2 +- src/base/component/icon.rs | 2 +- src/base/component/image.rs | 4 +- src/base/component/menu/element.rs | 4 +- src/base/component/menu/group.rs | 2 +- src/base/component/menu/item.rs | 4 +- src/base/component/menu/megamenu.rs | 2 +- src/base/component/menu/menu_main.rs | 2 +- src/base/component/menu/submenu.rs | 2 +- src/base/component/paragraph.rs | 2 +- src/base/component/powered_by.rs | 2 +- src/base/component/translate.rs | 2 +- src/base/component/wrapper.rs | 4 +- src/core/action/list.rs | 4 +- src/core/component/renderable.rs | 4 +- src/core/theme/regions.rs | 4 +- src/html/assets.rs | 4 +- src/html/assets/headscript.rs | 4 +- src/html/assets/headstyles.rs | 4 +- src/html/assets/javascript.rs | 4 +- src/html/assets/stylesheet.rs | 4 +- src/html/favicon.rs | 4 +- src/html/opt_classes.rs | 4 +- src/html/opt_id.rs | 4 +- src/html/opt_name.rs | 4 +- src/html/opt_string.rs | 4 +- src/html/opt_translated.rs | 4 +- src/html/unit.rs | 4 +- src/lib.rs | 5 +- src/locale.rs | 6 +- src/prelude.rs | 5 +- 51 files changed, 387 insertions(+), 103 deletions(-) create mode 100644 helpers/pagetop-macros/src/smart_default.rs create mode 100644 helpers/pagetop-macros/src/smart_default/body_impl.rs create mode 100644 helpers/pagetop-macros/src/smart_default/default_attr.rs create mode 100644 helpers/pagetop-macros/src/smart_default/util.rs diff --git a/CREDITS.md b/CREDITS.md index 9e8ac884..d5dc7f83 100644 --- a/CREDITS.md +++ b/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 diff --git a/Cargo.toml b/Cargo.toml index f861f7aa..6d5629b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/helpers/pagetop-macros/src/lib.rs b/helpers/pagetop-macros/src/lib.rs index 32c25968..6937b0a9 100644 --- a/helpers/pagetop-macros/src/lib.rs +++ b/helpers/pagetop-macros/src/lib.rs @@ -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; diff --git a/helpers/pagetop-macros/src/smart_default.rs b/helpers/pagetop-macros/src/smart_default.rs new file mode 100644 index 00000000..87177dca --- /dev/null +++ b/helpers/pagetop-macros/src/smart_default.rs @@ -0,0 +1,4 @@ +pub mod body_impl; + +mod default_attr; +mod util; diff --git a/helpers/pagetop-macros/src/smart_default/body_impl.rs b/helpers/pagetop-macros/src/smart_default/body_impl.rs new file mode 100644 index 00000000..6a76f904 --- /dev/null +++ b/helpers/pagetop-macros/src/smart_default/body_impl.rs @@ -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 { + 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::, 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::, 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(), + )) + } +} diff --git a/helpers/pagetop-macros/src/smart_default/default_attr.rs b/helpers/pagetop-macros/src/smart_default/default_attr.rs new file mode 100644 index 00000000..8487fc06 --- /dev/null +++ b/helpers/pagetop-macros/src/smart_default/default_attr.rs @@ -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, + conversion_strategy: Option, +} + +impl DefaultAttr { + pub fn find_in_attributes(attrs: &[syn::Attribute]) -> Result, 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::(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 { + let ident: syn::Ident = input.parse()?; + if ident != "_code" { + return Err(Error::new(ident.span(), "Expected `_code`")); + } + input.parse::()?; + let code: syn::LitStr = input.parse()?; + let code: TokenStream = code.parse()?; + Ok(ParseCodeHack(code)) + } +} diff --git a/helpers/pagetop-macros/src/smart_default/util.rs b/helpers/pagetop-macros/src/smart_default/util.rs new file mode 100644 index 00000000..0d4b247b --- /dev/null +++ b/helpers/pagetop-macros/src/smart_default/util.rs @@ -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(iter: impl Iterator, pred: F) -> Result, Error> +where + T: Spanned, + F: Fn(&T) -> Result, +{ + 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) +} diff --git a/src/base/component.rs b/src/base/component.rs index 51d8652a..985791b7 100644 --- a/src/base/component.rs +++ b/src/base/component.rs @@ -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, diff --git a/src/base/component/block.rs b/src/base/component/block.rs index ade3ec56..c254408e 100644 --- a/src/base/component/block.rs +++ b/src/base/component/block.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Block { id : OptionId, weight : Weight, diff --git a/src/base/component/branding.rs b/src/base/component/branding.rs index c79d1ef5..522a3064 100644 --- a/src/base/component/branding.rs +++ b/src/base/component/branding.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Branding { id : OptionId, weight : Weight, diff --git a/src/base/component/button.rs b/src/base/component/button.rs index 0a549dc5..b0895e03 100644 --- a/src/base/component/button.rs +++ b/src/base/component/button.rs @@ -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, diff --git a/src/base/component/flex.rs b/src/base/component/flex.rs index 66e0daad..34c130f6 100644 --- a/src/base/component/flex.rs +++ b/src/base/component/flex.rs @@ -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, diff --git a/src/base/component/flex/container.rs b/src/base/component/flex/container.rs index b880f5c1..86ec391c 100644 --- a/src/base/component/flex/container.rs +++ b/src/base/component/flex/container.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Container { id : OptionId, weight : Weight, diff --git a/src/base/component/flex/item.rs b/src/base/component/flex/item.rs index 08ec9863..6fdb362c 100644 --- a/src/base/component/flex/item.rs +++ b/src/base/component/flex/item.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Item { id : OptionId, weight : Weight, diff --git a/src/base/component/form/action_button.rs b/src/base/component/form/action_button.rs index 07ee1e35..db88923d 100644 --- a/src/base/component/form/action_button.rs +++ b/src/base/component/form/action_button.rs @@ -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, diff --git a/src/base/component/form/date.rs b/src/base/component/form/date.rs index b5fe504a..52a225ca 100644 --- a/src/base/component/form/date.rs +++ b/src/base/component/form/date.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Date { weight : Weight, renderable : Renderable, diff --git a/src/base/component/form/form_main.rs b/src/base/component/form/form_main.rs index 00d6720b..1eb933a1 100644 --- a/src/base/component/form/form_main.rs +++ b/src/base/component/form/form_main.rs @@ -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, diff --git a/src/base/component/form/hidden.rs b/src/base/component/form/hidden.rs index dea36991..b8cb3645 100644 --- a/src/base/component/form/hidden.rs +++ b/src/base/component/form/hidden.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Hidden { weight: Weight, name : OptionName, diff --git a/src/base/component/form/input.rs b/src/base/component/form/input.rs index 30a8624e..4ae4c1a2 100644 --- a/src/base/component/form/input.rs +++ b/src/base/component/form/input.rs @@ -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, diff --git a/src/base/component/heading.rs b/src/base/component/heading.rs index 1a589cdd..4787a0b6 100644 --- a/src/base/component/heading.rs +++ b/src/base/component/heading.rs @@ -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, diff --git a/src/base/component/html.rs b/src/base/component/html.rs index f82004e5..1ffaf6d8 100644 --- a/src/base/component/html.rs +++ b/src/base/component/html.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Html(Markup); impl ComponentTrait for Html { diff --git a/src/base/component/icon.rs b/src/base/component/icon.rs index 821de088..1dba24ba 100644 --- a/src/base/component/icon.rs +++ b/src/base/component/icon.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Icon { weight : Weight, renderable: Renderable, diff --git a/src/base/component/image.rs b/src/base/component/image.rs index 3c02bfcf..20199753 100644 --- a/src/base/component/image.rs +++ b/src/base/component/image.rs @@ -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, diff --git a/src/base/component/menu/element.rs b/src/base/component/menu/element.rs index b87f5e09..0bbaebee 100644 --- a/src/base/component/menu/element.rs +++ b/src/base/component/menu/element.rs @@ -5,7 +5,7 @@ use super::Submenu; type Content = ArcTypedComponent; type SubmenuItems = ArcTypedComponent; -#[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, diff --git a/src/base/component/menu/group.rs b/src/base/component/menu/group.rs index 9e7cf879..d4a4fbc9 100644 --- a/src/base/component/menu/group.rs +++ b/src/base/component/menu/group.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use super::Element; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Group { id : OptionId, weight : Weight, diff --git a/src/base/component/menu/item.rs b/src/base/component/menu/item.rs index e96e6e04..5dab73a3 100644 --- a/src/base/component/menu/item.rs +++ b/src/base/component/menu/item.rs @@ -7,7 +7,7 @@ type Content = ArcTypedComponent; type SubmenuItems = ArcTypedComponent; type MegamenuGroups = ArcTypedComponent; -#[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, diff --git a/src/base/component/menu/megamenu.rs b/src/base/component/menu/megamenu.rs index 91ddc321..f8919f54 100644 --- a/src/base/component/menu/megamenu.rs +++ b/src/base/component/menu/megamenu.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use super::Group; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Megamenu { id : OptionId, weight : Weight, diff --git a/src/base/component/menu/menu_main.rs b/src/base/component/menu/menu_main.rs index b88f9c97..7631dc17 100644 --- a/src/base/component/menu/menu_main.rs +++ b/src/base/component/menu/menu_main.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use super::Item; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Menu { id : OptionId, weight : Weight, diff --git a/src/base/component/menu/submenu.rs b/src/base/component/menu/submenu.rs index 7e654b4f..47577332 100644 --- a/src/base/component/menu/submenu.rs +++ b/src/base/component/menu/submenu.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use super::Item; #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Submenu { id : OptionId, weight : Weight, diff --git a/src/base/component/paragraph.rs b/src/base/component/paragraph.rs index 7b46990d..a74a7503 100644 --- a/src/base/component/paragraph.rs +++ b/src/base/component/paragraph.rs @@ -1,7 +1,7 @@ use crate::prelude::*; #[rustfmt::skip] -#[derive(ComponentClasses, SmartDefault)] +#[derive(AutoDefault, ComponentClasses)] pub struct Paragraph { id : OptionId, weight : Weight, diff --git a/src/base/component/powered_by.rs b/src/base/component/powered_by.rs index ab71ea9b..45452f9b 100644 --- a/src/base/component/powered_by.rs +++ b/src/base/component/powered_by.rs @@ -11,7 +11,7 @@ pub enum PoweredByLogo { } #[rustfmt::skip] -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct PoweredBy { weight : Weight, renderable: Renderable, diff --git a/src/base/component/translate.rs b/src/base/component/translate.rs index e4c355b6..6c619d91 100644 --- a/src/base/component/translate.rs +++ b/src/base/component/translate.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Translate(L10n); impl ComponentTrait for Translate { diff --git a/src/base/component/wrapper.rs b/src/base/component/wrapper.rs index d3b5c9b7..de05fe5d 100644 --- a/src/base/component/wrapper.rs +++ b/src/base/component/wrapper.rs @@ -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, diff --git a/src/core/action/list.rs b/src/core/action/list.rs index 617e9b95..ab3dad48 100644 --- a/src/core/action/list.rs +++ b/src/core/action/list.rs @@ -1,11 +1,11 @@ use crate::core::action::ActionTrait; -use crate::SmartDefault; +use crate::AutoDefault; use std::sync::{Arc, RwLock}; pub type Action = Box; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct ActionsList(Arc>>); impl ActionsList { diff --git a/src/core/component/renderable.rs b/src/core/component/renderable.rs index 2b0dcb68..2f0055ce 100644 --- a/src/core/component/renderable.rs +++ b/src/core/component/renderable.rs @@ -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, diff --git a/src/core/theme/regions.rs b/src/core/theme/regions.rs index 4c18ec7f..87296158 100644 --- a/src/core/theme/regions.rs +++ b/src/core/theme/regions.rs @@ -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>> = static COMMON_REGIONS: LazyStatic> = LazyStatic::new(|| RwLock::new(ComponentsInRegions::default())); -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct ComponentsInRegions(HashMap<&'static str, AnyComponents>); impl ComponentsInRegions { diff --git a/src/html/assets.rs b/src/html/assets.rs index 503fbcf9..9cbf344d 100644 --- a/src/html/assets.rs +++ b/src/html/assets.rs @@ -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(Vec); impl Assets { diff --git a/src/html/assets/headscript.rs b/src/html/assets/headscript.rs index ec7d6390..708ab3eb 100644 --- a/src/html/assets/headscript.rs +++ b/src/html/assets/headscript.rs @@ -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, diff --git a/src/html/assets/headstyles.rs b/src/html/assets/headstyles.rs index ecdd01e9..dcc36ba4 100644 --- a/src/html/assets/headstyles.rs +++ b/src/html/assets/headstyles.rs @@ -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, diff --git a/src/html/assets/javascript.rs b/src/html/assets/javascript.rs index dbe54d43..3f78681a 100644 --- a/src/html/assets/javascript.rs +++ b/src/html/assets/javascript.rs @@ -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, diff --git a/src/html/assets/stylesheet.rs b/src/html/assets/stylesheet.rs index 3974010c..463bf136 100644 --- a/src/html/assets/stylesheet.rs +++ b/src/html/assets/stylesheet.rs @@ -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, diff --git a/src/html/favicon.rs b/src/html/favicon.rs index 490e98ce..068efcb4 100644 --- a/src/html/favicon.rs +++ b/src/html/favicon.rs @@ -1,7 +1,7 @@ use crate::html::{html, Markup}; -use crate::SmartDefault; +use crate::AutoDefault; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct Favicon(Vec); impl Favicon { diff --git a/src/html/opt_classes.rs b/src/html/opt_classes.rs index eb8f06a9..8d835b73 100644 --- a/src/html/opt_classes.rs +++ b/src/html/opt_classes.rs @@ -9,7 +9,7 @@ //! **OptionClasses** assumes that the order of the classes is irrelevant //! (), 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); impl OptionClasses { diff --git a/src/html/opt_id.rs b/src/html/opt_id.rs index fa9df14f..37eb292e 100644 --- a/src/html/opt_id.rs +++ b/src/html/opt_id.rs @@ -1,6 +1,6 @@ -use crate::{fn_with, SmartDefault}; +use crate::{fn_with, AutoDefault}; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct OptionId(Option); impl OptionId { diff --git a/src/html/opt_name.rs b/src/html/opt_name.rs index 46421452..519be403 100644 --- a/src/html/opt_name.rs +++ b/src/html/opt_name.rs @@ -1,6 +1,6 @@ -use crate::{fn_with, SmartDefault}; +use crate::{fn_with, AutoDefault}; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct OptionName(Option); impl OptionName { diff --git a/src/html/opt_string.rs b/src/html/opt_string.rs index d34950ff..8e323283 100644 --- a/src/html/opt_string.rs +++ b/src/html/opt_string.rs @@ -1,6 +1,6 @@ -use crate::{fn_with, SmartDefault}; +use crate::{fn_with, AutoDefault}; -#[derive(SmartDefault)] +#[derive(AutoDefault)] pub struct OptionString(Option); impl OptionString { diff --git a/src/html/opt_translated.rs b/src/html/opt_translated.rs index ba1e7075..09d78fe3 100644 --- a/src/html/opt_translated.rs +++ b/src/html/opt_translated.rs @@ -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 { diff --git a/src/html/unit.rs b/src/html/unit.rs index 1c3bdffe..4af81be6 100644 --- a/src/html/unit.rs +++ b/src/html/unit.rs @@ -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, diff --git a/src/lib.rs b/src/lib.rs index 8ff51f50..3bafb52a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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. diff --git a/src/locale.rs b/src/locale.rs index 41d2bb6c..46a89c14 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -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>, diff --git a/src/prelude.rs b/src/prelude.rs index 14020656..19db1c10 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -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.