mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 19:32:10 +00:00
added a RegexGenerator to find the first markdown code fence with a csv attribute
This commit is contained in:
parent
701c27b06e
commit
d188dad4b4
@ -1,28 +1,67 @@
|
|||||||
using System.Diagnostics;
|
using System.Text.RegularExpressions;
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Dialogs;
|
|
||||||
using AIStudio.Tools.PluginSystem;
|
using AIStudio.Tools.PluginSystem;
|
||||||
using AIStudio.Tools.Rust;
|
using AIStudio.Tools.Rust;
|
||||||
using AIStudio.Tools.Services;
|
using AIStudio.Tools.Services;
|
||||||
using DialogOptions = MudBlazor.DialogOptions;
|
|
||||||
|
|
||||||
namespace AIStudio.Tools;
|
namespace AIStudio.Tools;
|
||||||
|
|
||||||
public static class PlainFileExport
|
public static partial class PlainFileExport
|
||||||
{
|
{
|
||||||
private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(PlainFileExport));
|
private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(PlainFileExport));
|
||||||
|
|
||||||
private sealed record ExportTarget(string DisplayName, FileTypeFilter FileType);
|
private sealed record ExportTarget(string DisplayName, FileTypeFilter FileType);
|
||||||
|
|
||||||
private static readonly ExportTarget MARKDOWN = new("Markdown (.md)", FileTypes.MARKDOWN);
|
private static readonly ExportTarget MARKDOWN = new("Markdown (.md)", FileTypes.MARKDOWN);
|
||||||
|
private static readonly ExportTarget CSV = new("CSV (.csv)", FileTypes.CSV);
|
||||||
|
|
||||||
private static string TB(string fallbackEn) => I18N.I.T(fallbackEn, typeof(PlainFileExport).Namespace, nameof(PlainFileExport));
|
private static string TB(string fallbackEn) => I18N.I.T(fallbackEn, typeof(PlainFileExport).Namespace, nameof(PlainFileExport));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extracts the content of the first complete Markdown code block marked as CSV.
|
||||||
|
/// </summary>
|
||||||
|
public static bool TryExtractCsvContent(IContent content, out string csvContent)
|
||||||
|
{
|
||||||
|
if (content is ContentText text)
|
||||||
|
{
|
||||||
|
var match = CsvCodeFenceRegex().Match(text.Text);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
csvContent = match.Groups["content"].Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
csvContent = string.Empty;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(
|
||||||
|
"""
|
||||||
|
# Matches an opening Markdown code fence and captures its delimiter.
|
||||||
|
^(?<fence>`{3,}|~{3,})
|
||||||
|
|
||||||
|
# Matches the csv language identifier and the end of the opening fence line.
|
||||||
|
# Also allow tab-separated, pipe-separated and semicolon separated values at the code fence
|
||||||
|
[ \t]*(csv|tsv|psv|ssv)[ \t]*\r?\n
|
||||||
|
|
||||||
|
# Captures the content of the first matching fenced code block.
|
||||||
|
(?<content>[\s\S]*?)
|
||||||
|
|
||||||
|
# Matches the corresponding closing fence followed by a line ending or end of input.
|
||||||
|
^\k<fence>[ \t]*(?=\r?\n|$)
|
||||||
|
""",
|
||||||
|
RegexOptions.IgnoreCase |
|
||||||
|
RegexOptions.Multiline |
|
||||||
|
RegexOptions.IgnorePatternWhitespace)]
|
||||||
|
private static partial Regex CsvCodeFenceRegex();
|
||||||
|
|
||||||
public static async Task<bool> ToFile(RustService rustService, FileExportFormat format, IContent markdownContent)
|
public static async Task<bool> ToFile(RustService rustService, FileExportFormat format, IContent markdownContent)
|
||||||
{
|
{
|
||||||
var exportTarget = format switch
|
var exportTarget = format switch
|
||||||
{
|
{
|
||||||
FileExportFormat.MARKDOWN => MARKDOWN,
|
FileExportFormat.MARKDOWN => MARKDOWN,
|
||||||
|
FileExportFormat.CSV => CSV,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(format), format, null),
|
_ => throw new ArgumentOutOfRangeException(nameof(format), format, null),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,14 +76,19 @@ public static class PlainFileExport
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var markdownText = markdownContent switch
|
var fileContent = format switch
|
||||||
{
|
{
|
||||||
ContentText text => text.Text,
|
FileExportFormat.MARKDOWN => markdownContent switch
|
||||||
ContentImage _ => "Image export is not yet possible.",
|
{
|
||||||
_ => "Unknown content type. Cannot export document."
|
ContentText text => text.Text,
|
||||||
|
ContentImage _ => "Image export is not yet possible.",
|
||||||
|
_ => "Unknown content type. Cannot export document."
|
||||||
|
},
|
||||||
|
FileExportFormat.CSV when TryExtractCsvContent(markdownContent, out var csvContent) => csvContent,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(format), format, null),
|
||||||
};
|
};
|
||||||
|
|
||||||
await File.WriteAllTextAsync(response.SaveFilePath, markdownText);
|
await File.WriteAllTextAsync(response.SaveFilePath, fileContent);
|
||||||
await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, TB("Document export successful")));
|
await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, TB("Document export successful")));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user