///|
pub struct GridTemplateAreas {
css : String
} derive(Eq, Debug)
///|
pub struct ContainerNames {
css : String
} derive(Eq, Debug)
///|
pub struct MaskImage {
css : String
} derive(Eq, Debug)
///|
pub struct MaskImageList {
css : String
} derive(Eq, Debug)
///|
pub struct PositionList {
css : String
} derive(Eq, Debug)
///|
pub struct RepeatStyleList {
css : String
} derive(Eq, Debug)
///|
pub struct BackgroundSizeList {
css : String
} derive(Eq, Debug)
///|
pub struct ClipPath {
css : String
} derive(Eq, Debug)
///|
pub struct ContentValue {
css : String
} derive(Eq, Debug)
///|
pub struct AnchorName {
css : String
} derive(Eq, Debug)
///|
pub struct AnchorNames {
css : String
} derive(Eq, Debug)
///|
pub struct PositionAnchor {
css : String
} derive(Eq, Debug)
///|
pub(all) enum PositionAreaHorizontal {
AreaLeft
AreaCenter
AreaRight
AreaInlineStart
AreaInlineEnd
} derive(Eq, Debug)
///|
pub(all) enum PositionAreaVertical {
AreaTop
AreaCenterVertical
AreaBottom
AreaBlockStart
AreaBlockEnd
} derive(Eq, Debug)
///|
pub struct PositionArea {
css : String
} derive(Eq, Debug)
///|
pub(all) enum PositionTryTactic {
TryFlipBlock
TryFlipInline
TryFlipStart
} derive(Eq, Debug)
///|
pub struct PositionTryFallback {
css : String
} derive(Eq, Debug)
///|
pub struct PositionTryFallbacks {
css : String
} derive(Eq, Debug)
///|
pub(all) enum PositionTryOrder {
TryOrderNormal
TryOrderMostWidth
TryOrderMostHeight
TryOrderMostBlockSize
TryOrderMostInlineSize
} derive(Eq, Debug)
///|
pub struct PositionTryValue {
css : String
} derive(Eq, Debug)
///|
pub struct ViewTransitionName {
css : String
} derive(Eq, Debug)
///|
pub struct ViewTransitionClass {
css : String
} derive(Eq, Debug)
///|
fn modern_invalid(label : String) -> String {
error_css(EmptyValue(label))
}
///|
fn modern_ident(value : String, label : String) -> String {
let value = value.trim().to_owned()
if valid_name_part(value) {
value
} else {
modern_invalid(label)
}
}
///|
fn modern_dashed_ident(value : String, label : String) -> String {
let value = value.trim().to_owned()
let identifier = if value.has_prefix("--") {
value[2:].to_owned()
} else {
value
}
if valid_name_part(identifier) {
"--" + identifier
} else {
modern_invalid(label)
}
}
///|
fn quoted_css_string(value : String, label : String) -> String {
if value.contains("\u0000") {
modern_invalid(label)
} else {
"\"" +
value
.replace_all(old="\\", new="\\\\")
.replace_all(old="\"", new="\\\"")
.replace_all(old="\n", new="\\a ")
.replace_all(old="\r", new="\\d ")
.replace_all(old="\u000c", new="\\c ") +
"\""
}
}
///|
pub fn authored_grid_template_areas(
rows : Array[Array[String]],
) -> GridTemplateAreas {
if rows.is_empty() || rows[0].is_empty() {
return { css: modern_invalid("grid-template-areas"), }
}
let columns = rows[0].length()
let rendered : Array[String] = []
for row in rows {
if row.length() != columns ||
row.any(cell => cell != "." && !valid_name_part(cell)) {
return { css: modern_invalid("grid-template-areas"), }
}
rendered.push(quoted_css_string(row.join(" "), "grid-template-areas"))
}
{ css: rendered.join(" "), }
}
///|
pub fn authored_container_names(values : Array[String]) -> ContainerNames {
if values.is_empty() {
{ css: modern_invalid("container-name"), }
} else {
{
css: values.map(value => modern_ident(value, "container-name")).join(" "),
}
}
}
///|
pub fn authored_mask_image_url(value : Url) -> MaskImage {
{ css: value.to_css(), }
}
///|
pub fn authored_mask_images(values : Array[MaskImage]) -> MaskImageList {
if values.is_empty() {
{ css: modern_invalid("mask-image"), }
} else {
{ css: values.map(value => value.css).join(", "), }
}
}
///|
pub fn authored_positions(values : Array[Position]) -> PositionList {
if values.is_empty() {
{ css: modern_invalid("position-list"), }
} else {
{ css: values.map(value => value.to_css()).join(", "), }
}
}
///|
pub fn authored_repeat_styles(values : Array[RepeatStyle]) -> RepeatStyleList {
if values.is_empty() {
{ css: modern_invalid("repeat-style-list"), }
} else {
{ css: values.map(RepeatStyle::to_css).join(", "), }
}
}
///|
pub fn authored_background_sizes(
values : Array[BackgroundSize],
) -> BackgroundSizeList {
if values.is_empty() {
{ css: modern_invalid("background-size-list"), }
} else {
{ css: values.map(value => value.to_css()).join(", "), }
}
}
///|
pub fn authored_clip_path_circle(
radius : LengthPercentage,
center~ : Position? = None,
) -> ClipPath {
let center_css = match center {
Some(value) => " at " + value.to_css()
None => ""
}
{ css: "circle(" + radius.to_css() + center_css + ")", }
}
///|
pub fn authored_clip_path_url(value : Url) -> ClipPath {
{ css: value.to_css(), }
}
///|
pub fn authored_content_text(value : String) -> ContentValue {
{ css: quoted_css_string(value, "content"), }
}
///|
pub fn authored_content_none() -> ContentValue {
{ css: "none", }
}
///|
pub fn authored_anchor_name(value : String) -> AnchorName {
{ css: modern_dashed_ident(value, "anchor-name"), }
}
///|
pub fn authored_anchor_names(values : Array[AnchorName]) -> AnchorNames {
if values.is_empty() {
{ css: modern_invalid("anchor-name"), }
} else {
{ css: values.map(value => value.css).join(", "), }
}
}
///|
pub fn authored_position_anchor(value : AnchorName) -> PositionAnchor {
{ css: value.css, }
}
///|
fn PositionAreaHorizontal::to_css(self : PositionAreaHorizontal) -> String {
match self {
AreaLeft => "left"
AreaCenter => "center"
AreaRight => "right"
AreaInlineStart => "inline-start"
AreaInlineEnd => "inline-end"
}
}
///|
fn PositionAreaVertical::to_css(self : PositionAreaVertical) -> String {
match self {
AreaTop => "top"
AreaCenterVertical => "center"
AreaBottom => "bottom"
AreaBlockStart => "block-start"
AreaBlockEnd => "block-end"
}
}
///|
pub fn authored_position_area(
horizontal : PositionAreaHorizontal,
vertical : PositionAreaVertical,
) -> PositionArea {
{ css: horizontal.to_css() + " " + vertical.to_css(), }
}
///|
fn PositionTryTactic::to_css(self : PositionTryTactic) -> String {
match self {
TryFlipBlock => "flip-block"
TryFlipInline => "flip-inline"
TryFlipStart => "flip-start"
}
}
///|
pub fn authored_position_try_named(value : String) -> PositionTryFallback {
{ css: modern_dashed_ident(value, "position-try-fallback"), }
}
///|
pub fn authored_position_try_area(value : PositionArea) -> PositionTryFallback {
{ css: value.css, }
}
///|
pub fn authored_position_try_tactic(
value : PositionTryTactic,
) -> PositionTryFallback {
{ css: value.to_css(), }
}
///|
pub fn authored_position_try_fallbacks(
values : Array[PositionTryFallback],
) -> PositionTryFallbacks {
if values.is_empty() {
{ css: modern_invalid("position-try-fallbacks"), }
} else {
{ css: values.map(value => value.css).join(", "), }
}
}
///|
pub fn PositionTryOrder::to_css(self : PositionTryOrder) -> String {
match self {
TryOrderNormal => "normal"
TryOrderMostWidth => "most-width"
TryOrderMostHeight => "most-height"
TryOrderMostBlockSize => "most-block-size"
TryOrderMostInlineSize => "most-inline-size"
}
}
///|
pub fn authored_position_try_value(
fallbacks : PositionTryFallbacks,
order~ : PositionTryOrder? = None,
) -> PositionTryValue {
{
css: match order {
Some(value) => value.to_css() + " " + fallbacks.css
None => fallbacks.css
},
}
}
///|
pub fn authored_view_transition_name(value : String) -> ViewTransitionName {
{ css: modern_ident(value, "view-transition-name"), }
}
///|
pub fn authored_view_transition_class(value : String) -> ViewTransitionClass {
{ css: modern_ident(value, "view-transition-class"), }
}
///|
pub fn FilterList::to_css(self : FilterList) -> String {
self.expression.to_css()
}
///|
pub fn BoxShadowList::to_css(self : BoxShadowList) -> String {
self.expression.to_css()
}
///|
pub fn TextShadowList::to_css(self : TextShadowList) -> String {
self.expression.to_css()
}
///|
pub fn GridTemplateAreas::to_css(self : GridTemplateAreas) -> String {
self.css
}
///|
pub fn ContainerNames::to_css(self : ContainerNames) -> String {
self.css
}
///|
pub fn MaskImageList::to_css(self : MaskImageList) -> String {
self.css
}
///|
pub fn PositionList::to_css(self : PositionList) -> String {
self.css
}
///|
pub fn RepeatStyleList::to_css(self : RepeatStyleList) -> String {
self.css
}
///|
pub fn BackgroundSizeList::to_css(self : BackgroundSizeList) -> String {
self.css
}
///|
pub fn ClipPath::to_css(self : ClipPath) -> String {
self.css
}
///|
pub fn ContentValue::to_css(self : ContentValue) -> String {
self.css
}
///|
pub fn AnchorNames::to_css(self : AnchorNames) -> String {
self.css
}
///|
pub fn PositionAnchor::to_css(self : PositionAnchor) -> String {
self.css
}
///|
pub fn PositionArea::to_css(self : PositionArea) -> String {
self.css
}
///|
pub fn PositionTryFallbacks::to_css(self : PositionTryFallbacks) -> String {
self.css
}
///|
pub fn PositionTryValue::to_css(self : PositionTryValue) -> String {
self.css
}
///|
pub fn ViewTransitionName::to_css(self : ViewTransitionName) -> String {
self.css
}
///|
pub fn ViewTransitionClass::to_css(self : ViewTransitionClass) -> String {
self.css
}