diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 02c0edab0..bc9dec043 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -18,6 +18,8 @@ on:
env:
DOTNET_VERSION: ${{ '8.0.201' }}
+ DOTNET_INSTALL_DIR: dotnet-install
+ DOTNET_ROOT: dotnet-install
ENABLE_DIAGNOSTICS: false
#COREHOST_TRACE: 1
MSBUILD_VERBOSITY: normal
@@ -257,9 +259,19 @@ jobs:
with:
vs-version: '[17.9,)'
+ - name: Define excluded MultiTargets (WinUI 2)
+ if: ${{ matrix.winui == '2' }}
+ run: |
+ echo "EXCLUDED_MULTITARGETS=wasdk" >> $env:GITHUB_ENV
+
+ - name: Define excluded MultiTargets (WinUI 3)
+ if: ${{ matrix.winui == '3' }}
+ run: |
+ echo "EXCLUDED_MULTITARGETS=uwp" >> $env:GITHUB_ENV
+
# Build and pack component nupkg
- name: Build and pack component packages
- run: ./tooling/Build-Toolkit-Components.ps1 -MultiTargets all -WinUIMajorVersion ${{ matrix.winui }} -DateForVersion ${{ env.VERSION_DATE }} ${{ env.VERSION_PROPERTY != '' && format('-PreviewVersion "{0}"', env.VERSION_PROPERTY) || '' }} ${{ env.ENABLE_DIAGNOSTICS == 'true' && '-EnableBinlogs' || '' }} ${{ env.ENABLE_DIAGNOSTICS == 'true' && '-Verbose' || '' }} -BinlogOutput ./ -NupkgOutput ./ -Release
+ run: ./tooling/Build-Toolkit-Components.ps1 -MultiTargets all -ExcludeMultiTargets ${{ env.EXCLUDED_MULTITARGETS }} -WinUIMajorVersion ${{ matrix.winui }} -DateForVersion ${{ env.VERSION_DATE }} ${{ env.VERSION_PROPERTY != '' && format('-PreviewVersion "{0}"', env.VERSION_PROPERTY) || '' }} ${{ env.ENABLE_DIAGNOSTICS == 'true' && '-EnableBinlogs' || '' }} ${{ env.ENABLE_DIAGNOSTICS == 'true' && '-Verbose' || '' }} -BinlogOutput ./ -NupkgOutput ./ -Release
- name: Validate package names
if: ${{ env.VERSION_PROPERTY != '' }}
diff --git a/Directory.Build.props b/Directory.Build.props
index 74436b013..72e05671d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -12,7 +12,10 @@
true
true
- $(NoWarn);Uno0001
+ $(NoWarn);Uno0001
+
+
+ NU1901;NU1902;NU1903;NU1904
diff --git a/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml b/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml
index 7173b399d..1ead34838 100644
--- a/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml
+++ b/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml
@@ -1,4 +1,4 @@
-
+
-
-
diff --git a/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml.cs b/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml.cs
index 01e3127dd..413bd1d6e 100644
--- a/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml.cs
+++ b/components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml.cs
@@ -607,5 +607,12 @@ public MarkdownTextBlockCustomSample()
_liveConfig = new MarkdownConfig();
_text = _markdown;
MarkdownTextBox.Text = "# Hello World\n\n";
+ MarkdownTextBlock1.OnLinkClicked += MarkdownTextBlock_OnLinkClicked;
+ MarkdownTextBlock2.OnLinkClicked += MarkdownTextBlock_OnLinkClicked;
+ }
+
+ private void MarkdownTextBlock_OnLinkClicked(object? sender, LinkClickedEventArgs e)
+ {
+ Debug.WriteLine($"Link Clicked: {e.Uri}");
}
}
diff --git a/components/MarkdownTextBlock/src/HtmlWriter.cs b/components/MarkdownTextBlock/src/HtmlWriter.cs
index 7875c0f01..3a9ece776 100644
--- a/components/MarkdownTextBlock/src/HtmlWriter.cs
+++ b/components/MarkdownTextBlock/src/HtmlWriter.cs
@@ -33,11 +33,21 @@ public static void WriteHtml(WinUIRenderer renderer, HtmlNodeCollection nodes)
IAddChild hyperLink;
if (node.ChildNodes.Any(n => n.Name != "#text"))
{
- hyperLink = new MyHyperlinkButton(node, renderer.Config.BaseUrl);
+ var myHyperlinkButton = new MyHyperlinkButton(node, renderer.Config.BaseUrl);
+ myHyperlinkButton.ClickEvent += (sender, e) =>
+ {
+ renderer.MarkdownTextBlock.RaiseLinkClickedEvent(((HyperlinkButton)sender).NavigateUri);
+ };
+ hyperLink = myHyperlinkButton;
}
else
{
- hyperLink = new MyHyperlink(node, renderer.Config.BaseUrl);
+ var myHyperlink = new MyHyperlink(node, renderer.Config.BaseUrl);
+ myHyperlink.ClickEvent += (sender, e) =>
+ {
+ renderer.MarkdownTextBlock.RaiseLinkClickedEvent(sender.NavigateUri);
+ };
+ hyperLink = myHyperlink;
}
renderer.Push(hyperLink);
WriteHtml(renderer, node.ChildNodes);
diff --git a/components/MarkdownTextBlock/src/LinkClickedEventArgs.cs b/components/MarkdownTextBlock/src/LinkClickedEventArgs.cs
new file mode 100644
index 000000000..9b1278bc8
--- /dev/null
+++ b/components/MarkdownTextBlock/src/LinkClickedEventArgs.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock;
+
+public class LinkClickedEventArgs : EventArgs
+{
+ public Uri Uri { get; }
+
+ public LinkClickedEventArgs(Uri uri)
+ {
+ this.Uri = uri;
+ }
+}
diff --git a/components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs b/components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs
index efba3cb4b..eef90cf74 100644
--- a/components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs
+++ b/components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs
@@ -42,6 +42,10 @@ public string Text
set => SetValue(TextProperty, value);
}
+ public event EventHandler? OnLinkClicked;
+
+ internal void RaiseLinkClickedEvent(Uri uri) => OnLinkClicked?.Invoke(this, new LinkClickedEventArgs(uri));
+
private static void OnConfigChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MarkdownTextBlock self && e.NewValue != null)
@@ -110,7 +114,7 @@ private void Build()
{
if (_renderer == null)
{
- _renderer = new WinUIRenderer(_document, Config);
+ _renderer = new WinUIRenderer(_document, Config, this);
}
_pipeline.Setup(_renderer);
ApplyText(false);
diff --git a/components/MarkdownTextBlock/src/MarkdownThemes.cs b/components/MarkdownTextBlock/src/MarkdownThemes.cs
index 0b1aaf734..ada70c9b4 100644
--- a/components/MarkdownTextBlock/src/MarkdownThemes.cs
+++ b/components/MarkdownTextBlock/src/MarkdownThemes.cs
@@ -49,7 +49,15 @@ public sealed class MarkdownThemes : DependencyObject
public FontWeight H6FontWeight { get; set; } = FontWeights.Normal;
+ public Thickness H1Margin { get; set; } = new(0);
+ public Thickness H2Margin { get; set; } = new(0);
+ public Thickness H3Margin { get; set; } = new(0);
+ public Thickness H4Margin { get; set; } = new(0);
+ public Thickness H5Margin { get; set; } = new(0);
+ public Thickness H6Margin { get; set; } = new(0);
+
public Brush InlineCodeBackground { get; set; } = (Brush)Application.Current.Resources["ExpanderHeaderBackground"];
+ public Brush InlineCodeForeground { get; set; } = (Brush)Application.Current.Resources["TextFillColorPrimaryBrush"];
public Brush InlineCodeBorderBrush { get; set; } = new SolidColorBrush(Colors.Gray);
diff --git a/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/AutoLinkInlineRenderer.cs b/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/AutoLinkInlineRenderer.cs
index 4e9d01f06..5dddedc7e 100644
--- a/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/AutoLinkInlineRenderer.cs
+++ b/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/AutoLinkInlineRenderer.cs
@@ -26,6 +26,10 @@ protected override void Write(WinUIRenderer renderer, AutolinkInline link)
}
var autolink = new MyAutolinkInline(link);
+ autolink.ClickEvent += (sender, e) =>
+ {
+ renderer.MarkdownTextBlock.RaiseLinkClickedEvent(sender.NavigateUri);
+ };
renderer.Push(autolink);
diff --git a/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/LinkInlineRenderer.cs b/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/LinkInlineRenderer.cs
index fa05d400a..5d78c4824 100644
--- a/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/LinkInlineRenderer.cs
+++ b/components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Inlines/LinkInlineRenderer.cs
@@ -30,11 +30,20 @@ protected override void Write(WinUIRenderer renderer, LinkInline link)
{
if (link.FirstChild is LinkInline linkInlineChild && linkInlineChild.IsImage)
{
- renderer.Push(new MyHyperlinkButton(link, renderer.Config.BaseUrl));
+ var myHyperlinkButton = new MyHyperlinkButton(link, renderer.Config.BaseUrl);
+ myHyperlinkButton.ClickEvent += (sender, e) =>
+ {
+ renderer.MarkdownTextBlock.RaiseLinkClickedEvent(((HyperlinkButton)sender).NavigateUri);
+ };
+ renderer.Push(myHyperlinkButton);
}
else
{
var hyperlink = new MyHyperlink(link, renderer.Config.BaseUrl);
+ hyperlink.ClickEvent += (sender, e) =>
+ {
+ renderer.MarkdownTextBlock.RaiseLinkClickedEvent(sender.NavigateUri);
+ };
renderer.Push(hyperlink);
}
diff --git a/components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs b/components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs
index af4d6cb01..a9f772423 100644
--- a/components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs
+++ b/components/MarkdownTextBlock/src/Renderers/WinUIRenderer.cs
@@ -23,11 +23,13 @@ public MarkdownConfig Config
get => _config;
set => _config = value;
}
+ public MarkdownTextBlock MarkdownTextBlock { get; }
- public WinUIRenderer(MyFlowDocument document, MarkdownConfig config)
+ public WinUIRenderer(MyFlowDocument document, MarkdownConfig config, MarkdownTextBlock markdownTextBlock)
{
_buffer = new char[1024];
Config = config;
+ MarkdownTextBlock = markdownTextBlock;
FlowDocument = document;
// set style
_stack.Push(FlowDocument);
diff --git a/components/MarkdownTextBlock/src/TextElements/MyAutolinkInline.cs b/components/MarkdownTextBlock/src/TextElements/MyAutolinkInline.cs
index bdea36eae..465d3c54b 100644
--- a/components/MarkdownTextBlock/src/TextElements/MyAutolinkInline.cs
+++ b/components/MarkdownTextBlock/src/TextElements/MyAutolinkInline.cs
@@ -12,6 +12,18 @@ internal class MyAutolinkInline : IAddChild
public TextElement TextElement { get; private set; }
+ public event TypedEventHandler? ClickEvent
+ {
+ add
+ {
+ ((Hyperlink)TextElement).Click += value;
+ }
+ remove
+ {
+ ((Hyperlink)TextElement).Click -= value;
+ }
+ }
+
public MyAutolinkInline(AutolinkInline autoLinkInline)
{
_autoLinkInline = autoLinkInline;
@@ -21,7 +33,6 @@ public MyAutolinkInline(AutolinkInline autoLinkInline)
};
}
-
public void AddChild(IAddChild child)
{
try
diff --git a/components/MarkdownTextBlock/src/TextElements/MyHeading.cs b/components/MarkdownTextBlock/src/TextElements/MyHeading.cs
index f06c62413..0c52a1be8 100644
--- a/components/MarkdownTextBlock/src/TextElements/MyHeading.cs
+++ b/components/MarkdownTextBlock/src/TextElements/MyHeading.cs
@@ -27,26 +27,7 @@ public MyHeading(HeadingBlock headingBlock, MarkdownConfig config)
_paragraph = new Paragraph();
_config = config;
- var level = headingBlock.Level;
- _paragraph.FontSize = level switch
- {
- 1 => _config.Themes.H1FontSize,
- 2 => _config.Themes.H2FontSize,
- 3 => _config.Themes.H3FontSize,
- 4 => _config.Themes.H4FontSize,
- 5 => _config.Themes.H5FontSize,
- _ => _config.Themes.H6FontSize,
- };
- _paragraph.Foreground = _config.Themes.HeadingForeground;
- _paragraph.FontWeight = level switch
- {
- 1 => _config.Themes.H1FontWeight,
- 2 => _config.Themes.H2FontWeight,
- 3 => _config.Themes.H3FontWeight,
- 4 => _config.Themes.H4FontWeight,
- 5 => _config.Themes.H5FontWeight,
- _ => _config.Themes.H6FontWeight,
- };
+ SetHProperties(headingBlock.Level);
}
public MyHeading(HtmlNode htmlNode, MarkdownConfig config)
@@ -65,7 +46,11 @@ public MyHeading(HtmlNode htmlNode, MarkdownConfig config)
_ => TextAlignment.Left,
};
- var level = int.Parse(htmlNode.Name.Substring(1));
+ SetHProperties(int.Parse(htmlNode.Name.Substring(1)));
+ }
+
+ private void SetHProperties(int level)
+ {
_paragraph.FontSize = level switch
{
1 => _config.Themes.H1FontSize,
@@ -85,6 +70,15 @@ public MyHeading(HtmlNode htmlNode, MarkdownConfig config)
5 => _config.Themes.H5FontWeight,
_ => _config.Themes.H6FontWeight,
};
+ _paragraph.Margin = level switch
+ {
+ 1 => _config.Themes.H1Margin,
+ 2 => _config.Themes.H2Margin,
+ 3 => _config.Themes.H3Margin,
+ 4 => _config.Themes.H4Margin,
+ 5 => _config.Themes.H5Margin,
+ _ => _config.Themes.H6Margin,
+ };
}
public void AddChild(IAddChild child)
diff --git a/components/MarkdownTextBlock/src/TextElements/MyHyperlink.cs b/components/MarkdownTextBlock/src/TextElements/MyHyperlink.cs
index 6a36a8d94..49dfa6338 100644
--- a/components/MarkdownTextBlock/src/TextElements/MyHyperlink.cs
+++ b/components/MarkdownTextBlock/src/TextElements/MyHyperlink.cs
@@ -14,6 +14,18 @@ internal class MyHyperlink : IAddChild
private HtmlNode? _htmlNode;
private string? _baseUrl;
+ public event TypedEventHandler ClickEvent
+ {
+ add
+ {
+ _hyperlink.Click += value;
+ }
+ remove
+ {
+ _hyperlink.Click -= value;
+ }
+ }
+
public bool IsHtml => _htmlNode != null;
public TextElement TextElement
diff --git a/components/MarkdownTextBlock/src/TextElements/MyHyperlinkButton.cs b/components/MarkdownTextBlock/src/TextElements/MyHyperlinkButton.cs
index 9d5297fea..deba711ce 100644
--- a/components/MarkdownTextBlock/src/TextElements/MyHyperlinkButton.cs
+++ b/components/MarkdownTextBlock/src/TextElements/MyHyperlinkButton.cs
@@ -9,12 +9,24 @@ namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
internal class MyHyperlinkButton : IAddChild
{
- private HyperlinkButton? _hyperLinkButton;
+ private HyperlinkButton _hyperLinkButton;
private InlineUIContainer _inlineUIContainer = new InlineUIContainer();
- private MyFlowDocument? _flowDoc;
+ private MyFlowDocument _flowDoc;
private string? _baseUrl;
private LinkInline? _linkInline;
private HtmlNode? _htmlNode;
+
+ public event RoutedEventHandler? ClickEvent
+ {
+ add
+ {
+ _hyperLinkButton.Click += value;
+ }
+ remove
+ {
+ _hyperLinkButton.Click -= value;
+ }
+ }
public bool IsHtml => _htmlNode != null;
@@ -24,43 +36,40 @@ public TextElement TextElement
}
public MyHyperlinkButton(LinkInline linkInline, string? baseUrl)
+ : this(linkInline.GetDynamicUrl != null ? linkInline.GetDynamicUrl() ?? linkInline.Url : linkInline.Url, baseUrl, null, linkInline)
{
- _baseUrl = baseUrl;
- var url = linkInline.GetDynamicUrl != null ? linkInline.GetDynamicUrl() ?? linkInline.Url : linkInline.Url;
- _linkInline = linkInline;
- Init(url, baseUrl);
}
public MyHyperlinkButton(HtmlNode htmlNode, string? baseUrl)
+ : this(htmlNode.GetAttribute("href", "#"), baseUrl, htmlNode, null)
{
- _baseUrl = baseUrl;
- _htmlNode = htmlNode;
- var url = htmlNode.GetAttribute("href", "#");
- Init(url, baseUrl);
}
- private void Init(string? url, string? baseUrl)
+ private MyHyperlinkButton(string? url, string? baseUrl, HtmlNode? htmlNode, LinkInline? linkInline)
{
- _hyperLinkButton = new HyperlinkButton()
+ _baseUrl = baseUrl;
+ _htmlNode = htmlNode;
+ _linkInline = linkInline;
+ _hyperLinkButton = new HyperlinkButton
{
NavigateUri = Extensions.GetUri(url, baseUrl),
};
_hyperLinkButton.Padding = new Thickness(0);
_hyperLinkButton.Margin = new Thickness(0);
- if (IsHtml && _htmlNode != null)
+ if (_htmlNode != null)
{
_flowDoc = new MyFlowDocument(_htmlNode);
}
- else if (_linkInline != null)
+ else
{
- _flowDoc = new MyFlowDocument(_linkInline);
+ _flowDoc = new MyFlowDocument(_linkInline!);
}
_inlineUIContainer.Child = _hyperLinkButton;
- _hyperLinkButton.Content = _flowDoc?.RichTextBlock;
+ _hyperLinkButton.Content = _flowDoc.RichTextBlock;
}
public void AddChild(IAddChild child)
{
- _flowDoc?.AddChild(child);
+ _flowDoc.AddChild(child);
}
}
diff --git a/components/MarkdownTextBlock/src/TextElements/MyInlineCode.cs b/components/MarkdownTextBlock/src/TextElements/MyInlineCode.cs
index 8e97d5963..30c3765d7 100644
--- a/components/MarkdownTextBlock/src/TextElements/MyInlineCode.cs
+++ b/components/MarkdownTextBlock/src/TextElements/MyInlineCode.cs
@@ -34,6 +34,7 @@ public MyInlineCode(CodeInline codeInline, MarkdownConfig config)
border.Transform3D = transform;
var textBlock = new TextBlock();
textBlock.FontSize = _config.Themes.InlineCodeFontSize;
+ textBlock.Foreground = _config.Themes.InlineCodeForeground;
textBlock.FontWeight = _config.Themes.InlineCodeFontWeight;
textBlock.Text = codeInline.Content.ToString();
border.Child = textBlock;