Esempio n. 1
0
        /// <summary>
        /// If this next work from the current point in the given string navigator appears to be a recognised pseudo class then this will return a result that
        /// will ensure that the current character is identified as a selector-or-property-name content rather than a property-name-value-separator colon (the
        /// string navigator passed here will be for the position directly after the colon, which is what is currently being negotiated). Any whitespace at
        /// the current position will be moved over when looking for pseudo class content. If the content does not appear to be for a pseudo class then null
        /// will be returned and the caller may continue with whatever logic it wants to.
        /// </summary>
        private CharacterProcessorResult GetPseudoClassHandlingProcessResultIfApplicable(IWalkThroughStrings stringNavigatorAtStartOfPotentialPseudoClass)
        {
            if (stringNavigatorAtStartOfPotentialPseudoClass == null)
            {
                throw new ArgumentNullException("stringNavigator");
            }

            // If the first character of the possible-psuedo-class content is a ":" then it means that we've encountered a "::" (since the first ":" triggered
            // this method to be called with the content after it) and that means that it's definitely a psuedo class and not a property name / value pair. As
            // such we'll return a process that swallows this second ":" and then processes the next content as selector-or-style-content (and not as property
            // name content)
            if (stringNavigatorAtStartOfPotentialPseudoClass.CurrentCharacter == ':')
            {
                var contentProcessor = GetSelectorOrStyleCharacterProcessor();
                return(new CharacterProcessorResult(
                           CharacterCategorisationOptions.SelectorOrStyleProperty,
                           new SkipCharactersSegment(CharacterCategorisationOptions.SelectorOrStyleProperty, 1, GetSelectorOrStyleCharacterProcessor())
                           ));
            }

            // Skip over any whitespace to find the start of the next content
            var whiteSpaceCharactersToSkipOver = 0;

            while (true)
            {
                var character = stringNavigatorAtStartOfPotentialPseudoClass.CurrentCharacter;
                if ((character == null) || !char.IsWhiteSpace(character.Value))
                {
                    break;
                }
                stringNavigatorAtStartOfPotentialPseudoClass = stringNavigatorAtStartOfPotentialPseudoClass.Next;
                whiteSpaceCharactersToSkipOver++;
            }

            // Determine whether that content (if there is any) matches any of the pseudo classes
            if (PseudoClasses.Any(c => stringNavigatorAtStartOfPotentialPseudoClass.DoesCurrentContentMatch(c)))
            {
                IProcessCharacters contentProcessor = GetSelectorOrStyleCharacterProcessor();
                if (whiteSpaceCharactersToSkipOver > 0)
                {
                    contentProcessor = new SkipCharactersSegment(CharacterCategorisationOptions.Whitespace, whiteSpaceCharactersToSkipOver, contentProcessor);
                }
                return(new CharacterProcessorResult(
                           CharacterCategorisationOptions.SelectorOrStyleProperty,
                           contentProcessor
                           ));
            }

            return(null);
        }