mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #19851 - emilio:content-distribution, r=nox
style: Update css-align to the spec (mostly) This is on top of #19850. This fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1430817, and updates us to the current version of the css-align spec. The only remaining change is the justify-items: auto FIXME. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19851) <!-- Reviewable:end -->
This commit is contained in:
commit
33818f6b40
6 changed files with 361 additions and 272 deletions
|
@ -69,8 +69,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
% else:
|
% else:
|
||||||
${helpers.predefined_type(name="justify-content",
|
${helpers.predefined_type(name="justify-content",
|
||||||
type="ContentDistribution",
|
type="JustifyContent",
|
||||||
initial_value="specified::ContentDistribution::normal()",
|
initial_value="specified::JustifyContent(specified::ContentDistribution::normal())",
|
||||||
spec="https://drafts.csswg.org/css-align/#propdef-justify-content",
|
spec="https://drafts.csswg.org/css-align/#propdef-justify-content",
|
||||||
extra_prefixes="webkit",
|
extra_prefixes="webkit",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
|
@ -90,8 +90,8 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
% else:
|
% else:
|
||||||
${helpers.predefined_type(name="align-content",
|
${helpers.predefined_type(name="align-content",
|
||||||
type="ContentDistribution",
|
type="AlignContent",
|
||||||
initial_value="specified::ContentDistribution::normal()",
|
initial_value="specified::AlignContent(specified::ContentDistribution::normal())",
|
||||||
spec="https://drafts.csswg.org/css-align/#propdef-align-content",
|
spec="https://drafts.csswg.org/css-align/#propdef-align-content",
|
||||||
extra_prefixes="webkit",
|
extra_prefixes="webkit",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
|
@ -138,15 +138,15 @@ ${helpers.predefined_type("flex-shrink", "NonNegativeNumber",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
% else:
|
% else:
|
||||||
${helpers.predefined_type(name="align-self",
|
${helpers.predefined_type(name="align-self",
|
||||||
type="SelfAlignment",
|
type="AlignSelf",
|
||||||
initial_value="specified::SelfAlignment::auto()",
|
initial_value="specified::AlignSelf(specified::SelfAlignment::auto())",
|
||||||
spec="https://drafts.csswg.org/css-align/#align-self-property",
|
spec="https://drafts.csswg.org/css-align/#align-self-property",
|
||||||
extra_prefixes="webkit",
|
extra_prefixes="webkit",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
|
|
||||||
${helpers.predefined_type(name="justify-self",
|
${helpers.predefined_type(name="justify-self",
|
||||||
type="SelfAlignment",
|
type="JustifySelf",
|
||||||
initial_value="specified::SelfAlignment::auto()",
|
initial_value="specified::JustifySelf(specified::SelfAlignment::auto())",
|
||||||
spec="https://drafts.csswg.org/css-align/#justify-self-property",
|
spec="https://drafts.csswg.org/css-align/#justify-self-property",
|
||||||
animation_value_type="discrete")}
|
animation_value_type="discrete")}
|
||||||
|
|
||||||
|
|
|
@ -615,33 +615,44 @@
|
||||||
<%helpers:shorthand name="place-content" sub_properties="align-content justify-content"
|
<%helpers:shorthand name="place-content" sub_properties="align-content justify-content"
|
||||||
spec="https://drafts.csswg.org/css-align/#propdef-place-content"
|
spec="https://drafts.csswg.org/css-align/#propdef-place-content"
|
||||||
products="gecko">
|
products="gecko">
|
||||||
use values::specified::align::{ContentDistribution, FallbackAllowed};
|
use values::specified::align::{AlignContent, JustifyContent, ContentDistribution, AxisDirection};
|
||||||
|
|
||||||
pub fn parse_value<'i, 't>(
|
pub fn parse_value<'i, 't>(
|
||||||
_: &ParserContext,
|
_: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Longhands, ParseError<'i>> {
|
) -> Result<Longhands, ParseError<'i>> {
|
||||||
let align = ContentDistribution::parse_with_fallback(input, FallbackAllowed::No)?;
|
let align_content =
|
||||||
if align.has_extra_flags() {
|
ContentDistribution::parse(input, AxisDirection::Block)?;
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
|
||||||
}
|
let justify_content = input.try(|input| {
|
||||||
let justify =
|
ContentDistribution::parse(input, AxisDirection::Inline)
|
||||||
input.try(|input| ContentDistribution::parse_with_fallback(input, FallbackAllowed::No))
|
});
|
||||||
.unwrap_or(align);
|
|
||||||
if justify.has_extra_flags() {
|
let justify_content = match justify_content {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(err) => {
|
||||||
|
if !align_content.is_valid_on_both_axes() {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
align_content
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if align_content.has_extra_flags() || justify_content.has_extra_flags() {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
align_content: align,
|
align_content: AlignContent(align_content),
|
||||||
justify_content: justify,
|
justify_content: JustifyContent(justify_content),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||||
self.align_content.to_css(dest)?;
|
self.align_content.to_css(dest)?;
|
||||||
if self.align_content != self.justify_content {
|
if self.align_content.0 != self.justify_content.0 {
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.justify_content.to_css(dest)?;
|
self.justify_content.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
@ -653,35 +664,43 @@
|
||||||
<%helpers:shorthand name="place-self" sub_properties="align-self justify-self"
|
<%helpers:shorthand name="place-self" sub_properties="align-self justify-self"
|
||||||
spec="https://drafts.csswg.org/css-align/#place-self-property"
|
spec="https://drafts.csswg.org/css-align/#place-self-property"
|
||||||
products="gecko">
|
products="gecko">
|
||||||
use values::specified::align::SelfAlignment;
|
use values::specified::align::{AlignSelf, JustifySelf, SelfAlignment, AxisDirection};
|
||||||
use parser::Parse;
|
|
||||||
|
|
||||||
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
pub fn parse_value<'i, 't>(
|
||||||
-> Result<Longhands, ParseError<'i>> {
|
_: &ParserContext,
|
||||||
let align = SelfAlignment::parse(context, input)?;
|
input: &mut Parser<'i, 't>,
|
||||||
if align.has_extra_flags() {
|
) -> Result<Longhands, ParseError<'i>> {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
let align = SelfAlignment::parse(input, AxisDirection::Block)?;
|
||||||
}
|
let justify = input.try(|input| SelfAlignment::parse(input, AxisDirection::Inline));
|
||||||
let justify = input.try(|input| SelfAlignment::parse(context, input)).unwrap_or(align.clone());
|
|
||||||
if justify.has_extra_flags() {
|
let justify = match justify {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(err) => {
|
||||||
|
if !align.is_valid_on_both_axes() {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
align
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if justify.has_extra_flags() || align.has_extra_flags() {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
align_self: align,
|
align_self: AlignSelf(align),
|
||||||
justify_self: justify,
|
justify_self: JustifySelf(justify),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||||
if self.align_self == self.justify_self {
|
self.align_self.to_css(dest)?;
|
||||||
self.align_self.to_css(dest)
|
if self.align_self.0 != self.justify_self.0 {
|
||||||
} else {
|
|
||||||
self.align_self.to_css(dest)?;
|
|
||||||
dest.write_str(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.justify_self.to_css(dest)
|
self.justify_self.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
|
@ -11,7 +11,8 @@ use style_traits::{CssWriter, ToCss};
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
use values::specified;
|
use values::specified;
|
||||||
|
|
||||||
pub use super::specified::{AlignItems, ContentDistribution, SelfAlignment};
|
pub use super::specified::{AlignContent, JustifyContent, AlignItems, SelfAlignment};
|
||||||
|
pub use super::specified::{AlignSelf, JustifySelf};
|
||||||
|
|
||||||
/// The computed value for the `justify-items` property.
|
/// The computed value for the `justify-items` property.
|
||||||
///
|
///
|
||||||
|
|
|
@ -32,7 +32,9 @@ use super::specified;
|
||||||
pub use app_units::Au;
|
pub use app_units::Au;
|
||||||
pub use properties::animated_properties::TransitionProperty;
|
pub use properties::animated_properties::TransitionProperty;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::align::{AlignItems, ContentDistribution, SelfAlignment, JustifyItems};
|
pub use self::align::{AlignItems, AlignContent, JustifyContent, SelfAlignment, JustifyItems};
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub use self::align::{AlignSelf, JustifySelf};
|
||||||
pub use self::angle::Angle;
|
pub use self::angle::Angle;
|
||||||
pub use self::background::{BackgroundSize, BackgroundRepeat};
|
pub use self::background::{BackgroundSize, BackgroundRepeat};
|
||||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||||
|
|
|
@ -18,8 +18,7 @@ bitflags! {
|
||||||
/// Constants shared by multiple CSS Box Alignment properties
|
/// Constants shared by multiple CSS Box Alignment properties
|
||||||
///
|
///
|
||||||
/// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
|
/// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[derive(MallocSizeOf, ToComputedValue)]
|
||||||
#[derive(ToComputedValue)]
|
|
||||||
pub struct AlignFlags: u8 {
|
pub struct AlignFlags: u8 {
|
||||||
// Enumeration stored in the lower 5 bits:
|
// Enumeration stored in the lower 5 bits:
|
||||||
/// 'auto'
|
/// 'auto'
|
||||||
|
@ -70,12 +69,27 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AlignFlags {
|
||||||
|
/// Returns the enumeration value stored in the lower 5 bits.
|
||||||
|
#[inline]
|
||||||
|
fn value(&self) -> Self {
|
||||||
|
*self & !AlignFlags::FLAG_BITS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToCss for AlignFlags {
|
impl ToCss for AlignFlags {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
let s = match *self & !AlignFlags::FLAG_BITS {
|
match *self & AlignFlags::FLAG_BITS {
|
||||||
|
AlignFlags::LEGACY => dest.write_str("legacy ")?,
|
||||||
|
AlignFlags::SAFE => dest.write_str("safe ")?,
|
||||||
|
// Don't serialize "unsafe", since it's the default.
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
dest.write_str(match self.value() {
|
||||||
AlignFlags::AUTO => "auto",
|
AlignFlags::AUTO => "auto",
|
||||||
AlignFlags::NORMAL => "normal",
|
AlignFlags::NORMAL => "normal",
|
||||||
AlignFlags::START => "start",
|
AlignFlags::START => "start",
|
||||||
|
@ -94,46 +108,29 @@ impl ToCss for AlignFlags {
|
||||||
AlignFlags::SPACE_AROUND => "space-around",
|
AlignFlags::SPACE_AROUND => "space-around",
|
||||||
AlignFlags::SPACE_EVENLY => "space-evenly",
|
AlignFlags::SPACE_EVENLY => "space-evenly",
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
})
|
||||||
dest.write_str(s)?;
|
|
||||||
|
|
||||||
match *self & AlignFlags::FLAG_BITS {
|
|
||||||
AlignFlags::LEGACY => { dest.write_str(" legacy")?; }
|
|
||||||
AlignFlags::SAFE => { dest.write_str(" safe")?; }
|
|
||||||
AlignFlags::UNSAFE => { dest.write_str(" unsafe")?; }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mask for a single AlignFlags value.
|
/// An axis direction, either inline (for the `justify` properties) or block,
|
||||||
const ALIGN_ALL_BITS: u16 = structs::NS_STYLE_ALIGN_ALL_BITS as u16;
|
/// (for the `align` properties).
|
||||||
/// Number of bits to shift a fallback alignment.
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT;
|
pub enum AxisDirection {
|
||||||
|
/// Block direction.
|
||||||
|
Block,
|
||||||
|
/// Inline direction.
|
||||||
|
Inline,
|
||||||
|
}
|
||||||
|
|
||||||
/// Value of the `align-content` or `justify-content` property.
|
/// Shared value for the `align-content` and `justify-content` properties.
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-align/#content-distribution>
|
/// <https://drafts.csswg.org/css-align/#content-distribution>
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
pub struct ContentDistribution {
|
pub struct ContentDistribution {
|
||||||
primary: AlignFlags,
|
primary: AlignFlags,
|
||||||
fallback: AlignFlags,
|
// FIXME(https://github.com/w3c/csswg-drafts/issues/1002): This will need to
|
||||||
}
|
// accept fallback alignment, eventually.
|
||||||
|
|
||||||
/// Whether fallback is allowed in align-content / justify-content parsing.
|
|
||||||
///
|
|
||||||
/// This is used for the place-content shorthand, until the resolutions from [1]
|
|
||||||
/// are specified.
|
|
||||||
///
|
|
||||||
/// [1]: https://github.com/w3c/csswg-drafts/issues/1002
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
|
||||||
pub enum FallbackAllowed {
|
|
||||||
/// Allow fallback alignment.
|
|
||||||
Yes,
|
|
||||||
/// Don't allow fallback alignment.
|
|
||||||
No,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentDistribution {
|
impl ContentDistribution {
|
||||||
|
@ -143,18 +140,35 @@ impl ContentDistribution {
|
||||||
Self::new(AlignFlags::NORMAL)
|
Self::new(AlignFlags::NORMAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a value with no fallback.
|
/// The initial value 'normal'
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(flags: AlignFlags) -> Self {
|
pub fn new(primary: AlignFlags) -> Self {
|
||||||
Self::with_fallback(flags, AlignFlags::empty())
|
Self { primary }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a value including a fallback alignment.
|
fn from_bits(bits: u16) -> Self {
|
||||||
///
|
Self {
|
||||||
/// <https://drafts.csswg.org/css-align/#fallback-alignment>
|
primary: AlignFlags::from_bits_truncate(bits as u8)
|
||||||
#[inline]
|
}
|
||||||
pub fn with_fallback(primary: AlignFlags, fallback: AlignFlags) -> Self {
|
}
|
||||||
Self { primary, fallback }
|
|
||||||
|
fn as_bits(&self) -> u16 {
|
||||||
|
self.primary.bits() as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this value is valid for both axis directions.
|
||||||
|
pub fn is_valid_on_both_axes(&self) -> bool {
|
||||||
|
match self.primary.value() {
|
||||||
|
// <baseline-position> is only allowed on the block axis.
|
||||||
|
AlignFlags::BASELINE |
|
||||||
|
AlignFlags::LAST_BASELINE => false,
|
||||||
|
|
||||||
|
// left | right are only allowed on the inline axis.
|
||||||
|
AlignFlags::LEFT |
|
||||||
|
AlignFlags::RIGHT => false,
|
||||||
|
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary alignment
|
/// The primary alignment
|
||||||
|
@ -163,83 +177,119 @@ impl ContentDistribution {
|
||||||
self.primary
|
self.primary
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The fallback alignment
|
|
||||||
#[inline]
|
|
||||||
pub fn fallback(self) -> AlignFlags {
|
|
||||||
self.fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether this value has extra flags.
|
/// Whether this value has extra flags.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_extra_flags(self) -> bool {
|
pub fn has_extra_flags(self) -> bool {
|
||||||
self.primary().intersects(AlignFlags::FLAG_BITS) ||
|
self.primary().intersects(AlignFlags::FLAG_BITS)
|
||||||
self.fallback().intersects(AlignFlags::FLAG_BITS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a value for align-content / justify-content, optionally allowing
|
/// Parse a value for align-content / justify-content.
|
||||||
/// fallback.
|
pub fn parse<'i, 't>(
|
||||||
pub fn parse_with_fallback<'i, 't>(
|
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
fallback_allowed: FallbackAllowed,
|
axis: AxisDirection,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
// normal | <baseline-position>
|
// Try to parse normal first
|
||||||
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
|
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(ContentDistribution::new(value))
|
return Ok(ContentDistribution::normal());
|
||||||
}
|
}
|
||||||
|
|
||||||
// <content-distribution> followed by optional <*-position>
|
// Parse <baseline-position>, but only on the block axis.
|
||||||
if let Ok(value) = input.try(|input| parse_content_distribution(input)) {
|
if axis == AxisDirection::Block {
|
||||||
if fallback_allowed == FallbackAllowed::Yes {
|
if let Ok(value) = input.try(parse_baseline) {
|
||||||
if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input)) {
|
return Ok(ContentDistribution::new(value));
|
||||||
return Ok(ContentDistribution::with_fallback(value, fallback))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(ContentDistribution::new(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
// <*-position> followed by optional <content-distribution>
|
|
||||||
let fallback = parse_overflow_content_position(input)?;
|
|
||||||
if fallback_allowed == FallbackAllowed::Yes {
|
|
||||||
if let Ok(value) = input.try(|input| parse_content_distribution(input)) {
|
|
||||||
return Ok(ContentDistribution::with_fallback(value, fallback))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ContentDistribution::new(fallback))
|
// <content-distribution>
|
||||||
}
|
if let Ok(value) = input.try(parse_content_distribution) {
|
||||||
}
|
return Ok(ContentDistribution::new(value));
|
||||||
|
|
||||||
impl ToCss for ContentDistribution {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
self.primary().to_css(dest)?;
|
|
||||||
match self.fallback() {
|
|
||||||
AlignFlags::AUTO => {}
|
|
||||||
fallback => {
|
|
||||||
dest.write_str(" ")?;
|
|
||||||
fallback.to_css(dest)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
|
// <overflow-position>? <content-position>
|
||||||
|
let overflow_position =
|
||||||
|
input.try(parse_overflow_position)
|
||||||
|
.unwrap_or(AlignFlags::empty());
|
||||||
|
|
||||||
|
let content_position = try_match_ident_ignore_ascii_case! { input,
|
||||||
|
"start" => AlignFlags::START,
|
||||||
|
"end" => AlignFlags::END,
|
||||||
|
"flex-start" => AlignFlags::FLEX_START,
|
||||||
|
"flex-end" => AlignFlags::FLEX_END,
|
||||||
|
"center" => AlignFlags::CENTER,
|
||||||
|
"left" if axis == AxisDirection::Inline => AlignFlags::LEFT,
|
||||||
|
"right" if axis == AxisDirection::Inline => AlignFlags::RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ContentDistribution::new(content_position | overflow_position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Value for the `align-content` property.
|
||||||
impl Parse for ContentDistribution {
|
|
||||||
// normal | <baseline-position> |
|
|
||||||
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
|
|
||||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
|
||||||
Self::parse_with_fallback(input, FallbackAllowed::Yes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Value of the `align-self` or `justify-self` property.
|
|
||||||
///
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-align/#propdef-align-content>
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
|
pub struct AlignContent(pub ContentDistribution);
|
||||||
|
|
||||||
|
impl Parse for AlignContent {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
_: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
Ok(AlignContent(ContentDistribution::parse(
|
||||||
|
input,
|
||||||
|
AxisDirection::Block,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl From<u16> for AlignContent {
|
||||||
|
fn from(bits: u16) -> Self {
|
||||||
|
AlignContent(ContentDistribution::from_bits(bits))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl From<AlignContent> for u16 {
|
||||||
|
fn from(v: AlignContent) -> u16 {
|
||||||
|
v.0.as_bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Value for the `justify-content` property.
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-align/#propdef-align-content>
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
|
pub struct JustifyContent(pub ContentDistribution);
|
||||||
|
|
||||||
|
impl Parse for JustifyContent {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
_: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
Ok(JustifyContent(ContentDistribution::parse(
|
||||||
|
input,
|
||||||
|
AxisDirection::Inline,
|
||||||
|
)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl From<u16> for JustifyContent {
|
||||||
|
fn from(bits: u16) -> Self {
|
||||||
|
JustifyContent(ContentDistribution::from_bits(bits))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl From<JustifyContent> for u16 {
|
||||||
|
fn from(v: JustifyContent) -> u16 {
|
||||||
|
v.0.as_bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-align/#self-alignment>
|
/// <https://drafts.csswg.org/css-align/#self-alignment>
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
|
|
||||||
pub struct SelfAlignment(pub AlignFlags);
|
pub struct SelfAlignment(pub AlignFlags);
|
||||||
|
|
||||||
impl SelfAlignment {
|
impl SelfAlignment {
|
||||||
|
@ -249,32 +299,105 @@ impl SelfAlignment {
|
||||||
SelfAlignment(AlignFlags::AUTO)
|
SelfAlignment(AlignFlags::AUTO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether this value is valid for both axis directions.
|
||||||
|
pub fn is_valid_on_both_axes(&self) -> bool {
|
||||||
|
match self.0.value() {
|
||||||
|
// <baseline-position> is only allowed on the block axis.
|
||||||
|
AlignFlags::BASELINE |
|
||||||
|
AlignFlags::LAST_BASELINE => false,
|
||||||
|
|
||||||
|
// left | right are only allowed on the inline axis.
|
||||||
|
AlignFlags::LEFT |
|
||||||
|
AlignFlags::RIGHT => false,
|
||||||
|
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether this value has extra flags.
|
/// Whether this value has extra flags.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_extra_flags(self) -> bool {
|
pub fn has_extra_flags(self) -> bool {
|
||||||
self.0.intersects(AlignFlags::FLAG_BITS)
|
self.0.intersects(AlignFlags::FLAG_BITS)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Parse a self-alignment value on one of the axis.
|
||||||
|
pub fn parse<'i, 't>(
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
axis: AxisDirection,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
// <baseline-position>, only on the block axis.
|
||||||
|
if axis == AxisDirection::Block {
|
||||||
|
if let Ok(value) = input.try(parse_baseline) {
|
||||||
|
return Ok(SelfAlignment(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for SelfAlignment {
|
// auto | normal | stretch
|
||||||
// auto | normal | stretch | <baseline-position> |
|
if let Ok(value) = input.try(parse_auto_normal_stretch) {
|
||||||
// [ <overflow-position>? && <self-position> ]
|
|
||||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
|
||||||
// auto | normal | stretch | <baseline-position>
|
|
||||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
|
||||||
return Ok(SelfAlignment(value))
|
return Ok(SelfAlignment(value))
|
||||||
}
|
}
|
||||||
// [ <overflow-position>? && <self-position> ]
|
|
||||||
Ok(SelfAlignment(parse_overflow_self_position(input)?))
|
// <overflow-position>? <self-position>
|
||||||
|
let overflow_position =
|
||||||
|
input.try(parse_overflow_position)
|
||||||
|
.unwrap_or(AlignFlags::empty());
|
||||||
|
let self_position = parse_self_position(input, axis)?;
|
||||||
|
Ok(SelfAlignment(overflow_position | self_position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The specified value of the align-self property.
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-align/#propdef-align-self>
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
|
pub struct AlignSelf(pub SelfAlignment);
|
||||||
|
|
||||||
|
impl Parse for AlignSelf {
|
||||||
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
|
Ok(AlignSelf(SelfAlignment::parse(input, AxisDirection::Block)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for AlignSelf {
|
||||||
|
fn from(bits: u8) -> Self {
|
||||||
|
AlignSelf(SelfAlignment(AlignFlags::from_bits_truncate(bits)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AlignSelf> for u8 {
|
||||||
|
fn from(align: AlignSelf) -> u8 {
|
||||||
|
(align.0).0.bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The specified value of the justify-self property.
|
||||||
|
///
|
||||||
|
/// <https://drafts.csswg.org/css-align/#propdef-justify-self>
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
|
pub struct JustifySelf(pub SelfAlignment);
|
||||||
|
|
||||||
|
impl Parse for JustifySelf {
|
||||||
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
|
Ok(JustifySelf(SelfAlignment::parse(input, AxisDirection::Inline)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for JustifySelf {
|
||||||
|
fn from(bits: u8) -> Self {
|
||||||
|
JustifySelf(SelfAlignment(AlignFlags::from_bits_truncate(bits)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<JustifySelf> for u8 {
|
||||||
|
fn from(justify: JustifySelf) -> u8 {
|
||||||
|
(justify.0).0.bits()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Value of the `align-items` property
|
/// Value of the `align-items` property
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-align/#self-alignment>
|
/// <https://drafts.csswg.org/css-align/#self-alignment>
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToComputedValue, ToCss)]
|
|
||||||
pub struct AlignItems(pub AlignFlags);
|
pub struct AlignItems(pub AlignFlags);
|
||||||
|
|
||||||
impl AlignItems {
|
impl AlignItems {
|
||||||
|
@ -294,22 +417,28 @@ impl AlignItems {
|
||||||
|
|
||||||
impl Parse for AlignItems {
|
impl Parse for AlignItems {
|
||||||
// normal | stretch | <baseline-position> |
|
// normal | stretch | <baseline-position> |
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// <overflow-position>? <self-position>
|
||||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// normal | stretch | <baseline-position>
|
// <baseline-position>
|
||||||
if let Ok(value) = input.try(parse_normal_stretch_baseline) {
|
if let Ok(baseline) = input.try(parse_baseline) {
|
||||||
|
return Ok(AlignItems(baseline));
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal | stretch
|
||||||
|
if let Ok(value) = input.try(parse_normal_stretch) {
|
||||||
return Ok(AlignItems(value))
|
return Ok(AlignItems(value))
|
||||||
}
|
}
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// <overflow-position>? <self-position>
|
||||||
Ok(AlignItems(parse_overflow_self_position(input)?))
|
let overflow = input.try(parse_overflow_position).unwrap_or(AlignFlags::empty());
|
||||||
|
let self_position = parse_self_position(input, AxisDirection::Block)?;
|
||||||
|
Ok(AlignItems(self_position | overflow))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Value of the `justify-items` property
|
/// Value of the `justify-items` property
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-align/#justify-items-property>
|
/// <https://drafts.csswg.org/css-align/#justify-items-property>
|
||||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)]
|
|
||||||
pub struct JustifyItems(pub AlignFlags);
|
pub struct JustifyItems(pub AlignFlags);
|
||||||
|
|
||||||
impl JustifyItems {
|
impl JustifyItems {
|
||||||
|
@ -332,52 +461,49 @@ impl JustifyItems {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Parse for JustifyItems {
|
impl Parse for JustifyItems {
|
||||||
// auto | normal | stretch | <baseline-position> |
|
|
||||||
// [ <overflow-position>? && <self-position> ]
|
|
||||||
// [ legacy && [ left | right | center ] ]
|
|
||||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// auto | normal | stretch | <baseline-position>
|
// <baseline-position>
|
||||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
//
|
||||||
|
// It's weird that this accepts <baseline-position>, but not the
|
||||||
|
// justify-self / justify-content properties...
|
||||||
|
if let Ok(baseline) = input.try(parse_baseline) {
|
||||||
|
return Ok(JustifyItems(baseline));
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto | normal | stretch
|
||||||
|
//
|
||||||
|
// FIXME(emilio): auto is no longer a keyword in the current spec, and
|
||||||
|
// has been renamed to legacy, but that needs different changes because
|
||||||
|
// right now it's the initial value for both style systems, and has that
|
||||||
|
// weird behavior of "inheriting" into descendants.
|
||||||
|
//
|
||||||
|
// Fix this in both.
|
||||||
|
//
|
||||||
|
// See also:
|
||||||
|
// https://bugs.webkit.org/show_bug.cgi?id=172711
|
||||||
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=726148
|
||||||
|
//
|
||||||
|
if let Ok(value) = input.try(parse_auto_normal_stretch) {
|
||||||
return Ok(JustifyItems(value))
|
return Ok(JustifyItems(value))
|
||||||
}
|
}
|
||||||
// [ legacy && [ left | right | center ] ]
|
|
||||||
|
// [ legacy || [ left | right | center ] ]
|
||||||
if let Ok(value) = input.try(parse_legacy) {
|
if let Ok(value) = input.try(parse_legacy) {
|
||||||
return Ok(JustifyItems(value))
|
return Ok(JustifyItems(value))
|
||||||
}
|
}
|
||||||
// [ <overflow-position>? && <self-position> ]
|
|
||||||
Ok(JustifyItems(parse_overflow_self_position(input)?))
|
// <overflow-position>? <self-position>
|
||||||
|
let overflow = input.try(parse_overflow_position).unwrap_or(AlignFlags::empty());
|
||||||
|
let self_position = parse_self_position(input, AxisDirection::Inline)?;
|
||||||
|
Ok(JustifyItems(overflow | self_position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
// auto | normal | stretch
|
||||||
impl From<u16> for ContentDistribution {
|
fn parse_auto_normal_stretch<'i, 't>(
|
||||||
fn from(bits: u16) -> ContentDistribution {
|
|
||||||
let primary =
|
|
||||||
AlignFlags::from_bits_truncate((bits & ALIGN_ALL_BITS) as u8);
|
|
||||||
let fallback =
|
|
||||||
AlignFlags::from_bits_truncate((bits >> ALIGN_ALL_SHIFT) as u8);
|
|
||||||
ContentDistribution::with_fallback(primary, fallback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
impl From<ContentDistribution> for u16 {
|
|
||||||
fn from(v: ContentDistribution) -> u16 {
|
|
||||||
v.primary().bits() as u16 |
|
|
||||||
((v.fallback().bits() as u16) << ALIGN_ALL_SHIFT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// auto | normal | stretch | <baseline-position>
|
|
||||||
fn parse_auto_normal_stretch_baseline<'i, 't>(
|
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<AlignFlags, ParseError<'i>> {
|
) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
|
||||||
return Ok(baseline);
|
|
||||||
}
|
|
||||||
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
"auto" => Ok(AlignFlags::AUTO),
|
"auto" => Ok(AlignFlags::AUTO),
|
||||||
"normal" => Ok(AlignFlags::NORMAL),
|
"normal" => Ok(AlignFlags::NORMAL),
|
||||||
|
@ -386,30 +512,15 @@ fn parse_auto_normal_stretch_baseline<'i, 't>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal | stretch | <baseline-position>
|
// normal | stretch | <baseline-position>
|
||||||
fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
fn parse_normal_stretch<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
|
||||||
return Ok(baseline);
|
|
||||||
}
|
|
||||||
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
"normal" => Ok(AlignFlags::NORMAL),
|
"normal" => Ok(AlignFlags::NORMAL),
|
||||||
"stretch" => Ok(AlignFlags::STRETCH),
|
"stretch" => Ok(AlignFlags::STRETCH),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal | <baseline-position>
|
|
||||||
fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
|
||||||
return Ok(baseline);
|
|
||||||
}
|
|
||||||
|
|
||||||
input.expect_ident_matching("normal")?;
|
|
||||||
Ok(AlignFlags::NORMAL)
|
|
||||||
}
|
|
||||||
|
|
||||||
// <baseline-position>
|
// <baseline-position>
|
||||||
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
// FIXME: remove clone() when lifetimes are non-lexical
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
"baseline" => Ok(AlignFlags::BASELINE),
|
"baseline" => Ok(AlignFlags::BASELINE),
|
||||||
"first" => {
|
"first" => {
|
||||||
|
@ -433,37 +544,6 @@ fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Alig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ <overflow-position>? && <content-position> ]
|
|
||||||
fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
|
||||||
// <content-position> followed by optional <overflow-position>
|
|
||||||
if let Ok(mut content) = input.try(parse_content_position) {
|
|
||||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
|
||||||
content |= overflow;
|
|
||||||
}
|
|
||||||
return Ok(content)
|
|
||||||
}
|
|
||||||
// <overflow-position> followed by required <content-position>
|
|
||||||
if let Ok(overflow) = parse_overflow_position(input) {
|
|
||||||
if let Ok(content) = parse_content_position(input) {
|
|
||||||
return Ok(overflow | content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
||||||
}
|
|
||||||
|
|
||||||
// <content-position>
|
|
||||||
fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
|
||||||
"start" => Ok(AlignFlags::START),
|
|
||||||
"end" => Ok(AlignFlags::END),
|
|
||||||
"flex-start" => Ok(AlignFlags::FLEX_START),
|
|
||||||
"flex-end" => Ok(AlignFlags::FLEX_END),
|
|
||||||
"center" => Ok(AlignFlags::CENTER),
|
|
||||||
"left" => Ok(AlignFlags::LEFT),
|
|
||||||
"right" => Ok(AlignFlags::RIGHT),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// <overflow-position>
|
// <overflow-position>
|
||||||
fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
|
@ -472,37 +552,22 @@ fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// <self-position> | left | right in the inline axis.
|
||||||
fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
fn parse_self_position<'i, 't>(
|
||||||
// <self-position> followed by optional <overflow-position>
|
input: &mut Parser<'i, 't>,
|
||||||
if let Ok(mut self_position) = input.try(parse_self_position) {
|
axis: AxisDirection,
|
||||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
self_position |= overflow;
|
Ok(try_match_ident_ignore_ascii_case! { input,
|
||||||
}
|
"start" => AlignFlags::START,
|
||||||
return Ok(self_position)
|
"end" => AlignFlags::END,
|
||||||
}
|
"flex-start" => AlignFlags::FLEX_START,
|
||||||
// <overflow-position> followed by required <self-position>
|
"flex-end" => AlignFlags::FLEX_END,
|
||||||
if let Ok(overflow) = parse_overflow_position(input) {
|
"center" => AlignFlags::CENTER,
|
||||||
if let Ok(self_position) = parse_self_position(input) {
|
"self-start" => AlignFlags::SELF_START,
|
||||||
return Ok(overflow | self_position)
|
"self-end" => AlignFlags::SELF_END,
|
||||||
}
|
"left" if axis == AxisDirection::Inline => AlignFlags::LEFT,
|
||||||
}
|
"right" if axis == AxisDirection::Inline => AlignFlags::RIGHT,
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// <self-position>
|
|
||||||
fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
|
||||||
"start" => Ok(AlignFlags::START),
|
|
||||||
"end" => Ok(AlignFlags::END),
|
|
||||||
"flex-start" => Ok(AlignFlags::FLEX_START),
|
|
||||||
"flex-end" => Ok(AlignFlags::FLEX_END),
|
|
||||||
"center" => Ok(AlignFlags::CENTER),
|
|
||||||
"left" => Ok(AlignFlags::LEFT),
|
|
||||||
"right" => Ok(AlignFlags::RIGHT),
|
|
||||||
"self-start" => Ok(AlignFlags::SELF_START),
|
|
||||||
"self-end" => Ok(AlignFlags::SELF_END),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ legacy && [ left | right | center ] ]
|
// [ legacy && [ left | right | center ] ]
|
||||||
|
|
|
@ -26,7 +26,9 @@ use values::specified::calc::CalcNode;
|
||||||
pub use properties::animated_properties::TransitionProperty;
|
pub use properties::animated_properties::TransitionProperty;
|
||||||
pub use self::angle::Angle;
|
pub use self::angle::Angle;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::align::{AlignItems, ContentDistribution, SelfAlignment, JustifyItems};
|
pub use self::align::{AlignContent, JustifyContent, AlignItems, ContentDistribution, SelfAlignment, JustifyItems};
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
pub use self::align::{AlignSelf, JustifySelf};
|
||||||
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue