private static ContainerOrTerminalNode ParseBlock(ContainerBlock block, CharacterPositionFinder finder, TextProvider textProvider)
        {
            var name         = GetName(block, textProvider);
            var type         = GetType(block);
            var locationSpan = GetLocationSpan(block, finder);

            var container = new Container
            {
                Type         = type,
                Name         = name,
                LocationSpan = locationSpan,
                HeaderSpan   = GetHeaderSpan(block),
                FooterSpan   = GetFooterSpan(block),
            };

            if (block is ListBlock list)
            {
                foreach (var listItem in list)
                {
                    var item = ParseBlock(listItem, finder, textProvider);
                    container.Children.Add(item);
                }
            }

            // TODO: RKN
            // - Table
            // - ListBlock

            // check whether we can use a terminal node instead
            var child = FinalAdjustAfterParsingComplete(container);

            return(child);
        }
        public static File ParseCore(string filePath, CharacterPositionFinder finder, Encoding encoding)
        {
            var text = SystemFile.ReadAllText(filePath, encoding);

            var file = new File
            {
                Name       = filePath,
                FooterSpan = new CharacterSpan(0, -1),                // there is no footer
            };

            try
            {
                var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
                var document = MarkdownParser.Parse(text, pipeline);

                var textProvider = new TextProvider(text);

                var locationSpan = GetLocationSpan(document, finder);

                var rootBlock = new Container
                {
                    Type         = "markdown",
                    Name         = string.Empty,
                    LocationSpan = locationSpan,
                    HeaderSpan   = new CharacterSpan(0, 0),                             // there is no header
                    FooterSpan   = new CharacterSpan(text.Length - 1, text.Length - 1), // there is no footer
                };
                file.Children.Add(rootBlock);

                // Parse the file and display the text content of each of the elements.
                var blocks = document.Where(_ => !_.Span.IsEmpty).ToList();
                foreach (var block in blocks)
                {
                    var parsedBlock = ParseBlock(block, finder, textProvider);
                    rootBlock.Children.Add(parsedBlock);
                }

                file.LocationSpan = locationSpan;
            }
            catch (Exception ex)
            {
                // try to adjust location span to include full file content
                // but ignore empty files as parsing errors
                var lines = SystemFile.ReadLines(filePath).Count();
                if (lines == 0)
                {
                    file.LocationSpan = new LocationSpan(new LineInfo(0, -1), new LineInfo(0, -1));
                }
                else
                {
                    file.ParsingErrors.Add(new ParsingError
                    {
                        ErrorMessage = ex.Message,
                        Location     = new LineInfo(0, -1),
                    });

                    file.LocationSpan = new LocationSpan(new LineInfo(1, 0), new LineInfo(lines + 1, 0));
                }
            }

            return(file);
        }
 private static ContainerOrTerminalNode FinalAdjustAfterParsingComplete(Container container) => container;