@@ -323,6 +397,8 @@
+
+
diff --git a/src/common/UnitTests-CommonLib/Settings.Tests.cpp b/src/common/UnitTests-CommonLib/Settings.Tests.cpp
index 853b33030..1d0ef8f36 100644
--- a/src/common/UnitTests-CommonLib/Settings.Tests.cpp
+++ b/src/common/UnitTests-CommonLib/Settings.Tests.cpp
@@ -433,7 +433,24 @@ namespace UnitTestsCommonLib
compareJsons(expected, actual);
}
- TEST_METHOD (SettingsAddStringMultiline)
+ TEST_METHOD(SettingsAddLargeHeader)
+ {
+ const auto value = L"large header sample text ";
+
+ Settings settings(nullptr, m_moduleName);
+ settings.add_header_szLarge(m_defaultSettingsName, m_defaultSettingsDescription, value);
+
+ auto expected = m_defaultSettingsJson;
+ auto expectedProperties = createSettingsProperties(L"header_large");
+ expectedProperties.SetNamedValue(L"value", json::JsonValue::CreateStringValue(value));
+ expected.GetNamedObject(L"properties").SetNamedValue(m_defaultSettingsName, expectedProperties);
+
+ const auto actual = json::JsonObject::Parse(settings.serialize());
+
+ compareJsons(expected, actual);
+ }
+
+ TEST_METHOD(SettingsAddStringMultiline)
{
const auto value = L"Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit,\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident,\nsunt in culpa qui officia deserunt mollit anim id est laborum.";
diff --git a/src/common/settings_objects.cpp b/src/common/settings_objects.cpp
index 450532116..3bb95c1fc 100644
--- a/src/common/settings_objects.cpp
+++ b/src/common/settings_objects.cpp
@@ -109,6 +109,17 @@ namespace PowerToysSettings
m_json.GetNamedObject(L"properties").SetNamedValue(name, ml_string);
}
+ void Settings::add_header_szLarge(std::wstring_view name, std::wstring_view description, std::wstring_view value)
+ {
+ json::JsonObject string;
+ string.SetNamedValue(L"display_name", json::value(description));
+ string.SetNamedValue(L"editor_type", json::value(L"header_large"));
+ string.SetNamedValue(L"value", json::value(value));
+ string.SetNamedValue(L"order", json::value(++m_curr_priority));
+
+ m_json.GetNamedObject(L"properties").SetNamedValue(name, string);
+ }
+
// add_color_picker overloads.
void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value)
{
diff --git a/src/common/settings_objects.h b/src/common/settings_objects.h
index 5001daf92..5bcd26f67 100644
--- a/src/common/settings_objects.h
+++ b/src/common/settings_objects.h
@@ -50,6 +50,7 @@ namespace PowerToysSettings
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value);
void add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value);
+ void add_header_szLarge(std::wstring_view name, std::wstring_view description, std::wstring_view value);
// Serialize the internal json to a string.
std::wstring serialize();
// Serialize the internal json to the input buffer.
diff --git a/src/modules/previewpane/MarkDownPreviewHandler/HTMLParsingExtension.cs b/src/modules/previewpane/MarkDownPreviewHandler/HTMLParsingExtension.cs
new file mode 100644
index 000000000..986670353
--- /dev/null
+++ b/src/modules/previewpane/MarkDownPreviewHandler/HTMLParsingExtension.cs
@@ -0,0 +1,117 @@
+// 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.
+
+using System;
+using System.IO;
+using Markdig;
+using Markdig.Extensions.Figures;
+using Markdig.Extensions.Tables;
+using Markdig.Renderers;
+using Markdig.Renderers.Html;
+using Markdig.Syntax;
+using Markdig.Syntax.Inlines;
+
+namespace MarkdownPreviewHandler
+{
+ ///
+ /// Callback if extension blocks external images.
+ ///
+ public delegate void ImagesBlockedCallBack();
+
+ ///
+ /// Markdig Extension to process html nodes in markdown AST.
+ ///
+ public class HTMLParsingExtension : IMarkdownExtension
+ {
+ ///
+ /// Callback if extension blocks external images.
+ ///
+ private readonly ImagesBlockedCallBack imagesBlockedCallBack;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Callback function if image is blocked by extension.
+ /// Absolute path of markdown file.
+ public HTMLParsingExtension(ImagesBlockedCallBack imagesBlockedCallBack, string baseUrl = "")
+ {
+ this.imagesBlockedCallBack = imagesBlockedCallBack;
+ this.BaseUrl = baseUrl;
+ }
+
+ ///
+ /// Gets or sets path to directory containing markdown file.
+ ///
+ public string BaseUrl { get; set; }
+
+ ///
+ public void Setup(MarkdownPipelineBuilder pipeline)
+ {
+ // Make sure we don't have a delegate twice
+ pipeline.DocumentProcessed -= this.PipelineOnDocumentProcessed;
+ pipeline.DocumentProcessed += this.PipelineOnDocumentProcessed;
+ }
+
+ ///
+ public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
+ {
+ }
+
+ ///
+ /// Process nodes in markdown AST.
+ ///
+ /// Markdown Document.
+ public void PipelineOnDocumentProcessed(MarkdownDocument document)
+ {
+ foreach (var node in document.Descendants())
+ {
+ if (node is Block)
+ {
+ if (node is Table)
+ {
+ node.GetAttributes().AddClass("table table-striped table-bordered");
+ }
+ else if (node is QuoteBlock)
+ {
+ node.GetAttributes().AddClass("blockquote");
+ }
+ else if (node is Figure)
+ {
+ node.GetAttributes().AddClass("figure");
+ }
+ else if (node is FigureCaption)
+ {
+ node.GetAttributes().AddClass("figure-caption");
+ }
+ }
+ else if (node is Inline)
+ {
+ if (node is LinkInline link)
+ {
+ if (link.IsImage)
+ {
+ link.GetAttributes().AddClass("img-fluid");
+ }
+
+ if (!Uri.TryCreate(link.Url, UriKind.Absolute, out _))
+ {
+ link.Url = link.Url.TrimStart('/', '\\');
+ this.BaseUrl = this.BaseUrl.TrimEnd('/', '\\');
+ Uri uriLink = new Uri(Path.Combine(this.BaseUrl, link.Url));
+ link.Url = uriLink.ToString();
+ }
+ else
+ {
+ if (link.IsImage)
+ {
+ link.Url = "#";
+ this.imagesBlockedCallBack();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/modules/previewpane/MarkDownPreviewHandler/MarkDownPreviewHandler.csproj b/src/modules/previewpane/MarkDownPreviewHandler/MarkDownPreviewHandler.csproj
new file mode 100644
index 000000000..b98ab4139
--- /dev/null
+++ b/src/modules/previewpane/MarkDownPreviewHandler/MarkDownPreviewHandler.csproj
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+ MarkdownPreviewHandler
+ Microsoft Corp.
+ Copyright (C) 2019 Microsoft Corp.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Debug
+ AnyCPU
+ {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}
+ Library
+ Properties
+ MarkdownPreviewHandler
+ MarkdownPreviewHandler
+ v4.7.2
+ 512
+ true
+
+
+
+ true
+ full
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\MarkdownPreviewPaneDocumentation.xml
+ x64
+
+
+ pdbonly
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\
+ TRACE
+ prompt
+ 4
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\MarkdownPreviewPaneDocumentation.xml
+ x64
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Code
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ 1.8.10
+
+
+ 0.18.0
+
+
+ 1.1.118
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+ StyleCop.json
+
+
+
+
+ {af2349b8-e5b6-4004-9502-687c1c7730b1}
+ PreviewHandlerCommon
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.cs b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.cs
new file mode 100644
index 000000000..be0b9ac73
--- /dev/null
+++ b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandler.cs
@@ -0,0 +1,34 @@
+// 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.
+
+using System;
+using System.Runtime.InteropServices;
+using Common;
+
+namespace MarkdownPreviewHandler
+{
+ ///
+ /// Implementation of preview handler for markdown files.
+ ///
+ [Guid("45769bcc-e8fd-42d0-947e-02beef77a1f5")]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComVisible(true)]
+ public class MarkdownPreviewHandler : FileBasedPreviewHandler
+ {
+ private MarkdownPreviewHandlerControl markdownPreviewHandlerControl;
+
+ ///
+ public override void DoPreview()
+ {
+ this.markdownPreviewHandlerControl.DoPreview(this.FilePath);
+ }
+
+ ///
+ protected override IPreviewHandlerControl CreatePreviewHandlerControl()
+ {
+ this.markdownPreviewHandlerControl = new MarkdownPreviewHandlerControl();
+ return this.markdownPreviewHandlerControl;
+ }
+ }
+}
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs
new file mode 100644
index 000000000..4e77c8338
--- /dev/null
+++ b/src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs
@@ -0,0 +1,179 @@
+// 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.
+
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Common;
+using Markdig;
+using MarkdownPreviewHandler.Properties;
+using PreviewHandlerCommon;
+
+namespace MarkdownPreviewHandler
+{
+ ///
+ /// Win Form Implementation for Markdown Preview Handler.
+ ///
+ public class MarkdownPreviewHandlerControl : FormHandlerControl
+ {
+ ///
+ /// Extension to modify markdown AST.
+ ///
+ private readonly HTMLParsingExtension extension;
+
+ ///
+ /// Markdig Pipeline builder.
+ ///
+ private readonly MarkdownPipelineBuilder pipelineBuilder;
+
+ ///
+ /// Markdown HTML header.
+ ///
+ private readonly string htmlHeader = "";
+
+ ///
+ /// Markdown HTML footer.
+ ///
+ private readonly string htmlFooter = "