2025-04-08 09:37:13 +00:00
using System.Diagnostics ;
using System.Runtime.InteropServices ;
using System.Text.RegularExpressions ;
2025-04-08 13:04:28 +00:00
using AIStudio.Components ;
2025-04-08 09:37:13 +00:00
namespace AIStudio.Tools ;
public static partial class Pandoc
{
2025-04-08 13:04:28 +00:00
private static readonly ILogger LOG = Program . LOGGER_FACTORY . CreateLogger ( "PluginFactory" ) ;
private static readonly Version MINIMUM_REQUIRED_VERSION = new Version ( 3 , 6 ) ;
2025-04-08 09:37:13 +00:00
/// <summary>
/// Checks if pandoc is available on the system and can be started as a process
/// </summary>
/// <returns>True, if pandoc is available and the minimum required version is met, else False.</returns>
public static async Task < bool > IsPandocAvailableAsync ( )
{
try
{
var startInfo = new ProcessStartInfo
{
FileName = GetPandocExecutableName ( ) ,
Arguments = "--version" ,
RedirectStandardOutput = true ,
UseShellExecute = false ,
CreateNoWindow = true
} ;
using var process = Process . Start ( startInfo ) ;
if ( process = = null )
2025-04-08 12:11:19 +00:00
{
2025-04-08 13:04:28 +00:00
await MessageBus . INSTANCE . SendError ( new ( Icons . Material . Filled . Help , "The pandoc process could not be started." ) ) ;
LOG . LogInformation ( "The pandoc process was not started, it was null" ) ;
2025-04-08 09:37:13 +00:00
return false ;
2025-04-08 12:11:19 +00:00
}
2025-04-08 09:37:13 +00:00
var output = await process . StandardOutput . ReadToEndAsync ( ) ;
await process . WaitForExitAsync ( ) ;
if ( process . ExitCode ! = 0 )
2025-04-08 12:11:19 +00:00
{
2025-04-08 13:04:28 +00:00
await MessageBus . INSTANCE . SendError ( new ( Icons . Material . Filled . Error , $"The pandoc process exited unexpectedly." ) ) ;
LOG . LogError ( "The pandoc process was exited with code {ProcessExitCode}" , process . ExitCode ) ;
2025-04-08 09:37:13 +00:00
return false ;
2025-04-08 12:11:19 +00:00
}
2025-04-08 09:37:13 +00:00
var versionMatch = PandocRegex ( ) . Match ( output ) ;
2025-04-08 12:11:19 +00:00
if ( ! versionMatch . Success )
{
2025-04-08 13:04:28 +00:00
await MessageBus . INSTANCE . SendError ( new ( Icons . Material . Filled . Terminal , $"pandoc --version returned an invalid format." ) ) ;
LOG . LogError ( "pandoc --version returned an invalid format:\n {Output}" , output ) ;
2025-04-08 12:11:19 +00:00
return false ;
}
2025-04-08 09:37:13 +00:00
var versions = versionMatch . Groups [ 1 ] . Value . Split ( '.' ) ;
var major = int . Parse ( versions [ 0 ] ) ;
var minor = int . Parse ( versions [ 1 ] ) ;
2025-04-08 13:04:28 +00:00
var installedVersion = new Version ( major , minor ) ;
2025-04-08 09:37:13 +00:00
2025-04-08 12:11:19 +00:00
if ( installedVersion > = MINIMUM_REQUIRED_VERSION )
return true ;
2025-04-08 13:04:28 +00:00
await MessageBus . INSTANCE . SendError ( new ( Icons . Material . Filled . Build , $"Pandoc {installedVersion.ToString()} is installed, but it doesn't match the required version ({MINIMUM_REQUIRED_VERSION.ToString()})." ) ) ;
LOG . LogInformation ( "Pandoc {Installed} is installed, but it does not match the required version ({Requirement})" , installedVersion . ToString ( ) , MINIMUM_REQUIRED_VERSION . ToString ( ) ) ;
2025-04-08 12:11:19 +00:00
return false ;
2025-04-08 09:37:13 +00:00
}
2025-04-08 13:04:28 +00:00
catch ( Exception e )
2025-04-08 09:37:13 +00:00
{
2025-04-08 13:04:28 +00:00
await MessageBus . INSTANCE . SendError ( new ( @Icons . Material . Filled . AppsOutage , "Pandoc is not installed." ) ) ;
LOG . LogError ( "Pandoc is not installed and threw an exception:\n {Message}" , e . Message ) ;
2025-04-08 09:37:13 +00:00
return false ;
}
}
/// <summary>
2025-04-08 12:11:19 +00:00
/// Returns the name of the pandoc executable based on the running operating system
2025-04-08 09:37:13 +00:00
/// </summary>
2025-04-08 12:11:19 +00:00
private static string GetPandocExecutableName ( ) = > RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? "pandoc.exe" : "pandoc" ;
2025-04-08 09:37:13 +00:00
2025-04-08 13:04:28 +00:00
[GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9] + \ . [ 0 - 9 ] + ) ")]
2025-04-08 09:37:13 +00:00
private static partial Regex PandocRegex ( ) ;
}