Modifica Assets por Context

This commit is contained in:
Manuel Cillero 2022-05-15 18:32:56 +02:00
parent 9e5d6e1a72
commit 72f5144b75
29 changed files with 375 additions and 372 deletions

View file

@ -55,7 +55,7 @@ impl ComponentTrait for Anchor {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
let target = match &self.target() { let target = match &self.target() {
AnchorTarget::Blank => Some("_blank"), AnchorTarget::Blank => Some("_blank"),
AnchorTarget::Context(name) => Some(name.as_str()), AnchorTarget::Context(name) => Some(name.as_str()),

View file

@ -37,8 +37,8 @@ impl ComponentTrait for Block {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
let id = assets.required_id::<Block>(self.id()); let id = context.required_id::<Block>(self.id());
html! { html! {
div id=(id) class=[self.classes()] { div id=(id) class=[self.classes()] {
@match self.title() { @match self.title() {
@ -46,7 +46,7 @@ impl ComponentTrait for Block {
None => {} None => {}
} }
div class="block-body" { div class="block-body" {
(self.components().render(assets)) (self.components().render(context))
} }
} }
} }

View file

@ -31,7 +31,7 @@ impl ComponentTrait for Chunck {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
html! { (*self.html()) } html! { (*self.html()) }
} }

View file

@ -41,39 +41,39 @@ impl ComponentTrait for Container {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
match self.container_type() { match self.container_type() {
ContainerType::Header => html! { ContainerType::Header => html! {
header id=[self.id()] class=[self.classes()] { header id=[self.id()] class=[self.classes()] {
div class=[self.inner_classes()] { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
}, },
ContainerType::Footer => html! { ContainerType::Footer => html! {
footer id=[self.id()] class=[self.classes()] { footer id=[self.id()] class=[self.classes()] {
div class=[self.inner_classes()] { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
}, },
ContainerType::Main => html! { ContainerType::Main => html! {
main id=[self.id()] class=[self.classes()] { main id=[self.id()] class=[self.classes()] {
div class=[self.inner_classes()] { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
}, },
ContainerType::Section => html! { ContainerType::Section => html! {
section id=[self.id()] class=[self.classes()] { section id=[self.id()] class=[self.classes()] {
div class=[self.inner_classes()] { div class=[self.inner_classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
}, },
_ => html! { _ => html! {
div id=[self.id()] class=[self.classes()] { div id=[self.id()] class=[self.classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
} }

View file

@ -44,7 +44,7 @@ impl ComponentTrait for Button {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
let button_type = match self.button_type() { let button_type = match self.button_type() {
ButtonType::Button => "button", ButtonType::Button => "button",
ButtonType::Reset => "reset", ButtonType::Reset => "reset",

View file

@ -52,7 +52,7 @@ impl ComponentTrait for Date {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
let id = match self.name() { let id = match self.name() {
Some(name) => Some(concat_string!("edit-", name)), Some(name) => Some(concat_string!("edit-", name)),
None => None, None => None,

View file

@ -43,7 +43,7 @@ impl ComponentTrait for Form {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
let method = match self.method() { let method = match self.method() {
FormMethod::Get => None, FormMethod::Get => None,
FormMethod::Post => Some("post".to_owned()) FormMethod::Post => Some("post".to_owned())
@ -56,7 +56,7 @@ impl ComponentTrait for Form {
method=[method] method=[method]
accept-charset=[self.charset()] accept-charset=[self.charset()]
{ {
div { (self.elements().render(assets)) } div { (self.elements().render(context)) }
} }
} }
} }

View file

@ -25,7 +25,7 @@ impl ComponentTrait for Hidden {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
let id = match self.name() { let id = match self.name() {
Some(name) => Some(concat_string!("value-", name)), Some(name) => Some(concat_string!("value-", name)),
_ => None _ => None

View file

@ -62,14 +62,14 @@ impl ComponentTrait for Input {
self.weight self.weight
} }
fn before_render(&mut self, _: &mut Assets) { fn before_render(&mut self, _: &mut Context) {
if let Some(name) = self.name() { if let Some(name) = self.name() {
let class = concat_string!("form-item-", name); let class = concat_string!("form-item-", name);
self.alter_classes(class.as_str(), ClassesOp::AddFirst); self.alter_classes(class.as_str(), ClassesOp::AddFirst);
} }
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
let type_input = match self.input_type() { let type_input = match self.input_type() {
InputType::Email => "email", InputType::Email => "email",
InputType::Password => "password", InputType::Password => "password",

View file

@ -35,10 +35,10 @@ impl ComponentTrait for Column {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
html! { html! {
div id=[self.id()] class=[self.classes()] { div id=[self.id()] class=[self.classes()] {
(self.components().render(assets)) (self.components().render(context))
} }
} }
} }

View file

@ -35,10 +35,10 @@ impl ComponentTrait for Row {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
html! { html! {
div id=[self.id()] class=[self.classes()] { div id=[self.id()] class=[self.classes()] {
(self.columns().render(assets)) (self.columns().render(context))
} }
} }
} }

View file

@ -50,7 +50,7 @@ impl ComponentTrait for Heading {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
html! { @match &self.heading() { html! { @match &self.heading() {
HeadingType::H1 => h1 id=[self.id()] class=[self.classes()] { (*self.html()) }, HeadingType::H1 => h1 id=[self.id()] class=[self.classes()] { (*self.html()) },
HeadingType::H2 => h2 id=[self.id()] class=[self.classes()] { (*self.html()) }, HeadingType::H2 => h2 id=[self.id()] class=[self.classes()] { (*self.html()) },

View file

@ -35,7 +35,7 @@ impl ComponentTrait for Image {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
html! { html! {
img img
src=[self.source()] src=[self.source()]

View file

@ -42,7 +42,7 @@ impl ComponentTrait for MenuItem {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
match self.item_type() { match self.item_type() {
MenuItemType::Label(label) => html! { MenuItemType::Label(label) => html! {
li class="label" { a href="#" { (label) } } li class="label" { a href="#" { (label) } }
@ -62,7 +62,7 @@ impl ComponentTrait for MenuItem {
li class="submenu" { li class="submenu" {
a href="#" { (label) } a href="#" { (label) }
ul { ul {
(menu.items().render(assets)) (menu.items().render(context))
} }
} }
}, },
@ -206,8 +206,8 @@ impl ComponentTrait for Menu {
self.weight self.weight
} }
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
assets context
.add_stylesheet(StyleSheet::source( .add_stylesheet(StyleSheet::source(
"/theme/menu/css/menu.css?ver=1.1.1" "/theme/menu/css/menu.css?ver=1.1.1"
)) ))
@ -219,10 +219,10 @@ impl ComponentTrait for Menu {
)) ))
.add_jquery(); .add_jquery();
let id = assets.required_id::<Menu>(self.id()); let id = context.required_id::<Menu>(self.id());
html! { html! {
ul id=(id) class=[self.classes()] { ul id=(id) class=[self.classes()] {
(self.items().render(assets)) (self.items().render(context))
} }
script type="text/javascript" defer { script type="text/javascript" defer {
"jQuery(function(){jQuery('#" (id) "').smartmenus({" "jQuery(function(){jQuery('#" (id) "').smartmenus({"

View file

@ -46,7 +46,7 @@ impl ComponentTrait for Paragraph {
self.weight self.weight
} }
fn default_render(&self, _: &mut Assets) -> Markup { fn default_render(&self, _: &mut Context) -> Markup {
html! { html! {
p id=[self.id()] class=[self.classes()] { (*self.html()) } p id=[self.id()] class=[self.classes()] { (*self.html()) }
} }

View file

@ -16,7 +16,7 @@ impl ThemeTrait for Aliner {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.assets() page.context()
.with_favicon( .with_favicon(
Favicon::new() Favicon::new()
.with_icon("/theme/favicon.png") .with_icon("/theme/favicon.png")

View file

@ -18,7 +18,7 @@ impl ThemeTrait for Bootsier {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.assets() page.context()
.with_favicon( .with_favicon(
Favicon::new() Favicon::new()
.with_icon("/theme/favicon.png") .with_icon("/theme/favicon.png")

View file

@ -16,7 +16,7 @@ impl ThemeTrait for Bulmix {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.assets() page.context()
.with_favicon( .with_favicon(
Favicon::new() Favicon::new()
.with_icon("/theme/favicon.png") .with_icon("/theme/favicon.png")
@ -33,7 +33,7 @@ impl ThemeTrait for Bulmix {
fn before_render_component( fn before_render_component(
&self, &self,
component: &mut dyn ComponentTrait, component: &mut dyn ComponentTrait,
_assets: &mut Assets _context: &mut Context
) { ) {
match component.handler() { match component.handler() {
HEADING_COMPONENT => { HEADING_COMPONENT => {

View file

@ -4,9 +4,9 @@ pub use hook::{
BeforeRenderComponentHook, BeforeRenderComponentHook,
}; };
mod assets; mod context;
pub use assets::{ pub use context::{
Assets, Context,
Favicon, Favicon,
JavaScript, JSMode, JavaScript, JSMode,
StyleSheet, StyleSheet,

View file

@ -1,302 +0,0 @@
use crate::{Lazy, base, concat_string, util};
use crate::config::SETTINGS;
use crate::html::{Markup, PreEscaped, html};
use crate::core::theme::*;
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
match all::theme_by_single_name(&SETTINGS.app.theme) {
Some(theme) => theme,
None => &base::theme::bootsier::Bootsier,
}
});
// Favicon.
pub struct Favicon(Vec<String>);
impl Favicon {
pub fn new() -> Self {
Favicon(Vec::new())
}
pub fn with_icon(self, image: &str) -> Self {
self.add_item("icon", image, "", "")
}
pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self {
self.add_item("icon", image, sizes, "")
}
pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self {
self.add_item("apple-touch-icon", image, sizes, "")
}
pub fn with_mask_icon(self, image: &str, color: &str) -> Self {
self.add_item("mask-icon", image, "", color)
}
pub fn with_manifest(self, file: &str) -> Self {
self.add_item("manifest", file, "", "")
}
pub fn with_theme_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"theme-color\" content=\"{}\">", color
));
self
}
pub fn with_ms_tile_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileColor\" content=\"{}\">", color
));
self
}
pub fn with_ms_tile_image(mut self, image: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileImage\" content=\"{}\">", image
));
self
}
fn add_item(
mut self,
rel : &str,
source: &str,
sizes : &str,
color : &str
) -> Self {
let mut link: String = format!("<link rel=\"{}\"", rel);
if let Some(i) = source.rfind('.') {
link = match source[i..].to_owned().to_lowercase().as_str() {
".gif" => format!("{} type=\"image/gif\"", link),
".ico" => format!("{} type=\"image/x-icon\"", link),
".jpg" => format!("{} type=\"image/jpg\"", link),
".png" => format!("{} type=\"image/png\"", link),
".svg" => format!("{} type=\"image/svg+xml\"", link),
_ => link
};
}
if !sizes.is_empty() {
link = format!("{} sizes=\"{}\"", link, sizes);
}
if !color.is_empty() {
link = format!("{} color=\"{}\"", link, color);
}
self.0.push(format!("{} href=\"{}\">", link, source));
self
}
fn render(&self) -> Markup {
html! {
@for item in &self.0 {
(PreEscaped(item))
}
}
}
}
// JavaScript.
#[derive(PartialEq)]
pub enum JSMode { Async, Defer, Normal }
pub struct JavaScript {
source: &'static str,
weight: isize,
mode : JSMode,
}
impl JavaScript {
pub fn source(s: &'static str) -> Self {
JavaScript {
source: s,
weight: 0,
mode : JSMode::Defer,
}
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn with_mode(mut self, mode: JSMode) -> Self {
self.mode = mode;
self
}
pub fn weight(self) -> isize {
self.weight
}
fn render(&self) -> Markup {
html! {
script type="text/javascript"
src=(self.source)
async[self.mode == JSMode::Async]
defer[self.mode == JSMode::Defer]
{};
}
}
}
// StyleSheet.
pub struct StyleSheet {
source: &'static str,
weight: isize,
}
impl StyleSheet {
pub fn source(s: &'static str) -> Self {
StyleSheet {
source: s,
weight: 0,
}
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn weight(self) -> isize {
self.weight
}
fn render(&self) -> Markup {
html! {
link rel="stylesheet" href=(self.source);
}
}
}
// Page assets.
pub struct Assets {
theme : &'static dyn ThemeTrait,
favicon : Option<Favicon>,
metadata : Vec<(String, String)>,
stylesheets: Vec<StyleSheet>,
javascripts: Vec<JavaScript>,
with_jquery: bool,
id_counter : usize,
}
impl Assets {
pub fn new() -> Self {
Assets {
theme : *DEFAULT_THEME,
favicon : None,
metadata : Vec::new(),
stylesheets: Vec::new(),
javascripts: Vec::new(),
with_jquery: false,
id_counter : 0,
}
}
pub fn using_theme(&mut self, theme_name: &str) -> &mut Self {
self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
self
}
pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self {
self.favicon = Some(favicon);
self
}
pub fn add_metadata(&mut self, name: String, content: String) -> &mut Self {
self.metadata.push((name, content));
self
}
pub fn add_stylesheet(&mut self, css: StyleSheet) -> &mut Self {
match self.stylesheets.iter().position(|x| x.source == css.source) {
Some(index) => if self.stylesheets[index].weight > css.weight {
self.stylesheets.remove(index);
self.stylesheets.push(css);
},
_ => self.stylesheets.push(css)
}
self
}
pub fn add_javascript(&mut self, js: JavaScript) -> &mut Self {
match self.javascripts.iter().position(|x| x.source == js.source) {
Some(index) => if self.javascripts[index].weight > js.weight {
self.javascripts.remove(index);
self.javascripts.push(js);
},
_ => self.javascripts.push(js)
}
self
}
pub fn add_jquery(&mut self) -> &mut Self {
if !self.with_jquery {
self.add_javascript(
JavaScript::source(
"/theme/js/jquery.min.js?ver=3.6.0"
)
.with_weight(isize::MIN)
.with_mode(JSMode::Normal)
);
self.with_jquery = true;
}
self
}
/// Assets GETTERS.
pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait {
self.theme
}
/// Assets RENDER.
pub fn render(&mut self) -> Markup {
let ordered_css = &mut self.stylesheets;
ordered_css.sort_by_key(|o| o.weight);
let ordered_js = &mut self.javascripts;
ordered_js.sort_by_key(|o| o.weight);
html! {
@match &self.favicon {
Some(favicon) => (favicon.render()),
None => "",
}
@for (name, content) in &self.metadata {
meta name=(name) content=(content) {}
}
@for css in ordered_css {
(css.render())
}
@for js in ordered_js {
(js.render())
}
}
}
// Assets EXTRAS.
pub fn required_id<T>(&mut self, id: &Option<String>) -> String {
match id {
Some(id) => id.to_string(),
None => {
let prefix = util::single_type_name::<T>()
.trim()
.replace(" ", "_")
.to_lowercase();
let prefix = if prefix.is_empty() {
"prefix".to_owned()
} else {
prefix
};
self.id_counter += 1;
concat_string!(prefix, "-", self.id_counter.to_string())
}
}
}
}

View file

@ -0,0 +1,148 @@
use crate::{Lazy, base, concat_string, util};
use crate::config::SETTINGS;
use crate::html::{Markup, html};
use crate::core::theme::*;
mod favicon;
pub use favicon::Favicon;
mod javascript;
pub use javascript::{JavaScript, JSMode};
mod stylesheet;
pub use stylesheet::StyleSheet;
static DEFAULT_THEME: Lazy<&dyn ThemeTrait> = Lazy::new(|| {
match all::theme_by_single_name(&SETTINGS.app.theme) {
Some(theme) => theme,
None => &base::theme::bootsier::Bootsier,
}
});
pub struct Context {
theme : &'static dyn ThemeTrait,
favicon : Option<Favicon>,
metadata : Vec<(String, String)>,
stylesheets: Vec<StyleSheet>,
javascripts: Vec<JavaScript>,
with_jquery: bool,
id_counter : usize,
}
impl Context {
pub fn new() -> Self {
Context {
theme : *DEFAULT_THEME,
favicon : None,
metadata : Vec::new(),
stylesheets: Vec::new(),
javascripts: Vec::new(),
with_jquery: false,
id_counter : 0,
}
}
pub fn using_theme(&mut self, theme_name: &str) -> &mut Self {
self.theme = all::theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
self
}
pub fn with_favicon(&mut self, favicon: Favicon) -> &mut Self {
self.favicon = Some(favicon);
self
}
pub fn add_metadata(&mut self, name: String, content: String) -> &mut Self {
self.metadata.push((name, content));
self
}
pub fn add_stylesheet(&mut self, css: StyleSheet) -> &mut Self {
match self.stylesheets.iter().position(|x| x.source == css.source) {
Some(index) => if self.stylesheets[index].weight > css.weight {
self.stylesheets.remove(index);
self.stylesheets.push(css);
},
_ => self.stylesheets.push(css)
}
self
}
pub fn add_javascript(&mut self, js: JavaScript) -> &mut Self {
match self.javascripts.iter().position(|x| x.source == js.source) {
Some(index) => if self.javascripts[index].weight > js.weight {
self.javascripts.remove(index);
self.javascripts.push(js);
},
_ => self.javascripts.push(js)
}
self
}
pub fn add_jquery(&mut self) -> &mut Self {
if !self.with_jquery {
self.add_javascript(
JavaScript::source(
"/theme/js/jquery.min.js?ver=3.6.0"
)
.with_weight(isize::MIN)
.with_mode(JSMode::Normal)
);
self.with_jquery = true;
}
self
}
/// Context GETTERS.
pub(crate) fn theme(&mut self) -> &'static dyn ThemeTrait {
self.theme
}
/// Context RENDER.
pub fn render(&mut self) -> Markup {
let ordered_css = &mut self.stylesheets;
ordered_css.sort_by_key(|o| o.weight);
let ordered_js = &mut self.javascripts;
ordered_js.sort_by_key(|o| o.weight);
html! {
@match &self.favicon {
Some(favicon) => (favicon.render()),
None => "",
}
@for (name, content) in &self.metadata {
meta name=(name) content=(content) {}
}
@for css in ordered_css {
(css.render())
}
@for js in ordered_js {
(js.render())
}
}
}
// Context EXTRAS.
pub fn required_id<T>(&mut self, id: &Option<String>) -> String {
match id {
Some(id) => id.to_string(),
None => {
let prefix = util::single_type_name::<T>()
.trim()
.replace(" ", "_")
.to_lowercase();
let prefix = if prefix.is_empty() {
"prefix".to_owned()
} else {
prefix
};
self.id_counter += 1;
concat_string!(prefix, "-", self.id_counter.to_string())
}
}
}
}

View file

@ -0,0 +1,86 @@
use crate::html::{Markup, PreEscaped, html};
pub struct Favicon(Vec<String>);
impl Favicon {
pub fn new() -> Self {
Favicon(Vec::new())
}
pub fn with_icon(self, image: &str) -> Self {
self.add_item("icon", image, "", "")
}
pub fn with_icon_for_sizes(self, image: &str, sizes: &str) -> Self {
self.add_item("icon", image, sizes, "")
}
pub fn with_apple_touch_icon(self, image: &str, sizes: &str) -> Self {
self.add_item("apple-touch-icon", image, sizes, "")
}
pub fn with_mask_icon(self, image: &str, color: &str) -> Self {
self.add_item("mask-icon", image, "", color)
}
pub fn with_manifest(self, file: &str) -> Self {
self.add_item("manifest", file, "", "")
}
pub fn with_theme_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"theme-color\" content=\"{}\">", color
));
self
}
pub fn with_ms_tile_color(mut self, color: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileColor\" content=\"{}\">", color
));
self
}
pub fn with_ms_tile_image(mut self, image: &str) -> Self {
self.0.push(format!(
"<meta name=\"msapplication-TileImage\" content=\"{}\">", image
));
self
}
fn add_item(
mut self,
rel : &str,
source: &str,
sizes : &str,
color : &str
) -> Self {
let mut link: String = format!("<link rel=\"{}\"", rel);
if let Some(i) = source.rfind('.') {
link = match source[i..].to_owned().to_lowercase().as_str() {
".gif" => format!("{} type=\"image/gif\"", link),
".ico" => format!("{} type=\"image/x-icon\"", link),
".jpg" => format!("{} type=\"image/jpg\"", link),
".png" => format!("{} type=\"image/png\"", link),
".svg" => format!("{} type=\"image/svg+xml\"", link),
_ => link
};
}
if !sizes.is_empty() {
link = format!("{} sizes=\"{}\"", link, sizes);
}
if !color.is_empty() {
link = format!("{} color=\"{}\"", link, color);
}
self.0.push(format!("{} href=\"{}\">", link, source));
self
}
pub(super) fn render(&self) -> Markup {
html! {
@for item in &self.0 {
(PreEscaped(item))
}
}
}
}

View file

@ -0,0 +1,43 @@
use crate::html::{Markup, html};
#[derive(PartialEq)]
pub enum JSMode { Async, Defer, Normal }
pub struct JavaScript {
pub(super) source: &'static str,
pub(super) weight: isize,
pub(super) mode : JSMode,
}
impl JavaScript {
pub fn source(s: &'static str) -> Self {
JavaScript {
source: s,
weight: 0,
mode : JSMode::Defer,
}
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn with_mode(mut self, mode: JSMode) -> Self {
self.mode = mode;
self
}
pub fn weight(self) -> isize {
self.weight
}
pub(super) fn render(&self) -> Markup {
html! {
script type="text/javascript"
src=(self.source)
async[self.mode == JSMode::Async]
defer[self.mode == JSMode::Defer]
{};
}
}
}

View file

@ -0,0 +1,29 @@
use crate::html::{Markup, html};
pub struct StyleSheet {
pub(super) source: &'static str,
pub(super) weight: isize,
}
impl StyleSheet {
pub fn source(s: &'static str) -> Self {
StyleSheet {
source: s,
weight: 0,
}
}
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn weight(self) -> isize {
self.weight
}
pub(super) fn render(&self) -> Markup {
html! {
link rel="stylesheet" href=(self.source);
}
}
}

View file

@ -1,8 +1,7 @@
use crate::util; use crate::util;
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use crate::core::hook::{hook_ref, run_hooks}; use crate::core::hook::{hook_ref, run_hooks};
use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook}; use super::{BEFORE_RENDER_COMPONENT_HOOK, BeforeRenderComponentHook, Context};
use super::Assets;
pub use std::any::Any as AnyComponent; pub use std::any::Any as AnyComponent;
@ -28,11 +27,11 @@ pub trait ComponentTrait: AnyComponent + Send + Sync {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render(&mut self, assets: &mut Assets) { fn before_render(&mut self, context: &mut Context) {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn default_render(&self, assets: &mut Assets) -> Markup { fn default_render(&self, context: &mut Context) -> Markup {
html! {} html! {}
} }
@ -49,24 +48,24 @@ pub fn component_mut<C: 'static>(component: &mut dyn ComponentTrait) -> &mut C {
component.as_mut_any().downcast_mut::<C>().unwrap() component.as_mut_any().downcast_mut::<C>().unwrap()
} }
pub fn render_component(component: &mut dyn ComponentTrait, assets: &mut Assets) -> Markup { pub fn render_component(component: &mut dyn ComponentTrait, context: &mut Context) -> Markup {
// Acciones del componente antes de renderizar. // Acciones del componente antes de renderizar.
component.before_render(assets); component.before_render(context);
// Acciones de los módulos antes de renderizar el componente. // Acciones de los módulos antes de renderizar el componente.
run_hooks( run_hooks(
BEFORE_RENDER_COMPONENT_HOOK, BEFORE_RENDER_COMPONENT_HOOK,
|a| hook_ref::<BeforeRenderComponentHook>(&**a).run(component, assets) |a| hook_ref::<BeforeRenderComponentHook>(&**a).run(component, context)
); );
// Acciones del tema antes de renderizar el componente. // Acciones del tema antes de renderizar el componente.
assets.theme().before_render_component(component, assets); context.theme().before_render_component(component, context);
match component.is_renderable() { match component.is_renderable() {
true => { true => {
match assets.theme().render_component(component, assets) { match context.theme().render_component(component, context) {
Some(html) => html, Some(html) => html,
None => component.default_render(assets) None => component.default_render(context)
} }
}, },
false => html! {} false => html! {}

View file

@ -1,5 +1,5 @@
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use super::{Assets, ComponentTrait}; use super::{Context, ComponentTrait};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -21,12 +21,12 @@ impl ComponentsHolder {
self.0.push(Arc::new(RwLock::new(component))); self.0.push(Arc::new(RwLock::new(component)));
} }
pub fn render(&self, assets: &mut Assets) -> Markup { pub fn render(&self, context: &mut Context) -> Markup {
let mut components = self.0.clone(); let mut components = self.0.clone();
components.sort_by_key(|c| c.read().unwrap().weight()); components.sort_by_key(|c| c.read().unwrap().weight());
html! { html! {
@for c in components.iter() { @for c in components.iter() {
(super::render_component(&mut *c.write().unwrap(), assets)) (super::render_component(&mut *c.write().unwrap(), context))
} }
} }
} }

View file

@ -1,10 +1,10 @@
use crate::core::hook::{HookTrait, AnyHook}; use crate::core::hook::{HookTrait, AnyHook};
use super::{Assets, ComponentTrait}; use super::{ComponentTrait, Context};
pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::hook::before_render_component"; pub const BEFORE_RENDER_COMPONENT_HOOK: &str = "pagetop::hook::before_render_component";
pub struct BeforeRenderComponentHook { pub struct BeforeRenderComponentHook {
hook: Option<fn(&mut dyn ComponentTrait, &mut Assets)>, hook: Option<fn(&mut dyn ComponentTrait, &mut Context)>,
weight: isize, weight: isize,
} }
@ -30,7 +30,7 @@ impl HookTrait for BeforeRenderComponentHook {
} }
impl BeforeRenderComponentHook { impl BeforeRenderComponentHook {
pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Assets)) -> Self { pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut Context)) -> Self {
self.hook = Some(hook); self.hook = Some(hook);
self self
} }
@ -40,9 +40,9 @@ impl BeforeRenderComponentHook {
self self
} }
pub fn run(&self, component: &mut dyn ComponentTrait, assets: &mut Assets) { pub fn run(&self, component: &mut dyn ComponentTrait, context: &mut Context) {
if let Some(hook) = self.hook { if let Some(hook) = self.hook {
hook(component, assets) hook(component, context)
} }
} }
} }

View file

@ -2,7 +2,7 @@ use crate::{concat_string, util};
use crate::config::SETTINGS; use crate::config::SETTINGS;
use crate::html::{Markup, html}; use crate::html::{Markup, html};
use crate::core::app; use crate::core::app;
use crate::core::component::{Assets, ComponentTrait, Favicon}; use crate::core::component::{ComponentTrait, Context, Favicon};
use crate::response::page::Page; use crate::response::page::Page;
use crate::base::component::Chunck; use crate::base::component::Chunck;
@ -28,7 +28,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.assets() page.context()
.with_favicon( .with_favicon(
Favicon::new() Favicon::new()
.with_icon("/theme/favicon.png") .with_icon("/theme/favicon.png")
@ -56,7 +56,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
meta http-equiv="X-UA-Compatible" content="IE=edge"; meta http-equiv="X-UA-Compatible" content="IE=edge";
meta name="viewport" content=(viewport); meta name="viewport" content=(viewport);
(page.assets().render()) (page.context().render())
} }
} }
} }
@ -86,7 +86,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn before_render_component( fn before_render_component(
&self, &self,
component: &mut dyn ComponentTrait, component: &mut dyn ComponentTrait,
assets: &mut Assets context: &mut Context
) { ) {
/* /*
Cómo usarlo: Cómo usarlo:
@ -105,7 +105,7 @@ pub trait ThemeTrait: BaseTheme + Send + Sync {
fn render_component( fn render_component(
&self, &self,
component: &dyn ComponentTrait, component: &dyn ComponentTrait,
assets: &mut Assets context: &mut Context
) -> Option<Markup> { ) -> Option<Markup> {
None None
/* /*

View file

@ -42,7 +42,7 @@ pub struct Page<'a> {
direction : OptAttr, direction : OptAttr,
title : OptAttr, title : OptAttr,
description : OptAttr, description : OptAttr,
assets : Assets, context : Context,
regions : HashMap<&'a str, ComponentsHolder>, regions : HashMap<&'a str, ComponentsHolder>,
body_classes: Classes, body_classes: Classes,
template : String, template : String,
@ -62,7 +62,7 @@ impl<'a> Page<'a> {
}, },
title : OptAttr::new(), title : OptAttr::new(),
description : OptAttr::new(), description : OptAttr::new(),
assets : Assets::new(), context : Context::new(),
regions : common_components(), regions : common_components(),
body_classes: Classes::new_with_default("body"), body_classes: Classes::new_with_default("body"),
template : "default".to_owned(), template : "default".to_owned(),
@ -136,8 +136,8 @@ impl<'a> Page<'a> {
self.description.option() self.description.option()
} }
pub fn assets(&mut self) -> &mut Assets { pub fn context(&mut self) -> &mut Context {
&mut self.assets &mut self.context
} }
pub fn body_classes(&self) -> &Option<String> { pub fn body_classes(&self) -> &Option<String> {
@ -158,13 +158,13 @@ impl<'a> Page<'a> {
); );
// Acciones del tema antes de renderizar la página. // Acciones del tema antes de renderizar la página.
self.assets.theme().before_render_page(self); self.context.theme().before_render_page(self);
// Primero, renderizar el cuerpo. // Primero, renderizar el cuerpo.
let body = self.assets.theme().render_page_body(self); let body = self.context.theme().render_page_body(self);
// Luego, renderizar la cabecera. // Luego, renderizar la cabecera.
let head = self.assets.theme().render_page_head(self); let head = self.context.theme().render_page_head(self);
// Finalmente, renderizar la página. // Finalmente, renderizar la página.
return Ok(html! { return Ok(html! {
@ -178,7 +178,7 @@ impl<'a> Page<'a> {
pub fn render_region(&mut self, region: &str) -> Markup { pub fn render_region(&mut self, region: &str) -> Markup {
match self.regions.get_mut(region) { match self.regions.get_mut(region) {
Some(components) => components.render(&mut self.assets), Some(components) => components.render(&mut self.context),
None => html! {} None => html! {}
} }
} }
@ -186,7 +186,7 @@ impl<'a> Page<'a> {
// Page EXTRAS. // Page EXTRAS.
pub fn using_theme(&mut self, theme_name: &str) -> &mut Self { pub fn using_theme(&mut self, theme_name: &str) -> &mut Self {
self.assets.using_theme(theme_name); self.context.using_theme(theme_name);
self self
} }
} }