Exemple #1
0
 public MediaCondition(EMediaCombinator op, IEnumerable <IMediaCondition> conditions)
 {
     Conditions = new LinkedList <IMediaCondition>(conditions);
     Op         = op;
 }
Exemple #2
0
        /// <summary>
        /// Consumes a new <see cref="MediaCondition"/> or <see cref="MediaFeature"/>
        /// </summary>
        /// <param name="Stream"></param>
        /// <returns></returns>
        static IMediaCondition Consume_Media_Condition(DataConsumer <CssToken> Stream)
        {/* Docs: https://www.w3.org/TR/mediaqueries-4/#media-condition */
            if (Stream is null)
            {
                throw new CssParserException(CssErrors.STREAM_IS_NULL);
            }

            Consume_All_Whitespace(Stream);
            if (ParserCommon.Starts_Media_Feature(Stream.AsSpan()))
            {
                /* Consume opening parentheses */
                Stream.Consume();
                var feature = Consume_Media_Feature(Stream);

                /* Consume closing parentheses */
                if (Stream.Next.Type == ECssTokenType.Parenth_Close)
                {
                    Stream.Consume();
                }

                return(feature);
            }
            else if (ParserCommon.Starts_Media_Condition(Stream.AsSpan()))
            {
                EMediaCombinator Combinator = EMediaCombinator.None;
                var conditionList           = new LinkedList <IMediaCondition>();


                if (Stream.Next.Type == ECssTokenType.Parenth_Close)
                {
                    /* Empty media condition block */
                    Stream.Consume();
                    return(new MediaCondition(EMediaCombinator.None, Array.Empty <MediaFeature>()));
                }
                else if (Stream.Next.Type == ECssTokenType.Parenth_Open)
                {
                    Stream.Consume();
                }

                Consume_All_Whitespace(Stream);
                /* Repeatedly consume sub-media-conditions until we hit a closing parentheses */
                do
                {
                    Consume_All_Whitespace(Stream);

                    if (Stream.Next.Type == ECssTokenType.Parenth_Close)
                    {
                        /* End of this media condition block */
                        break;
                    }

                    /* Anything other than the first condition *MUST* specify a combinator */
                    if (conditionList.Count > 0)
                    {
                        if (!ParserCommon.Is_Combinator(Stream.Next))
                        {
                            throw new CssSyntaxErrorException(CssErrors.EXPECTING_COMBINATOR, Stream);
                        }
                    }

                    /* Otherwise we just COULD have a combinator */
                    if (ParserCommon.Is_Combinator(Stream.Next))
                    {
                        /* Consume combinator */
                        IdentToken combinatorToken = Stream.Consume() as IdentToken;
                        if (!Lookup.TryEnum(combinatorToken.Value, out EMediaCombinator combLookup))
                        {
                            throw new CssSyntaxErrorException(String.Format(CultureInfo.InvariantCulture, CssErrors.INVALID_COMBINATOR, combinatorToken.Value), Stream);
                        }
                        else if (Combinator == EMediaCombinator.None)
                        {/* This is the first combinator specified */
                            Combinator = combLookup;
                        }
                        else if (Combinator != EMediaCombinator.None && combLookup != Combinator)
                        {/* Ensure this new combinator matches the combinator for this method group */
                            throw new CssSyntaxErrorException(CssErrors.INVALID_MULTIPLE_COMBINATORS_ON_MEDIARULE, Stream);
                        }
                    }

                    Consume_All_Whitespace(Stream);
                    if (Stream.Next.Type != ECssTokenType.Parenth_Open)
                    {
                        throw new CssSyntaxErrorException(CssErrors.EXPECTING_OPENING_PARENTHESES, Stream);
                    }

                    /* Oh look a yummy little sub-condition for us to gobble up! */
                    var feature = Consume_Media_Condition(Stream);
                    conditionList.AddLast(feature);
                }while (Stream.Next.Type != ECssTokenType.EOF);

                /* Consume closing parentheses */
                if (Stream.Next.Type == ECssTokenType.Parenth_Close)
                {
                    Stream.Consume();
                }

                return(new MediaCondition(Combinator, conditionList));
            }

            throw new CssSyntaxErrorException(CssErrors.EXPECTING_MEDIA_CONDITION_START, Stream);
        }