public static void ProcessStage2(Syntax.Block document, CommonMarkSettings settings = null)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (document.Tag != Syntax.BlockTag.Document)
            {
                throw new ArgumentException("The block element passed to this method must represent a top level document.", nameof(document));
            }

            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            try
            {
                BlockMethods.ProcessInlines(document, document.Document, settings);
            }
            catch (CommonMarkException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new CommonMarkException("An error occurred during inline parsing.", ex);
            }
        }
        public static void ProcessStage3(Syntax.Block document, TextWriter target, CommonMarkSettings settings = null)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (document.Tag != Syntax.BlockTag.Document)
            {
                throw new ArgumentException("The block element passed to this method must represent a top level document.", nameof(document));
            }

            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            try
            {
                switch (settings.OutputFormat)
                {
                case OutputFormat.Html:
                    HtmlFormatterSlim.BlocksToHtml(target, document, settings);
                    break;

                case OutputFormat.SyntaxTree:
                    Printer.PrintBlocks(target, document, settings);
                    break;

                case OutputFormat.CustomDelegate:
                    if (settings.OutputDelegate == null)
                    {
                        throw new CommonMarkException("If `settings.OutputFormat` is set to `CustomDelegate`, the `settings.OutputDelegate` property must be populated.");
                    }
                    settings.OutputDelegate(document, target, settings);
                    break;

                default:
                    throw new CommonMarkException("Unsupported value '" + settings.OutputFormat + "' in `settings.OutputFormat`.");
                }
            }
            catch (CommonMarkException)
            {
                throw;
            }
            catch (IOException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new CommonMarkException("An error occurred during formatting of the document.", ex);
            }
        }
        public static Syntax.Block ProcessStage1(TextReader source, CommonMarkSettings settings = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            var cur  = Syntax.Block.CreateDocument();
            var doc  = cur;
            var line = new LineInfo(settings.TrackSourcePosition);

            try
            {
                var reader = new TabTextReader(source);
                reader.ReadLine(line);
                while (line.Line != null)
                {
                    BlockMethods.IncorporateLine(line, ref cur);
                    reader.ReadLine(line);
                }
            }
            catch (IOException)
            {
                throw;
            }
            catch (CommonMarkException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new CommonMarkException("An error occurred while parsing line " + line.ToString(), cur, ex);
            }

            try
            {
                do
                {
                    BlockMethods.Finalize(cur, line);
                    cur = cur.Parent;
                } while (cur != null);
            }
            catch (CommonMarkException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new CommonMarkException("An error occurred while finalizing open containers.", cur, ex);
            }

            return(doc);
        }
        /// <summary>
        /// Parses the given source data and returns the document syntax tree. Use <see cref="ProcessStage3"/> to
        /// convert the document to HTML using the built-in converter.
        /// </summary>
        /// <param name="source">The source data.</param>
        /// <param name="settings">The object containing settings for the parsing and formatting process.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="source"/> is <see langword="null"/></exception>
        /// <exception cref="CommonMarkException">when errors occur during parsing.</exception>
        /// <exception cref="IOException">when error occur while reading or writing the data.</exception>
        public static Syntax.Block Parse(string source, CommonMarkSettings settings = null)
        {
            if (source == null)
            {
                return(null);
            }

            using (var reader = new System.IO.StringReader(source))
                return(Parse(reader, settings));
        }
        /// <summary>
        /// Converts the given source data and writes the result directly to the target.
        /// </summary>
        /// <param name="source">The reader that contains the source data.</param>
        /// <param name="target">The target text writer where the result will be written to.</param>
        /// <param name="settings">The object containing settings for the parsing and formatting process.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="source"/> or <paramref name="target"/> is <see langword="null"/></exception>
        /// <exception cref="CommonMarkException">when errors occur during parsing or formatting.</exception>
        /// <exception cref="IOException">when error occur while reading or writing the data.</exception>
        public static void Convert(TextReader source, TextWriter target, CommonMarkSettings settings = null)
        {
            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            var document = ProcessStage1(source, settings);

            ProcessStage2(document, settings);
            ProcessStage3(document, target, settings);
        }
        /// <summary>
        /// Parses the given source data and returns the document syntax tree. Use <see cref="ProcessStage3"/> to
        /// convert the document to HTML using the built-in converter.
        /// </summary>
        /// <param name="source">The reader that contains the source data.</param>
        /// <param name="settings">The object containing settings for the parsing and formatting process.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="source"/> is <see langword="null"/></exception>
        /// <exception cref="CommonMarkException">when errors occur during parsing.</exception>
        /// <exception cref="IOException">when error occur while reading or writing the data.</exception>
        public static Syntax.Block Parse(TextReader source, CommonMarkSettings settings = null)
        {
            if (settings == null)
            {
                settings = CommonMarkSettings.Default;
            }

            var document = ProcessStage1(source, settings);

            ProcessStage2(document, settings);
            return(document);
        }
        /// <summary>
        /// Converts the given source data and returns the result as a string.
        /// </summary>
        /// <param name="source">The source data.</param>
        /// <param name="settings">The object containing settings for the parsing and formatting process.</param>
        /// <exception cref="CommonMarkException">when errors occur during parsing or formatting.</exception>
        /// <returns>The converted data.</returns>
        public static string Convert(string source, CommonMarkSettings settings = null)
        {
            if (source == null)
            {
                return(null);
            }

            using (var reader = new System.IO.StringReader(source))
                using (var writer = new System.IO.StringWriter(System.Globalization.CultureInfo.CurrentCulture))
                {
                    Convert(reader, writer, settings);

                    return(writer.ToString());
                }
        }