diff --git a/src/Markdig.Tests/TestPipeTable.cs b/src/Markdig.Tests/TestPipeTable.cs
index f36f9fb0..06bf3849 100644
--- a/src/Markdig.Tests/TestPipeTable.cs
+++ b/src/Markdig.Tests/TestPipeTable.cs
@@ -1,5 +1,7 @@
+using Markdig;
using Markdig.Extensions.Tables;
using Markdig.Syntax;
+using Markdig.Syntax.Inlines;
namespace Markdig.Tests;
@@ -101,4 +103,103 @@ public void TableWithUnbalancedCodeSpanParsesWithoutDepthLimitError()
Assert.That(html, Does.Contain("
`C"));
}
+
+ [Test]
+ public void CodeInlineWithPipeDelimitersRemainsCodeInline()
+ {
+ const string markdown = "`|| hidden text ||`";
+
+ var pipeline = new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .Build();
+
+ var document = Markdown.Parse(markdown, pipeline);
+
+ var codeInline = document.Descendants().OfType().SingleOrDefault();
+ Assert.IsNotNull(codeInline);
+ Assert.That(codeInline!.Content, Is.EqualTo("|| hidden text ||"));
+ Assert.That(document.ToHtml(), Is.EqualTo("|| hidden text ||
\n"));
+ }
+
+ [Test]
+ public void MultiLineCodeInlineWithPipeDelimitersRendersAsCode()
+ {
+ string markdown =
+ """
+ `
+ || hidden text ||
+ `
+ """.ReplaceLineEndings("\n");
+
+ var pipeline = new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .Build();
+
+ var html = Markdown.ToHtml(markdown, pipeline);
+
+ Assert.That(html, Is.EqualTo("|| hidden text ||
\n"));
+ }
+
+ [Test]
+ public void TableCellWithCodeInlineRendersCorrectly()
+ {
+ const string markdown =
+ """
+ | Count | A | B | C | D | E |
+ |-------|---|---|---|---|---|
+ | 0 | B | C | D | E | F |
+ | 1 | B | `Code block` | D | E | F |
+ | 2 | B | C | D | E | F |
+ """;
+
+ var pipeline = new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .Build();
+
+ var html = Markdown.ToHtml(markdown, pipeline);
+
+ Assert.That(html, Does.Contain("Code block | "));
+ }
+
+ [Test]
+ public void CodeInlineWithIndentedContentPreservesWhitespace()
+ {
+ const string markdown = "`\n foo\n`";
+
+ var pipeline = new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .Build();
+
+ var document = Markdown.Parse(markdown, pipeline);
+ var codeInline = document.Descendants().OfType().Single();
+
+ Assert.That(codeInline.Content, Is.EqualTo("foo"));
+ Assert.That(Markdown.ToHtml(markdown, pipeline), Is.EqualTo("foo
\n"));
+ }
+
+ [Test]
+ public void TableWithIndentedPipeAfterCodeInlineParsesCorrectly()
+ {
+ var markdown =
+ """
+ `
+ || hidden text ||
+ `
+
+ | Count | Value |
+ |-------|-------|
+ | 0 | B |
+
+ """.ReplaceLineEndings("\n");
+
+ var pipeline = new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .Build();
+
+ var html = Markdown.ToHtml(markdown, pipeline);
+
+ Assert.That(html, Does.Contain("|| hidden text ||
"));
+ Assert.That(html, Does.Contain("B"));
+ }
}
diff --git a/src/Markdig/Helpers/HtmlHelper.cs b/src/Markdig/Helpers/HtmlHelper.cs
index 4887653f..317c6dde 100644
--- a/src/Markdig/Helpers/HtmlHelper.cs
+++ b/src/Markdig/Helpers/HtmlHelper.cs
@@ -1,5 +1,5 @@
// 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 System.Diagnostics;
@@ -430,7 +430,7 @@ private static bool TryParseHtmlTagHtmlComment(ref StringSlice text, ref ValueSt
const string EndOfComment = "-->";
- int endOfComment = slice.IndexOf(EndOfComment, StringComparison.Ordinal);
+ int endOfComment = slice.IndexOf(EndOfComment.AsSpan(), StringComparison.Ordinal);
if (endOfComment < 0)
{
return false;
@@ -474,7 +474,7 @@ private static bool TryParseHtmlTagProcessingInstruction(ref StringSlice text, r
public static string Unescape(string? text, bool removeBackSlash = true)
{
// Credits: code from CommonMark.NET
- // Copyright (c) 2014, Kārlis Gaņģis All rights reserved.
+ // Copyright (c) 2014, Kārlis Gaņģis All rights reserved.
// See license for details: https://github.com/Knagis/CommonMark.NET/blob/master/LICENSE.md
if (string.IsNullOrEmpty(text))
{
@@ -553,7 +553,7 @@ public static string Unescape(string? text, bool removeBackSlash = true)
public static int ScanEntity(T slice, out int numericEntity, out int namedEntityStart, out int namedEntityLength) where T : ICharIterator
{
// Credits: code from CommonMark.NET
- // Copyright (c) 2014, Kārlis Gaņģis All rights reserved.
+ // Copyright (c) 2014, Kārlis Gaņģis All rights reserved.
// See license for details: https://github.com/Knagis/CommonMark.NET/blob/master/LICENSE.md
numericEntity = 0;
@@ -568,7 +568,7 @@ public static int ScanEntity(T slice, out int numericEntity, out int namedEnt
var start = slice.Start;
char c = slice.NextChar();
int counter = 0;
-
+
if (c == '#')
{
c = slice.PeekChar();
diff --git a/src/Markdig/Parsers/Inlines/CodeInlineParser.cs b/src/Markdig/Parsers/Inlines/CodeInlineParser.cs
index 34a2a1fc..e71029f9 100644
--- a/src/Markdig/Parsers/Inlines/CodeInlineParser.cs
+++ b/src/Markdig/Parsers/Inlines/CodeInlineParser.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
+using Markdig.Extensions.Tables;
using Markdig.Helpers;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
@@ -84,15 +85,16 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
{
lookAhead = lookAhead.Slice(1);
}
- int whitespace = 0;
- while (whitespace < lookAhead.Length && (lookAhead[whitespace] == ' ' || lookAhead[whitespace] == '\t'))
+ if (lookAhead[0] == '|')
{
- whitespace++;
- }
- if (whitespace < lookAhead.Length && lookAhead[whitespace] == '|')
- {
- slice.Start = openingStart;
- return false;
+ // We saw the start of a code inline, but the close sticks are not present on the same line.
+ // If the next line starts with a pipe character, this is likely an incomplete CodeInline within a table.
+ // Treat it as regular text to avoid breaking the overall table shape.
+ if (processor.Inline != null && processor.Inline.ContainsParentOfType())
+ {
+ slice.Start = openingStart;
+ return false;
+ }
}
containsNewLines = true;