Optimized

This commit is contained in:
Thorsten Sommer 2026-04-09 15:47:38 +02:00
parent 56805874c2
commit 2c54df46b9
No known key found for this signature in database
GPG Key ID: B0B7E2FC074BF1F5

View File

@ -1,4 +1,5 @@
using Markdig; using Markdig;
using System.Text;
namespace AIStudio.Tools; namespace AIStudio.Tools;
@ -32,51 +33,117 @@ public static class Markdown
if (string.IsNullOrWhiteSpace(value)) if (string.IsNullOrWhiteSpace(value))
return string.Empty; return string.Empty;
var normalized = value.Replace("\r\n", "\n"); return RemoveSharedIndentation(value.AsSpan());
var lines = normalized.Split('\n'); }
var firstContentLine = 0;
while (firstContentLine < lines.Length && string.IsNullOrWhiteSpace(lines[firstContentLine]))
firstContentLine++;
var lastContentLine = lines.Length - 1;
while (lastContentLine >= firstContentLine && string.IsNullOrWhiteSpace(lines[lastContentLine]))
lastContentLine--;
if (firstContentLine > lastContentLine)
return string.Empty;
private static string RemoveSharedIndentation(ReadOnlySpan<char> value)
{
var firstContentLineStart = -1;
var lastContentLineStart = -1;
var lastContentLineEnd = -1;
var commonIndentation = int.MaxValue; var commonIndentation = int.MaxValue;
for (var i = firstContentLine; i <= lastContentLine; i++) var position = 0;
while (TryGetNextLine(value, position, out var lineStart, out var currentLineEnd, out var nextPosition))
{ {
var line = lines[i]; var lineContent = value[lineStart..currentLineEnd];
if (string.IsNullOrWhiteSpace(line)) if (IsWhiteSpace(lineContent))
{
position = nextPosition;
continue; continue;
}
var indentation = 0; if (firstContentLineStart < 0)
while (indentation < line.Length && char.IsWhiteSpace(line[indentation])) firstContentLineStart = lineStart;
indentation++;
commonIndentation = Math.Min(commonIndentation, indentation); lastContentLineStart = lineStart;
lastContentLineEnd = currentLineEnd;
commonIndentation = Math.Min(commonIndentation, CountIndentation(lineContent));
position = nextPosition;
} }
if (firstContentLineStart < 0)
return string.Empty;
if (commonIndentation == int.MaxValue) if (commonIndentation == int.MaxValue)
commonIndentation = 0; commonIndentation = 0;
for (var i = firstContentLine; i <= lastContentLine; i++) var builder = new StringBuilder(lastContentLineEnd - firstContentLineStart);
var shouldAppendLineBreak = false;
position = firstContentLineStart;
while (TryGetNextLine(value, position, out var lineStart, out var lineEnd, out var nextPosition))
{ {
var line = lines[i]; var lineContent = value[lineStart..lineEnd];
if (string.IsNullOrWhiteSpace(line))
{
lines[i] = string.Empty;
continue;
}
lines[i] = line.Length <= commonIndentation if (shouldAppendLineBreak)
? string.Empty builder.Append('\n');
: line[commonIndentation..];
if (IsWhiteSpace(lineContent))
shouldAppendLineBreak = true;
else if (lineContent.Length > commonIndentation)
{
builder.Append(lineContent[commonIndentation..]);
shouldAppendLineBreak = true;
}
else
shouldAppendLineBreak = true;
if (lineStart == lastContentLineStart)
break;
position = nextPosition;
} }
return string.Join('\n', lines[firstContentLine..(lastContentLine + 1)]); return builder.ToString();
}
private static bool IsWhiteSpace(ReadOnlySpan<char> value)
{
foreach (var character in value)
{
if (!char.IsWhiteSpace(character))
return false;
}
return true;
}
private static int CountIndentation(ReadOnlySpan<char> value)
{
var indentation = 0;
while (indentation < value.Length && char.IsWhiteSpace(value[indentation]))
indentation++;
return indentation;
}
private static bool TryGetNextLine(ReadOnlySpan<char> value, int position, out int lineStart, out int lineEnd, out int nextPosition)
{
if (position > value.Length)
{
lineStart = 0;
lineEnd = 0;
nextPosition = position;
return false;
}
lineStart = position;
for (var i = position; i < value.Length; i++)
{
if (value[i] != '\n')
continue;
lineEnd = i > lineStart && value[i - 1] == '\r'
? i - 1
: i;
nextPosition = i + 1;
return true;
}
lineEnd = value.Length;
nextPosition = value.Length + 1;
return true;
} }
} }