🚧 Doc & code tweaks
This commit is contained in:
parent
fea6c2f69e
commit
c1e641723b
12 changed files with 79 additions and 53 deletions
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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" {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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! {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
src/lib.rs
18
src/lib.rs
|
|
@ -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, it’s crucial that each package explicitly declares its
|
//! Nevertheless, it’s 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))]
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
src/util.rs
32
src/util.rs
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue