RobotNet/RobotNet.WebApp/Scripts/Monaco/MarkdownHelpers.cs
2025-10-15 15:15:53 +07:00

261 lines
7.4 KiB
C#

using Microsoft.CodeAnalysis;
using System.Collections.Immutable;
using System.Text.RegularExpressions;
using System.Text;
namespace RobotNet.WebApp.Scripts.Monaco;
public enum MarkdownFormat
{
Default,
Italicize,
FirstLineAsCSharp,
FirstLineDefaultRestCSharp,
AllTextAsCSharp
}
public static class MarkdownHelpers
{
private static readonly Regex EscapeRegex = new("([\\\\`\\*_\\{\\}\\[\\]\\(\\)#+\\-\\.!])", RegexOptions.Compiled);
private const string ContainerStart = "ContainerStart";
private const string ContainerEnd = "ContainerEnd";
public static string Escape(string markdown) => string.IsNullOrEmpty(markdown) ? string.Empty : EscapeRegex.Replace(markdown, "\\$1");
public static void TaggedTextToMarkdown(ImmutableArray<TaggedText> taggedParts, StringBuilder stringBuilder, string newLine, MarkdownFormat markdownFormat, out bool endedWithLineBreak)
{
bool isInCodeBlock = false;
bool brokeLine = true;
bool afterFirstLine = false;
if (markdownFormat == MarkdownFormat.Italicize)
{
stringBuilder.Append('_');
}
int num = 0;
while (num < taggedParts.Length)
{
TaggedText taggedText = taggedParts[num];
bool flag;
if (brokeLine && markdownFormat != MarkdownFormat.Italicize)
{
brokeLine = false;
if (!afterFirstLine)
{
if (markdownFormat != MarkdownFormat.FirstLineAsCSharp)
{
goto IL_00a2;
}
flag = true;
}
else
{
if (markdownFormat != MarkdownFormat.FirstLineDefaultRestCSharp)
{
goto IL_00a2;
}
flag = true;
}
goto IL_00bf;
}
goto IL_0279;
IL_00a2:
flag = markdownFormat == MarkdownFormat.AllTextAsCSharp;
goto IL_00bf;
IL_0279:
switch (taggedText.Tag)
{
case "Text":
if (!isInCodeBlock)
{
addText(taggedText.Text);
break;
}
endBlock();
addText(taggedText.Text);
break;
case "Space":
if (isInCodeBlock)
{
if (indexIsTag(num + 1, ["Text"]))
{
endBlock();
}
addText(taggedText.Text);
break;
}
goto case "Punctuation";
case "Punctuation":
addText(taggedText.Text);
break;
case ContainerStart:
addNewline();
addText(taggedText.Text);
break;
case ContainerEnd:
addNewline();
break;
case "LineBreak":
if (stringBuilder.Length != 0 && !indexIsTag(num + 1, [ContainerStart, ContainerEnd]) && num + 1 != taggedParts.Length)
{
addNewline();
}
break;
default:
if (!isInCodeBlock)
{
isInCodeBlock = true;
stringBuilder.Append('`');
}
stringBuilder.Append(taggedText.Text);
brokeLine = false;
break;
}
num++;
continue;
IL_00bf:
bool flag2 = flag;
if (!flag2)
{
for (int j = num; j < taggedParts.Length; flag2 = true, j++)
{
switch (taggedParts[j].Tag)
{
case "Text":
flag2 = false;
break;
default:
continue;
case ContainerStart:
case ContainerEnd:
case "LineBreak":
break;
}
break;
}
}
else
{
flag2 = !indexIsTag(num,
[
ContainerStart,
ContainerEnd,
"LineBreak"
]);
}
if (flag2)
{
afterFirstLine = true;
stringBuilder.Append("```csharp");
stringBuilder.Append(newLine);
while (true)
{
if (num < taggedParts.Length)
{
taggedText = taggedParts[num];
if (taggedText.Tag == ContainerStart || taggedText.Tag == ContainerEnd || taggedText.Tag == "LineBreak")
{
stringBuilder.Append(newLine);
if (markdownFormat != MarkdownFormat.AllTextAsCSharp && markdownFormat != MarkdownFormat.FirstLineDefaultRestCSharp)
{
break;
}
}
else
{
stringBuilder.Append(taggedText.Text);
}
num++;
continue;
}
stringBuilder.Append(newLine);
stringBuilder.Append("```");
endedWithLineBreak = false;
return;
}
stringBuilder.Append("```");
}
goto IL_0279;
}
if (isInCodeBlock)
{
endBlock();
}
if (!brokeLine && markdownFormat == MarkdownFormat.Italicize)
{
stringBuilder.Append('_');
}
endedWithLineBreak = brokeLine;
void addNewline()
{
if (isInCodeBlock)
{
endBlock();
}
if (markdownFormat == MarkdownFormat.Italicize)
{
stringBuilder.Append('_');
}
stringBuilder.Append(newLine);
stringBuilder.Append(newLine);
brokeLine = true;
if (markdownFormat == MarkdownFormat.Italicize)
{
stringBuilder.Append('_');
}
}
void addText(string text)
{
brokeLine = false;
afterFirstLine = true;
if (!isInCodeBlock)
{
text = Escape(text);
}
stringBuilder.Append(text);
}
void endBlock()
{
stringBuilder.Append('`');
isInCodeBlock = false;
}
bool indexIsTag(int i, string[] tags)
{
if (i < taggedParts.Length)
{
return tags.Contains(taggedParts[i].Tag);
}
return false;
}
}
}