Exemplo n.º 1
0
        public override BlockState TryOpen(BlockProcessor processor)
        {
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var column         = processor.Column;
            var sourcePosition = processor.Start;

            // 5.1 Block quotes
            // A block quote marker consists of 0-3 spaces of initial indent, plus (a) the character > together with a following space, or (b) a single character > not followed by a space.
            var quoteChar = processor.CurrentChar;
            var c         = processor.NextChar();

            if (c.IsSpaceOrTab())
            {
                processor.NextColumn();
            }
            processor.NewBlocks.Push(new QuoteBlock(this)
            {
                QuoteChar = quoteChar,
                Column    = column,
                Span      = new SourceSpan(sourcePosition, processor.Line.End),
            });
            return(BlockState.Continue);
        }
Exemplo n.º 2
0
        public override BlockState TryContinue(BlockProcessor processor, Block block)
        {
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var quote          = (QuoteBlock)block;
            var sourcePosition = processor.Start;

            // 5.1 Block quotes
            // A block quote marker consists of 0-3 spaces of initial indent, plus (a) the character > together with a following space, or (b) a single character > not followed by a space.
            var  c = processor.CurrentChar;
            bool hasSpaceAfterQuoteChar = false;

            if (c != quote.QuoteChar)
            {
                if (processor.IsBlankLine)
                {
                    return(BlockState.BreakDiscard);
                }
                else
                {
                    quote.QuoteLines.Add(new QuoteBlockLine
                    {
                        QuoteChar = false,
                        NewLine   = processor.Line.NewLine,
                    });
                    return(BlockState.None);
                }
            }
            c = processor.NextChar(); // Skip quote marker char
            if (c == ' ')
            {
                processor.NextColumn();
                hasSpaceAfterQuoteChar         = true;
                processor.SkipFirstUnwindSpace = true;
            }
            else if (c == '\t')
            {
                processor.NextColumn();
            }
            var         TriviaSpaceBefore = processor.UseTrivia(sourcePosition - 1);
            StringSlice triviaAfter       = StringSlice.Empty;
            bool        wasEmptyLine      = false;

            if (processor.Line.IsEmptyOrWhitespace())
            {
                processor.TriviaStart = processor.Start;
                triviaAfter           = processor.UseTrivia(processor.Line.End);
                wasEmptyLine          = true;
            }
            quote.QuoteLines.Add(new QuoteBlockLine
            {
                QuoteChar = true,
                HasSpaceAfterQuoteChar = hasSpaceAfterQuoteChar,
                TriviaBefore           = TriviaSpaceBefore,
                TriviaAfter            = triviaAfter,
                NewLine = processor.Line.NewLine,
            });

            if (!wasEmptyLine)
            {
                processor.TriviaStart = processor.Start;
            }
            block.UpdateSpanEnd(processor.Line.End);
            return(BlockState.Continue);
        }
Exemplo n.º 3
0
        private BlockState TryParseListItem(BlockProcessor state, Block block)
        {
            // If we have a code indent and we are not in a ListItem, early exit
            if (!(block is ListItemBlock) && state.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var currentListItem = block as ListItemBlock;
            var currentParent   = block as ListBlock ?? (ListBlock)currentListItem?.Parent;

            var initColumnBeforeIndent = state.ColumnBeforeIndent;
            var initColumn             = state.Column;
            var sourcePosition         = state.Start;
            var sourceEndPosition      = state.Line.End;

            var  c          = state.CurrentChar;
            var  itemParser = mapItemParsers[c];
            bool isOrdered  = itemParser is OrderedListItemParser;

            if (itemParser == null)
            {
                return(BlockState.None);
            }

            // Try to parse the list item
            ListInfo listInfo;

            if (!itemParser.TryParse(state, currentParent?.BulletType ?? '\0', out listInfo))
            {
                // Reset to an a start position
                state.GoToColumn(initColumn);
                return(BlockState.None);
            }

            // Gets the current character after a succesfull parsing of the list information
            c = state.CurrentChar;

            // Item starting with a blank line
            int columnWidth;

            // Do we have a blank line right after the bullet?
            if (c == '\0')
            {
                // Use a negative number to store the number of expected chars
                columnWidth = -(state.Column - initColumnBeforeIndent + 1);
            }
            else
            {
                if (!c.IsSpaceOrTab())
                {
                    state.GoToColumn(initColumn);
                    return(BlockState.None);
                }

                // We require at least one char
                state.NextColumn();

                // Parse the following indent
                state.RestartIndent();
                var columnBeforeIndent = state.Column;
                state.ParseIndent();

                if (state.IsCodeIndent)
                {
                    state.GoToColumn(columnBeforeIndent);
                }

                // Number of spaces required for the following content to be part of this list item
                // If the list item starts with a blank line, the number of spaces
                // following the list marker doesn't change the required indentation
                columnWidth = (state.IsBlankLine ? columnBeforeIndent : state.Column) - initColumnBeforeIndent;
            }

            var newListItem = new ListItemBlock(this)
            {
                Column      = initColumn,
                ColumnWidth = columnWidth,
                Span        = new SourceSpan(sourcePosition, sourceEndPosition)
            };

            state.NewBlocks.Push(newListItem);

            if (currentParent != null)
            {
                // If we have a new list item, close the previous one
                if (currentListItem != null)
                {
                    state.Close(currentListItem);
                }

                // Reset the list if it is a new list or a new type of bullet
                if (currentParent.IsOrdered != isOrdered ||
                    currentParent.OrderedDelimiter != listInfo.OrderedDelimiter ||
                    currentParent.BulletType != listInfo.BulletType)
                {
                    state.Close(currentParent);
                    currentParent = null;
                }
            }

            if (currentParent == null)
            {
                var newList = new ListBlock(this)
                {
                    Column              = initColumn,
                    Span                = new SourceSpan(sourcePosition, sourceEndPosition),
                    IsOrdered           = isOrdered,
                    BulletType          = listInfo.BulletType,
                    OrderedDelimiter    = listInfo.OrderedDelimiter,
                    DefaultOrderedStart = listInfo.DefaultOrderedStart,
                    OrderedStart        = listInfo.OrderedStart,
                };
                state.NewBlocks.Push(newList);
            }

            return(BlockState.Continue);
        }
Exemplo n.º 4
0
        public override BlockState TryOpen(BlockProcessor processor)
        {
            if (processor.IsCodeIndent)
            {
                return(BlockState.None);
            }

            var sourcePosition = processor.Start;

            // 5.1 Block quotes
            // A block quote marker consists of 0-3 spaces of initial indent, plus (a) the character > together with a following space, or (b) a single character > not followed by a space.
            var quoteChar = processor.CurrentChar;
            var column    = processor.Column;
            var c         = processor.NextChar();

            var quoteBlock = new QuoteBlock(this)
            {
                QuoteChar   = quoteChar,
                Column      = column,
                Span        = new SourceSpan(sourcePosition, processor.Line.End),
                LinesBefore = processor.UseLinesBefore()
            };

            bool hasSpaceAfterQuoteChar = false;

            if (c == ' ')
            {
                processor.NextColumn();
                hasSpaceAfterQuoteChar         = true;
                processor.SkipFirstUnwindSpace = true;
            }
            else if (c == '\t')
            {
                processor.NextColumn();
            }

            var         triviaBefore = processor.UseTrivia(sourcePosition - 1);
            StringSlice triviaAfter  = StringSlice.Empty;
            bool        wasEmptyLine = false;

            if (processor.Line.IsEmptyOrWhitespace())
            {
                processor.TriviaStart = processor.Start;
                triviaAfter           = processor.UseTrivia(processor.Line.End);
                wasEmptyLine          = true;
            }
            quoteBlock.QuoteLines.Add(new QuoteBlockLine
            {
                TriviaBefore           = triviaBefore,
                TriviaAfter            = triviaAfter,
                QuoteChar              = true,
                HasSpaceAfterQuoteChar = hasSpaceAfterQuoteChar,
                NewLine = processor.Line.NewLine,
            });
            processor.NewBlocks.Push(quoteBlock);
            if (!wasEmptyLine)
            {
                processor.TriviaStart = processor.Start;
            }
            return(BlockState.Continue);
        }