diff --git a/src/Markdig.Tests/TestSourcePosition.cs b/src/Markdig.Tests/TestSourcePosition.cs
index 27212653..eed7139a 100644
--- a/src/Markdig.Tests/TestSourcePosition.cs
+++ b/src/Markdig.Tests/TestSourcePosition.cs
@@ -834,6 +834,29 @@ literal ( 2, 2) 11-11
", "pipetables");
}
+ [Test]
+ public void TestGridTable()
+ {
+ Check("0\n\n+-+-+\n|A|B|\n+=+=+\n|C|D|\n+-+-+", @"
+paragraph ( 0, 0) 0-0
+literal ( 0, 0) 0-0
+table ( 2, 0) 3-31
+tablerow ( 3, 0) 9-13
+tablecell ( 3, 0) 9-11
+paragraph ( 3, 1) 10-10
+literal ( 3, 1) 10-10
+tablecell ( 3, 2) 11-13
+paragraph ( 3, 3) 12-12
+literal ( 3, 3) 12-12
+tablerow ( 5, 0) 21-25
+tablecell ( 5, 0) 21-23
+paragraph ( 5, 1) 22-22
+literal ( 5, 1) 22-22
+tablecell ( 5, 2) 23-25
+paragraph ( 5, 3) 24-24
+literal ( 5, 3) 24-24", "gridtables");
+ }
+
[Test]
public void TestIndentedCode()
{
diff --git a/src/Markdig/Extensions/Tables/GridTableParser.cs b/src/Markdig/Extensions/Tables/GridTableParser.cs
index 847bd94c..30ce2c3d 100644
--- a/src/Markdig/Extensions/Tables/GridTableParser.cs
+++ b/src/Markdig/Extensions/Tables/GridTableParser.cs
@@ -1,10 +1,11 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
-// This file is licensed under the BSD-Clause 2 license.
+// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Syntax;
+using System.Linq;
namespace Markdig.Extensions.Tables;
@@ -60,7 +61,12 @@ public class GridTableParser : BlockParser
}
// Store the line (if we need later to build a ParagraphBlock because the GridTable was in fact invalid)
tableState.AddLine(ref processor.Line);
- var table = new Table(this);
+ var table = new Table(this)
+ {
+ Line = processor.LineIndex,
+ Column = processor.Column,
+ Span = { Start = lineStart }
+ };
table.SetData(typeof(GridTableState), tableState);
// Calculate the total width of all columns
@@ -94,10 +100,12 @@ public class GridTableParser : BlockParser
tableState.AddLine(ref processor.Line);
if (processor.CurrentChar == '+')
{
+ gridTable.UpdateSpanEnd(processor.Line.End);
return HandleNewRow(processor, tableState, gridTable);
}
if (processor.CurrentChar == '|')
{
+ gridTable.UpdateSpanEnd(processor.Line.End);
return HandleContents(processor, tableState, gridTable);
}
TerminateCurrentRow(processor, tableState, gridTable, true);
@@ -182,8 +190,18 @@ public class GridTableParser : BlockParser
var columnSlice = columns[i];
if (columnSlice.CurrentCell != null)
{
- currentRow ??= new TableRow();
-
+ if (currentRow == null)
+ {
+ TableCell firstCell = columns.First(c => c.CurrentCell != null).CurrentCell!;
+ TableCell lastCell = columns.Last(c => c.CurrentCell != null).CurrentCell!;
+
+ currentRow ??= new TableRow()
+ {
+ Span = new SourceSpan(firstCell.Span.Start, lastCell.Span.End),
+ Line = firstCell.Line
+ };
+ }
+
// If this cell does not already belong to a row
if (columnSlice.CurrentCell.Parent is null)
{
@@ -271,7 +289,10 @@ public class GridTableParser : BlockParser
columnSlice.CurrentCell = new TableCell(this)
{
ColumnSpan = columnSlice.CurrentColumnSpan,
- ColumnIndex = i
+ ColumnIndex = i,
+ Column = columnSlice.Start,
+ Line = processor.LineIndex,
+ Span = new SourceSpan(line.Start + columnSlice.Start, line.Start + columnSlice.End)
};
columnSlice.BlockProcessor ??= processor.CreateChild();
@@ -281,7 +302,8 @@ public class GridTableParser : BlockParser
}
// Process the content of the cell
columnSlice.BlockProcessor!.LineIndex = processor.LineIndex;
- columnSlice.BlockProcessor.ProcessLine(sliceForCell);
+
+ columnSlice.BlockProcessor.ProcessLinePart(sliceForCell, sliceForCell.Start - line.Start);
}
// Go to next column
diff --git a/src/Markdig/Parsers/BlockProcessor.cs b/src/Markdig/Parsers/BlockProcessor.cs
index 225ed971..39f03d3f 100644
--- a/src/Markdig/Parsers/BlockProcessor.cs
+++ b/src/Markdig/Parsers/BlockProcessor.cs
@@ -493,8 +493,34 @@ public class BlockProcessor
ContinueProcessingLine = true;
- ResetLine(newLine);
+ ResetLine(newLine, 0);
+ Process();
+
+ LineIndex++;
+ }
+
+ ///
+ /// Processes part of a line.
+ ///
+ /// The line.
+ /// The column.
+ public void ProcessLinePart(StringSlice line, int column)
+ {
+ CurrentLineStartPosition = line.Start - column;
+
+ ContinueProcessingLine = true;
+
+ ResetLine(line, column);
+
+ Process();
+ }
+
+ ///
+ /// Process current string slice.
+ ///
+ private void Process()
+ {
TryContinueBlocks();
// If the line was not entirely processed by pending blocks, try to process it with any new block
@@ -502,8 +528,6 @@ public class BlockProcessor
// Close blocks that are no longer opened
CloseAll(false);
-
- LineIndex++;
}
internal bool IsOpen(Block block)
@@ -956,18 +980,17 @@ public class BlockProcessor
ContinueProcessingLine = !result.IsDiscard();
}
- private void ResetLine(StringSlice newLine)
+ private void ResetLine(StringSlice newLine, int column)
{
Line = newLine;
- Column = 0;
+ Column = column;
ColumnBeforeIndent = 0;
StartBeforeIndent = Start;
- originalLineStart = newLine.Start;
+ originalLineStart = newLine.Start - column;
TriviaStart = newLine.Start;
}
-
[MemberNotNull(nameof(Document), nameof(Parsers))]
internal void Setup(MarkdownDocument document, BlockParserList parsers, MarkdownParserContext? context, bool trackTrivia)
{