Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ui.mako.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

macro_rules! try_parse_one {
    ($context: expr, $input: expr, $var: ident, $prop_module: ident) => {
        if $var.is_none() {
            if let Ok(value) = $input.try_parse(|i| {
                $prop_module::single_value::parse($context, i)
            }) {
                $var = Some(value);
                continue;
            }
        }
    };
}

<%helpers:shorthand name="transition"
                    engines="gecko servo"
                    extra_prefixes="moz:layout.css.prefixes.transitions webkit"
                    sub_properties="transition-property transition-duration
                                    transition-timing-function
                                    transition-delay transition-behavior"
                    spec="https://drafts.csswg.org/css-transitions/#propdef-transition">
    use crate::parser::Parse;
    % for prop in "delay duration property timing_function behavior".split():
    use crate::properties::longhands::transition_${prop};
    % endfor
    use crate::values::specified::TransitionProperty;

    pub fn parse_value<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Longhands, ParseError<'i>> {
        struct SingleTransition {
            % for prop in "property duration timing_function delay behavior".split():
            transition_${prop}: transition_${prop}::SingleSpecifiedValue,
            % endfor
        }

        fn parse_one_transition<'i, 't>(
            context: &ParserContext,
            input: &mut Parser<'i, 't>,
            first: bool,
        ) -> Result<SingleTransition,ParseError<'i>> {
            % for prop in "property duration timing_function delay behavior".split():
            let mut ${prop} = None;
            % endfor

            let mut parsed = 0;
            loop {
                parsed += 1;

                try_parse_one!(context, input, duration, transition_duration);
                try_parse_one!(context, input, timing_function, transition_timing_function);
                try_parse_one!(context, input, delay, transition_delay);
                if static_prefs::pref!("layout.css.transition-behavior.enabled") {
                    try_parse_one!(context, input, behavior, transition_behavior);
                }
                // Must check 'transition-property' after 'transition-timing-function' since
                // 'transition-property' accepts any keyword.
                if property.is_none() {
                    if let Ok(value) = input.try_parse(|i| TransitionProperty::parse(context, i)) {
                        property = Some(value);
                        continue;
                    }

                    // 'none' is not a valid value for <single-transition-property>,
                    // so it's only acceptable as the first item.
                    if first && input.try_parse(|i| i.expect_ident_matching("none")).is_ok() {
                        property = Some(TransitionProperty::none());
                        continue;
                    }
                }

                parsed -= 1;
                break
            }

            if parsed != 0 {
                Ok(SingleTransition {
                    % for prop in "property duration timing_function delay behavior".split():
                    transition_${prop}: ${prop}.unwrap_or_else(transition_${prop}::single_value
                                                                                 ::get_initial_specified_value),
                    % endfor
                })
            } else {
                Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
            }
        }

        % for prop in "property duration timing_function delay behavior".split():
        let mut ${prop}s = Vec::new();
        % endfor

        let mut first = true;
        let mut has_transition_property_none = false;
        let results = input.parse_comma_separated(|i| {
            if has_transition_property_none {
                // If you specify transition-property: none, multiple items are invalid.
                return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError))
            }
            let transition = parse_one_transition(context, i, first)?;
            first = false;
            has_transition_property_none = transition.transition_property.is_none();
            Ok(transition)
        })?;
        for result in results {
            % for prop in "property duration timing_function delay behavior".split():
            ${prop}s.push(result.transition_${prop});
            % endfor
        }

        Ok(expanded! {
            % for prop in "property duration timing_function delay behavior".split():
            transition_${prop}: transition_${prop}::SpecifiedValue(${prop}s.into()),
            % endfor
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
            use crate::Zero;
            use style_traits::values::SequenceWriter;

            let property_len = self.transition_property.0.len();

            // There are two cases that we can do shorthand serialization:
            // * when all value lists have the same length, or
            // * when transition-property is none, and other value lists have exactly one item.
            if property_len == 0 {
                % for name in "duration delay timing_function".split():
                    if self.transition_${name}.0.len() != 1 {
                        return Ok(());
                    }
                % endfor

                if let Some(behavior) = self.transition_behavior {
                    if behavior.0.len() != 1 {
                        return Ok(());
                    }
                }
            } else {
                % for name in "duration delay timing_function".split():
                    if self.transition_${name}.0.len() != property_len {
                        return Ok(());
                    }
                % endfor

                if let Some(behavior) = self.transition_behavior {
                    if behavior.0.len() != property_len {
                        return Ok(());
                    }
                }
            }

            // Representative length.
            let len = self.transition_duration.0.len();

            for i in 0..len {
                if i != 0 {
                    dest.write_str(", ")?;
                }

                let has_duration = !self.transition_duration.0[i].is_zero();
                let has_timing = !self.transition_timing_function.0[i].is_ease();
                let has_delay = !self.transition_delay.0[i].is_zero();
                let has_behavior = match self.transition_behavior {
                    Some(behavior) => !behavior.0[i].is_normal(),
                    _ => false,
                };
                let has_any = has_duration || has_timing || has_delay || has_behavior;

                let mut writer = SequenceWriter::new(dest, " ");

                if property_len == 0 {
                    writer.raw_item("none")?;
                } else if !self.transition_property.0[i].is_all() || !has_any {
                    writer.item(&self.transition_property.0[i])?;
                }

                // In order to avoid ambiguity, we have to serialize duration if we have delay.
                if has_duration || has_delay {
                    writer.item(&self.transition_duration.0[i])?;
                }

                if has_timing {
                    writer.item(&self.transition_timing_function.0[i])?;
                }

                if has_delay {
                    writer.item(&self.transition_delay.0[i])?;
                }

                if has_behavior {
                    writer.item(&self.transition_behavior.unwrap().0[i])?;
                }
            }
            Ok(())
        }
    }
</%helpers:shorthand>

<%helpers:shorthand name="animation"
                    engines="gecko servo"
                    extra_prefixes="moz:layout.css.prefixes.animations webkit"
                    sub_properties="animation-name animation-duration
                                    animation-timing-function animation-delay
                                    animation-iteration-count animation-direction
                                    animation-fill-mode animation-play-state animation-timeline"
                    rule_types_allowed="Style"
                    spec="https://drafts.csswg.org/css-animations/#propdef-animation">
    <%
        props = "name duration timing_function delay iteration_count \
                 direction fill_mode play_state".split()
    %>
    % for prop in props:
    use crate::properties::longhands::animation_${prop};
    % endfor
    use crate::properties::longhands::animation_timeline;

    pub fn parse_value<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Longhands, ParseError<'i>> {
        struct SingleAnimation {
            % for prop in props:
            animation_${prop}: animation_${prop}::SingleSpecifiedValue,
            % endfor
        }

        fn parse_one_animation<'i, 't>(
            context: &ParserContext,
            input: &mut Parser<'i, 't>,
        ) -> Result<SingleAnimation, ParseError<'i>> {
            % for prop in props:
            let mut ${prop} = None;
            % endfor

            let mut parsed = 0;
            // NB: Name must be the last one here so that keywords valid for other
            // longhands are not interpreted as names.
            //
            // Also, duration must be before delay, see
            // https://drafts.csswg.org/css-animations/#typedef-single-animation
            loop {
                parsed += 1;
                try_parse_one!(context, input, duration, animation_duration);
                try_parse_one!(context, input, timing_function, animation_timing_function);
                try_parse_one!(context, input, delay, animation_delay);
                try_parse_one!(context, input, iteration_count, animation_iteration_count);
                try_parse_one!(context, input, direction, animation_direction);
                try_parse_one!(context, input, fill_mode, animation_fill_mode);
                try_parse_one!(context, input, play_state, animation_play_state);
                try_parse_one!(context, input, name, animation_name);

                // Note: per spec issue discussion, all animation longhands not defined in
                // Animations 1 are defined as reset-only sub-properties for now.
                // https://github.com/w3c/csswg-drafts/issues/6946#issuecomment-1233190360
                //
                // FIXME: Bug 1824261. We should revisit this when the spec gets updated with the
                // new syntax.
                // https://github.com/w3c/csswg-drafts/issues/6946

                parsed -= 1;
                break
            }

            // If nothing is parsed, this is an invalid entry.
            if parsed == 0 {
                Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
            } else {
                Ok(SingleAnimation {
                    % for prop in props:
                    animation_${prop}: ${prop}.unwrap_or_else(animation_${prop}::single_value
                                                              ::get_initial_specified_value),
                    % endfor
                })
            }
        }

        % for prop in props:
        let mut ${prop}s = vec![];
        % endfor

        let results = input.parse_comma_separated(|i| parse_one_animation(context, i))?;
        for result in results.into_iter() {
            % for prop in props:
            ${prop}s.push(result.animation_${prop});
            % endfor
        }

        Ok(expanded! {
            % for prop in props:
            animation_${prop}: animation_${prop}::SpecifiedValue(${prop}s.into()),
            % endfor
            // FIXME: Bug 1824261. animation-timeline is reset-only for now.
            animation_timeline: animation_timeline::SpecifiedValue(
                vec![animation_timeline::single_value::get_initial_specified_value()].into()
            ),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
            use crate::values::specified::easing::TimingFunction;
            use crate::values::specified::{
                AnimationDirection, AnimationFillMode, AnimationPlayState,
            };
            use crate::Zero;
            use style_traits::values::SequenceWriter;

            let len = self.animation_name.0.len();
            // There should be at least one declared value
            if len == 0 {
                return Ok(());
            }

            // If any value list length is differs then we don't do a shorthand serialization
            // either.
            % for name in props[1:]:
                if len != self.animation_${name}.0.len() {
                    return Ok(())
                }
            % endfor

            // FIXME: Bug 1824261. We don't serialize this shorthand if the animation-timeline is
            // speficied, per the wpt update: https://github.com/web-platform-tests/wpt/pull/38848.
            if self.animation_timeline.map_or(false, |v| v.0.len() != 1 || !v.0[0].is_auto()) {
                return Ok(());
            }

            for i in 0..len {
                if i != 0 {
                    dest.write_str(", ")?;
                }

                // We follow the order of this syntax:
                // <single-animation> =
                //   <animation-duration> ||
                //   <easing-function> ||
                //   <animation-delay> ||
                //   <single-animation-iteration-count> ||
                //   <single-animation-direction> ||
                //   <single-animation-fill-mode> ||
                //   <single-animation-play-state> ||
                //   [ none | <keyframes-name> ] ||
                //   <single-animation-timeline>
                //
                // https://drafts.csswg.org/css-animations-2/#animation-shorthand
                //
                // Note: animation-timeline is not serialized for now because it is always the
                // initial value in this loop. Therefore, animation-duration is always resolved as
                // 0s if it is auto because animation-timeline is the initial value, i.e.
                // time-driven animations. In conclusion, we don't serialize animation-duration if
                // it is auto (for specified value) or if it is 0s (for resolved value).
                // https://drafts.csswg.org/css-animations-2/#animation-duration
                let has_duration = !self.animation_duration.0[i].is_auto()
                    && !self.animation_duration.0[i].is_zero();
                let has_timing_function = !self.animation_timing_function.0[i].is_ease();
                let has_delay = !self.animation_delay.0[i].is_zero();
                let has_iteration_count = !self.animation_iteration_count.0[i].is_one();
                let has_direction =
                    !matches!(self.animation_direction.0[i], AnimationDirection::Normal);
                let has_fill_mode =
                    !matches!(self.animation_fill_mode.0[i], AnimationFillMode::None);
                let has_play_state =
                    !matches!(self.animation_play_state.0[i], AnimationPlayState::Running);
                let animation_name = &self.animation_name.0[i];
                let has_name = !animation_name.is_none();

                let mut writer = SequenceWriter::new(dest, " ");

                // To avoid ambiguity, we have to serialize duration if duration is initial
                // but delay is not. (In other words, it's ambiguous if we serialize delay only.)
                if has_duration || has_delay {
                    writer.item(&self.animation_duration.0[i])?;
                }

                if has_timing_function || TimingFunction::match_keywords(animation_name) {
                    writer.item(&self.animation_timing_function.0[i])?;
                }

                // For animation-delay and animation-iteration-count.
                % for name in props[3:5]:
                if has_${name} {
                    writer.item(&self.animation_${name}.0[i])?;
                }
                % endfor

                if has_direction || AnimationDirection::match_keywords(animation_name) {
                    writer.item(&self.animation_direction.0[i])?;
                }

                if has_fill_mode || AnimationFillMode::match_keywords(animation_name) {
                    writer.item(&self.animation_fill_mode.0[i])?;
                }

                if has_play_state || AnimationPlayState::match_keywords(animation_name) {
                    writer.item(&self.animation_play_state.0[i])?;
                }

                // If all values are initial, we must serialize animation-name.
                let has_any = {
                    has_duration
                % for name in props[2:]:
                        || has_${name}
                % endfor
                };
                if has_name || !has_any {
                    writer.item(animation_name)?;
                }
            }
            Ok(())
        }
    }
</%helpers:shorthand>

<%helpers:shorthand
    engines="gecko"
    name="scroll-timeline"
    sub_properties="scroll-timeline-name scroll-timeline-axis"
    gecko_pref="layout.css.scroll-driven-animations.enabled",
    spec="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand"
>
    pub fn parse_value<'i>(
        context: &ParserContext,
        input: &mut Parser<'i, '_>,
    ) -> Result<Longhands, ParseError<'i>> {
        use crate::properties::longhands::{scroll_timeline_axis, scroll_timeline_name};

        let mut names = Vec::with_capacity(1);
        let mut axes = Vec::with_capacity(1);
        input.parse_comma_separated(|input| {
            let name = scroll_timeline_name::single_value::parse(context, input)?;
            let axis = input.try_parse(|i| scroll_timeline_axis::single_value::parse(context, i));

            names.push(name);
            axes.push(axis.unwrap_or_default());

            Ok(())
        })?;

        Ok(expanded! {
            scroll_timeline_name: scroll_timeline_name::SpecifiedValue(names.into()),
            scroll_timeline_axis: scroll_timeline_axis::SpecifiedValue(axes.into()),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
            // If any value list length is differs then we don't do a shorthand serialization
            // either.
            let len = self.scroll_timeline_name.0.len();
            if len != self.scroll_timeline_axis.0.len() {
                return Ok(());
            }

            for i in 0..len {
                if i != 0 {
                    dest.write_str(", ")?;
                }

                self.scroll_timeline_name.0[i].to_css(dest)?;

                if self.scroll_timeline_axis.0[i] != Default::default() {
                    dest.write_char(' ')?;
                    self.scroll_timeline_axis.0[i].to_css(dest)?;
                }

            }
            Ok(())
        }
    }
</%helpers:shorthand>

// Note: view-timeline shorthand doesn't take view-timeline-inset into account.
<%helpers:shorthand
    engines="gecko"
    name="view-timeline"
    sub_properties="view-timeline-name view-timeline-axis"
    gecko_pref="layout.css.scroll-driven-animations.enabled",
    spec="https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand"
>
    pub fn parse_value<'i>(
        context: &ParserContext,
        input: &mut Parser<'i, '_>,
    ) -> Result<Longhands, ParseError<'i>> {
        use crate::properties::longhands::{view_timeline_axis, view_timeline_name};

        let mut names = Vec::with_capacity(1);
        let mut axes = Vec::with_capacity(1);
        input.parse_comma_separated(|input| {
            let name = view_timeline_name::single_value::parse(context, input)?;
            let axis = input.try_parse(|i| view_timeline_axis::single_value::parse(context, i));

            names.push(name);
            axes.push(axis.unwrap_or_default());

            Ok(())
        })?;

        Ok(expanded! {
            view_timeline_name: view_timeline_name::SpecifiedValue(names.into()),
            view_timeline_axis: view_timeline_axis::SpecifiedValue(axes.into()),
        })
    }

    impl<'a> ToCss for LonghandsToSerialize<'a>  {
        fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
            // If any value list length is differs then we don't do a shorthand serialization
            // either.
            let len = self.view_timeline_name.0.len();
            if len != self.view_timeline_axis.0.len() {
                return Ok(());
            }

            for i in 0..len {
                if i != 0 {
                    dest.write_str(", ")?;
                }

                self.view_timeline_name.0[i].to_css(dest)?;

                if self.view_timeline_axis.0[i] != Default::default() {
                    dest.write_char(' ')?;
                    self.view_timeline_axis.0[i].to_css(dest)?;
                }

            }
            Ok(())
        }
    }
</%helpers:shorthand>

[ Dauer der Verarbeitung: 0.46 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge