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
* 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

View file

@ -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"

View file

@ -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;

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::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,

View file

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

View file

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

View file

@ -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,

View file

@ -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,

View file

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

View file

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

View file

@ -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,

View file

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

View file

@ -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,

View file

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

View file

@ -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,

View file

@ -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,

View file

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

View file

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

View file

@ -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,

View file

@ -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,

View file

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

View file

@ -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,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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,

View file

@ -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 {

View file

@ -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,

View file

@ -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 {

View file

@ -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> {

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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 {

View file

@ -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 {

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>);
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>);
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>);
impl OptionString {

View file

@ -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 {

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
// 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,

View file

@ -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.

View file

@ -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>,

View file

@ -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.