Skip to content

Commit 8f21b73

Browse files
committed
Merge remote-tracking branch 'upstream/main' into 5bfa/CQ-Shimmer
2 parents 3f85536 + 186f3d8 commit 8f21b73

File tree

11 files changed

+269
-99
lines changed

11 files changed

+269
-99
lines changed

components/MarkdownTextBlock/samples/MarkdownTextBlockCustomSample.xaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
<controls:MarkdownTextBlock x:Name="MarkdownTextBlock2"
4242
Grid.Row="3"
4343
Config="{x:Bind MarkdownConfig, Mode=OneTime}"
44-
Text="{x:Bind Text, Mode=OneTime}" />
44+
Text="{x:Bind Text, Mode=OneTime}"
45+
UseAutoLinks="True"
46+
UseEmphasisExtras="True"
47+
UseListExtras="True"
48+
UsePipeTables="True"
49+
UseTaskLists="True" />
4550
</Grid>
4651
</Page>

components/MarkdownTextBlock/src/Extensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,13 +710,13 @@ public static Size GetMarkdownImageSize(LinkInline link)
710710
return new(0, 0);
711711
}
712712

713-
public static SolidColorBrush GetAccentColorBrush()
713+
public static SolidColorBrush GetAccentColorBrush(UIColorType colorType = UIColorType.Accent)
714714
{
715715
// Create a UISettings object to get the accent color
716716
var uiSettings = new UISettings();
717717

718718
// Get the accent color as a Color value
719-
var accentColor = uiSettings.GetColorValue(UIColorType.Accent);
719+
var accentColor = uiSettings.GetColorValue(colorType);
720720

721721
// Create a SolidColorBrush from the accent color
722722
var accentBrush = new SolidColorBrush(accentColor);
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Markdig.Syntax;
6+
7+
namespace CommunityToolkit.Labs.WinUI.MarkdownTextBlock;
8+
9+
public partial class MarkdownTextBlock
10+
{
11+
/// <summary>
12+
/// Identifies the <see cref="Config"/> dependency property.
13+
/// </summary>
14+
private static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(
15+
nameof(Config),
16+
typeof(MarkdownConfig),
17+
typeof(MarkdownTextBlock),
18+
new PropertyMetadata(null, OnConfigChanged)
19+
);
20+
21+
/// <summary>
22+
/// Identifies the <see cref="Text"/> dependency property.
23+
/// </summary>
24+
private static readonly DependencyProperty TextProperty = DependencyProperty.Register(
25+
nameof(Text),
26+
typeof(string),
27+
typeof(MarkdownTextBlock),
28+
new PropertyMetadata(null, OnTextChanged));
29+
30+
/// <summary>
31+
/// Identifies the <see cref="UseEmphasisExtras"/> dependency property.
32+
/// </summary>
33+
private static readonly DependencyProperty UseEmphasisExtrasProperty = DependencyProperty.Register(
34+
nameof(UseEmphasisExtras),
35+
typeof(bool),
36+
typeof(MarkdownTextBlock),
37+
new PropertyMetadata(false));
38+
39+
/// <summary>
40+
/// Identifies the <see cref="UsePipeTables"/> dependency property.
41+
/// </summary>
42+
private static readonly DependencyProperty UsePipeTablesProperty = DependencyProperty.Register(
43+
nameof(UsePipeTables),
44+
typeof(bool),
45+
typeof(MarkdownTextBlock),
46+
new PropertyMetadata(false));
47+
48+
/// <summary>
49+
/// Identifies the <see cref="UseListExtras"/> dependency property.
50+
/// </summary>
51+
private static readonly DependencyProperty UseListExtrasProperty = DependencyProperty.Register(
52+
nameof(UseListExtras),
53+
typeof(bool),
54+
typeof(MarkdownTextBlock),
55+
new PropertyMetadata(false));
56+
57+
/// <summary>
58+
/// Identifies the <see cref="UseTaskLists"/> dependency property.
59+
/// </summary>
60+
private static readonly DependencyProperty UseTaskListsProperty = DependencyProperty.Register(
61+
nameof(UseTaskLists),
62+
typeof(bool),
63+
typeof(MarkdownTextBlock),
64+
new PropertyMetadata(false));
65+
66+
/// <summary>
67+
/// Identifies the <see cref="UseAutoLinks"/> dependency property.
68+
/// </summary>
69+
private static readonly DependencyProperty UseAutoLinksProperty = DependencyProperty.Register(
70+
nameof(UseAutoLinks),
71+
typeof(bool),
72+
typeof(MarkdownTextBlock),
73+
new PropertyMetadata(false));
74+
75+
/// <summary>
76+
/// Identifies the <see cref="UseSoftlineBreakAsHardlineBreak"/> dependency property.
77+
/// </summary>
78+
private static readonly DependencyProperty UseSoftlineBreakAsHardlineBreakProperty = DependencyProperty.Register(
79+
nameof(UseSoftlineBreakAsHardlineBreak),
80+
typeof(bool),
81+
typeof(MarkdownTextBlock),
82+
new PropertyMetadata(false));
83+
84+
/// <summary>
85+
/// Identifies the <see cref="MarkdownDocument"/> dependency property.
86+
/// </summary>
87+
private static readonly DependencyProperty MarkdownDocumentProperty = DependencyProperty.Register(
88+
nameof(MarkdownDocument),
89+
typeof(MarkdownDocument),
90+
typeof(MarkdownTextBlock),
91+
new PropertyMetadata(null));
92+
93+
public MarkdownConfig Config
94+
{
95+
get => (MarkdownConfig)GetValue(ConfigProperty);
96+
set => SetValue(ConfigProperty, value);
97+
}
98+
99+
/// <summary>
100+
/// Gets or sets the markdown text to display.
101+
/// </summary>
102+
public string Text
103+
{
104+
get => (string)GetValue(TextProperty);
105+
set => SetValue(TextProperty, value);
106+
}
107+
108+
/// <summary>
109+
/// If true, adds support for strikethroughs, superscript, subscript, inserted, and marked text.
110+
/// </summary>
111+
public bool UseEmphasisExtras
112+
{
113+
get => (bool)GetValue(UseEmphasisExtrasProperty);
114+
set => SetValue(UseEmphasisExtrasProperty, value);
115+
}
116+
117+
/// <summary>
118+
/// If true, adds support for GitHub-style pipe tables.
119+
/// </summary>
120+
public bool UsePipeTables
121+
{
122+
get => (bool)GetValue(UsePipeTablesProperty);
123+
set => SetValue(UsePipeTablesProperty, value);
124+
}
125+
126+
/// <summary>
127+
/// If true, adds support for alphabetic and roman numbering in lists.
128+
/// </summary>
129+
public bool UseListExtras
130+
{
131+
get => (bool)GetValue(UseListExtrasProperty);
132+
set => SetValue(UseListExtrasProperty, value);
133+
}
134+
135+
/// <summary>
136+
/// If true, adds support for GitHub-style task lists using the [ ] and [x] syntax.
137+
/// </summary>
138+
public bool UseTaskLists
139+
{
140+
get => (bool)GetValue(UseTaskListsProperty);
141+
set => SetValue(UseTaskListsProperty, value);
142+
}
143+
144+
/// <summary>
145+
/// If true, parses text that looks like URIs into hyperlinks (e.g. https://...).
146+
/// </summary>
147+
public bool UseAutoLinks
148+
{
149+
get => (bool)GetValue(UseAutoLinksProperty);
150+
set => SetValue(UseAutoLinksProperty, value);
151+
}
152+
153+
/// <summary>
154+
/// If true, considers single newlines as hardline breaks.
155+
/// </summary>
156+
public bool UseSoftlineBreakAsHardlineBreak
157+
{
158+
get => (bool)GetValue(UseSoftlineBreakAsHardlineBreakProperty);
159+
set => SetValue(UseSoftlineBreakAsHardlineBreakProperty, value);
160+
}
161+
162+
/// <summary>
163+
/// Gets the parsed markdown document. May be null if the document has not been parsed yet.
164+
/// </summary>
165+
public MarkdownDocument? MarkdownDocument
166+
{
167+
get => (MarkdownDocument)GetValue(MarkdownDocumentProperty);
168+
private set => SetValue(MarkdownDocumentProperty, value);
169+
}
170+
}

components/MarkdownTextBlock/src/MarkdownTextBlock.xaml.cs

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
// See the LICENSE file in the project root for more information.
44

55
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers;
6+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers;
7+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers.Extensions;
8+
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.Renderers.ObjectRenderers.Inlines;
69
using CommunityToolkit.Labs.WinUI.MarkdownTextBlock.TextElements;
710
using Markdig;
811
using Markdig.Syntax;
@@ -14,47 +17,10 @@ public partial class MarkdownTextBlock : Control
1417
{
1518
private const string MarkdownContainerName = "MarkdownContainer";
1619
private Grid? _container;
17-
private MarkdownPipeline _pipeline;
20+
private MarkdownPipeline _pipeline = null!;
1821
private MyFlowDocument _document;
1922
private WinUIRenderer? _renderer;
2023

21-
private static readonly DependencyProperty ConfigProperty = DependencyProperty.Register(
22-
nameof(Config),
23-
typeof(MarkdownConfig),
24-
typeof(MarkdownTextBlock),
25-
new PropertyMetadata(null, OnConfigChanged)
26-
);
27-
28-
private static readonly DependencyProperty TextProperty = DependencyProperty.Register(
29-
nameof(Text),
30-
typeof(string),
31-
typeof(MarkdownTextBlock),
32-
new PropertyMetadata(null, OnTextChanged));
33-
34-
private static readonly DependencyProperty MarkdownDocumentProperty = DependencyProperty.Register(
35-
nameof(MarkdownDocument),
36-
typeof(MarkdownDocument),
37-
typeof(MarkdownTextBlock),
38-
new PropertyMetadata(null));
39-
40-
public MarkdownConfig Config
41-
{
42-
get => (MarkdownConfig)GetValue(ConfigProperty);
43-
set => SetValue(ConfigProperty, value);
44-
}
45-
46-
public string Text
47-
{
48-
get => (string)GetValue(TextProperty);
49-
set => SetValue(TextProperty, value);
50-
}
51-
52-
public MarkdownDocument? MarkdownDocument
53-
{
54-
get => (MarkdownDocument)GetValue(MarkdownDocumentProperty);
55-
private set => SetValue(MarkdownDocumentProperty, value);
56-
}
57-
5824
public event EventHandler<LinkClickedEventArgs>? OnLinkClicked;
5925

6026
internal void RaiseLinkClickedEvent(Uri uri) => OnLinkClicked?.Invoke(this, new LinkClickedEventArgs(uri));
@@ -79,17 +45,24 @@ public MarkdownTextBlock()
7945
{
8046
this.DefaultStyleKey = typeof(MarkdownTextBlock);
8147
_document = new MyFlowDocument();
82-
_pipeline = new MarkdownPipelineBuilder()
83-
.UseEmphasisExtras()
84-
.UseAutoLinks()
85-
.UseTaskLists()
86-
.UsePipeTables()
87-
.Build();
8848
}
8949

9050
protected override void OnApplyTemplate()
9151
{
9252
base.OnApplyTemplate();
53+
54+
var pipelineBuilder = new MarkdownPipelineBuilder();
55+
56+
// NOTE: Order matters here
57+
if (UseEmphasisExtras) pipelineBuilder = pipelineBuilder.UseEmphasisExtras();
58+
if (UsePipeTables) pipelineBuilder = pipelineBuilder.UsePipeTables();
59+
if (UseListExtras) pipelineBuilder = pipelineBuilder.UseListExtras();
60+
if (UseTaskLists) pipelineBuilder = pipelineBuilder.UseTaskLists();
61+
if (UseAutoLinks) pipelineBuilder = pipelineBuilder.UseAutoLinks();
62+
if (UseSoftlineBreakAsHardlineBreak) pipelineBuilder = pipelineBuilder.UseSoftlineBreakAsHardlineBreak();
63+
64+
_pipeline = pipelineBuilder.Build();
65+
9366
_container = (Grid)GetTemplateChild(MarkdownContainerName);
9467
_container.Children.Clear();
9568
_container.Children.Add(_document.RichTextBlock);
@@ -115,8 +88,9 @@ private void ApplyText(bool rerender)
11588

11689
if (!string.IsNullOrEmpty(Text))
11790
{
118-
this.MarkdownDocument = Markdown.Parse(Text, _pipeline);
119-
_renderer.Render(this.MarkdownDocument);
91+
var parsedMarkdown = Markdown.Parse(Text, _pipeline);
92+
this.MarkdownDocument = parsedMarkdown;
93+
_renderer.Render(parsedMarkdown);
12094
}
12195
}
12296
}
@@ -128,6 +102,31 @@ private void Build()
128102
if (_renderer == null)
129103
{
130104
_renderer = new WinUIRenderer(_document, Config, this);
105+
106+
// Default block renderers
107+
_renderer.ObjectRenderers.Add(new CodeBlockRenderer());
108+
_renderer.ObjectRenderers.Add(new ListRenderer());
109+
_renderer.ObjectRenderers.Add(new HeadingRenderer());
110+
_renderer.ObjectRenderers.Add(new ParagraphRenderer());
111+
_renderer.ObjectRenderers.Add(new QuoteBlockRenderer());
112+
_renderer.ObjectRenderers.Add(new ThematicBreakRenderer());
113+
_renderer.ObjectRenderers.Add(new HtmlBlockRenderer());
114+
115+
// Default inline renderers
116+
if (UseAutoLinks) _renderer.ObjectRenderers.Add(new AutoLinkInlineRenderer());
117+
_renderer.ObjectRenderers.Add(new CodeInlineRenderer());
118+
_renderer.ObjectRenderers.Add(new DelimiterInlineRenderer());
119+
_renderer.ObjectRenderers.Add(new EmphasisInlineRenderer());
120+
_renderer.ObjectRenderers.Add(new HtmlEntityInlineRenderer());
121+
_renderer.ObjectRenderers.Add(new LineBreakInlineRenderer());
122+
_renderer.ObjectRenderers.Add(new LinkInlineRenderer());
123+
_renderer.ObjectRenderers.Add(new LiteralInlineRenderer());
124+
_renderer.ObjectRenderers.Add(new ContainerInlineRenderer());
125+
126+
// Extension renderers
127+
if (UsePipeTables) _renderer.ObjectRenderers.Add(new TableRenderer());
128+
if (UseTaskLists) _renderer.ObjectRenderers.Add(new TaskListRenderer());
129+
_renderer.ObjectRenderers.Add(new HtmlInlineRenderer());
131130
}
132131
_pipeline.Setup(_renderer);
133132
ApplyText(false);

components/MarkdownTextBlock/src/MarkdownThemes.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public sealed class MarkdownThemes : DependencyObject
5656
public Thickness H5Margin { get; set; } = new(left: 0, top: 8, right: 0, bottom: 0);
5757
public Thickness H6Margin { get; set; } = new(left: 0, top: 8, right: 0, bottom: 0);
5858

59+
public Brush BorderBrush { get; set; } = new SolidColorBrush(Colors.Gray);
60+
61+
public Brush TableHeadingBackground { get; set; } = Extensions.GetAccentColorBrush(Windows.UI.ViewManagement.UIColorType.AccentLight3);
62+
5963
public Brush InlineCodeBackground { get; set; } = (Brush)Application.Current.Resources["ExpanderHeaderBackground"];
6064
public Brush InlineCodeForeground { get; set; } = (Brush)Application.Current.Resources["TextFillColorPrimaryBrush"];
6165

components/MarkdownTextBlock/src/Renderers/ObjectRenderers/Extensions/TableRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected override void Write(WinUIRenderer renderer, Table table)
1414
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
1515
if (table == null) throw new ArgumentNullException(nameof(table));
1616

17-
var myTable = new MyTable(table);
17+
var myTable = new MyTable(table, renderer.Config.Themes);
1818

1919
renderer.Push(myTable);
2020

components/MarkdownTextBlock/src/Renderers/ObjectRenderers/ThematicBreakRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected override void Write(WinUIRenderer renderer, ThematicBreakBlock obj)
1414
if (renderer == null) throw new ArgumentNullException(nameof(renderer));
1515
if (obj == null) throw new ArgumentNullException(nameof(obj));
1616

17-
var thematicBreak = new MyThematicBreak(obj);
17+
var thematicBreak = new MyThematicBreak(obj, renderer.Config.Themes);
1818

1919
renderer.WriteBlock(thematicBreak);
2020
}

0 commit comments

Comments
 (0)