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); }
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); }
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); }
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); } }
public static SpanConstructor MarkupTransition(this SpanFactory self, HtmlSymbolType type) { return(self .Span(SpanKindInternal.Transition, SyntaxConstants.TransitionString, type) .Accepts(AcceptedCharactersInternal.None)); }
public SpanConstructor Span(SpanKindInternal kind, string content, HtmlSymbolType type) { return(CreateSymbolSpan(kind, content, () => new HtmlSymbol(content, type))); }
/// <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); }
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(); } }
public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type) { return(self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None)); }
/// <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)); }
public SpanConstructor Span(SpanKind kind, string content, HtmlSymbolType type) { return CreateSymbolSpan(kind, content, st => new HtmlSymbol(st, content, type)); }
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); }