Ejemplo n.º 1
0
        private void MinifyMarkup(BlockBuilder block)
        {
            var codeGenerator        = new MarkupCodeGenerator();
            var previousIsWhiteSpace = true;
            var previousTokenEndsWithBlockElement = true;
            var insideScript = false;

            for (int i = 0; i < block.Children.Count; i++)
            {
                var node = block.Children[i];
                var span = node as Span;
                if (span == null)
                {
                    // When we have a dynamic markup, we can't know if the last char will be whitespace
                    // => to make it work in all cases, we won't minifiy whitespace just after code.
                    previousIsWhiteSpace = false;
                    previousTokenEndsWithBlockElement = false;

                    var section = node as Block;
                    if ((section != null) && (section.Type == BlockType.Section))
                    {
                        // Sections are special as they force us to recurse the minification
                        block.Children[i]    = MinifySectionBlock(section);
                        previousIsWhiteSpace = false;
                        previousTokenEndsWithBlockElement = false;
                    }
                    continue;
                }

                // There may be several HTML tokens just one after the other.
                // => we concatenate everything in a single token to minify everyting in a single scan
                // (we is better for Javascript minification).
                var sb = new StringBuilder();
                sb.Append(span.Content);
                if (i < block.Children.Count - 1)
                {
                    var markup = block.Children[i + 1] as Span;
                    while ((markup != null) && (markup.Kind == SpanKind.Markup) && ((markup.Next == null) || ((markup.Next != null) && ((markup.Next.Kind == SpanKind.Markup) || ((markup.Next.Kind != SpanKind.Markup) && !markup.Content.EndsWith("\""))))))
                    {
                        block.Children.RemoveAt(i + 1);
                        sb.Append(markup.Content);
                        markup = i + 1 < block.Children.Count ? block.Children[i + 1] as Span : null;
                    }
                }

                var content = sb.ToString();
                if (string.IsNullOrEmpty(content))
                {
                    // Nothing to minify
                    block.Children.RemoveAt(i);
                    continue;
                }

                content = _minifier.Minify(content, previousIsWhiteSpace, previousTokenEndsWithBlockElement, insideScript);

                _minifier.AnalyseContent(content, ref previousIsWhiteSpace, ref previousTokenEndsWithBlockElement, ref insideScript);

                // We replace the content with the minified markup
                // and then let the CSharp/VB generator do their jobs.
                var builder = new SpanBuilder()
                {
                    CodeGenerator = codeGenerator, EditHandler = span.EditHandler, Kind = span.Kind, Start = span.Start
                };
                var symbol = new MarkupSymbol()
                {
                    Content = content
                };
                builder.Accept(symbol);
                span.ReplaceWith(builder);
            }
        }
Ejemplo n.º 2
0
        private static Block RebuildCodeGenerators(Block block)
        {
            var builder = new BlockBuilder(block);

            var isDynamic = builder.CodeGenerator is DynamicAttributeBlockCodeGenerator;

            // We don't want any attribute specific logic here, null out the block code generator.
            if (isDynamic || builder.CodeGenerator is AttributeBlockCodeGenerator)
            {
                builder.CodeGenerator = BlockCodeGenerator.Null;
            }

            for (var i = 0; i < builder.Children.Count; i++)
            {
                var child = builder.Children[i];

                if (child.IsBlock)
                {
                    // The child is a block, recurse down into the block to rebuild its children
                    builder.Children[i] = RebuildCodeGenerators((Block)child);
                }
                else
                {
                    var childSpan = (Span)child;
                    ISpanCodeGenerator newCodeGenerator = null;
                    var literalGenerator = childSpan.CodeGenerator as LiteralAttributeCodeGenerator;

                    if (literalGenerator != null)
                    {
                        if (literalGenerator.ValueGenerator == null || literalGenerator.ValueGenerator.Value == null)
                        {
                            newCodeGenerator = new MarkupCodeGenerator();
                        }
                        else
                        {
                            newCodeGenerator = literalGenerator.ValueGenerator.Value;
                        }
                    }
                    else if (isDynamic && childSpan.CodeGenerator == SpanCodeGenerator.Null)
                    {
                        // Usually the dynamic code generator handles rendering the null code generators underneath
                        // it. This doesn't make sense in terms of tag helpers though, we need to change null code
                        // generators to markup code generators.

                        newCodeGenerator = new MarkupCodeGenerator();
                    }

                    // If we have a new code generator we'll need to re-build the child
                    if (newCodeGenerator != null)
                    {
                        var childSpanBuilder = new SpanBuilder(childSpan)
                        {
                            CodeGenerator = newCodeGenerator
                        };

                        builder.Children[i] = childSpanBuilder.Build();
                    }
                }
            }

            return(builder.Build());
        }