Exemple #1
0
        /// <summary>
        /// Retrieves unquoted attribute value
        /// </summary>
        /// <returns>Attribute value token</returns>
        public IHtmlAttributeValueToken GetUnquotedAttributeValue(int tagEnd)
        {
            // Need to handle <a b=c=d /> and figure out that c=d is a valid pair while
            // b= is missing a value. One way is to check if 'c' happens to be
            // one of the known HTML attributes, but it only works for plain HTML
            // and won't work for ASP.NET controls that can define any attributes
            // via .NET properties.

            // Options (value is unquoted)
            //      a. Attribute value is either a sequence of characters or a number
            //         except if it is ID or CLASS.
            //      b. Attribute name is typically a sequence of characters and does not include digits
            //      c. Attribute value is not normally followed by =

            Debug.Assert(!_cs.IsAtString());

            AttributeValueToken token = null;
            int start = _cs.Position;
            int end   = _cs.Position;

            ITextRange    nextTokenRange;
            NextTokenType nextTokenType = NextToken.PeekNextToken(_cs, tagEnd, out nextTokenRange);

            switch (nextTokenType)
            {
            case NextTokenType.None:        // attrName={EOF}
            case NextTokenType.Tag:         // attName=<foo
            case NextTokenType.Equals:      // attrName==
                return(null);

            case NextTokenType.Number:
            // attrName = 1.0
            case NextTokenType.Unknown:
            // id=#
            case NextTokenType.Identifier:
                // attrName = foo12. There are no know attributes of this form.
                end = nextTokenRange.End;
                break;

            case NextTokenType.Letters:
                // Legal value. Need to check against attribute names to be sure.
                bool isKnownAttribute = AttributeTable.IsKnownAttribute(_cs.GetSubstringAt(nextTokenRange.Start, nextTokenRange.Length));
                if (!isKnownAttribute)
                {
                    end = nextTokenRange.End;
                }
                break;
            }

            char closeQuote = '\0';

            if (end > start)
            {
                closeQuote = _cs[end - 1];
                if (closeQuote != '\'' && closeQuote != '\"')
                {
                    closeQuote = '\0';
                }
            }

            token        = AttributeValueToken.Create(HtmlToken.FromBounds(start, end), '\0', closeQuote);
            _cs.Position = end;

            return(token);
        }
Exemple #2
0
        public static NextTokenType PeekNextToken(HtmlCharStream cs, int tagEnd, out ITextRange range)
        {
            NextTokenType tokenType = NextTokenType.Unknown;
            int           current   = cs.Position;

            if (cs.IsEndOfStream() || cs.Position == tagEnd)
            {
                range = new TextRange();
                return(NextTokenType.None);
            }

            int start = cs.Position;

            while (cs.IsWhiteSpace())
            {
                cs.MoveToNextChar();
            }

            if (cs.IsEndOfStream() || cs.Position == tagEnd)
            {
                range = TextRange.FromBounds(start, cs.Position);
                return(NextTokenType.Unknown);
            }

            if (cs.IsAtTagDelimiter())
            {
                tokenType = NextTokenType.Tag;
            }
            else if (cs.CurrentChar == '=')
            {
                tokenType = NextTokenType.Equals;
            }
            else
            {
                int  digits      = 0;
                bool firstLetter = false;
                int  length      = 0;
                int  chars       = 0;

                if (cs.IsAnsiLetter())
                {
                    firstLetter = true;
                }

                while (!cs.IsEndOfStream() && !cs.IsWhiteSpace() && !cs.IsAtTagDelimiter() && cs.CurrentChar != '=' && cs.Position < tagEnd)
                {
                    if (cs.IsAnsiLetter() || cs.CurrentChar == '_' || cs.CurrentChar == '-')
                    {
                        chars++;
                    }
                    else if (cs.IsDecimal() || cs.CurrentChar == '.')
                    {
                        digits++;
                    }

                    cs.MoveToNextChar();
                    length++;
                }

                if (length > 0)
                {
                    if (length == digits)
                    {
                        tokenType = NextTokenType.Number;
                    }
                    else if (length == chars)
                    {
                        tokenType = NextTokenType.Letters;
                    }
                    else if (firstLetter)
                    {
                        tokenType = NextTokenType.Identifier;
                    }
                }
            }

            range       = TextRange.FromBounds(start, cs.Position);
            cs.Position = current;
            return(tokenType);
        }