Añade nuevas posibilidades para manipular contexto

This commit is contained in:
Manuel Cillero 2022-07-29 22:41:00 +02:00
parent 33c3262426
commit de0785c29f
13 changed files with 129 additions and 108 deletions

View file

@ -32,9 +32,9 @@ impl ComponentTrait for Icon {
} }
fn before_render(&mut self, context: &mut InContext) { fn before_render(&mut self, context: &mut InContext) {
context.alter(InContextOp::StyleSheet(AssetsOp::Add( context.alter(InContextOp::AddStyleSheet(
StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"), StyleSheet::located("/theme/icons/bootstrap-icons.css").with_version("1.8.2"),
))); ));
} }
fn default_render(&self, _: &mut InContext) -> Markup { fn default_render(&self, _: &mut InContext) -> Markup {

View file

@ -206,15 +206,15 @@ impl ComponentTrait for Menu {
fn default_render(&self, context: &mut InContext) -> Markup { fn default_render(&self, context: &mut InContext) -> Markup {
context context
.alter(InContextOp::StyleSheet(AssetsOp::Add( .alter(InContextOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"), StyleSheet::located("/theme/menu/css/menu.css").with_version("1.1.1"),
))) ))
.alter(InContextOp::StyleSheet(AssetsOp::Add( .alter(InContextOp::AddStyleSheet(
StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"), StyleSheet::located("/theme/menu/css/menu-clean.css").with_version("1.1.1"),
))) ))
.alter(InContextOp::JavaScript(AssetsOp::Add( .alter(InContextOp::AddJavaScript(
JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"), JavaScript::located("/theme/menu/js/menu.min.js").with_version("1.1.1"),
))) ))
.alter(InContextOp::AddJQuery); .alter(InContextOp::AddJQuery);
let id = context.required_id::<Menu>(self.id()); let id = context.required_id::<Menu>(self.id());

View file

@ -27,9 +27,9 @@ impl ModuleTrait for DefaultHomePage {
async fn demo() -> ResultPage<Markup, FatalError> { async fn demo() -> ResultPage<Markup, FatalError> {
Page::new() Page::new()
.with_title(l("page_title").as_str()) .with_title(l("page_title").as_str())
.with_context(InContextOp::StyleSheet(AssetsOp::Add(StyleSheet::located( .with_context(InContextOp::AddStyleSheet(
"/theme/module/homepage/styles.css", StyleSheet::located("/theme/module/homepage/styles.css"
)))) )))
.add_to("region-content", hello_world()) .add_to("region-content", hello_world())
.add_to("region-content", welcome()) .add_to("region-content", welcome())
.add_to("region-content", about_pagetop()) .add_to("region-content", about_pagetop())

View file

@ -16,11 +16,12 @@ impl ThemeTrait for Aliner {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(InContextOp::Favicon(Some( page
Favicon::new().with_icon("/theme/favicon.png"), .alter_context(InContextOp::AddFavicon(
))) Favicon::new().with_icon("/theme/favicon.png"),
.alter_context(InContextOp::StyleSheet(AssetsOp::Add( ))
StyleSheet::located("/aliner/css/styles.css").with_weight(-99), .alter_context(InContextOp::AddStyleSheet(
))); StyleSheet::located("/aliner/css/styles.css").with_weight(-99),
));
} }
} }

View file

@ -18,20 +18,21 @@ impl ThemeTrait for Bootsier {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(InContextOp::Favicon(Some( page
Favicon::new().with_icon("/theme/favicon.png"), .alter_context(InContextOp::AddFavicon(
))) Favicon::new().with_icon("/theme/favicon.png"),
.alter_context(InContextOp::StyleSheet(AssetsOp::Add( ))
StyleSheet::located("/bootsier/css/bootstrap.min.css") .alter_context(InContextOp::AddStyleSheet(
.with_version("5.1.3") StyleSheet::located("/bootsier/css/bootstrap.min.css")
.with_weight(-99), .with_version("5.1.3")
))) .with_weight(-99),
.alter_context(InContextOp::JavaScript(AssetsOp::Add( ))
JavaScript::located("/bootsier/js/bootstrap.bundle.min.js") .alter_context(InContextOp::AddJavaScript(
.with_version("5.1.3") JavaScript::located("/bootsier/js/bootstrap.bundle.min.js")
.with_weight(-99), .with_version("5.1.3")
))) .with_weight(-99),
.alter_context(InContextOp::AddJQuery); ))
.alter_context(InContextOp::AddJQuery);
} }
fn error_404_not_found(&self) -> Container { fn error_404_not_found(&self) -> Container {

View file

@ -16,15 +16,16 @@ impl ThemeTrait for Bulmix {
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {
page.alter_context(InContextOp::Favicon(Some( page
Favicon::new().with_icon("/theme/favicon.png"), .alter_context(InContextOp::AddFavicon(
))) Favicon::new().with_icon("/theme/favicon.png"),
.alter_context(InContextOp::StyleSheet(AssetsOp::Add( ))
StyleSheet::located("/bulmix/css/bulma.min.css") .alter_context(InContextOp::AddStyleSheet(
.with_version("0.9.4") StyleSheet::located("/bulmix/css/bulma.min.css")
.with_weight(-99), .with_version("0.9.4")
))) .with_weight(-99),
.alter_context(InContextOp::AddJQuery); ))
.alter_context(InContextOp::AddJQuery);
} }
fn before_render_component( fn before_render_component(

View file

@ -13,17 +13,26 @@ static DEFAULT_THEME: LazyStatic<&dyn ThemeTrait> = LazyStatic::new(||
pub enum InContextOp { pub enum InContextOp {
SetTheme(&'static str), SetTheme(&'static str),
AddFavicon(Favicon),
RemoveFavicon,
AddMetadata(&'static str, &'static str), AddMetadata(&'static str, &'static str),
Favicon(Option<Favicon>), AddProperty(&'static str, &'static str),
StyleSheet(AssetsOp<StyleSheet>),
JavaScript(AssetsOp<JavaScript>), AddStyleSheet(StyleSheet),
RemoveStyleSheet(&'static str),
AddJavaScript(JavaScript),
RemoveJavaScript(&'static str),
AddJQuery, AddJQuery,
} }
pub struct InContext { pub struct InContext {
theme : &'static dyn ThemeTrait, theme : &'static dyn ThemeTrait,
favicon : Option<Favicon>, favicon : Option<Favicon>,
metadata : Vec<(String, String)>, metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
stylesheets: Assets<StyleSheet>, stylesheets: Assets<StyleSheet>,
javascripts: Assets<JavaScript>, javascripts: Assets<JavaScript>,
with_jquery: bool, with_jquery: bool,
@ -36,6 +45,7 @@ impl InContext {
theme : *DEFAULT_THEME, theme : *DEFAULT_THEME,
favicon : None, favicon : None,
metadata : Vec::new(), metadata : Vec::new(),
properties : Vec::new(),
stylesheets: Assets::<StyleSheet>::new(), stylesheets: Assets::<StyleSheet>::new(),
javascripts: Assets::<JavaScript>::new(), javascripts: Assets::<JavaScript>::new(),
with_jquery: false, with_jquery: false,
@ -48,26 +58,42 @@ impl InContext {
InContextOp::SetTheme(theme_name) => { InContextOp::SetTheme(theme_name) => {
self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME); self.theme = theme_by_single_name(theme_name).unwrap_or(*DEFAULT_THEME);
} }
InContextOp::AddFavicon(favicon) => {
self.favicon = Some(favicon);
}
InContextOp::RemoveFavicon => {
self.favicon = None;
}
InContextOp::AddMetadata(name, content) => { InContextOp::AddMetadata(name, content) => {
self.metadata.push((name.to_owned(), content.to_owned())); self.metadata.push((name, content));
} }
InContextOp::Favicon(favicon) => { InContextOp::AddProperty(property, content) => {
self.favicon = favicon; self.properties.push((property, content));
} }
InContextOp::StyleSheet(css) => {
self.stylesheets.alter(css); InContextOp::AddStyleSheet(css) => {
self.stylesheets.add(css);
} }
InContextOp::JavaScript(js) => { InContextOp::RemoveStyleSheet(source) => {
self.javascripts.alter(js); self.stylesheets.remove(source);
}
InContextOp::AddJavaScript(js) => {
self.javascripts.add(js);
}
InContextOp::RemoveJavaScript(source) => {
self.javascripts.remove(source);
} }
InContextOp::AddJQuery => { InContextOp::AddJQuery => {
if !self.with_jquery { if !self.with_jquery {
self.javascripts.alter(AssetsOp::Add( self.javascripts.add(
JavaScript::located("/theme/js/jquery.min.js") JavaScript::located("/theme/js/jquery.min.js")
.with_version("3.6.0") .with_version("3.6.0")
.with_weight(isize::MIN) .with_weight(isize::MIN)
.with_mode(JSMode::Normal), .with_mode(JSMode::Normal),
)); );
self.with_jquery = true; self.with_jquery = true;
} }
} }
@ -92,6 +118,9 @@ impl InContext {
@for (name, content) in &self.metadata { @for (name, content) in &self.metadata {
meta name=(name) content=(content) {} meta name=(name) content=(content) {}
} }
@for (property, content) in &self.properties {
meta property=(property) content=(content) {}
}
(self.stylesheets.render()) (self.stylesheets.render())
(self.javascripts.render()) (self.javascripts.render())
} }

View file

@ -28,9 +28,9 @@ 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.alter_context(InContextOp::Favicon(Some( page.alter_context(InContextOp::AddFavicon(
Favicon::new().with_icon("/theme/favicon.png"), Favicon::new().with_icon("/theme/favicon.png"),
))); ));
} }
fn render_page_head(&self, page: &mut Page) -> Markup { fn render_page_head(&self, page: &mut Page) -> Markup {

View file

@ -3,7 +3,7 @@ pub use maud::{html, Markup, PreEscaped, DOCTYPE};
mod assets; mod assets;
pub use assets::javascript::{JSMode, JavaScript}; pub use assets::javascript::{JSMode, JavaScript};
pub use assets::stylesheet::{StyleSheet, TargetMedia}; pub use assets::stylesheet::{StyleSheet, TargetMedia};
pub use assets::{Assets, AssetsOp, SourceValue}; pub use assets::Assets;
mod favicon; mod favicon;
pub use favicon::Favicon; pub use favicon::Favicon;

View file

@ -3,21 +3,14 @@ pub mod stylesheet;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
pub type SourceValue = &'static str;
pub trait AssetsTrait { pub trait AssetsTrait {
fn source(&self) -> SourceValue; fn source(&self) -> &'static str;
fn weight(&self) -> isize; fn weight(&self) -> isize;
fn render(&self) -> Markup; fn render(&self) -> Markup;
} }
pub enum AssetsOp<T: AssetsTrait> {
Add(T),
Remove(SourceValue),
}
#[derive(Default)] #[derive(Default)]
pub struct Assets<T>(Vec<T>); pub struct Assets<T>(Vec<T>);
@ -26,25 +19,23 @@ impl<T: AssetsTrait> Assets<T> {
Assets::<T>(Vec::<T>::new()) Assets::<T>(Vec::<T>::new())
} }
pub fn alter(&mut self, op: AssetsOp<T>) -> &mut Self { pub fn add(&mut self, asset: T) -> &mut Self {
match op { match self.0.iter().position(|x| x.source() == asset.source()) {
AssetsOp::Add(asset) => { Some(index) => {
match self.0.iter().position(|x| x.source() == asset.source()) { if self.0[index].weight() > asset.weight() {
Some(index) => {
if self.0[index].weight() > asset.weight() {
self.0.remove(index);
self.0.push(asset);
}
}
_ => self.0.push(asset),
}
}
AssetsOp::Remove(source) => {
if let Some(index) = self.0.iter().position(|x| x.source() == source) {
self.0.remove(index); self.0.remove(index);
self.0.push(asset);
} }
} }
} _ => self.0.push(asset),
};
self
}
pub fn remove(&mut self, source: &'static str) -> &mut Self {
if let Some(index) = self.0.iter().position(|x| x.source() == source) {
self.0.remove(index);
};
self self
} }

View file

@ -1,4 +1,4 @@
use super::{AssetsTrait, SourceValue}; use super::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
#[derive(PartialEq)] #[derive(PartialEq)]
@ -9,7 +9,7 @@ pub enum JSMode {
} }
pub struct JavaScript { pub struct JavaScript {
source : SourceValue, source : &'static str,
prefix : &'static str, prefix : &'static str,
version: &'static str, version: &'static str,
weight : isize, weight : isize,
@ -17,7 +17,7 @@ pub struct JavaScript {
} }
impl AssetsTrait for JavaScript { impl AssetsTrait for JavaScript {
fn source(&self) -> SourceValue { fn source(&self) -> &'static str {
self.source self.source
} }
@ -37,7 +37,7 @@ impl AssetsTrait for JavaScript {
} }
impl JavaScript { impl JavaScript {
pub fn located(source: SourceValue) -> Self { pub fn located(source: &'static str) -> Self {
JavaScript { JavaScript {
source, source,
prefix : "", prefix : "",

View file

@ -1,10 +1,10 @@
use super::{AssetsTrait, SourceValue}; use super::AssetsTrait;
use crate::html::{html, Markup}; use crate::html::{html, Markup};
pub enum TargetMedia {Default, Print, Screen, Speech} pub enum TargetMedia {Default, Print, Screen, Speech}
pub struct StyleSheet { pub struct StyleSheet {
source : SourceValue, source : &'static str,
prefix : &'static str, prefix : &'static str,
version: &'static str, version: &'static str,
media : Option<&'static str>, media : Option<&'static str>,
@ -12,7 +12,7 @@ pub struct StyleSheet {
} }
impl AssetsTrait for StyleSheet { impl AssetsTrait for StyleSheet {
fn source(&self) -> SourceValue { fn source(&self) -> &'static str {
self.source self.source
} }
@ -31,7 +31,7 @@ impl AssetsTrait for StyleSheet {
} }
impl StyleSheet { impl StyleSheet {
pub fn located(source: SourceValue) -> Self { pub fn located(source: &'static str) -> Self {
StyleSheet { StyleSheet {
source, source,
prefix : "", prefix : "",

View file

@ -60,34 +60,32 @@ async fn mdbook_page(request: app::HttpRequest) -> ResultPage<Markup, FatalError
Page::new() Page::new()
.with_title(title) .with_title(title)
.with_context(InContextOp::AddMetadata("theme-color", "#ffffff")) .with_context(InContextOp::AddMetadata("theme-color", "#ffffff"))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/css/variables.css")) StyleSheet::located("/doc/css/variables.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/css/general.css")) StyleSheet::located("/doc/css/general.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/css/chrome.css")) StyleSheet::located("/doc/css/chrome.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add( StyleSheet::located("/doc/css/print.css").for_media(TargetMedia::Print)
StyleSheet::located("/doc/css/print.css").for_media(TargetMedia::Print)
)
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/FontAwesome/css/font-awesome.css")) StyleSheet::located("/doc/FontAwesome/css/font-awesome.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/fonts/fonts.css")) StyleSheet::located("/doc/fonts/fonts.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/highlight.css")) StyleSheet::located("/doc/highlight.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/tomorrow-night.css")) StyleSheet::located("/doc/tomorrow-night.css")
)) ))
.with_context(InContextOp::StyleSheet( .with_context(InContextOp::AddStyleSheet(
AssetsOp::<StyleSheet>::Add(StyleSheet::located("/doc/ayu-highlight.css")) StyleSheet::located("/doc/ayu-highlight.css")
)) ))
.add_to( .add_to(
"region-content", "region-content",