Represents a single row in the table.
        /// <summary>
        /// Parses a table block.
        /// </summary>
        /// <param name="markdown"> The markdown text. </param>
        /// <param name="start"> The location of the first character in the block. </param>
        /// <param name="endOfFirstLine"> The location of the end of the first line. </param>
        /// <param name="maxEnd"> The location to stop parsing. </param>
        /// <param name="quoteDepth"> The current nesting level for block quoting. </param>
        /// <param name="actualEnd"> Set to the end of the block when the return value is non-null. </param>
        /// <returns> A parsed table block, or <c>null</c> if this is not a table block. </returns>
        internal static TableBlock Parse(string markdown, int start, int endOfFirstLine, int maxEnd, int quoteDepth, out int actualEnd)
        {
            // A table is a line of text, with at least one vertical bar (|), followed by a line of
            // of text that consists of alternating dashes (-) and vertical bars (|) and optionally
            // vertical bars at the start and end.  The second line must have at least as many
            // interior vertical bars as there are interior vertical bars on the first line.

            actualEnd = start;

            // First thing to do is to check if there is a vertical bar on the line.
            int barOrNewLineIndex = markdown.IndexOf('|', start, endOfFirstLine - start);
            if (barOrNewLineIndex < 0)
                return null;

            var rows = new List<TableRow>();

            // Parse the first row.
            var firstRow = new TableRow();
            start = firstRow.Parse(markdown, start, maxEnd, quoteDepth);
            rows.Add(firstRow);

            // Parse the contents of the second row.
            var secondRowContents = new List<string>();
            start = TableRow.ParseContents(markdown, start, maxEnd, quoteDepth, requireVerticalBar: false,
                contentParser: (start2, end2) => secondRowContents.Add(markdown.Substring(start2, end2 - start2)));

            // There must be at least as many columns in the second row as in the first row.
            if (secondRowContents.Count < firstRow.Cells.Count)
                return null;

            // Check each column definition.
            // Note: excess columns past firstRowColumnCount are ignored and can contain anything.
            var columnDefinitions = new List<TableColumnDefinition>(firstRow.Cells.Count);
            for (int i = 0; i < firstRow.Cells.Count; i++)
            {
                var cellContent = secondRowContents[i];
                if (cellContent.Length == 0)
                    return null;

                // The first and last characters can be '-' or ':'.
                if (cellContent[0] != ':' && cellContent[0] != '-')
                    return null;
                if (cellContent[cellContent.Length - 1] != ':' && cellContent[cellContent.Length - 1] != '-')
                    return null;

                // Every other character must be '-'.
                for (int j = 1; j < cellContent.Length - 1; j++)
                    if (cellContent[j] != '-')
                        return null;

                // Record the alignment.
                var columnDefinition = new TableColumnDefinition();
                if (cellContent.Length > 1 && cellContent[0] == ':' && cellContent[cellContent.Length - 1] == ':')
                    columnDefinition.Alignment = ColumnAlignment.Center;
                else if (cellContent[0] == ':')
                    columnDefinition.Alignment = ColumnAlignment.Left;
                else if (cellContent[cellContent.Length - 1] == ':')
                    columnDefinition.Alignment = ColumnAlignment.Right;
                columnDefinitions.Add(columnDefinition);
            }

            // Parse additional rows.
            while (start < maxEnd)
            {
                var row = new TableRow();
                start = row.Parse(markdown, start, maxEnd, quoteDepth);
                if (row.Cells.Count == 0)
                    break;
                rows.Add(row);
            }

            actualEnd = start;
            return new TableBlock { ColumnDefinitions = columnDefinitions, Rows = rows };
        }