🚧 Doc & code tweaks

This commit is contained in:
Manuel Cillero 2024-07-27 19:19:18 +02:00
parent fea6c2f69e
commit c1e641723b
12 changed files with 79 additions and 53 deletions

View file

@ -80,14 +80,14 @@ impl Application {
let maxlen = (term_width / 10) - 2; let maxlen = (term_width / 10) - 2;
let mut app = app_name.substring(0, maxlen).to_owned(); let mut app = app_name.substring(0, maxlen).to_owned();
if app_name.len() > maxlen { if app_name.len() > maxlen {
app = format!("{}...", app); app = format!("{app}...");
} }
if let Some(ff) = figfont::FIGFONT.convert(&app) { if let Some(ff) = figfont::FIGFONT.convert(&app) {
app_name = ff.to_string(); app_name = ff.to_string();
} }
} }
} }
println!("\n{}", app_name); println!("\n{app_name}");
// Application description. // Application description.
if !config::SETTINGS.app.description.is_empty() { if !config::SETTINGS.app.description.is_empty() {

View file

@ -94,7 +94,7 @@ impl PoweredBy {
fn logo_line(&self, r: u8, g: u8, b: u8, cx: &mut Context) -> Markup { fn logo_line(&self, r: u8, g: u8, b: u8, cx: &mut Context) -> Markup {
let logo_txt = L10n::l("pagetop_logo").using(cx.langid()); let logo_txt = L10n::l("pagetop_logo").using(cx.langid());
let logo_rgb = format!("rgb({},{},{})", r, g, b); let logo_rgb = format!("rgb({r},{g},{b})");
html! { html! {
span class="poweredby__logo" aria-label=[logo_txt] { span class="poweredby__logo" aria-label=[logo_txt] {
svg viewBox="0 0 1614 1614" xmlns="http://www.w3.org/2000/svg" role="img" { svg viewBox="0 0 1614 1614" xmlns="http://www.w3.org/2000/svg" role="img" {

View file

@ -8,7 +8,7 @@
//! de desarrollo, pre-producción, producción, etc. //! de desarrollo, pre-producción, producción, etc.
//! //!
//! A veces las aplicaciones guardan configuraciones como constantes en el código, lo que implica //! A veces las aplicaciones guardan configuraciones como constantes en el código, lo que implica
//! una violación de esta metodología. PageTop recomienda una **estricta separación entre código y //! una violación de esta metodología. `PageTop` recomienda una **estricta separación entre código y
//! configuración**. La configuración variará en cada tipo de despliegue, y el código no. //! configuración**. La configuración variará en cada tipo de despliegue, y el código no.
//! //!
//! //!
@ -17,7 +17,7 @@
//! Si tu aplicación requiere archivos de configuración debes crear un directorio *config* al mismo //! Si tu aplicación requiere archivos de configuración debes crear un directorio *config* al mismo
//! nivel del archivo *Cargo.toml* de tu proyecto (o del ejecutable binario de la aplicación). //! nivel del archivo *Cargo.toml* de tu proyecto (o del ejecutable binario de la aplicación).
//! //!
//! PageTop se encargará de cargar todos los ajustes de configuración de tu aplicación leyendo los //! `PageTop` se encargará de cargar todos los ajustes de configuración de tu aplicación leyendo los
//! siguientes archivos TOML en este orden (todos los archivos son opcionales): //! siguientes archivos TOML en este orden (todos los archivos son opcionales):
//! //!
//! 1. **config/common.toml**, útil para los ajustes comunes a cualquier entorno. Estos valores //! 1. **config/common.toml**, útil para los ajustes comunes a cualquier entorno. Estos valores
@ -26,8 +26,8 @@
//! 2. **config/{file}.toml**, donde *{file}* se define con la variable de entorno //! 2. **config/{file}.toml**, donde *{file}* se define con la variable de entorno
//! `PAGETOP_RUN_MODE`: //! `PAGETOP_RUN_MODE`:
//! //!
//! * Si no está definida se asumirá *default* por defecto y PageTop intentará cargar el archivo //! * Si no está definida se asumirá *default* por defecto y `PageTop` intentará cargar el
//! *config/default.toml* si existe. //! archivo *config/default.toml* si existe.
//! //!
//! * De esta manera podrás tener diferentes ajustes de configuración para diferentes entornos //! * De esta manera podrás tener diferentes ajustes de configuración para diferentes entornos
//! de ejecución. Por ejemplo, para *devel.toml*, *staging.toml* o *production.toml*. O //! de ejecución. Por ejemplo, para *devel.toml*, *staging.toml* o *production.toml*. O
@ -155,7 +155,7 @@ pub static CONFIG: LazyLock<ConfigData> = LazyLock::new(|| {
File::with_name(&concat_string!(CONFIG_DIR, "/", run_mode, ".toml")) File::with_name(&concat_string!(CONFIG_DIR, "/", run_mode, ".toml"))
.required(false) .required(false)
).unwrap() ).unwrap()
// Añade la configuración local reservada del entorno. Por defecto 'default.local.toml'. // Añade la configuración local reservada del entorno. Por defecto 'local.default.toml'.
.merge( .merge(
File::with_name(&concat_string!(CONFIG_DIR, "/local.", run_mode, ".toml")) File::with_name(&concat_string!(CONFIG_DIR, "/local.", run_mode, ".toml"))
.required(false), .required(false),
@ -349,5 +349,5 @@ default_settings!(
// [server] // [server]
"server.bind_address" => "localhost", "server.bind_address" => "localhost",
"server.bind_port" => 8088, "server.bind_port" => 8088,
"server.session_lifetime" => 604800, "server.session_lifetime" => 604_800,
); );

View file

@ -15,6 +15,7 @@ pub trait AnyBase: Any {
fn as_any_mut(&mut self) -> &mut dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any;
} }
#[allow(clippy::inline_always)]
impl<T: Any> AnyBase for T { impl<T: Any> AnyBase for T {
#[inline(always)] #[inline(always)]
fn type_name(&self) -> &'static str { fn type_name(&self) -> &'static str {

View file

@ -44,7 +44,7 @@ impl fmt::Display for ParamError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ParamError::NotFound => write!(f, "Parameter not found"), ParamError::NotFound => write!(f, "Parameter not found"),
ParamError::ParseError(e) => write!(f, "Parse error: {}", e), ParamError::ParseError(e) => write!(f, "Parse error: {e}"),
} }
} }
} }
@ -180,22 +180,21 @@ impl Context {
// Context EXTRAS. // Context EXTRAS.
pub fn required_id<T>(&mut self, id: Option<String>) -> String { pub fn required_id<T>(&mut self, id: Option<String>) -> String {
match id { if let Some(id) = id {
Some(id) => id, id
None => { } else {
let prefix = TypeInfo::ShortName let prefix = TypeInfo::ShortName
.of::<T>() .of::<T>()
.trim() .trim()
.replace(' ', "_") .replace(' ', "_")
.to_lowercase(); .to_lowercase();
let prefix = if prefix.is_empty() { let prefix = if prefix.is_empty() {
"prefix".to_owned() "prefix".to_owned()
} else { } else {
prefix prefix
}; };
self.id_counter += 1; self.id_counter += 1;
concat_string!(prefix, "-", self.id_counter.to_string()) concat_string!(prefix, "-", self.id_counter.to_string())
}
} }
} }
} }

View file

@ -60,7 +60,7 @@ fn add_to_enabled(list: &mut Vec<PackageRef>, package: PackageRef) {
// Reverse dependencies to add them in correct order (dependencies first). // Reverse dependencies to add them in correct order (dependencies first).
let mut dependencies = package.dependencies(); let mut dependencies = package.dependencies();
dependencies.reverse(); dependencies.reverse();
for d in dependencies.iter() { for d in &dependencies {
add_to_enabled(list, *d); add_to_enabled(list, *d);
} }
@ -83,7 +83,7 @@ fn add_to_enabled(list: &mut Vec<PackageRef>, package: PackageRef) {
fn add_to_dropped(list: &mut Vec<PackageRef>, package: PackageRef) { fn add_to_dropped(list: &mut Vec<PackageRef>, package: PackageRef) {
// Iterate through packages recommended to be dropped. // Iterate through packages recommended to be dropped.
for d in package.drop_packages().iter() { for d in &package.drop_packages() {
// Check if the package is not already in the dropped list. // Check if the package is not already in the dropped list.
if !list.iter().any(|p| p.type_id() == d.type_id()) { if !list.iter().any(|p| p.type_id() == d.type_id()) {
// Check if the package is currently enabled. If so, log a warning. // Check if the package is currently enabled. If so, log a warning.
@ -103,7 +103,7 @@ fn add_to_dropped(list: &mut Vec<PackageRef>, package: PackageRef) {
trace::debug!("Package \"{}\" dropped", d.short_name()); trace::debug!("Package \"{}\" dropped", d.short_name());
// Recursively add the dependencies of the dropped package to the dropped list. // Recursively add the dependencies of the dropped package to the dropped list.
// This ensures that all dependencies are also considered for dropping. // This ensures that all dependencies are also considered for dropping.
for dependency in package.dependencies().iter() { for dependency in &package.dependencies() {
add_to_dropped(list, *dependency); add_to_dropped(list, *dependency);
} }
} }

View file

@ -44,7 +44,7 @@ impl<T: AssetsTrait> Assets<T> {
pub fn prepare(&mut self) -> Markup { pub fn prepare(&mut self) -> Markup {
let assets = &mut self.0; let assets = &mut self.0;
assets.sort_by_key(|a| a.weight()); assets.sort_by_key(AssetsTrait::weight);
html! { html! {
@for a in assets { @for a in assets {
(a.prepare()) (a.prepare())

View file

@ -61,12 +61,12 @@ impl StyleSheet {
} }
#[rustfmt::skip] #[rustfmt::skip]
pub fn for_media(mut self, media: TargetMedia) -> Self { pub fn for_media(mut self, media: &TargetMedia) -> Self {
self.media = match media { self.media = match media {
TargetMedia::Print => Some("print"), TargetMedia::Default => None,
TargetMedia::Screen => Some("screen"), TargetMedia::Print => Some("print"),
TargetMedia::Speech => Some("speech"), TargetMedia::Screen => Some("screen"),
_ => None, TargetMedia::Speech => Some("speech"),
}; };
self self
} }

View file

@ -37,9 +37,10 @@ impl<C: ComponentTrait> OptionComponent<C> {
} }
pub fn render(&self, cx: &mut Context) -> Markup { pub fn render(&self, cx: &mut Context) -> Markup {
match &self.0 { if let Some(component) = &self.0 {
Some(component) => component.render(cx), component.render(cx)
_ => html! {}, } else {
html! {}
} }
} }
} }

View file

@ -14,16 +14,16 @@
//! <br> //! <br>
//! </div> //! </div>
//! //!
//! The PageTop core API provides a comprehensive toolkit for extending its functionalities to //! The `PageTop` core API provides a comprehensive toolkit for extending its functionalities to
//! specific requirements and application scenarios through actions, components, packages, and //! specific requirements and application scenarios through actions, components, packages, and
//! themes: //! themes:
//! //!
//! * **Actions** serve as a mechanism to customize PageTop's internal behavior by intercepting //! * **Actions** serve as a mechanism to customize `PageTop`'s internal behavior by intercepting
//! its execution flow. //! its execution flow.
//! * **Components** encapsulate HTML, CSS, and JavaScript into functional, configurable, and //! * **Components** encapsulate HTML, CSS, and JavaScript into functional, configurable, and
//! well-defined units. //! well-defined units.
//! * **Packages** extend or customize existing functionality by interacting with PageTop APIs or //! * **Packages** extend or customize existing functionality by interacting with `PageTop` APIs
//! third-party package APIs. //! or third-party package APIs.
//! * **Themes** enable developers to alter the appearance of pages and components without //! * **Themes** enable developers to alter the appearance of pages and components without
//! affecting their functionality. //! affecting their functionality.
//! //!
@ -53,21 +53,21 @@
//! ``` //! ```
//! This program implements a package named `HelloWorld` with one service that returns a web page //! This program implements a package named `HelloWorld` with one service that returns a web page
//! that greets the world whenever it is accessed from the browser at `http://localhost:8088` (using //! that greets the world whenever it is accessed from the browser at `http://localhost:8088` (using
//! the [default configuration settings](`config::Server`)). You can find this code in the PageTop //! the [default configuration settings](`config::Server`)). You can find this code in the `PageTop`
//! [examples repository](https://github.com/manuelcillero/pagetop/tree/latest/examples). //! [examples repository](https://github.com/manuelcillero/pagetop/tree/latest/examples).
//! //!
//! # 🧩 Dependency Management //! # 🧩 Dependency Management
//! //!
//! Projects leveraging PageTop will use `cargo` to resolve dependencies, similar to any other Rust //! Projects leveraging `PageTop` will use `cargo` to resolve dependencies, similar to any other
//! project. //! Rust project.
//! //!
//! Nevertheless, its crucial that each package explicitly declares its //! Nevertheless, its crucial that each package explicitly declares its
//! [dependencies](core::package::PackageTrait#method.dependencies), if any, to assist PageTop in //! [dependencies](core::package::PackageTrait#method.dependencies), if any, to assist `PageTop` in
//! structuring and initializing the application in a modular fashion. //! structuring and initializing the application in a modular fashion.
//! //!
//! # 🚧 Warning //! # 🚧 Warning
//! //!
//! **PageTop** framework is currently in active development. The API is unstable and subject to //! **`PageTop`** framework is currently in active development. The API is unstable and subject to
//! frequent changes. Production use is not recommended until version **0.1.0**. //! frequent changes. Production use is not recommended until version **0.1.0**.
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]

View file

@ -87,7 +87,7 @@
//! ``` //! ```
use crate::html::{Markup, PreEscaped}; use crate::html::{Markup, PreEscaped};
use crate::{config, kv, AutoDefault, LazyStatic, LOCALES_PAGETOP}; use crate::{config, kv, AutoDefault, LOCALES_PAGETOP};
pub use fluent_templates; pub use fluent_templates;
pub use unic_langid::LanguageIdentifier; pub use unic_langid::LanguageIdentifier;
@ -132,8 +132,7 @@ pub fn langid_for(language: impl Into<String>) -> Result<&'static LanguageIdenti
Ok(&LANGID_FALLBACK) Ok(&LANGID_FALLBACK)
} else { } else {
Err(format!( Err(format!(
"Failed to get langid. Unicode Language Identifier \"{}\" is not accepted.", "No langid for Unicode Language Identifier \"{language}\".",
language,
)) ))
} }
} }

View file

@ -85,6 +85,32 @@ impl TypeInfo {
// FUNCTIONS HELPERS. // FUNCTIONS HELPERS.
// ************************************************************************************************* // *************************************************************************************************
/// Calculates the absolute directory given a root path and a relative path.
///
/// # Arguments
///
/// * `root_path` - A string slice that holds the root path.
/// * `relative_path` - A string slice that holds the relative path.
///
/// # Returns
///
/// * `Ok` - If the operation is successful, returns the absolute directory as a `String`.
/// * `Err` - If an I/O error occurs, returns an `io::Error`.
///
/// # Errors
///
/// This function will return an error if:
/// - The root path or relative path are invalid.
/// - There is an issue with file system operations, such as reading the directory.
///
/// # Examples
///
/// ```
/// let root = "/home/user";
/// let relative = "documents";
/// let abs_dir = absolute_dir(root, relative).unwrap();
/// println!("{}", abs_dir);
/// ```
pub fn absolute_dir( pub fn absolute_dir(
root_path: impl Into<String>, root_path: impl Into<String>,
relative_path: impl Into<String>, relative_path: impl Into<String>,
@ -94,19 +120,19 @@ pub fn absolute_dir(
let absolute_dir = full_path.to_string_lossy().into(); let absolute_dir = full_path.to_string_lossy().into();
if !full_path.is_absolute() { if !full_path.is_absolute() {
let message = format!("Path \"{}\" is not absolute", absolute_dir); let message = format!("Path \"{absolute_dir}\" is not absolute");
trace::warn!(message); trace::warn!(message);
return Err(io::Error::new(io::ErrorKind::InvalidInput, message)); return Err(io::Error::new(io::ErrorKind::InvalidInput, message));
} }
if !full_path.exists() { if !full_path.exists() {
let message = format!("Path \"{}\" does not exist", absolute_dir); let message = format!("Path \"{absolute_dir}\" does not exist");
trace::warn!(message); trace::warn!(message);
return Err(io::Error::new(io::ErrorKind::NotFound, message)); return Err(io::Error::new(io::ErrorKind::NotFound, message));
} }
if !full_path.is_dir() { if !full_path.is_dir() {
let message = format!("Path \"{}\" is not a directory", absolute_dir); let message = format!("Path \"{absolute_dir}\" is not a directory");
trace::warn!(message); trace::warn!(message);
return Err(io::Error::new(io::ErrorKind::InvalidInput, message)); return Err(io::Error::new(io::ErrorKind::InvalidInput, message));
} }