mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Introduce #[css(if_empty = "…", iterable)]
This commit is contained in:
parent
92f116a95c
commit
90b23963b7
4 changed files with 48 additions and 80 deletions
|
@ -83,10 +83,6 @@
|
||||||
need_animatable=need_animatable, **kwargs)">
|
need_animatable=need_animatable, **kwargs)">
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
% if allow_empty:
|
|
||||||
use std::fmt::{self, Write};
|
|
||||||
use style_traits::{CssWriter, Separator, ToCss};
|
|
||||||
% endif
|
|
||||||
|
|
||||||
pub mod single_value {
|
pub mod single_value {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
@ -120,23 +116,22 @@
|
||||||
use values::computed::ComputedVecIter;
|
use values::computed::ComputedVecIter;
|
||||||
|
|
||||||
/// The computed value, effectively a list of single values.
|
/// The computed value, effectively a list of single values.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
|
||||||
% if need_animatable or animation_value_type == "ComputedValue":
|
|
||||||
#[derive(Animate, ComputeSquaredDistance)]
|
|
||||||
% endif
|
|
||||||
% if not allow_empty:
|
|
||||||
% if separator == "Comma":
|
% if separator == "Comma":
|
||||||
#[css(comma)]
|
#[css(comma)]
|
||||||
% endif
|
% endif
|
||||||
#[derive(ToCss)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
|
% if need_animatable or animation_value_type == "ComputedValue":
|
||||||
|
#[derive(Animate, ComputeSquaredDistance)]
|
||||||
% endif
|
% endif
|
||||||
pub struct T(
|
pub struct T(
|
||||||
|
% if not allow_empty:
|
||||||
|
#[css(iterable)]
|
||||||
|
% else:
|
||||||
|
#[css(if_empty = "none", iterable)]
|
||||||
|
% endif
|
||||||
% if allow_empty and allow_empty != "NotInitial":
|
% if allow_empty and allow_empty != "NotInitial":
|
||||||
pub Vec<single_value::T>,
|
pub Vec<single_value::T>,
|
||||||
% else:
|
% else:
|
||||||
% if not allow_empty:
|
|
||||||
#[css(iterable)]
|
|
||||||
% endif
|
|
||||||
pub SmallVec<[single_value::T; 1]>,
|
pub SmallVec<[single_value::T; 1]>,
|
||||||
% endif
|
% endif
|
||||||
);
|
);
|
||||||
|
@ -165,63 +160,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
% if allow_empty:
|
|
||||||
impl ToCss for computed_value::T {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
let mut iter = self.0.iter();
|
|
||||||
if let Some(val) = iter.next() {
|
|
||||||
val.to_css(dest)?;
|
|
||||||
} else {
|
|
||||||
return dest.write_str("none");
|
|
||||||
}
|
|
||||||
for i in iter {
|
|
||||||
dest.write_str(::style_traits::${separator}::separator())?;
|
|
||||||
i.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
/// The specified value of ${name}.
|
/// The specified value of ${name}.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
|
||||||
% if not allow_empty:
|
|
||||||
% if separator == "Comma":
|
% if separator == "Comma":
|
||||||
#[css(comma)]
|
#[css(comma)]
|
||||||
% endif
|
% endif
|
||||||
#[derive(ToCss)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
% endif
|
|
||||||
pub struct SpecifiedValue(
|
pub struct SpecifiedValue(
|
||||||
% if not allow_empty:
|
% if not allow_empty:
|
||||||
#[css(iterable)]
|
#[css(iterable)]
|
||||||
|
% else:
|
||||||
|
#[css(if_empty = "none", iterable)]
|
||||||
% endif
|
% endif
|
||||||
pub Vec<single_value::SpecifiedValue>,
|
pub Vec<single_value::SpecifiedValue>,
|
||||||
);
|
);
|
||||||
|
|
||||||
% if allow_empty:
|
|
||||||
impl ToCss for SpecifiedValue {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
let mut iter = self.0.iter();
|
|
||||||
if let Some(val) = iter.next() {
|
|
||||||
val.to_css(dest)?;
|
|
||||||
} else {
|
|
||||||
return dest.write_str("none");
|
|
||||||
}
|
|
||||||
for i in iter {
|
|
||||||
dest.write_str(::style_traits::${separator}::separator())?;
|
|
||||||
i.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
% if allow_empty and allow_empty != "NotInitial":
|
% if allow_empty and allow_empty != "NotInitial":
|
||||||
computed_value::T(vec![])
|
computed_value::T(vec![])
|
||||||
|
|
|
@ -736,9 +736,12 @@ pub enum VariantAlternates {
|
||||||
HistoricalForms,
|
HistoricalForms,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
/// List of Variant Alternates
|
/// List of Variant Alternates
|
||||||
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
|
pub struct VariantAlternatesList(
|
||||||
|
#[css(if_empty = "normal", iterable)]
|
||||||
|
pub Box<[VariantAlternates]>,
|
||||||
|
);
|
||||||
|
|
||||||
impl VariantAlternatesList {
|
impl VariantAlternatesList {
|
||||||
/// Returns the length of all variant alternates.
|
/// Returns the length of all variant alternates.
|
||||||
|
@ -759,25 +762,6 @@ impl VariantAlternatesList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for VariantAlternatesList {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
if self.0.is_empty() {
|
|
||||||
return dest.write_str("normal");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut iter = self.0.iter();
|
|
||||||
iter.next().unwrap().to_css(dest)?;
|
|
||||||
for alternate in iter {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
alternate.to_css(dest)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||||
/// Control over the selection of these alternate glyphs
|
/// Control over the selection of these alternate glyphs
|
||||||
pub enum FontVariantAlternates {
|
pub enum FontVariantAlternates {
|
||||||
|
|
|
@ -150,6 +150,20 @@ fn derive_single_field_expr(
|
||||||
where_clause: &mut WhereClause,
|
where_clause: &mut WhereClause,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
if attrs.iterable {
|
if attrs.iterable {
|
||||||
|
if let Some(if_empty) = attrs.if_empty {
|
||||||
|
return quote! {
|
||||||
|
{
|
||||||
|
let mut iter = #field.iter().peekable();
|
||||||
|
if iter.peek().is_none() {
|
||||||
|
writer.item(&::style_traits::values::Verbatim(#if_empty))?;
|
||||||
|
} else {
|
||||||
|
for item in iter {
|
||||||
|
writer.item(&item)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
quote! {
|
quote! {
|
||||||
for item in #field.iter() {
|
for item in #field.iter() {
|
||||||
writer.item(&item)?;
|
writer.item(&item)?;
|
||||||
|
@ -186,6 +200,7 @@ pub struct CssVariantAttrs {
|
||||||
#[darling(attributes(css), default)]
|
#[darling(attributes(css), default)]
|
||||||
#[derive(Default, FromField)]
|
#[derive(Default, FromField)]
|
||||||
struct CssFieldAttrs {
|
struct CssFieldAttrs {
|
||||||
|
if_empty: Option<String>,
|
||||||
ignore_bound: bool,
|
ignore_bound: bool,
|
||||||
iterable: bool,
|
iterable: bool,
|
||||||
skip: bool,
|
skip: bool,
|
||||||
|
|
|
@ -27,6 +27,8 @@ use std::fmt::{self, Write};
|
||||||
/// * if `#[css(iterable)]` is found on a function variant, that variant needs
|
/// * if `#[css(iterable)]` is found on a function variant, that variant needs
|
||||||
/// to have a single member, and that member needs to be iterable. The
|
/// to have a single member, and that member needs to be iterable. The
|
||||||
/// iterable will be serialized as the arguments for the function;
|
/// iterable will be serialized as the arguments for the function;
|
||||||
|
/// * an iterable field can also be annotated with `#[css(if_empty = "foo")]`
|
||||||
|
/// to print `"foo"` if the iterator is empty;
|
||||||
/// * if `#[css(dimension)]` is found on a variant, that variant needs
|
/// * if `#[css(dimension)]` is found on a variant, that variant needs
|
||||||
/// to have a single member. The variant would be serialized as a CSS
|
/// to have a single member. The variant would be serialized as a CSS
|
||||||
/// dimension token, like: <member><identifier>;
|
/// dimension token, like: <member><identifier>;
|
||||||
|
@ -210,6 +212,21 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper type that implements `ToCss` by printing its inner field.
|
||||||
|
pub struct Verbatim<'a, T>(pub &'a T)
|
||||||
|
where
|
||||||
|
T: ?Sized + 'a;
|
||||||
|
|
||||||
|
impl<'a, T> ToCss for Verbatim<'a, T>
|
||||||
|
where
|
||||||
|
T: AsRef<str> + ?Sized + 'a,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: Write {
|
||||||
|
dest.write_str(self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
/// Type used as the associated type in the `OneOrMoreSeparated` trait on a
|
||||||
/// type to indicate that a serialized list of elements of this type is
|
/// type to indicate that a serialized list of elements of this type is
|
||||||
/// separated by commas.
|
/// separated by commas.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue