diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 0c7cc2a0e1..5da12c1831 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -836,6 +836,7 @@ IFilter
ifndef
IFolder
IFormat
+IFormatter
ifstream
IGraph
iid
diff --git a/src/modules/previewpane/MonacoPreviewHandler/Formatters/IFormatter.cs b/src/modules/previewpane/MonacoPreviewHandler/Formatters/IFormatter.cs
new file mode 100644
index 0000000000..88bb982bc2
--- /dev/null
+++ b/src/modules/previewpane/MonacoPreviewHandler/Formatters/IFormatter.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.PreviewHandler.Monaco.Formatters
+{
+ public interface IFormatter
+ {
+ ///
+ /// Gets the language to which the formatter is applied
+ ///
+ string LangSet { get; }
+
+ ///
+ /// Format the value
+ ///
+ /// The value to format
+ /// The value formatted
+ string Format(string value);
+ }
+}
diff --git a/src/modules/previewpane/MonacoPreviewHandler/Formatters/JsonFormatter.cs b/src/modules/previewpane/MonacoPreviewHandler/Formatters/JsonFormatter.cs
new file mode 100644
index 0000000000..b2b82f625d
--- /dev/null
+++ b/src/modules/previewpane/MonacoPreviewHandler/Formatters/JsonFormatter.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.PreviewHandler.Monaco.Formatters
+{
+ using System.Text.Json;
+
+ public class JsonFormatter : IFormatter
+ {
+ ///
+ public string LangSet => "json";
+
+ ///
+ public string Format(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return string.Empty;
+ }
+
+ using (var jDocument = JsonDocument.Parse(value, new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip }))
+ {
+ return JsonSerializer.Serialize(jDocument, new JsonSerializerOptions { WriteIndented = true });
+ }
+ }
+ }
+}
diff --git a/src/modules/previewpane/MonacoPreviewHandler/Formatters/XmlFormatter.cs b/src/modules/previewpane/MonacoPreviewHandler/Formatters/XmlFormatter.cs
new file mode 100644
index 0000000000..a7cb976616
--- /dev/null
+++ b/src/modules/previewpane/MonacoPreviewHandler/Formatters/XmlFormatter.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.PreviewHandler.Monaco.Formatters
+{
+ using System.Text;
+ using System.Xml;
+
+ public class XmlFormatter : IFormatter
+ {
+ ///
+ public string LangSet => "xml";
+
+ ///
+ public string Format(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return string.Empty;
+ }
+
+ var xmlDocument = new XmlDocument();
+ xmlDocument.LoadXml(value);
+
+ var stringBuilder = new StringBuilder();
+ var xmlWriterSettings = new XmlWriterSettings()
+ {
+ OmitXmlDeclaration = xmlDocument.FirstChild.NodeType != XmlNodeType.XmlDeclaration,
+ Indent = true,
+ };
+
+ using (var xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings))
+ {
+ xmlDocument.Save(xmlWriter);
+ }
+
+ return stringBuilder.ToString();
+ }
+ }
+}
diff --git a/src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandlerControl.cs b/src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandlerControl.cs
index acda8aa497..c900e7b6ea 100644
--- a/src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandlerControl.cs
+++ b/src/modules/previewpane/MonacoPreviewHandler/MonacoPreviewHandlerControl.cs
@@ -3,14 +3,16 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Diagnostics;
+using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common;
+using Microsoft.PowerToys.PreviewHandler.Monaco.Formatters;
using Microsoft.PowerToys.PreviewHandler.Monaco.Helpers;
using Microsoft.PowerToys.PreviewHandler.Monaco.Properties;
using Microsoft.Web.WebView2.Core;
@@ -26,6 +28,15 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
///
private readonly Settings _settings = new Settings();
+ ///
+ /// Formatters applied before rendering the preview
+ ///
+ private readonly IReadOnlyCollection _formatters = new List
+ {
+ new JsonFormatter(),
+ new XmlFormatter(),
+ }.AsReadOnly();
+
///
/// Saves if the user already navigated to the index page
///
@@ -367,6 +378,23 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
{
Logger.LogInfo("Starting reading requested file");
var fileContent = fileReader.ReadToEnd();
+
+ if (_settings.TryFormat)
+ {
+ var formatter = _formatters.SingleOrDefault(f => f.LangSet == _vsCodeLangSet);
+ if (formatter != null)
+ {
+ try
+ {
+ fileContent = formatter.Format(fileContent);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError($"Failed to apply formatting to {filePath}", ex);
+ }
+ }
+ }
+
fileReader.Close();
_base64FileCode = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(fileContent));
Logger.LogInfo("Reading requested file ended");
@@ -379,7 +407,7 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
_html = htmlFileReader.ReadToEnd();
htmlFileReader.Close();
Logger.LogInfo("Reading HTML source file ended");
- }
+ }
_html = _html.Replace("[[PT_LANG]]", _vsCodeLangSet, StringComparison.InvariantCulture);
_html = _html.Replace("[[PT_WRAP]]", _settings.Wrap ? "1" : "0", StringComparison.InvariantCulture);
diff --git a/src/modules/previewpane/MonacoPreviewHandler/Settings.cs b/src/modules/previewpane/MonacoPreviewHandler/Settings.cs
index 218895b5a8..e03cbcf409 100644
--- a/src/modules/previewpane/MonacoPreviewHandler/Settings.cs
+++ b/src/modules/previewpane/MonacoPreviewHandler/Settings.cs
@@ -37,6 +37,26 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
}
}
+ ///
+ /// Gets a value indicating whether to try formatting the file. Set by PT settings.
+ ///
+ public bool TryFormat
+ {
+ get
+ {
+ try
+ {
+ return moduleSettings.GetSettings(PowerPreviewSettings.ModuleName).Properties.MonacoPreviewTryFormat;
+ }
+ catch (FileNotFoundException)
+ {
+ // Couldn't read the settings.
+ // Assume default of false.
+ return false;
+ }
+ }
+ }
+
///
/// Max file size for displaying (in bytes).
///
diff --git a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs
index 67cb96ae34..eee0800e48 100644
--- a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs
+++ b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs
@@ -99,6 +99,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
+ private bool monacoPreviewTryFormat;
+
+ [JsonPropertyName("monaco-previewer-toggle-try-format")]
+ [JsonConverter(typeof(BoolPropertyJsonConverter))]
+ public bool MonacoPreviewTryFormat
+ {
+ get => monacoPreviewTryFormat;
+ set
+ {
+ if (value != monacoPreviewTryFormat)
+ {
+ LogTelemetryEvent(value);
+ monacoPreviewTryFormat = value;
+ }
+ }
+ }
+
private bool enablePdfPreview;
[JsonPropertyName("pdf-previewer-toggle-setting")]
diff --git a/src/settings-ui/Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs b/src/settings-ui/Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
index 7e4833dfcc..e1d3b3fe1f 100644
--- a/src/settings-ui/Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
+++ b/src/settings-ui/Settings.UI.Library/ViewModels/PowerPreviewViewModel.cs
@@ -51,6 +51,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
_mdRenderIsEnabled = Settings.Properties.EnableMdPreview;
_monacoRenderIsEnabled = Settings.Properties.EnableMonacoPreview;
_monacoWrapText = Settings.Properties.EnableMonacoPreviewWordWrap;
+ _monacoPreviewTryFormat = Settings.Properties.MonacoPreviewTryFormat;
_pdfRenderIsEnabled = Settings.Properties.EnablePdfPreview;
_gcodeRenderIsEnabled = Settings.Properties.EnableGcodePreview;
_pdfThumbnailIsEnabled = Settings.Properties.EnablePdfThumbnail;
@@ -63,6 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private bool _mdRenderIsEnabled;
private bool _monacoRenderIsEnabled;
private bool _monacoWrapText;
+ private bool _monacoPreviewTryFormat;
private bool _pdfRenderIsEnabled;
private bool _gcodeRenderIsEnabled;
private bool _svgThumbnailIsEnabled;
@@ -161,6 +163,24 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
+ public bool MonacoPreviewTryFormat
+ {
+ get
+ {
+ return _monacoPreviewTryFormat;
+ }
+
+ set
+ {
+ if (_monacoPreviewTryFormat != value)
+ {
+ _monacoPreviewTryFormat = value;
+ Settings.Properties.MonacoPreviewTryFormat = value;
+ RaisePropertyChanged();
+ }
+ }
+ }
+
public bool PDFRenderIsEnabled
{
get
diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
index 04ecd5fc6d..bd2c5df0dc 100644
--- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
+++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw
@@ -422,21 +422,21 @@
Wait for more input before searching. This reduces interface jumpiness and system load.
- Immediate plugins
+ Immediate plugins
-
- Affects the plugins that make the UI wait for their results by this amount. Recommended: 30-50 ms.
+
+ Affects the plugins that make the UI wait for their results by this amount. Recommended: 30-50 ms.
-
- Background execution plugins
+
+ Background execution plugins
-
- Affects the plugins that execute in the background by this amount. Recommended: 100-150 ms.
+
+ Affects the plugins that execute in the background by this amount. Recommended: 100-150 ms.
-
+
Fast plugin throttle (ms)
ms = milliseconds
-
+
To:
Keyboard Manager mapping keys view right header
@@ -2164,6 +2164,12 @@ From there, simply click on one of the supported files in the File Explorer and
Enable round corners
+
+ Applies to json and xml. Files remain unchanged.
+
+
+ Try to format the source for preview
+
Some characters and phrases may conflict with global queries of other plugins if you use them as activation command.
diff --git a/src/settings-ui/Settings.UI/Views/PowerPreviewPage.xaml b/src/settings-ui/Settings.UI/Views/PowerPreviewPage.xaml
index 93b82a92d2..f6c0387c9f 100644
--- a/src/settings-ui/Settings.UI/Views/PowerPreviewPage.xaml
+++ b/src/settings-ui/Settings.UI/Views/PowerPreviewPage.xaml
@@ -57,6 +57,11 @@
IsChecked="{x:Bind ViewModel.MonacoWrapText, Mode=TwoWay}"
Margin="{StaticResource ExpanderSettingMargin}"
IsEnabled="{x:Bind ViewModel.MonacoRenderIsEnabled, Mode=OneWay}" />
+
+