示例#1
0
 public static SpanConstructor Comment(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return(self.Span(SpanKind.Comment, content, type));
 }
 public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
 }
示例#3
0
 public static SpanConstructor MetaMarkup(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return(self.Span(SpanKind.MetaCode, content, type));
 }
 public static SpanConstructor MetaMarkup(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return self.Span(SpanKind.MetaCode, content, type);
 }
 public static SpanConstructor Comment(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return self.Span(SpanKind.Comment, content, type);
 }
示例#6
0
        private void AttributeValue(HtmlSymbolType quote)
        {
            var prefixStart = CurrentLocation;
            var prefix      = ReadWhile(sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine);

            if (At(HtmlSymbolType.Transition))
            {
                if (NextIs(HtmlSymbolType.Transition))
                {
                    // Wrapping this in a block so that the ConditionalAttributeCollapser doesn't rewrite it.
                    using (Context.StartBlock(BlockType.Markup))
                    {
                        Accept(prefix);

                        // Render a single "@" in place of "@@".
                        Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
                            prefix.GetContent(prefixStart),
                            new LocationTagged <string>(CurrentSymbol.GetContent(), CurrentLocation));
                        AcceptAndMoveNext();
                        Output(SpanKind.Markup, AcceptedCharacters.None);

                        Span.ChunkGenerator = SpanChunkGenerator.Null;
                        AcceptAndMoveNext();
                        Output(SpanKind.Markup, AcceptedCharacters.None);
                    }
                }
                else
                {
                    Accept(prefix);
                    var valueStart = CurrentLocation;
                    PutCurrentBack();

                    // Output the prefix but as a null-span. DynamicAttributeBlockChunkGenerator will render it
                    Span.ChunkGenerator = SpanChunkGenerator.Null;

                    // Dynamic value, start a new block and set the chunk generator
                    using (Context.StartBlock(BlockType.Markup))
                    {
                        Context.CurrentBlock.ChunkGenerator =
                            new DynamicAttributeBlockChunkGenerator(prefix.GetContent(prefixStart), valueStart);

                        OtherParserBlock();
                    }
                }
            }
            else if (At(HtmlSymbolType.Text) &&
                     CurrentSymbol.Content.Length > 0 &&
                     CurrentSymbol.Content[0] == '~' &&
                     NextIs(HtmlSymbolType.ForwardSlash))
            {
                Accept(prefix);

                // Virtual Path value
                var valueStart = CurrentLocation;
                VirtualPath();
                Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
                    prefix.GetContent(prefixStart),
                    new LocationTagged <SpanChunkGenerator>(new ResolveUrlChunkGenerator(), valueStart));
            }
            else
            {
                Accept(prefix);

                // Literal value
                // 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have
                // "Unknown" type.
                var value = ReadWhile(sym =>
                                      // These three conditions find separators which break the attribute value into portions
                                      sym.Type != HtmlSymbolType.WhiteSpace &&
                                      sym.Type != HtmlSymbolType.NewLine &&
                                      sym.Type != HtmlSymbolType.Transition &&
                                      // This condition checks for the end of the attribute value (it repeats some of the checks above
                                      // but for now that's ok)
                                      !IsEndOfAttributeValue(quote, sym));
                Accept(value);
                Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
                    prefix.GetContent(prefixStart),
                    value.GetContent(prefixStart));
            }
            Output(SpanKind.Markup);
        }
示例#7
0
 internal void TestSingleToken(string text, HtmlSymbolType expectedSymbolType)
 {
     TestTokenizer(text, new HtmlSymbol(text, expectedSymbolType));
 }
        private void AttributeValue(HtmlSymbolType quote)
        {
            var prefixStart = CurrentLocation;
            var prefix = ReadWhile(sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine);

            if (At(HtmlSymbolType.Transition))
            {
                if (NextIs(HtmlSymbolType.Transition))
                {
                    // Wrapping this in a block so that the ConditionalAttributeCollapser doesn't rewrite it.
                    using (Context.StartBlock(BlockType.Markup))
                    {
                        Accept(prefix);

                        // Render a single "@" in place of "@@".
                        Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
                            prefix.GetContent(prefixStart),
                            new LocationTagged<string>(CurrentSymbol.GetContent(), CurrentLocation));
                        AcceptAndMoveNext();
                        Output(SpanKind.Markup, AcceptedCharacters.None);

                        Span.ChunkGenerator = SpanChunkGenerator.Null;
                        AcceptAndMoveNext();
                        Output(SpanKind.Markup, AcceptedCharacters.None);
                    }
                }
                else
                {
                    Accept(prefix);
                    var valueStart = CurrentLocation;
                    PutCurrentBack();

                    // Output the prefix but as a null-span. DynamicAttributeBlockChunkGenerator will render it
                    Span.ChunkGenerator = SpanChunkGenerator.Null;

                    // Dynamic value, start a new block and set the chunk generator
                    using (Context.StartBlock(BlockType.Markup))
                    {
                        Context.CurrentBlock.ChunkGenerator =
                            new DynamicAttributeBlockChunkGenerator(prefix.GetContent(prefixStart), valueStart);

                        OtherParserBlock();
                    }
                }
            }
            else
            {
                Accept(prefix);

                // Literal value
                // 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have
                // "Unknown" type.
                var value = ReadWhile(sym =>
                    // These three conditions find separators which break the attribute value into portions
                    sym.Type != HtmlSymbolType.WhiteSpace &&
                    sym.Type != HtmlSymbolType.NewLine &&
                    sym.Type != HtmlSymbolType.Transition &&
                    // This condition checks for the end of the attribute value (it repeats some of the checks above
                    // but for now that's ok)
                    !IsEndOfAttributeValue(quote, sym));
                Accept(value);
                Span.ChunkGenerator = new LiteralAttributeChunkGenerator(
                    prefix.GetContent(prefixStart),
                    value.GetContent(prefixStart));
            }
            Output(SpanKind.Markup);
        }
 private bool IsEndOfAttributeValue(HtmlSymbolType quote, HtmlSymbol sym)
 {
     return EndOfFile || sym == null ||
            (quote != HtmlSymbolType.Unknown
                 ? sym.Type == quote // If quoted, just wait for the quote
                 : IsUnquotedEndOfAttributeValue(sym));
 }
        private void AttributeValue(HtmlSymbolType quote)
        {
            SourceLocation prefixStart = CurrentLocation;
            var prefix = ReadWhile(sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine);
            Accept(prefix);

            if (At(HtmlSymbolType.Transition))
            {
                SourceLocation valueStart = CurrentLocation;
                PutCurrentBack();

                // Output the prefix but as a null-span. DynamicAttributeBlockCodeGenerator will render it
                Span.CodeGenerator = SpanCodeGenerator.Null;

                // Dynamic value, start a new block and set the code generator
                using (Context.StartBlock(BlockType.Markup))
                {
                    Context.CurrentBlock.CodeGenerator = new DynamicAttributeBlockCodeGenerator(prefix.GetContent(prefixStart), valueStart);

                    OtherParserBlock();
                }
            }
            else if (At(HtmlSymbolType.Text) && CurrentSymbol.Content.Length > 0 && CurrentSymbol.Content[0] == '~' && NextIs(HtmlSymbolType.Solidus))
            {
                // Virtual Path value
                SourceLocation valueStart = CurrentLocation;
                VirtualPath();
                Span.CodeGenerator = new LiteralAttributeCodeGenerator(
                    prefix.GetContent(prefixStart),
                    new LocationTagged<SpanCodeGenerator>(new ResolveUrlCodeGenerator(), valueStart));
            }
            else
            {
                // Literal value
                // 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have "Unknown" type.
                var value = ReadWhile(sym =>
                    // These three conditions find separators which break the attribute value into portions
                                      sym.Type != HtmlSymbolType.WhiteSpace &&
                                      sym.Type != HtmlSymbolType.NewLine &&
                                      sym.Type != HtmlSymbolType.Transition &&
                                          // This condition checks for the end of the attribute value (it repeats some of the checks above but for now that's ok)
                                      !IsEndOfAttributeValue(quote, sym));
                Accept(value);
                Span.CodeGenerator = new LiteralAttributeCodeGenerator(prefix.GetContent(prefixStart), value.GetContent(prefixStart));
            }
            Output(SpanKind.Markup);
        }
        private void AttributePrefix(IEnumerable <HtmlSymbol> whitespace, IEnumerable <HtmlSymbol> nameSymbols)
        {
            // First, determine if this is a 'data-' attribute (since those can't use conditional attributes)
            LocationTagged <string> name   = nameSymbols.GetContent(Span.Start);
            bool attributeCanBeConditional = !name.Value.StartsWith("data-", StringComparison.OrdinalIgnoreCase);

            // Accept the whitespace and name
            Accept(whitespace);
            Accept(nameSymbols);
            Assert(HtmlSymbolType.Equals); // We should be at "="
            AcceptAndMoveNext();
            HtmlSymbolType quote = HtmlSymbolType.Unknown;

            if (At(HtmlSymbolType.SingleQuote) || At(HtmlSymbolType.DoubleQuote))
            {
                quote = CurrentSymbol.Type;
                AcceptAndMoveNext();
            }

            // We now have the prefix: (i.e. '      foo="')
            LocationTagged <string> prefix = Span.GetContent();

            if (attributeCanBeConditional)
            {
                Span.CodeGenerator = SpanCodeGenerator.Null; // The block code generator will render the prefix
                Output(SpanKind.Markup);

                // Read the values
                while (!EndOfFile && !IsEndOfAttributeValue(quote, CurrentSymbol))
                {
                    AttributeValue(quote);
                }

                // Capture the suffix
                LocationTagged <string> suffix = new LocationTagged <string>(String.Empty, CurrentLocation);
                if (quote != HtmlSymbolType.Unknown && At(quote))
                {
                    suffix = CurrentSymbol.GetContent();
                    AcceptAndMoveNext();
                }

                if (Span.Symbols.Count > 0)
                {
                    Span.CodeGenerator = SpanCodeGenerator.Null; // Again, block code generator will render the suffix
                    Output(SpanKind.Markup);
                }

                // Create the block code generator
                Context.CurrentBlock.CodeGenerator = new AttributeBlockCodeGenerator(
                    name, prefix, suffix);
            }
            else
            {
                // Not a "conditional" attribute, so just read the value
                SkipToAndParseCode(sym => IsEndOfAttributeValue(quote, sym));
                if (quote != HtmlSymbolType.Unknown)
                {
                    Optional(quote);
                }
                Output(SpanKind.Markup);
            }
        }
示例#12
0
 public static SpanConstructor MarkupTransition(this SpanFactory self, HtmlSymbolType type)
 {
     return(self
            .Span(SpanKindInternal.Transition, SyntaxConstants.TransitionString, type)
            .Accepts(AcceptedCharactersInternal.None));
 }
示例#13
0
 public SpanConstructor Span(SpanKindInternal kind, string content, HtmlSymbolType type)
 {
     return(CreateSymbolSpan(kind, content, () => new HtmlSymbol(content, type)));
 }
示例#14
0
 /// <summary>
 /// Converts the generic <see cref="IEnumerable{ISymbol}"/> to a <see cref="IEnumerable{HtmlSymbol}"/> and
 /// finds the first <see cref="HtmlSymbol"/> with type <paramref name="type"/>.
 /// </summary>
 /// <param name="symbols">The <see cref="IEnumerable{ISymbol}"/> instance this method extends.</param>
 /// <param name="type">The <see cref="HtmlSymbolType"/> to search for.</param>
 /// <returns>The first <see cref="HtmlSymbol"/> of type <paramref name="type"/>.</returns>
 public static HtmlSymbol FirstHtmlSymbolAs(this IEnumerable<ISymbol> symbols, HtmlSymbolType type)
 {
     return symbols.OfType<HtmlSymbol>().FirstOrDefault(sym => (type & sym.Type) == sym.Type);
 }
示例#15
0
 public SpanConstructor Span(SpanKind kind, string content, HtmlSymbolType type)
 {
     return(CreateSymbolSpan(kind, content, st => new HtmlSymbol(st, content, type)));
 }
 private void ParseQuoted(HtmlSymbolType type)
 {
     SkipToAndParseCode(type);
     if (!EndOfFile)
     {
         Assert(type);
         AcceptAndMoveNext();
     }
 }
示例#17
0
 public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type)
 {
     return(self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None));
 }
示例#18
0
 /// <summary>
 /// Converts the generic <see cref="IEnumerable{ISymbol}"/> to a <see cref="IEnumerable{HtmlSymbol}"/> and
 /// finds the first <see cref="HtmlSymbol"/> with type <paramref name="type"/>.
 /// </summary>
 /// <param name="symbols">The <see cref="IEnumerable{ISymbol}"/> instance this method extends.</param>
 /// <param name="type">The <see cref="HtmlSymbolType"/> to search for.</param>
 /// <returns>The first <see cref="HtmlSymbol"/> of type <paramref name="type"/>.</returns>
 public static HtmlSymbol FirstHtmlSymbolAs(this IEnumerable <ISymbol> symbols, HtmlSymbolType type)
 {
     return(symbols.OfType <HtmlSymbol>().FirstOrDefault(sym => (type & sym.Type) == sym.Type));
 }
示例#19
0
 public SpanConstructor Span(SpanKind kind, string content, HtmlSymbolType type)
 {
     return CreateSymbolSpan(kind, content, st => new HtmlSymbol(st, content, type));
 }
示例#20
0
        private void AttributeValue(HtmlSymbolType quote)
        {
            SourceLocation prefixStart = CurrentLocation;
            var            prefix      = ReadWhile(
                sym => sym.Type == HtmlSymbolType.WhiteSpace || sym.Type == HtmlSymbolType.NewLine
                );

            Accept(prefix);

            if (At(HtmlSymbolType.Transition))
            {
                SourceLocation valueStart = CurrentLocation;
                PutCurrentBack();

                // Output the prefix but as a null-span. DynamicAttributeBlockCodeGenerator will render it
                Span.CodeGenerator = SpanCodeGenerator.Null;

                // Dynamic value, start a new block and set the code generator
                using (Context.StartBlock(BlockType.Markup))
                {
                    Context.CurrentBlock.CodeGenerator = new DynamicAttributeBlockCodeGenerator(
                        prefix.GetContent(prefixStart),
                        valueStart
                        );

                    OtherParserBlock();
                }
            }
            else if (
                At(HtmlSymbolType.Text) &&
                CurrentSymbol.Content.Length > 0 &&
                CurrentSymbol.Content[0] == '~' &&
                NextIs(HtmlSymbolType.Solidus)
                )
            {
                // Virtual Path value
                SourceLocation valueStart = CurrentLocation;
                VirtualPath();
                Span.CodeGenerator = new LiteralAttributeCodeGenerator(
                    prefix.GetContent(prefixStart),
                    new LocationTagged <SpanCodeGenerator>(new ResolveUrlCodeGenerator(), valueStart)
                    );
            }
            else
            {
                // Literal value
                // 'quote' should be "Unknown" if not quoted and symbols coming from the tokenizer should never have "Unknown" type.
                var value = ReadWhile(
                    sym =>
                    // These three conditions find separators which break the attribute value into portions
                    sym.Type != HtmlSymbolType.WhiteSpace &&
                    sym.Type != HtmlSymbolType.NewLine &&
                    sym.Type != HtmlSymbolType.Transition
                    &&
                    // This condition checks for the end of the attribute value (it repeats some of the checks above but for now that's ok)
                    !IsEndOfAttributeValue(quote, sym)
                    );
                Accept(value);
                Span.CodeGenerator = new LiteralAttributeCodeGenerator(
                    prefix.GetContent(prefixStart),
                    value.GetContent(prefixStart)
                    );
            }
            Output(SpanKind.Markup);
        }