261 lines
7.4 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|