Пример #1
0
        private static TryParseResult TryParseBlock(
            string tagName,
            Block block,
            IEnumerable <TagHelperDescriptor> descriptors,
            ErrorSink errorSink,
            HashSet <string> processedBoundAttributeNames)
        {
            // TODO: Accept more than just spans: https://github.com/aspnet/Razor/issues/96.
            // The first child will only ever NOT be a Span if a user is doing something like:
            // <input @checked />

            var childSpan = block.Children.First() as Span;

            if (childSpan == null || childSpan.Kind != SpanKindInternal.Markup)
            {
                errorSink.OnError(
                    block.Start,
                    LegacyResources.FormatTagHelpers_CannotHaveCSharpInTagDeclaration(tagName),
                    block.Length);

                return(null);
            }

            var builder = new BlockBuilder(block);

            // If there's only 1 child it means that it's plain text inside of the attribute.
            // i.e. <div class="plain text in attribute">
            if (builder.Children.Count == 1)
            {
                return(TryParseSpan(childSpan, descriptors, errorSink, processedBoundAttributeNames));
            }

            var nameSymbols = childSpan
                              .Symbols
                              .OfType <HtmlSymbol>()
                              .SkipWhile(symbol => !HtmlMarkupParser.IsValidAttributeNameSymbol(symbol)) // Skip prefix
                              .TakeWhile(nameSymbol => HtmlMarkupParser.IsValidAttributeNameSymbol(nameSymbol))
                              .Select(nameSymbol => nameSymbol.Content);

            var name = string.Concat(nameSymbols);

            if (string.IsNullOrEmpty(name))
            {
                errorSink.OnError(
                    childSpan.Start,
                    LegacyResources.FormatTagHelpers_AttributesMustHaveAName(tagName),
                    childSpan.Length);

                return(null);
            }

            // Have a name now. Able to determine correct isBoundNonStringAttribute value.
            var result = CreateTryParseResult(name, descriptors, processedBoundAttributeNames);

            var firstChild = builder.Children[0] as Span;

            if (firstChild != null && firstChild.Symbols[0] is HtmlSymbol)
            {
                var htmlSymbol = firstChild.Symbols[firstChild.Symbols.Count - 1] as HtmlSymbol;
                switch (htmlSymbol.Type)
                {
                case HtmlSymbolType.Equals:
                    if (builder.Children.Count == 2 &&
                        builder.Children[1] is Span value &&
                        value.Kind == SpanKindInternal.Markup)
                    {
                        // Attribute value is a string literal. Eg: <tag my-attribute=foo />.
                        result.AttributeStructure = AttributeStructure.NoQuotes;
                    }
                    else
                    {
                        // Could be an expression, treat NoQuotes and DoubleQuotes equivalently. We purposefully do not persist NoQuotes
                        // ValueStyles at code generation time to protect users from rendering dynamic content with spaces
                        // that can break attributes.
                        // Ex: <tag my-attribute=@value /> where @value results in the test "hello world".
                        // This way, the above code would render <tag my-attribute="hello world" />.
                        result.AttributeStructure = AttributeStructure.DoubleQuotes;
                    }
                    break;