예제 #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;
            }
        private static MarkdownDocument CreateDocument(List <Block> blocks)
        {
            var result = new MarkdownDocument();

            foreach (var block in blocks)
            {
                block.Parent?.Remove(block);
                result.Add(block);
            }
            return(result);
        }
예제 #3
0
        private MarkdownDocument CreateDocument(List <Block> blocks)
        {
            var result = new MarkdownDocument();

            foreach (var block in blocks)
            {
                block.Parent?.Remove(block);
                result.Add(block);
            }
            result.SetData("filePath", _file);
            return(result);
        }
예제 #4
0
        protected async Task <MarkdownDocument> ExtractVersionDocument(MarkdownStream changelogMarkdown)
        {
            using var reader = new StreamReader(changelogMarkdown.Stream, leaveOpen: true);
            var text = await reader.ReadToEndAsync();

            var document = Markdown.Parse(text);
            var nodes    = ExtractDocumentBlocksDestructively(document).ToList();

            var sectionDocument = new MarkdownDocument();

            foreach (var block in nodes)
            {
                sectionDocument.Add(block);
            }

            return(sectionDocument);
        }
        private MarkdownDocument CreateDocument(MarkdownPropertyModel model)
        {
            var result = new MarkdownDocument();

            if (model != null)
            {
                foreach (var block in model.PropertyValue)
                {
                    block.Parent?.Remove(block);
                    result.Add(block);
                }
                result.SetData("filePath", _file);
                result.SetData(Constants.OPathStringDataName, model.PropertyName);
                result.SetData(Constants.OPathLineNumberDataName, model.PropertyNameSource.Line + 1);
            }
            return(result);
        }
예제 #6
0
        private static MarkdownDocument ExtractChangelogFromBody(string markdownText)
        {
            if (string.IsNullOrEmpty(markdownText))
            {
                throw new ArgumentNullException(nameof(markdownText));
            }

            MarkdownDocument markdownDocument = Markdown.Parse(markdownText);
            MarkdownDocument result           = new MarkdownDocument();

            foreach (Block block in markdownDocument.SkipWhile(block => !(block is HeadingBlock headingBlock) || (headingBlock.Inline.FirstChild == null) || !(headingBlock.Inline.FirstChild is LiteralInline literalInline) || (literalInline.Content.ToString() != "Changelog")).Skip(1).TakeWhile(block => !(block is ThematicBreakBlock)).ToList())
            {
                // All blocks that we're interested in must be removed from original markdownDocument firstly
                markdownDocument.Remove(block);
                result.Add(block);
            }

            return(result);
        }
예제 #7
0
        private static void AssertSyntax(string expected, MarkdownObject syntax)
        {
            var writer     = new StringWriter();
            var normalizer = new NormalizeRenderer(writer);
            var document   = new MarkdownDocument();

            if (syntax is Block)
            {
                document.Add(syntax as Block);
            }
            else
            {
                throw new InvalidOperationException();
            }
            normalizer.Render(document);

            var actual = writer.ToString();

            Assert.AreEqual(expected, actual);
        }
예제 #8
0
        private void ProcessBlocks()
        {
            while (true)
            {
                // Get the precise position of the begining of the line
                var lineText = lineReader.ReadLine();

                // If this is the end of file and the last line is empty
                if (lineText.Text is null)
                {
                    if (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);
                        }
                    }
                    break;
                }
                blockProcessor.ProcessLine(lineText);
            }