diff --git a/packages/mrml-core/src/helper/sort.rs b/packages/mrml-core/src/helper/sort.rs index 1d3920ff..6d1cf9db 100644 --- a/packages/mrml-core/src/helper/sort.rs +++ b/packages/mrml-core/src/helper/sort.rs @@ -1,5 +1,5 @@ use std::cmp::Ordering; pub fn sort_by_key(a: &(&String, V), b: &(&String, V)) -> Ordering { - a.0.partial_cmp(b.0).unwrap() + a.0.cmp(b.0) } diff --git a/packages/mrml-core/src/mj_carousel/render.rs b/packages/mrml-core/src/mj_carousel/render.rs index a3583044..1428cb73 100644 --- a/packages/mrml-core/src/mj_carousel/render.rs +++ b/packages/mrml-core/src/mj_carousel/render.rs @@ -215,13 +215,13 @@ impl<'root> Renderer<'root, MjCarousel, MjCarouselExtra> { self.render_controls( "previous", - self.attribute("left-icon").unwrap(), + self.attribute("left-icon").unwrap_or(DEFAULT_LEFT_ICON), &mut cursor.buffer, )?; self.render_images(cursor)?; self.render_controls( "next", - self.attribute("right-icon").unwrap(), + self.attribute("right-icon").unwrap_or(DEFAULT_RIGHT_ICON), &mut cursor.buffer, )?; @@ -271,7 +271,7 @@ impl<'root> Renderer<'root, MjCarousel, MjCarouselExtra> { .add_content("display: table-cell !important;") .add_content(format!( "width: {} !important;", - self.attribute("icon-width").unwrap() + self.attribute("icon-width").unwrap_or(DEFAULT_ICON_WIDTH) )) .to_string(), Style::default() @@ -340,7 +340,8 @@ impl<'root> Renderer<'root, MjCarousel, MjCarouselExtra> { style.push( base.add_content(format!( "border-color: {} !important;", - self.attribute("tb-selected-border-color").unwrap() + self.attribute("tb-selected-border-color") + .unwrap_or(DEFAULT_TB_SELECTED_BORDER_COLOR) )) .to_string(), ); @@ -368,7 +369,8 @@ impl<'root> Renderer<'root, MjCarousel, MjCarouselExtra> { .add_selector(".mj-carousel-thumbnail:hover") .add_content(format!( "border-color: {} !important;", - self.attribute("tb-hover-border-color").unwrap() + self.attribute("tb-hover-border-color") + .unwrap_or(DEFAULT_TB_HOVER_BORDER_COLOR) )) .to_string(), ); @@ -406,19 +408,25 @@ impl<'root> Renderer<'root, MjCarousel, MjCarouselExtra> { } } +const DEFAULT_ICON_WIDTH: &str = "44px"; +const DEFAULT_LEFT_ICON: &str = "https://i.imgur.com/xTh3hln.png"; +const DEFAULT_RIGHT_ICON: &str = "https://i.imgur.com/os7o9kz.png"; +const DEFAULT_TB_HOVER_BORDER_COLOR: &str = "#fead0d"; +const DEFAULT_TB_SELECTED_BORDER_COLOR: &str = "#cccccc"; + impl<'root> Render<'root> for Renderer<'root, MjCarousel, MjCarouselExtra> { fn default_attribute(&self, name: &str) -> Option<&'static str> { match name { "align" => Some("center"), "border-radius" => Some("6px"), - "icon-width" => Some("44px"), - "left-icon" => Some("https://i.imgur.com/xTh3hln.png"), - "right-icon" => Some("https://i.imgur.com/os7o9kz.png"), + "icon-width" => Some(DEFAULT_ICON_WIDTH), + "left-icon" => Some(DEFAULT_LEFT_ICON), + "right-icon" => Some(DEFAULT_RIGHT_ICON), "thumbnails" => Some("visible"), "tb-border" => Some("2px solid transparent"), "tb-border-radius" => Some("6px"), - "tb-hover-border-color" => Some("#fead0d"), - "tb-selected-border-color" => Some("#cccccc"), + "tb-hover-border-color" => Some(DEFAULT_TB_HOVER_BORDER_COLOR), + "tb-selected-border-color" => Some(DEFAULT_TB_SELECTED_BORDER_COLOR), _ => None, } } diff --git a/packages/mrml-core/src/mj_divider/render.rs b/packages/mrml-core/src/mj_divider/render.rs index abe6a01e..00e731b7 100644 --- a/packages/mrml-core/src/mj_divider/render.rs +++ b/packages/mrml-core/src/mj_divider/render.rs @@ -8,9 +8,12 @@ impl<'root> Renderer<'root, MjDivider, ()> { "border-top", format!( "{} {} {}", - self.attribute("border-style").unwrap(), - self.attribute("border-width").unwrap(), - self.attribute("border-color").unwrap() + self.attribute("border-style") + .unwrap_or(DEFAULT_BORDER_STYLE), + self.attribute("border-width") + .unwrap_or(DEFAULT_BORDER_WIDTH), + self.attribute("border-color") + .unwrap_or(DEFAULT_BORDER_COLOR) ), ) .add_style("font-size", "1px") @@ -27,16 +30,16 @@ impl<'root> Renderer<'root, MjDivider, ()> { fn set_style_outlook<'t>(&self, tag: Tag<'t>) -> Tag<'t> { self.set_style_p_without_width(tag) - .add_style("width", self.get_outlook_width().to_string()) + .maybe_add_style("width", self.get_outlook_width().map(|v| v.to_string())) } - fn get_outlook_width(&self) -> Pixel { - let container_width = self.container_width.as_ref().unwrap(); + fn get_outlook_width(&self) -> Option { + let container_width = self.container_width.as_ref()?; let padding_horizontal = self.get_padding_horizontal(); let width = self .attribute_as_size("width") .unwrap_or_else(|| Size::percent(100.0)); - match width { + Some(match width { Size::Percent(value) => { let effective = container_width.value() - padding_horizontal.value(); let multiplier = value.value() / 100.0; @@ -44,14 +47,14 @@ impl<'root> Renderer<'root, MjDivider, ()> { } Size::Pixel(value) => value, _ => Pixel::new(container_width.value() - padding_horizontal.value()), - } + }) } fn render_after(&self, buf: &mut RenderBuffer) -> Result<(), Error> { let table = self .set_style_outlook(Tag::table_presentation()) .add_attribute("align", "center") - .add_attribute("width", self.get_outlook_width().to_string()); + .maybe_add_attribute("width", self.get_outlook_width().map(|v| v.to_string())); let tr = Tag::tr(); let td = Tag::td() .add_style("height", "0") @@ -69,13 +72,17 @@ impl<'root> Renderer<'root, MjDivider, ()> { } } +const DEFAULT_BORDER_COLOR: &str = "#000000"; +const DEFAULT_BORDER_STYLE: &str = "solid"; +const DEFAULT_BORDER_WIDTH: &str = "4px"; + impl<'root> Render<'root> for Renderer<'root, MjDivider, ()> { fn default_attribute(&self, key: &str) -> Option<&'static str> { match key { "align" => Some("center"), - "border-color" => Some("#000000"), - "border-style" => Some("solid"), - "border-width" => Some("4px"), + "border-color" => Some(DEFAULT_BORDER_COLOR), + "border-style" => Some(DEFAULT_BORDER_STYLE), + "border-width" => Some(DEFAULT_BORDER_WIDTH), "padding" => Some("10px 25px"), "width" => Some("100%"), _ => None, diff --git a/packages/mrml-core/src/mj_group/render.rs b/packages/mrml-core/src/mj_group/render.rs index aa93b5d3..7b15cdcc 100644 --- a/packages/mrml-core/src/mj_group/render.rs +++ b/packages/mrml-core/src/mj_group/render.rs @@ -5,8 +5,8 @@ use crate::helper::size::{Pixel, Size}; use crate::prelude::render::*; impl<'root> Renderer<'root, MjGroup, ()> { - fn current_width(&self) -> Pixel { - let parent_width = self.container_width.as_ref().unwrap(); + fn current_width(&self) -> Option { + let parent_width = self.container_width.as_ref()?; let non_raw_siblings = self.non_raw_siblings(); let borders = self.get_border_horizontal(); let paddings = self.get_padding_horizontal(); @@ -24,11 +24,11 @@ impl<'root> Renderer<'root, MjGroup, ()> { let container_width = self .attribute_as_size("width") .unwrap_or_else(|| Size::pixel(parent_width.value() / (non_raw_siblings as f32))); - if let Size::Percent(pc) = container_width { + Some(if let Size::Percent(pc) = container_width { Pixel::new((parent_width.value() * pc.value() / 100.0) - all_paddings) } else { Pixel::new(container_width.value() - all_paddings) - } + }) } fn non_raw_siblings(&self) -> usize { @@ -71,7 +71,7 @@ impl<'root> Renderer<'root, MjGroup, ()> { 'a: 't, { tag.maybe_add_style("vertical-align", self.attribute("vertical-align")) - .add_style("width", self.current_width().to_string()) + .maybe_add_style("width", self.current_width().map(|v| v.to_string())) } fn render_children(&self, cursor: &mut RenderCursor) -> Result<(), Error> { @@ -89,7 +89,7 @@ impl<'root> Renderer<'root, MjGroup, ()> { renderer.set_index(index); renderer.set_siblings(siblings); renderer.set_raw_siblings(raw_siblings); - renderer.set_container_width(Some(current_width)); + renderer.set_container_width(current_width); renderer.add_extra_attribute("mobile-width", "mobile-width"); if child.is_raw() { renderer.render(cursor)?; @@ -139,7 +139,7 @@ impl<'root> Render<'root> for Renderer<'root, MjGroup, ()> { } fn get_width(&self) -> Option { - Some(Size::Pixel(self.current_width())) + self.current_width().map(Size::Pixel) } fn set_container_width(&mut self, width: Option) { diff --git a/packages/mrml-core/src/mj_hero/render.rs b/packages/mrml-core/src/mj_hero/render.rs index 6db1e728..0720993a 100644 --- a/packages/mrml-core/src/mj_hero/render.rs +++ b/packages/mrml-core/src/mj_hero/render.rs @@ -247,7 +247,10 @@ impl<'root> Renderer<'root, MjHero, ()> { fn render_mode_fixed(&self, cursor: &mut RenderCursor) -> Result<(), Error> { // has a default value - let height = self.attribute_as_pixel("height").unwrap().value(); + let height = self + .attribute_as_pixel("height") + .map(|v| v.value()) + .unwrap_or(0.0); let padding = self.get_padding_vertical().value(); let height = height - padding; let td = self diff --git a/packages/mrml-core/src/mj_section/render.rs b/packages/mrml-core/src/mj_section/render.rs index eed622d5..733b7561 100644 --- a/packages/mrml-core/src/mj_section/render.rs +++ b/packages/mrml-core/src/mj_section/render.rs @@ -22,8 +22,9 @@ pub trait WithMjSectionBackground<'root>: Render<'root> { where 'root: 'a, { - // can be unwraped because has default value - let position = self.attribute("background-position").unwrap(); + let position = self + .attribute("background-position") + .unwrap_or(DEFAULT_BACKGROUND_POSITION); let mut positions = position.split_whitespace(); if let Some(first) = positions.next() { if let Some(second) = positions.next() { @@ -70,12 +71,17 @@ pub trait WithMjSectionBackground<'root>: Render<'root> { format!( "{} / {}", self.get_background_position_str(), - self.attribute("background-size").unwrap() + self.attribute("background-size") + .unwrap_or(DEFAULT_BACKGROUND_SIZE) ) .into(), ); // has default value - res.push(self.attribute("background-repeat").unwrap().into()); + res.push( + self.attribute("background-repeat") + .unwrap_or(DEFAULT_BACKGROUND_REPEAT) + .into(), + ); } if res.is_empty() { @@ -524,12 +530,16 @@ impl<'root> SectionLikeRender<'root> for Renderer<'root, MjSection, ()> { } } +const DEFAULT_BACKGROUND_POSITION: &str = "top center"; +const DEFAULT_BACKGROUND_REPEAT: &str = "repeat"; +const DEFAULT_BACKGROUND_SIZE: &str = "auto"; + impl<'root> Render<'root> for Renderer<'root, MjSection, ()> { fn default_attribute(&self, name: &str) -> Option<&'static str> { match name { - "background-position" => Some("top center"), - "background-repeat" => Some("repeat"), - "background-size" => Some("auto"), + "background-position" => Some(DEFAULT_BACKGROUND_POSITION), + "background-repeat" => Some(DEFAULT_BACKGROUND_REPEAT), + "background-size" => Some(DEFAULT_BACKGROUND_SIZE), "direction" => Some("ltr"), "padding" => Some("20px 0"), "text-align" => Some("center"),