Пример #1
0
        /// <summary>
        /// Parses the specified markdown into an AST <see cref="MarkdownDocument"/>
        /// </summary>
        /// <param name="text">A Markdown text</param>
        /// <param name="pipeline">The pipeline used for the parsing.</param>
        /// <param name="context">A parser context used for the parsing.</param>
        /// <returns>An AST Markdown document</returns>
        /// <exception cref="ArgumentNullException">if reader variable is null</exception>
        public static MarkdownDocument Parse(string text, MarkdownPipeline?pipeline = null, MarkdownParserContext?context = null)
        {
            if (text is null)
            {
                ThrowHelper.ArgumentNullException_text();
            }

            pipeline ??= Markdown.DefaultPipeline;

            text = FixupZero(text);

            var document = new MarkdownDocument
            {
                IsOpen = true
            };

            if (pipeline.PreciseSourceLocation)
            {
                int roughLineCountEstimate = text.Length / 32;
                roughLineCountEstimate    = Math.Max(4, Math.Min(512, roughLineCountEstimate));
                document.LineStartIndexes = new List <int>(roughLineCountEstimate);
            }

            var blockProcessor = BlockProcessor.Rent(document, pipeline.BlockParsers, context, pipeline.TrackTrivia);

            try
            {
                blockProcessor.Open(document);

                ProcessBlocks(blockProcessor, new LineReader(text));

                if (pipeline.TrackTrivia)
                {
                    Block?lastBlock = blockProcessor.LastBlock;
                    if (lastBlock is null && document.Count == 0)
                    {
                        // this means we have unassigned characters
                        var noBlocksFoundBlock         = new EmptyBlock(null);
                        List <StringSlice> linesBefore = blockProcessor.UseLinesBefore();
                        noBlocksFoundBlock.LinesAfter = new List <StringSlice>();
                        noBlocksFoundBlock.LinesAfter.AddRange(linesBefore);
                        document.Add(noBlocksFoundBlock);
                    }
                    else if (lastBlock != null && blockProcessor.LinesBefore != null)
                    {
                        // this means we're out of lines, but still have unassigned empty lines.
                        // thus, we'll assign the empty unsassigned lines to the last block
                        // of the document.
                        var rootMostContainerBlock = Block.FindRootMostContainerParent(lastBlock);
                        rootMostContainerBlock.LinesAfter ??= new List <StringSlice>();
                        var linesBefore = blockProcessor.UseLinesBefore();
                        rootMostContainerBlock.LinesAfter.AddRange(linesBefore);
                    }
                }

                // At this point the LineIndex is the same as the number of lines in the document
                document.LineCount = blockProcessor.LineIndex;
            }