diff --git a/src/common/FilePreviewCommon/Assets/Monaco/monacoExtraExtensions.txt b/src/common/FilePreviewCommon/Assets/Monaco/monacoExtraExtensions.txt new file mode 100644 index 000000000000..aa52256aa8b4 --- /dev/null +++ b/src/common/FilePreviewCommon/Assets/Monaco/monacoExtraExtensions.txt @@ -0,0 +1,5 @@ +# Extra file extensions to preview with Monaco. + +.ahk # AutoHotKey scripts +.csv # comma-separated values +.tsv # tab-separated values diff --git a/src/common/FilePreviewCommon/FilePreviewCommon.csproj b/src/common/FilePreviewCommon/FilePreviewCommon.csproj index 5849155ca015..f1acd182f790 100644 --- a/src/common/FilePreviewCommon/FilePreviewCommon.csproj +++ b/src/common/FilePreviewCommon/FilePreviewCommon.csproj @@ -26,6 +26,9 @@ Always + + Always + Always diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/ShellPreviewHandlerPreviewer/ShellPreviewHandlerPreviewer.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/ShellPreviewHandlerPreviewer/ShellPreviewHandlerPreviewer.cs index 0e1eb5c90f13..69a6efa1ce66 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/ShellPreviewHandlerPreviewer/ShellPreviewHandlerPreviewer.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/ShellPreviewHandlerPreviewer/ShellPreviewHandlerPreviewer.cs @@ -206,9 +206,14 @@ public void Clear() } } + public static bool IsExtensionSupported(string extension) + { + return !string.IsNullOrEmpty(GetPreviewHandlerGuid(extension)); + } + public static bool IsItemSupported(IFileSystemItem item) { - return !string.IsNullOrEmpty(GetPreviewHandlerGuid(item.Extension)); + return IsExtensionSupported(item.Extension); } private static string? GetPreviewHandlerGuid(string fileExt) diff --git a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs index a1ff9d136d59..c4e60460fd45 100644 --- a/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs +++ b/src/modules/peek/Peek.FilePreviewer/Previewers/WebBrowserPreviewer/Helpers/MonacoHelper.cs @@ -8,21 +8,28 @@ using System.IO; using System.Linq; using System.Text.Json; +using System.Text.RegularExpressions; using Common.UI; using ManagedCommon; namespace Peek.FilePreviewer.Previewers { - public class MonacoHelper + public partial class MonacoHelper { - public static readonly HashSet SupportedMonacoFileTypes = GetExtensions(); + public static readonly HashSet SupportedMonacoFileTypes; + + static MonacoHelper() + { + SupportedMonacoFileTypes = GetExtensions().Union(GetExtraSupportedExtensions()).ToHashSet(); + } public static HashSet GetExtensions() { - HashSet set = new HashSet(); + HashSet set = []; + try { - JsonDocument languageListDocument = Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.GetLanguages(); + using JsonDocument languageListDocument = Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.GetLanguages(); JsonElement languageList = languageListDocument.RootElement.GetProperty("list"); foreach (JsonElement e in languageList.EnumerateArray()) { @@ -43,6 +50,39 @@ public static HashSet GetExtensions() return set; } + /// + /// Get the file extensions which are not present in the JSON languages document but which + /// may still be previewed by Monaco. + /// + /// Filters out extensions handled by Shell preview handlers, so Office will still + /// handle rendering .csv and others if it is installed. + private static IEnumerable GetExtraSupportedExtensions() + { + try + { + string path = Path.Combine( + Microsoft.PowerToys.FilePreviewCommon.MonacoHelper.GetRuntimeMonacoDirectory(), + "monacoExtraExtensions.txt"); + + return File.Exists(path) ? + File.ReadAllLines(path) + .Select(line => ExtensionsFileRegex().Match(line)) + .Where(match => match.Success && + !ShellPreviewHandlerPreviewer.IsExtensionSupported(match.Groups[1].Value)) + .Select(match => match.Groups[1].Value) : []; + } + catch + { + return []; + } + } + + /// + /// Extracts the extensions from the extra supported extensions file, ignoring comments. + /// + [GeneratedRegex(@"^\s*(\.\w+)\s*(#.*)?$")] + private static partial Regex ExtensionsFileRegex(); + /// /// Prepares temp html for the previewing ///